133965Sjdp/* read.c - read a source file -
278828Sobrien   Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
3218822Sdim   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
4218822Sdim   Free Software Foundation, Inc.
533965Sjdp
633965SjdpThis file is part of GAS, the GNU Assembler.
733965Sjdp
833965SjdpGAS is free software; you can redistribute it and/or modify
933965Sjdpit under the terms of the GNU General Public License as published by
1033965Sjdpthe Free Software Foundation; either version 2, or (at your option)
1133965Sjdpany later version.
1233965Sjdp
1333965SjdpGAS is distributed in the hope that it will be useful,
1433965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
1533965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1633965SjdpGNU General Public License for more details.
1733965Sjdp
1833965SjdpYou should have received a copy of the GNU General Public License
1933965Sjdpalong with GAS; see the file COPYING.  If not, write to the Free
20218822SdimSoftware Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21218822Sdim02110-1301, USA.  */
2233965Sjdp
23218822Sdim/* If your chars aren't 8 bits, you will change this a bit (eg. to 0xFF).
2477298Sobrien   But then, GNU isn't spozed to run on your machine anyway.
2577298Sobrien   (RMS is so shortsighted sometimes.)  */
2677298Sobrien#define MASK_CHAR ((int)(unsigned char) -1)
2733965Sjdp
2833965Sjdp/* This is the largest known floating point format (for now). It will
2977298Sobrien   grow when we do 4361 style flonums.  */
3033965Sjdp#define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)
3133965Sjdp
32130561Sobrien/* Routines that read assembler source text to build spaghetti in memory.
3333965Sjdp   Another group of these functions is in the expr.c module.  */
3433965Sjdp
3533965Sjdp#include "as.h"
3689857Sobrien#include "safe-ctype.h"
3733965Sjdp#include "subsegs.h"
3833965Sjdp#include "sb.h"
3933965Sjdp#include "macro.h"
4033965Sjdp#include "obstack.h"
4133965Sjdp#include "ecoff.h"
42130561Sobrien#include "dw2gencfi.h"
4333965Sjdp
4433965Sjdp#ifndef TC_START_LABEL
45104834Sobrien#define TC_START_LABEL(x,y) (x == ':')
4633965Sjdp#endif
4733965Sjdp
4860484Sobrien/* Set by the object-format or the target.  */
4960484Sobrien#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
50130561Sobrien#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR)		\
5177298Sobrien  do								\
52130561Sobrien    {								\
53130561Sobrien      if ((SIZE) >= 8)						\
54130561Sobrien	(P2VAR) = 3;						\
55130561Sobrien      else if ((SIZE) >= 4)					\
56130561Sobrien	(P2VAR) = 2;						\
57130561Sobrien      else if ((SIZE) >= 2)					\
58130561Sobrien	(P2VAR) = 1;						\
59130561Sobrien      else							\
60130561Sobrien	(P2VAR) = 0;						\
6177298Sobrien    }								\
6277298Sobrien  while (0)
6360484Sobrien#endif
6460484Sobrien
6577298Sobrienchar *input_line_pointer;	/*->next char of source file to parse.  */
6633965Sjdp
6733965Sjdp#if BITS_PER_CHAR != 8
6833965Sjdp/*  The following table is indexed by[(char)] and will break if
6933965Sjdp    a char does not have exactly 256 states (hopefully 0:255!)!  */
7033965Sjdpdie horribly;
7133965Sjdp#endif
7233965Sjdp
7333965Sjdp#ifndef LEX_AT
7433965Sjdp#define LEX_AT 0
7533965Sjdp#endif
7633965Sjdp
7733965Sjdp#ifndef LEX_BR
7833965Sjdp/* The RS/6000 assembler uses {,},[,] as parts of symbol names.  */
7933965Sjdp#define LEX_BR 0
8033965Sjdp#endif
8133965Sjdp
8233965Sjdp#ifndef LEX_PCT
8333965Sjdp/* The Delta 68k assembler permits % inside label names.  */
8433965Sjdp#define LEX_PCT 0
8533965Sjdp#endif
8633965Sjdp
8733965Sjdp#ifndef LEX_QM
8833965Sjdp/* The PowerPC Windows NT assemblers permits ? inside label names.  */
8933965Sjdp#define LEX_QM 0
9033965Sjdp#endif
9133965Sjdp
9260484Sobrien#ifndef LEX_HASH
9377298Sobrien/* The IA-64 assembler uses # as a suffix designating a symbol.  We include
9477298Sobrien   it in the symbol and strip it out in tc_canonicalize_symbol_name.  */
9560484Sobrien#define LEX_HASH 0
9660484Sobrien#endif
9760484Sobrien
9833965Sjdp#ifndef LEX_DOLLAR
9933965Sjdp#define LEX_DOLLAR 3
10033965Sjdp#endif
10133965Sjdp
10233965Sjdp#ifndef LEX_TILDE
10333965Sjdp/* The Delta 68k assembler permits ~ at start of label names.  */
10433965Sjdp#define LEX_TILDE 0
10533965Sjdp#endif
10633965Sjdp
10777298Sobrien/* Used by is_... macros. our ctype[].  */
10877298Sobrienchar lex_type[256] = {
10933965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* @ABCDEFGHIJKLMNO */
11033965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* PQRSTUVWXYZ[\]^_ */
11160484Sobrien  0, 0, 0, LEX_HASH, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
11233965Sjdp  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM,	/* 0123456789:;<=>? */
11333965Sjdp  LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,	/* @ABCDEFGHIJKLMNO */
11433965Sjdp  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
11533965Sjdp  0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,	/* `abcdefghijklmno */
11677298Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~.  */
11760484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
11860484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
11960484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12060484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12160484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12260484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12360484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12460484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
12533965Sjdp};
12633965Sjdp
12777298Sobrien/* In: a character.
12877298Sobrien   Out: 1 if this character ends a line.  */
12977298Sobrienchar is_end_of_line[256] = {
13033965Sjdp#ifdef CR_EOL
13177298Sobrien  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,	/* @abcdefghijklmno */
13233965Sjdp#else
13377298Sobrien  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,	/* @abcdefghijklmno */
13433965Sjdp#endif
13577298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
13677298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* _!"#$%&'()*+,-./ */
13777298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0123456789:;<=>? */
13877298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
13977298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14077298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14177298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14277298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14377298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14477298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14577298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14677298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14777298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14877298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14977298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0	/* */
15033965Sjdp};
15133965Sjdp
152130561Sobrien#ifndef TC_CASE_SENSITIVE
15377298Sobrienchar original_case_string[128];
15477298Sobrien#endif
15533965Sjdp
15677298Sobrien/* Functions private to this file.  */
15733965Sjdp
15877298Sobrienstatic char *buffer;	/* 1st char of each buffer of lines is here.  */
15977298Sobrienstatic char *buffer_limit;	/*->1 + last char in buffer.  */
16077298Sobrien
16177298Sobrien/* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1
16277298Sobrien   in the tc-<CPU>.h file.  See the "Porting GAS" section of the
16377298Sobrien   internals manual.  */
16433965Sjdpint target_big_endian = TARGET_BYTES_BIG_ENDIAN;
16533965Sjdp
16677298Sobrien/* Variables for handling include file directory table.  */
16733965Sjdp
16877298Sobrien/* Table of pointers to directories to search for .include's.  */
16977298Sobrienchar **include_dirs;
17033965Sjdp
17177298Sobrien/* How many are in the table.  */
17277298Sobrienint include_dir_count;
17377298Sobrien
17477298Sobrien/* Length of longest in table.  */
17577298Sobrienint include_dir_maxlen = 1;
17677298Sobrien
17733965Sjdp#ifndef WORKING_DOT_WORD
17833965Sjdpstruct broken_word *broken_words;
17933965Sjdpint new_broken_words;
18033965Sjdp#endif
18133965Sjdp
18233965Sjdp/* The current offset into the absolute section.  We don't try to
18333965Sjdp   build frags in the absolute section, since no data can be stored
18433965Sjdp   there.  We just keep track of the current offset.  */
18533965SjdpaddressT abs_section_offset;
18633965Sjdp
18733965Sjdp/* If this line had an MRI style label, it is stored in this variable.
18833965Sjdp   This is used by some of the MRI pseudo-ops.  */
18933965SjdpsymbolS *line_label;
19033965Sjdp
19133965Sjdp/* This global variable is used to support MRI common sections.  We
19233965Sjdp   translate such sections into a common symbol.  This variable is
19333965Sjdp   non-NULL when we are in an MRI common section.  */
19433965SjdpsymbolS *mri_common_symbol;
19533965Sjdp
19633965Sjdp/* In MRI mode, after a dc.b pseudo-op with an odd number of bytes, we
19733965Sjdp   need to align to an even byte boundary unless the next pseudo-op is
19833965Sjdp   dc.b, ds.b, or dcb.b.  This variable is set to 1 if an alignment
19933965Sjdp   may be needed.  */
20033965Sjdpstatic int mri_pending_align;
20133965Sjdp
20238889Sjdp#ifndef NO_LISTING
20338889Sjdp#ifdef OBJ_ELF
20438889Sjdp/* This variable is set to be non-zero if the next string we see might
20538889Sjdp   be the name of the source file in DWARF debugging information.  See
20638889Sjdp   the comment in emit_expr for the format we look for.  */
20738889Sjdpstatic int dwarf_file_string;
20838889Sjdp#endif
20938889Sjdp#endif
21038889Sjdp
211218822Sdimstatic void do_s_func (int end_p, const char *default_prefix);
212130561Sobrienstatic void do_align (int, char *, int, int);
213130561Sobrienstatic void s_align (int, int);
214218822Sdimstatic void s_altmacro (int);
215218822Sdimstatic void s_bad_end (int);
216218822Sdim#ifdef OBJ_ELF
217218822Sdimstatic void s_gnu_attribute (int);
218218822Sdim#endif
219218822Sdimstatic void s_reloc (int);
220130561Sobrienstatic int hex_float (int, char *);
221130561Sobrienstatic segT get_known_segmented_expression (expressionS * expP);
222130561Sobrienstatic void pobegin (void);
223130561Sobrienstatic int get_line_sb (sb *);
224130561Sobrienstatic void generate_file_debug (void);
225218822Sdimstatic char *_find_end_of_line (char *, int, int);
22633965Sjdp
22733965Sjdpvoid
228130561Sobrienread_begin (void)
22933965Sjdp{
23033965Sjdp  const char *p;
23133965Sjdp
23233965Sjdp  pobegin ();
23333965Sjdp  obj_read_begin_hook ();
23433965Sjdp
23533965Sjdp  /* Something close -- but not too close -- to a multiple of 1024.
23633965Sjdp     The debugging malloc I'm using has 24 bytes of overhead.  */
23733965Sjdp  obstack_begin (&notes, chunksize);
23833965Sjdp  obstack_begin (&cond_obstack, chunksize);
23933965Sjdp
24077298Sobrien  /* Use machine dependent syntax.  */
24133965Sjdp  for (p = line_separator_chars; *p; p++)
24233965Sjdp    is_end_of_line[(unsigned char) *p] = 1;
24377298Sobrien  /* Use more.  FIXME-SOMEDAY.  */
24433965Sjdp
24533965Sjdp  if (flag_mri)
24633965Sjdp    lex_type['?'] = 3;
24733965Sjdp}
24833965Sjdp
249218822Sdim#ifndef TC_ADDRESS_BYTES
250218822Sdim#define TC_ADDRESS_BYTES address_bytes
251218822Sdim
252218822Sdimstatic inline int
253218822Sdimaddress_bytes (void)
254218822Sdim{
255218822Sdim  /* Choose smallest of 1, 2, 4, 8 bytes that is large enough to
256218822Sdim     contain an address.  */
257218822Sdim  int n = (stdoutput->arch_info->bits_per_address - 1) / 8;
258218822Sdim  n |= n >> 1;
259218822Sdim  n |= n >> 2;
260218822Sdim  n += 1;
261218822Sdim  return n;
262218822Sdim}
263218822Sdim#endif
264218822Sdim
26577298Sobrien/* Set up pseudo-op tables.  */
26633965Sjdp
26733965Sjdpstatic struct hash_control *po_hash;
26833965Sjdp
26977298Sobrienstatic const pseudo_typeS potable[] = {
27033965Sjdp  {"abort", s_abort, 0},
27133965Sjdp  {"align", s_align_ptwo, 0},
272218822Sdim  {"altmacro", s_altmacro, 1},
27333965Sjdp  {"ascii", stringer, 0},
27433965Sjdp  {"asciz", stringer, 1},
27533965Sjdp  {"balign", s_align_bytes, 0},
27633965Sjdp  {"balignw", s_align_bytes, -2},
27733965Sjdp  {"balignl", s_align_bytes, -4},
27877298Sobrien/* block  */
27933965Sjdp  {"byte", cons, 1},
28033965Sjdp  {"comm", s_comm, 0},
28133965Sjdp  {"common", s_mri_common, 0},
28233965Sjdp  {"common.s", s_mri_common, 1},
28333965Sjdp  {"data", s_data, 0},
28433965Sjdp  {"dc", cons, 2},
285218822Sdim#ifdef TC_ADDRESS_BYTES
286218822Sdim  {"dc.a", cons, 0},
287218822Sdim#endif
28833965Sjdp  {"dc.b", cons, 1},
28933965Sjdp  {"dc.d", float_cons, 'd'},
29033965Sjdp  {"dc.l", cons, 4},
29133965Sjdp  {"dc.s", float_cons, 'f'},
29233965Sjdp  {"dc.w", cons, 2},
29333965Sjdp  {"dc.x", float_cons, 'x'},
29433965Sjdp  {"dcb", s_space, 2},
29533965Sjdp  {"dcb.b", s_space, 1},
29633965Sjdp  {"dcb.d", s_float_space, 'd'},
29733965Sjdp  {"dcb.l", s_space, 4},
29833965Sjdp  {"dcb.s", s_float_space, 'f'},
29933965Sjdp  {"dcb.w", s_space, 2},
30033965Sjdp  {"dcb.x", s_float_space, 'x'},
30133965Sjdp  {"ds", s_space, 2},
30233965Sjdp  {"ds.b", s_space, 1},
30333965Sjdp  {"ds.d", s_space, 8},
30433965Sjdp  {"ds.l", s_space, 4},
30533965Sjdp  {"ds.p", s_space, 12},
30633965Sjdp  {"ds.s", s_space, 4},
30733965Sjdp  {"ds.w", s_space, 2},
30833965Sjdp  {"ds.x", s_space, 12},
30933965Sjdp  {"debug", s_ignore, 0},
31033965Sjdp#ifdef S_SET_DESC
31133965Sjdp  {"desc", s_desc, 0},
31233965Sjdp#endif
31377298Sobrien/* dim  */
31433965Sjdp  {"double", float_cons, 'd'},
31577298Sobrien/* dsect  */
31677298Sobrien  {"eject", listing_eject, 0},	/* Formfeed listing.  */
31733965Sjdp  {"else", s_else, 0},
31833965Sjdp  {"elsec", s_else, 0},
31960484Sobrien  {"elseif", s_elseif, (int) O_ne},
32033965Sjdp  {"end", s_end, 0},
32133965Sjdp  {"endc", s_endif, 0},
32260484Sobrien  {"endfunc", s_func, 1},
32333965Sjdp  {"endif", s_endif, 0},
324218822Sdim  {"endm", s_bad_end, 0},
325218822Sdim  {"endr", s_bad_end, 1},
32677298Sobrien/* endef  */
32733965Sjdp  {"equ", s_set, 0},
32833965Sjdp  {"equiv", s_set, 1},
329218822Sdim  {"eqv", s_set, -1},
33033965Sjdp  {"err", s_err, 0},
331218822Sdim  {"error", s_errwarn, 1},
33233965Sjdp  {"exitm", s_mexit, 0},
33377298Sobrien/* extend  */
33477298Sobrien  {"extern", s_ignore, 0},	/* We treat all undef as ext.  */
33533965Sjdp  {"appfile", s_app_file, 1},
336218822Sdim  {"appline", s_app_line, 1},
33733965Sjdp  {"fail", s_fail, 0},
33833965Sjdp  {"file", s_app_file, 0},
33933965Sjdp  {"fill", s_fill, 0},
34033965Sjdp  {"float", float_cons, 'f'},
34133965Sjdp  {"format", s_ignore, 0},
34260484Sobrien  {"func", s_func, 0},
34333965Sjdp  {"global", s_globl, 0},
34433965Sjdp  {"globl", s_globl, 0},
345218822Sdim#ifdef OBJ_ELF
346218822Sdim  {"gnu_attribute", s_gnu_attribute, 0},
347218822Sdim#endif
34833965Sjdp  {"hword", cons, 2},
34933965Sjdp  {"if", s_if, (int) O_ne},
350218822Sdim  {"ifb", s_ifb, 1},
35133965Sjdp  {"ifc", s_ifc, 0},
35233965Sjdp  {"ifdef", s_ifdef, 0},
35333965Sjdp  {"ifeq", s_if, (int) O_eq},
35433965Sjdp  {"ifeqs", s_ifeqs, 0},
35533965Sjdp  {"ifge", s_if, (int) O_ge},
35633965Sjdp  {"ifgt", s_if, (int) O_gt},
35733965Sjdp  {"ifle", s_if, (int) O_le},
35833965Sjdp  {"iflt", s_if, (int) O_lt},
359218822Sdim  {"ifnb", s_ifb, 0},
36033965Sjdp  {"ifnc", s_ifc, 1},
36133965Sjdp  {"ifndef", s_ifdef, 1},
36233965Sjdp  {"ifne", s_if, (int) O_ne},
36333965Sjdp  {"ifnes", s_ifeqs, 1},
36433965Sjdp  {"ifnotdef", s_ifdef, 1},
36589857Sobrien  {"incbin", s_incbin, 0},
36633965Sjdp  {"include", s_include, 0},
36733965Sjdp  {"int", cons, 4},
36833965Sjdp  {"irp", s_irp, 0},
36933965Sjdp  {"irep", s_irp, 0},
37033965Sjdp  {"irpc", s_irp, 1},
37133965Sjdp  {"irepc", s_irp, 1},
37233965Sjdp  {"lcomm", s_lcomm, 0},
37377298Sobrien  {"lflags", listing_flags, 0},	/* Listing flags.  */
374218822Sdim  {"linefile", s_app_line, 0},
37533965Sjdp  {"linkonce", s_linkonce, 0},
37677298Sobrien  {"list", listing_list, 1},	/* Turn listing on.  */
37733965Sjdp  {"llen", listing_psize, 1},
37833965Sjdp  {"long", cons, 4},
37933965Sjdp  {"lsym", s_lsym, 0},
38033965Sjdp  {"macro", s_macro, 0},
38133965Sjdp  {"mexit", s_mexit, 0},
38233965Sjdp  {"mri", s_mri, 0},
38333965Sjdp  {".mri", s_mri, 0},	/* Special case so .mri works in MRI mode.  */
38433965Sjdp  {"name", s_ignore, 0},
385218822Sdim  {"noaltmacro", s_altmacro, 0},
38633965Sjdp  {"noformat", s_ignore, 0},
38777298Sobrien  {"nolist", listing_list, 0},	/* Turn listing off.  */
38833965Sjdp  {"nopage", listing_nopage, 0},
38933965Sjdp  {"octa", cons, 16},
39033965Sjdp  {"offset", s_struct, 0},
39133965Sjdp  {"org", s_org, 0},
39233965Sjdp  {"p2align", s_align_ptwo, 0},
39333965Sjdp  {"p2alignw", s_align_ptwo, -2},
39433965Sjdp  {"p2alignl", s_align_ptwo, -4},
39533965Sjdp  {"page", listing_eject, 0},
39633965Sjdp  {"plen", listing_psize, 0},
39733965Sjdp  {"print", s_print, 0},
39877298Sobrien  {"psize", listing_psize, 0},	/* Set paper size.  */
39933965Sjdp  {"purgem", s_purgem, 0},
40033965Sjdp  {"quad", cons, 8},
401218822Sdim  {"reloc", s_reloc, 0},
40233965Sjdp  {"rep", s_rept, 0},
40333965Sjdp  {"rept", s_rept, 0},
40433965Sjdp  {"rva", s_rva, 4},
40577298Sobrien  {"sbttl", listing_title, 1},	/* Subtitle of listing.  */
40677298Sobrien/* scl  */
40777298Sobrien/* sect  */
40833965Sjdp  {"set", s_set, 0},
40933965Sjdp  {"short", cons, 2},
41033965Sjdp  {"single", float_cons, 'f'},
41177298Sobrien/* size  */
41233965Sjdp  {"space", s_space, 0},
41333965Sjdp  {"skip", s_space, 0},
41438889Sjdp  {"sleb128", s_leb128, 1},
41533965Sjdp  {"spc", s_ignore, 0},
41633965Sjdp  {"stabd", s_stab, 'd'},
41733965Sjdp  {"stabn", s_stab, 'n'},
41833965Sjdp  {"stabs", s_stab, 's'},
41933965Sjdp  {"string", stringer, 1},
42033965Sjdp  {"struct", s_struct, 0},
42177298Sobrien/* tag  */
42233965Sjdp  {"text", s_text, 0},
42333965Sjdp
42433965Sjdp  /* This is for gcc to use.  It's only just been added (2/94), so gcc
42533965Sjdp     won't be able to use it for a while -- probably a year or more.
42633965Sjdp     But once this has been released, check with gcc maintainers
42733965Sjdp     before deleting it or even changing the spelling.  */
42833965Sjdp  {"this_GCC_requires_the_GNU_assembler", s_ignore, 0},
42933965Sjdp  /* If we're folding case -- done for some targets, not necessarily
43033965Sjdp     all -- the above string in an input file will be converted to
43133965Sjdp     this one.  Match it either way...  */
43233965Sjdp  {"this_gcc_requires_the_gnu_assembler", s_ignore, 0},
43333965Sjdp
43477298Sobrien  {"title", listing_title, 0},	/* Listing title.  */
43533965Sjdp  {"ttl", listing_title, 0},
43677298Sobrien/* type  */
43738889Sjdp  {"uleb128", s_leb128, 0},
43877298Sobrien/* use  */
43977298Sobrien/* val  */
44033965Sjdp  {"xcom", s_comm, 0},
44133965Sjdp  {"xdef", s_globl, 0},
44233965Sjdp  {"xref", s_ignore, 0},
44333965Sjdp  {"xstabs", s_xstab, 's'},
444218822Sdim  {"warning", s_errwarn, 0},
445218822Sdim  {"weakref", s_weakref, 0},
44633965Sjdp  {"word", cons, 2},
44733965Sjdp  {"zero", s_space, 0},
44877298Sobrien  {NULL, NULL, 0}			/* End sentinel.  */
44933965Sjdp};
45033965Sjdp
451218822Sdimstatic offsetT
452218822Sdimget_absolute_expr (expressionS *exp)
453218822Sdim{
454218822Sdim  expression_and_evaluate (exp);
455218822Sdim  if (exp->X_op != O_constant)
456218822Sdim    {
457218822Sdim      if (exp->X_op != O_absent)
458218822Sdim	as_bad (_("bad or irreducible absolute expression"));
459218822Sdim      exp->X_add_number = 0;
460218822Sdim    }
461218822Sdim  return exp->X_add_number;
462218822Sdim}
463218822Sdim
464218822SdimoffsetT
465218822Sdimget_absolute_expression (void)
466218822Sdim{
467218822Sdim  expressionS exp;
468218822Sdim
469218822Sdim  return get_absolute_expr (&exp);
470218822Sdim}
471218822Sdim
47233965Sjdpstatic int pop_override_ok = 0;
47333965Sjdpstatic const char *pop_table_name;
47433965Sjdp
47533965Sjdpvoid
476130561Sobrienpop_insert (const pseudo_typeS *table)
47733965Sjdp{
47833965Sjdp  const char *errtxt;
47933965Sjdp  const pseudo_typeS *pop;
48033965Sjdp  for (pop = table; pop->poc_name; pop++)
48133965Sjdp    {
48233965Sjdp      errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
48333965Sjdp      if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists")))
48460484Sobrien	as_fatal (_("error constructing %s pseudo-op table: %s"), pop_table_name,
48533965Sjdp		  errtxt);
48633965Sjdp    }
48733965Sjdp}
48833965Sjdp
48933965Sjdp#ifndef md_pop_insert
49033965Sjdp#define md_pop_insert()		pop_insert(md_pseudo_table)
49133965Sjdp#endif
49233965Sjdp
49333965Sjdp#ifndef obj_pop_insert
49433965Sjdp#define obj_pop_insert()	pop_insert(obj_pseudo_table)
49533965Sjdp#endif
49633965Sjdp
497130561Sobrien#ifndef cfi_pop_insert
498130561Sobrien#define cfi_pop_insert()	pop_insert(cfi_pseudo_table)
499130561Sobrien#endif
500130561Sobrien
50177298Sobrienstatic void
502130561Sobrienpobegin (void)
50333965Sjdp{
50433965Sjdp  po_hash = hash_new ();
50533965Sjdp
50677298Sobrien  /* Do the target-specific pseudo ops.  */
50733965Sjdp  pop_table_name = "md";
50833965Sjdp  md_pop_insert ();
50933965Sjdp
51077298Sobrien  /* Now object specific.  Skip any that were in the target table.  */
51133965Sjdp  pop_table_name = "obj";
51233965Sjdp  pop_override_ok = 1;
51333965Sjdp  obj_pop_insert ();
51433965Sjdp
51577298Sobrien  /* Now portable ones.  Skip any that we've seen already.  */
51633965Sjdp  pop_table_name = "standard";
51733965Sjdp  pop_insert (potable);
518130561Sobrien
519130561Sobrien#ifdef TARGET_USE_CFIPOP
520130561Sobrien  pop_table_name = "cfi";
521130561Sobrien  pop_override_ok = 1;
522130561Sobrien  cfi_pop_insert ();
523130561Sobrien#endif
52433965Sjdp}
52533965Sjdp
52633965Sjdp#define HANDLE_CONDITIONAL_ASSEMBLY()					\
52733965Sjdp  if (ignore_input ())							\
52833965Sjdp    {									\
529218822Sdim      char *eol = find_end_of_line (input_line_pointer, flag_m68k_mri);	\
530218822Sdim      input_line_pointer = (input_line_pointer <= buffer_limit		\
531218822Sdim			    && eol >= buffer_limit)			\
532218822Sdim			   ? buffer_limit				\
533218822Sdim			   : eol + 1;					\
53433965Sjdp      continue;								\
53533965Sjdp    }
53633965Sjdp
53733965Sjdp/* This function is used when scrubbing the characters between #APP
53833965Sjdp   and #NO_APP.  */
53933965Sjdp
54033965Sjdpstatic char *scrub_string;
54133965Sjdpstatic char *scrub_string_end;
54233965Sjdp
54333965Sjdpstatic int
544130561Sobrienscrub_from_string (char *buf, int buflen)
54533965Sjdp{
54660484Sobrien  int copy;
54733965Sjdp
54860484Sobrien  copy = scrub_string_end - scrub_string;
54960484Sobrien  if (copy > buflen)
55060484Sobrien    copy = buflen;
55160484Sobrien  memcpy (buf, scrub_string, copy);
55260484Sobrien  scrub_string += copy;
55360484Sobrien  return copy;
55433965Sjdp}
55533965Sjdp
556218822Sdim/* Helper function of read_a_source_file, which tries to expand a macro.  */
557218822Sdimstatic int
558218822Sdimtry_macro (char term, const char *line)
559218822Sdim{
560218822Sdim  sb out;
561218822Sdim  const char *err;
562218822Sdim  macro_entry *macro;
563218822Sdim
564218822Sdim  if (check_macro (line, &out, &err, &macro))
565218822Sdim    {
566218822Sdim      if (err != NULL)
567218822Sdim	as_bad ("%s", err);
568218822Sdim      *input_line_pointer++ = term;
569218822Sdim      input_scrub_include_sb (&out,
570218822Sdim			      input_line_pointer, 1);
571218822Sdim      sb_kill (&out);
572218822Sdim      buffer_limit =
573218822Sdim	input_scrub_next_buffer (&input_line_pointer);
574218822Sdim#ifdef md_macro_info
575218822Sdim      md_macro_info (macro);
576218822Sdim#endif
577218822Sdim      return 1;
578218822Sdim    }
579218822Sdim  return 0;
580218822Sdim}
581218822Sdim
58277298Sobrien/* We read the file, putting things into a web that represents what we
58377298Sobrien   have been reading.  */
58477298Sobrienvoid
585130561Sobrienread_a_source_file (char *name)
58633965Sjdp{
58733965Sjdp  register char c;
58877298Sobrien  register char *s;		/* String of symbol, '\0' appended.  */
58933965Sjdp  register int temp;
59033965Sjdp  pseudo_typeS *pop;
59133965Sjdp
59277298Sobrien#ifdef WARN_COMMENTS
59377298Sobrien  found_comment = 0;
59477298Sobrien#endif
59577298Sobrien
59633965Sjdp  buffer = input_scrub_new_file (name);
59733965Sjdp
59833965Sjdp  listing_file (name);
59938889Sjdp  listing_newline (NULL);
60038889Sjdp  register_dependency (name);
60133965Sjdp
60260484Sobrien  /* Generate debugging information before we've read anything in to denote
60360484Sobrien     this file as the "main" source file and not a subordinate one
60460484Sobrien     (e.g. N_SO vs N_SOL in stabs).  */
60560484Sobrien  generate_file_debug ();
60660484Sobrien
60733965Sjdp  while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0)
60877298Sobrien    {				/* We have another line to parse.  */
609218822Sdim#ifndef NO_LISTING
610218822Sdim      /* In order to avoid listing macro expansion lines with labels
611218822Sdim	 multiple times, keep track of which line was last issued.  */
612218822Sdim      static char *last_eol;
613130561Sobrien
614218822Sdim      last_eol = NULL;
615218822Sdim#endif
61633965Sjdp      while (input_line_pointer < buffer_limit)
61733965Sjdp	{
61877298Sobrien	  /* We have more of this buffer to parse.  */
61933965Sjdp
62077298Sobrien	  /* We now have input_line_pointer->1st char of next line.
62177298Sobrien	     If input_line_pointer [-1] == '\n' then we just
62277298Sobrien	     scanned another line: so bump line counters.  */
62333965Sjdp	  if (is_end_of_line[(unsigned char) input_line_pointer[-1]])
62433965Sjdp	    {
62533965Sjdp#ifdef md_start_line_hook
62633965Sjdp	      md_start_line_hook ();
62733965Sjdp#endif
62833965Sjdp	      if (input_line_pointer[-1] == '\n')
62933965Sjdp		bump_line_counters ();
63033965Sjdp
63133965Sjdp	      line_label = NULL;
63233965Sjdp
63360484Sobrien	      if (LABELS_WITHOUT_COLONS || flag_m68k_mri)
63433965Sjdp		{
63533965Sjdp		  /* Text at the start of a line must be a label, we
63633965Sjdp		     run down and stick a colon in.  */
63733965Sjdp		  if (is_name_beginner (*input_line_pointer))
63833965Sjdp		    {
63933965Sjdp		      char *line_start = input_line_pointer;
64033965Sjdp		      char c;
64133965Sjdp		      int mri_line_macro;
64233965Sjdp
64333965Sjdp		      LISTING_NEWLINE ();
64433965Sjdp		      HANDLE_CONDITIONAL_ASSEMBLY ();
64533965Sjdp
64633965Sjdp		      c = get_symbol_end ();
64733965Sjdp
64833965Sjdp		      /* In MRI mode, the EQU and MACRO pseudoops must
64933965Sjdp			 be handled specially.  */
65033965Sjdp		      mri_line_macro = 0;
65133965Sjdp		      if (flag_m68k_mri)
65233965Sjdp			{
65333965Sjdp			  char *rest = input_line_pointer + 1;
65433965Sjdp
65533965Sjdp			  if (*rest == ':')
65633965Sjdp			    ++rest;
65733965Sjdp			  if (*rest == ' ' || *rest == '\t')
65833965Sjdp			    ++rest;
65933965Sjdp			  if ((strncasecmp (rest, "EQU", 3) == 0
66033965Sjdp			       || strncasecmp (rest, "SET", 3) == 0)
66133965Sjdp			      && (rest[3] == ' ' || rest[3] == '\t'))
66233965Sjdp			    {
66333965Sjdp			      input_line_pointer = rest + 3;
66433965Sjdp			      equals (line_start,
66533965Sjdp				      strncasecmp (rest, "SET", 3) == 0);
66633965Sjdp			      continue;
66733965Sjdp			    }
66833965Sjdp			  if (strncasecmp (rest, "MACRO", 5) == 0
66933965Sjdp			      && (rest[5] == ' '
67033965Sjdp				  || rest[5] == '\t'
67133965Sjdp				  || is_end_of_line[(unsigned char) rest[5]]))
67233965Sjdp			    mri_line_macro = 1;
67333965Sjdp			}
67433965Sjdp
67533965Sjdp		      /* In MRI mode, we need to handle the MACRO
676130561Sobrien			 pseudo-op specially: we don't want to put the
677130561Sobrien			 symbol in the symbol table.  */
67877298Sobrien		      if (!mri_line_macro
67960484Sobrien#ifdef TC_START_LABEL_WITHOUT_COLON
68077298Sobrien			  && TC_START_LABEL_WITHOUT_COLON(c,
68177298Sobrien							  input_line_pointer)
68260484Sobrien#endif
68377298Sobrien			  )
68433965Sjdp			line_label = colon (line_start);
68533965Sjdp		      else
68633965Sjdp			line_label = symbol_create (line_start,
68733965Sjdp						    absolute_section,
68833965Sjdp						    (valueT) 0,
68933965Sjdp						    &zero_address_frag);
69033965Sjdp
69133965Sjdp		      *input_line_pointer = c;
69233965Sjdp		      if (c == ':')
69333965Sjdp			input_line_pointer++;
69433965Sjdp		    }
69533965Sjdp		}
69633965Sjdp	    }
69733965Sjdp
698130561Sobrien	  /* We are at the beginning of a line, or similar place.
69977298Sobrien	     We expect a well-formed assembler statement.
70077298Sobrien	     A "symbol-name:" is a statement.
70177298Sobrien
70277298Sobrien	     Depending on what compiler is used, the order of these tests
70377298Sobrien	     may vary to catch most common case 1st.
704218822Sdim	     Each test is independent of all other tests at the (top)
705218822Sdim	     level.  */
706218822Sdim	  do
70777298Sobrien	    c = *input_line_pointer++;
708218822Sdim	  while (c == '\t' || c == ' ' || c == '\f');
70938889Sjdp
71038889Sjdp#ifndef NO_LISTING
71138889Sjdp	  /* If listing is on, and we are expanding a macro, then give
71238889Sjdp	     the listing code the contents of the expanded line.  */
71338889Sjdp	  if (listing)
71438889Sjdp	    {
71538889Sjdp	      if ((listing & LISTING_MACEXP) && macro_nest > 0)
71638889Sjdp		{
71738889Sjdp		  char *copy;
71838889Sjdp		  int len;
71938889Sjdp
72038889Sjdp		  /* Find the end of the current expanded macro line.  */
721218822Sdim		  s = find_end_of_line (input_line_pointer - 1, flag_m68k_mri);
72238889Sjdp
723218822Sdim		  if (s != last_eol)
724218822Sdim		    {
725218822Sdim		      last_eol = s;
726218822Sdim		      /* Copy it for safe keeping.  Also give an indication of
727218822Sdim			 how much macro nesting is involved at this point.  */
728218822Sdim		      len = s - (input_line_pointer - 1);
729218822Sdim		      copy = (char *) xmalloc (len + macro_nest + 2);
730218822Sdim		      memset (copy, '>', macro_nest);
731218822Sdim		      copy[macro_nest] = ' ';
732218822Sdim		      memcpy (copy + macro_nest + 1, input_line_pointer - 1, len);
733218822Sdim		      copy[macro_nest + 1 + len] = '\0';
73438889Sjdp
735218822Sdim		      /* Install the line with the listing facility.  */
736218822Sdim		      listing_newline (copy);
737218822Sdim		    }
73838889Sjdp		}
73938889Sjdp	      else
74038889Sjdp		listing_newline (NULL);
74138889Sjdp	    }
74238889Sjdp#endif
74377298Sobrien	  /* C is the 1st significant character.
74477298Sobrien	     Input_line_pointer points after that character.  */
74533965Sjdp	  if (is_name_beginner (c))
74633965Sjdp	    {
74777298Sobrien	      /* Want user-defined label or pseudo/opcode.  */
74833965Sjdp	      HANDLE_CONDITIONAL_ASSEMBLY ();
74933965Sjdp
75033965Sjdp	      s = --input_line_pointer;
75177298Sobrien	      c = get_symbol_end ();	/* name's delimiter.  */
75277298Sobrien
75377298Sobrien	      /* C is character after symbol.
754130561Sobrien		 That character's place in the input line is now '\0'.
755130561Sobrien		 S points to the beginning of the symbol.
756130561Sobrien		   [In case of pseudo-op, s->'.'.]
757130561Sobrien		 Input_line_pointer->'\0' where c was.  */
75877298Sobrien	      if (TC_START_LABEL (c, input_line_pointer))
75933965Sjdp		{
76033965Sjdp		  if (flag_m68k_mri)
76133965Sjdp		    {
76233965Sjdp		      char *rest = input_line_pointer + 1;
76333965Sjdp
76433965Sjdp		      /* In MRI mode, \tsym: set 0 is permitted.  */
76533965Sjdp		      if (*rest == ':')
76633965Sjdp			++rest;
76777298Sobrien
76833965Sjdp		      if (*rest == ' ' || *rest == '\t')
76933965Sjdp			++rest;
77077298Sobrien
77133965Sjdp		      if ((strncasecmp (rest, "EQU", 3) == 0
77233965Sjdp			   || strncasecmp (rest, "SET", 3) == 0)
77333965Sjdp			  && (rest[3] == ' ' || rest[3] == '\t'))
77433965Sjdp			{
77533965Sjdp			  input_line_pointer = rest + 3;
77633965Sjdp			  equals (s, 1);
77733965Sjdp			  continue;
77833965Sjdp			}
77933965Sjdp		    }
78033965Sjdp
78177298Sobrien		  line_label = colon (s);	/* User-defined label.  */
78277298Sobrien		  /* Put ':' back for error messages' sake.  */
78377298Sobrien		  *input_line_pointer++ = ':';
784130561Sobrien#ifdef tc_check_label
785130561Sobrien		  tc_check_label (line_label);
786130561Sobrien#endif
78777298Sobrien		  /* Input_line_pointer->after ':'.  */
78833965Sjdp		  SKIP_WHITESPACE ();
78933965Sjdp		}
790218822Sdim              else if (input_line_pointer[1] == '='
791218822Sdim		       && (c == '='
792218822Sdim			   || ((c == ' ' || c == '\t')
793218822Sdim			       && input_line_pointer[2] == '=')))
794218822Sdim		{
795218822Sdim		  equals (s, -1);
796218822Sdim		  demand_empty_rest_of_line ();
797218822Sdim		}
798218822Sdim              else if ((c == '='
799218822Sdim                       || ((c == ' ' || c == '\t')
800218822Sdim                            && input_line_pointer[1] == '='))
80133965Sjdp#ifdef TC_EQUAL_IN_INSN
802218822Sdim                           && !TC_EQUAL_IN_INSN (c, s)
80333965Sjdp#endif
804218822Sdim                           )
80533965Sjdp		{
80633965Sjdp		  equals (s, 1);
80733965Sjdp		  demand_empty_rest_of_line ();
80833965Sjdp		}
80933965Sjdp	      else
81077298Sobrien		{
81177298Sobrien		  /* Expect pseudo-op or machine instruction.  */
81233965Sjdp		  pop = NULL;
81333965Sjdp
814130561Sobrien#ifndef TC_CASE_SENSITIVE
81533965Sjdp		  {
81633965Sjdp		    char *s2 = s;
81777298Sobrien
81877298Sobrien		    strncpy (original_case_string, s2, sizeof (original_case_string));
81977298Sobrien		    original_case_string[sizeof (original_case_string) - 1] = 0;
82077298Sobrien
82133965Sjdp		    while (*s2)
82233965Sjdp		      {
82389857Sobrien			*s2 = TOLOWER (*s2);
82433965Sjdp			s2++;
82533965Sjdp		      }
82633965Sjdp		  }
82733965Sjdp#endif
82860484Sobrien		  if (NO_PSEUDO_DOT || flag_m68k_mri)
82933965Sjdp		    {
830218822Sdim		      /* The MRI assembler uses pseudo-ops without
831218822Sdim			 a period.  */
83233965Sjdp		      pop = (pseudo_typeS *) hash_find (po_hash, s);
83333965Sjdp		      if (pop != NULL && pop->poc_handler == NULL)
83433965Sjdp			pop = NULL;
83533965Sjdp		    }
83633965Sjdp
83733965Sjdp		  if (pop != NULL
83877298Sobrien		      || (!flag_m68k_mri && *s == '.'))
83933965Sjdp		    {
84077298Sobrien		      /* PSEUDO - OP.
84133965Sjdp
842130561Sobrien			 WARNING: c has next char, which may be end-of-line.
843130561Sobrien			 We lookup the pseudo-op table with s+1 because we
844130561Sobrien			 already know that the pseudo-op begins with a '.'.  */
84577298Sobrien
84633965Sjdp		      if (pop == NULL)
84733965Sjdp			pop = (pseudo_typeS *) hash_find (po_hash, s + 1);
848130561Sobrien		      if (pop && !pop->poc_handler)
849130561Sobrien			pop = NULL;
85033965Sjdp
85133965Sjdp		      /* In MRI mode, we may need to insert an
852130561Sobrien			 automatic alignment directive.  What a hack
853130561Sobrien			 this is.  */
85433965Sjdp		      if (mri_pending_align
85533965Sjdp			  && (pop == NULL
85677298Sobrien			      || !((pop->poc_handler == cons
85777298Sobrien				    && pop->poc_val == 1)
85877298Sobrien				   || (pop->poc_handler == s_space
85977298Sobrien				       && pop->poc_val == 1)
86033965Sjdp#ifdef tc_conditional_pseudoop
86177298Sobrien				   || tc_conditional_pseudoop (pop)
86233965Sjdp#endif
86377298Sobrien				   || pop->poc_handler == s_if
86477298Sobrien				   || pop->poc_handler == s_ifdef
86577298Sobrien				   || pop->poc_handler == s_ifc
86677298Sobrien				   || pop->poc_handler == s_ifeqs
86777298Sobrien				   || pop->poc_handler == s_else
86877298Sobrien				   || pop->poc_handler == s_endif
86977298Sobrien				   || pop->poc_handler == s_globl
87077298Sobrien				   || pop->poc_handler == s_ignore)))
87133965Sjdp			{
87233965Sjdp			  do_align (1, (char *) NULL, 0, 0);
87333965Sjdp			  mri_pending_align = 0;
87477298Sobrien
87533965Sjdp			  if (line_label != NULL)
87633965Sjdp			    {
87760484Sobrien			      symbol_set_frag (line_label, frag_now);
87833965Sjdp			      S_SET_VALUE (line_label, frag_now_fix ());
87933965Sjdp			    }
88033965Sjdp			}
88133965Sjdp
88277298Sobrien		      /* Print the error msg now, while we still can.  */
88333965Sjdp		      if (pop == NULL)
88433965Sjdp			{
885218822Sdim			  char *end = input_line_pointer;
886218822Sdim
88733965Sjdp			  *input_line_pointer = c;
88833965Sjdp			  s_ignore (0);
889218822Sdim			  c = *--input_line_pointer;
890218822Sdim			  *input_line_pointer = '\0';
891218822Sdim			  if (! macro_defined || ! try_macro (c, s))
892218822Sdim			    {
893218822Sdim			      *end = '\0';
894218822Sdim			      as_bad (_("unknown pseudo-op: `%s'"), s);
895218822Sdim			      *input_line_pointer++ = c;
896218822Sdim			    }
89733965Sjdp			  continue;
89833965Sjdp			}
89933965Sjdp
90077298Sobrien		      /* Put it back for error messages etc.  */
90133965Sjdp		      *input_line_pointer = c;
90233965Sjdp		      /* The following skip of whitespace is compulsory.
90333965Sjdp			 A well shaped space is sometimes all that separates
90477298Sobrien			 keyword from operands.  */
90533965Sjdp		      if (c == ' ' || c == '\t')
90633965Sjdp			input_line_pointer++;
90777298Sobrien
90877298Sobrien		      /* Input_line is restored.
909130561Sobrien			 Input_line_pointer->1st non-blank char
910130561Sobrien			 after pseudo-operation.  */
91133965Sjdp		      (*pop->poc_handler) (pop->poc_val);
91233965Sjdp
91333965Sjdp		      /* If that was .end, just get out now.  */
91433965Sjdp		      if (pop->poc_handler == s_end)
91533965Sjdp			goto quit;
91633965Sjdp		    }
91733965Sjdp		  else
91833965Sjdp		    {
91977298Sobrien		      /* WARNING: c has char, which may be end-of-line.  */
92077298Sobrien		      /* Also: input_line_pointer->`\0` where c was.  */
92133965Sjdp		      *input_line_pointer = c;
922218822Sdim		      input_line_pointer = _find_end_of_line (input_line_pointer, flag_m68k_mri, 1);
92333965Sjdp		      c = *input_line_pointer;
92433965Sjdp		      *input_line_pointer = '\0';
92533965Sjdp
92660484Sobrien		      generate_lineno_debug ();
92738889Sjdp
928218822Sdim		      if (macro_defined && try_macro (c, s))
929218822Sdim			continue;
93033965Sjdp
93133965Sjdp		      if (mri_pending_align)
93233965Sjdp			{
93333965Sjdp			  do_align (1, (char *) NULL, 0, 0);
93433965Sjdp			  mri_pending_align = 0;
93533965Sjdp			  if (line_label != NULL)
93633965Sjdp			    {
93760484Sobrien			      symbol_set_frag (line_label, frag_now);
93833965Sjdp			      S_SET_VALUE (line_label, frag_now_fix ());
93933965Sjdp			    }
94033965Sjdp			}
94133965Sjdp
94277298Sobrien		      md_assemble (s);	/* Assemble 1 instruction.  */
94333965Sjdp
94433965Sjdp		      *input_line_pointer++ = c;
94533965Sjdp
94633965Sjdp		      /* We resume loop AFTER the end-of-line from
94777298Sobrien			 this instruction.  */
94877298Sobrien		    }
94977298Sobrien		}
95033965Sjdp	      continue;
95177298Sobrien	    }
95233965Sjdp
95333965Sjdp	  /* Empty statement?  */
95433965Sjdp	  if (is_end_of_line[(unsigned char) c])
95533965Sjdp	    continue;
95633965Sjdp
95789857Sobrien	  if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (c))
95833965Sjdp	    {
95977298Sobrien	      /* local label  ("4:")  */
96033965Sjdp	      char *backup = input_line_pointer;
96133965Sjdp
96233965Sjdp	      HANDLE_CONDITIONAL_ASSEMBLY ();
96333965Sjdp
96433965Sjdp	      temp = c - '0';
96533965Sjdp
96677298Sobrien	      /* Read the whole number.  */
96789857Sobrien	      while (ISDIGIT (*input_line_pointer))
96833965Sjdp		{
96933965Sjdp		  temp = (temp * 10) + *input_line_pointer - '0';
97033965Sjdp		  ++input_line_pointer;
97177298Sobrien		}
97233965Sjdp
97333965Sjdp	      if (LOCAL_LABELS_DOLLAR
97433965Sjdp		  && *input_line_pointer == '$'
97533965Sjdp		  && *(input_line_pointer + 1) == ':')
97633965Sjdp		{
97733965Sjdp		  input_line_pointer += 2;
97833965Sjdp
97933965Sjdp		  if (dollar_label_defined (temp))
98033965Sjdp		    {
98160484Sobrien		      as_fatal (_("label \"%d$\" redefined"), temp);
98233965Sjdp		    }
98333965Sjdp
98433965Sjdp		  define_dollar_label (temp);
98533965Sjdp		  colon (dollar_label_name (temp, 0));
98633965Sjdp		  continue;
98733965Sjdp		}
98833965Sjdp
98933965Sjdp	      if (LOCAL_LABELS_FB
99033965Sjdp		  && *input_line_pointer++ == ':')
99133965Sjdp		{
99233965Sjdp		  fb_label_instance_inc (temp);
99333965Sjdp		  colon (fb_label_name (temp, 0));
99433965Sjdp		  continue;
99533965Sjdp		}
99633965Sjdp
99733965Sjdp	      input_line_pointer = backup;
99833965Sjdp	    }			/* local label  ("4:") */
99933965Sjdp
100033965Sjdp	  if (c && strchr (line_comment_chars, c))
100177298Sobrien	    {			/* Its a comment.  Better say APP or NO_APP.  */
1002130561Sobrien	      sb sbuf;
100333965Sjdp	      char *ends;
100433965Sjdp	      char *new_buf;
100533965Sjdp	      char *new_tmp;
100633965Sjdp	      unsigned int new_length;
100733965Sjdp	      char *tmp_buf = 0;
100833965Sjdp
100933965Sjdp	      s = input_line_pointer;
101033965Sjdp	      if (strncmp (s, "APP\n", 4))
1011218822Sdim		{
1012218822Sdim		  /* We ignore it.  */
1013218822Sdim		  ignore_rest_of_line ();
1014218822Sdim		  continue;
1015218822Sdim		}
1016218822Sdim	      bump_line_counters ();
101733965Sjdp	      s += 4;
101833965Sjdp
1019130561Sobrien	      sb_new (&sbuf);
102033965Sjdp	      ends = strstr (s, "#NO_APP\n");
102133965Sjdp
102233965Sjdp	      if (!ends)
102333965Sjdp		{
102433965Sjdp		  unsigned int tmp_len;
102533965Sjdp		  unsigned int num;
102633965Sjdp
102733965Sjdp		  /* The end of the #APP wasn't in this buffer.  We
102833965Sjdp		     keep reading in buffers until we find the #NO_APP
102933965Sjdp		     that goes with this #APP  There is one.  The specs
1030130561Sobrien		     guarantee it...  */
103133965Sjdp		  tmp_len = buffer_limit - s;
103233965Sjdp		  tmp_buf = xmalloc (tmp_len + 1);
103333965Sjdp		  memcpy (tmp_buf, s, tmp_len);
103433965Sjdp		  do
103533965Sjdp		    {
103633965Sjdp		      new_tmp = input_scrub_next_buffer (&buffer);
103733965Sjdp		      if (!new_tmp)
103833965Sjdp			break;
103933965Sjdp		      else
104033965Sjdp			buffer_limit = new_tmp;
104133965Sjdp		      input_line_pointer = buffer;
104233965Sjdp		      ends = strstr (buffer, "#NO_APP\n");
104333965Sjdp		      if (ends)
104433965Sjdp			num = ends - buffer;
104533965Sjdp		      else
104633965Sjdp			num = buffer_limit - buffer;
104733965Sjdp
104833965Sjdp		      tmp_buf = xrealloc (tmp_buf, tmp_len + num);
104933965Sjdp		      memcpy (tmp_buf + tmp_len, buffer, num);
105033965Sjdp		      tmp_len += num;
105133965Sjdp		    }
105233965Sjdp		  while (!ends);
105333965Sjdp
105433965Sjdp		  input_line_pointer = ends ? ends + 8 : NULL;
105533965Sjdp
105633965Sjdp		  s = tmp_buf;
105733965Sjdp		  ends = s + tmp_len;
105833965Sjdp
105933965Sjdp		}
106033965Sjdp	      else
106133965Sjdp		{
106233965Sjdp		  input_line_pointer = ends + 8;
106333965Sjdp		}
106433965Sjdp
106533965Sjdp	      scrub_string = s;
106633965Sjdp	      scrub_string_end = ends;
106733965Sjdp
106833965Sjdp	      new_length = ends - s;
106933965Sjdp	      new_buf = (char *) xmalloc (new_length);
107033965Sjdp	      new_tmp = new_buf;
107133965Sjdp	      for (;;)
107233965Sjdp		{
107333965Sjdp		  int space;
107433965Sjdp		  int size;
107533965Sjdp
107633965Sjdp		  space = (new_buf + new_length) - new_tmp;
107733965Sjdp		  size = do_scrub_chars (scrub_from_string, new_tmp, space);
107833965Sjdp
107933965Sjdp		  if (size < space)
108033965Sjdp		    {
1081130561Sobrien		      new_tmp[size] = 0;
108233965Sjdp		      break;
108333965Sjdp		    }
108433965Sjdp
108533965Sjdp		  new_buf = xrealloc (new_buf, new_length + 100);
108633965Sjdp		  new_tmp = new_buf + new_length;
108733965Sjdp		  new_length += 100;
108833965Sjdp		}
108933965Sjdp
109033965Sjdp	      if (tmp_buf)
109133965Sjdp		free (tmp_buf);
109277298Sobrien
1093130561Sobrien	      /* We've "scrubbed" input to the preferred format.  In the
1094130561Sobrien		 process we may have consumed the whole of the remaining
1095130561Sobrien		 file (and included files).  We handle this formatted
1096130561Sobrien		 input similar to that of macro expansion, letting
1097130561Sobrien		 actual macro expansion (possibly nested) and other
1098130561Sobrien		 input expansion work.  Beware that in messages, line
1099130561Sobrien		 numbers and possibly file names will be incorrect.  */
1100130561Sobrien	      sb_add_string (&sbuf, new_buf);
1101130561Sobrien	      input_scrub_include_sb (&sbuf, input_line_pointer, 0);
1102130561Sobrien	      sb_kill (&sbuf);
1103130561Sobrien	      buffer_limit = input_scrub_next_buffer (&input_line_pointer);
1104130561Sobrien	      free (new_buf);
110533965Sjdp	      continue;
110633965Sjdp	    }
110733965Sjdp
110833965Sjdp	  HANDLE_CONDITIONAL_ASSEMBLY ();
110933965Sjdp
111033965Sjdp#ifdef tc_unrecognized_line
111133965Sjdp	  if (tc_unrecognized_line (c))
111233965Sjdp	    continue;
111333965Sjdp#endif
111489857Sobrien	  input_line_pointer--;
1115218822Sdim	  /* Report unknown char as error.  */
1116130561Sobrien	  demand_empty_rest_of_line ();
111777298Sobrien	}
111833965Sjdp
111933965Sjdp#ifdef md_after_pass_hook
112033965Sjdp      md_after_pass_hook ();
112133965Sjdp#endif
112277298Sobrien    }
112333965Sjdp
112433965Sjdp quit:
112533965Sjdp
112633965Sjdp#ifdef md_cleanup
112777298Sobrien  md_cleanup ();
112833965Sjdp#endif
112977298Sobrien  /* Close the input file.  */
113077298Sobrien  input_scrub_close ();
113177298Sobrien#ifdef WARN_COMMENTS
113277298Sobrien  {
113377298Sobrien    if (warn_comment && found_comment)
113477298Sobrien      as_warn_where (found_comment_file, found_comment,
113577298Sobrien		     "first comment found here");
113677298Sobrien  }
113777298Sobrien#endif
113833965Sjdp}
113933965Sjdp
1140218822Sdim/* Convert O_constant expression EXP into the equivalent O_big representation.
1141218822Sdim   Take the sign of the number from X_unsigned rather than X_add_number.  */
1142218822Sdim
1143218822Sdimstatic void
1144218822Sdimconvert_to_bignum (expressionS *exp)
1145218822Sdim{
1146218822Sdim  valueT value;
1147218822Sdim  unsigned int i;
1148218822Sdim
1149218822Sdim  value = exp->X_add_number;
1150218822Sdim  for (i = 0; i < sizeof (exp->X_add_number) / CHARS_PER_LITTLENUM; i++)
1151218822Sdim    {
1152218822Sdim      generic_bignum[i] = value & LITTLENUM_MASK;
1153218822Sdim      value >>= LITTLENUM_NUMBER_OF_BITS;
1154218822Sdim    }
1155218822Sdim  /* Add a sequence of sign bits if the top bit of X_add_number is not
1156218822Sdim     the sign of the original value.  */
1157218822Sdim  if ((exp->X_add_number < 0) != !exp->X_unsigned)
1158218822Sdim    generic_bignum[i++] = exp->X_unsigned ? 0 : LITTLENUM_MASK;
1159218822Sdim  exp->X_op = O_big;
1160218822Sdim  exp->X_add_number = i;
1161218822Sdim}
1162218822Sdim
116333965Sjdp/* For most MRI pseudo-ops, the line actually ends at the first
116433965Sjdp   nonquoted space.  This function looks for that point, stuffs a null
116533965Sjdp   in, and sets *STOPCP to the character that used to be there, and
116633965Sjdp   returns the location.
116733965Sjdp
116833965Sjdp   Until I hear otherwise, I am going to assume that this is only true
116933965Sjdp   for the m68k MRI assembler.  */
117033965Sjdp
117133965Sjdpchar *
1172130561Sobrienmri_comment_field (char *stopcp)
117333965Sjdp{
117477298Sobrien  char *s;
117533965Sjdp#ifdef TC_M68K
117633965Sjdp  int inquote = 0;
117733965Sjdp
117833965Sjdp  know (flag_m68k_mri);
117933965Sjdp
118033965Sjdp  for (s = input_line_pointer;
118177298Sobrien       ((!is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t')
118233965Sjdp	|| inquote);
118333965Sjdp       s++)
118433965Sjdp    {
118533965Sjdp      if (*s == '\'')
118677298Sobrien	inquote = !inquote;
118733965Sjdp    }
118833965Sjdp#else
118977298Sobrien  for (s = input_line_pointer;
119077298Sobrien       !is_end_of_line[(unsigned char) *s];
119177298Sobrien       s++)
119233965Sjdp    ;
119377298Sobrien#endif
119433965Sjdp  *stopcp = *s;
119533965Sjdp  *s = '\0';
119677298Sobrien
119733965Sjdp  return s;
119833965Sjdp}
119933965Sjdp
120033965Sjdp/* Skip to the end of an MRI comment field.  */
120133965Sjdp
120233965Sjdpvoid
1203130561Sobrienmri_comment_end (char *stop, int stopc)
120433965Sjdp{
120533965Sjdp  know (flag_mri);
120633965Sjdp
120733965Sjdp  input_line_pointer = stop;
120833965Sjdp  *stop = stopc;
120977298Sobrien  while (!is_end_of_line[(unsigned char) *input_line_pointer])
121033965Sjdp    ++input_line_pointer;
121133965Sjdp}
121233965Sjdp
121377298Sobrienvoid
1214130561Sobriens_abort (int ignore ATTRIBUTE_UNUSED)
121533965Sjdp{
121660484Sobrien  as_fatal (_(".abort detected.  Abandoning ship."));
121733965Sjdp}
121833965Sjdp
121933965Sjdp/* Guts of .align directive.  N is the power of two to which to align.
122033965Sjdp   FILL may be NULL, or it may point to the bytes of the fill pattern.
122133965Sjdp   LEN is the length of whatever FILL points to, if anything.  MAX is
122233965Sjdp   the maximum number of characters to skip when doing the alignment,
122333965Sjdp   or 0 if there is no maximum.  */
122433965Sjdp
122577298Sobrienstatic void
1226130561Sobriendo_align (int n, char *fill, int len, int max)
122733965Sjdp{
122889857Sobrien  if (now_seg == absolute_section)
122989857Sobrien    {
123089857Sobrien      if (fill != NULL)
123189857Sobrien	while (len-- > 0)
123289857Sobrien	  if (*fill++ != '\0')
123389857Sobrien	    {
123489857Sobrien	      as_warn (_("ignoring fill value in absolute section"));
123589857Sobrien	      break;
123689857Sobrien	    }
123789857Sobrien      fill = NULL;
123889857Sobrien      len = 0;
123989857Sobrien    }
124089857Sobrien
1241218822Sdim#ifdef md_flush_pending_output
1242218822Sdim  md_flush_pending_output ();
1243218822Sdim#endif
124433965Sjdp#ifdef md_do_align
124533965Sjdp  md_do_align (n, fill, len, max, just_record_alignment);
124633965Sjdp#endif
124733965Sjdp
124877298Sobrien  /* Only make a frag if we HAVE to...  */
124933965Sjdp  if (n != 0 && !need_pass_2)
125033965Sjdp    {
125177298Sobrien      if (fill == NULL)
125277298Sobrien	{
125377298Sobrien	  if (subseg_text_p (now_seg))
125477298Sobrien	    frag_align_code (n, max);
125577298Sobrien	  else
125677298Sobrien	    frag_align (n, 0, max);
125777298Sobrien	}
125877298Sobrien      else if (len <= 1)
125933965Sjdp	frag_align (n, *fill, max);
126033965Sjdp      else
126133965Sjdp	frag_align_pattern (n, fill, len, max);
126233965Sjdp    }
126333965Sjdp
126433965Sjdp#ifdef md_do_align
1265130561Sobrien just_record_alignment: ATTRIBUTE_UNUSED_LABEL
126633965Sjdp#endif
126733965Sjdp
126860484Sobrien  record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
126933965Sjdp}
127033965Sjdp
127133965Sjdp/* Handle the .align pseudo-op.  A positive ARG is a default alignment
127233965Sjdp   (in bytes).  A negative ARG is the negative of the length of the
127333965Sjdp   fill pattern.  BYTES_P is non-zero if the alignment value should be
127433965Sjdp   interpreted as the byte boundary, rather than the power of 2.  */
127533965Sjdp
1276218822Sdim#define ALIGN_LIMIT (stdoutput->arch_info->bits_per_address - 1)
1277218822Sdim
127833965Sjdpstatic void
1279130561Sobriens_align (int arg, int bytes_p)
128033965Sjdp{
1281218822Sdim  unsigned int align_limit = ALIGN_LIMIT;
1282218822Sdim  unsigned int align;
128333965Sjdp  char *stop = NULL;
1284218822Sdim  char stopc = 0;
128533965Sjdp  offsetT fill = 0;
128633965Sjdp  int max;
128733965Sjdp  int fill_p;
128833965Sjdp
128933965Sjdp  if (flag_mri)
129033965Sjdp    stop = mri_comment_field (&stopc);
129133965Sjdp
129233965Sjdp  if (is_end_of_line[(unsigned char) *input_line_pointer])
129333965Sjdp    {
129433965Sjdp      if (arg < 0)
129533965Sjdp	align = 0;
129633965Sjdp      else
129777298Sobrien	align = arg;	/* Default value from pseudo-op table.  */
129833965Sjdp    }
129933965Sjdp  else
130033965Sjdp    {
130133965Sjdp      align = get_absolute_expression ();
130233965Sjdp      SKIP_WHITESPACE ();
130333965Sjdp    }
130433965Sjdp
130533965Sjdp  if (bytes_p)
130633965Sjdp    {
130733965Sjdp      /* Convert to a power of 2.  */
130833965Sjdp      if (align != 0)
130933965Sjdp	{
131033965Sjdp	  unsigned int i;
131133965Sjdp
131233965Sjdp	  for (i = 0; (align & 1) == 0; align >>= 1, ++i)
131333965Sjdp	    ;
131433965Sjdp	  if (align != 1)
131589857Sobrien	    as_bad (_("alignment not a power of 2"));
131677298Sobrien
131733965Sjdp	  align = i;
131833965Sjdp	}
131933965Sjdp    }
132033965Sjdp
1321218822Sdim  if (align > align_limit)
132233965Sjdp    {
1323218822Sdim      align = align_limit;
132489857Sobrien      as_warn (_("alignment too large: %u assumed"), align);
132533965Sjdp    }
132633965Sjdp
132733965Sjdp  if (*input_line_pointer != ',')
132833965Sjdp    {
132933965Sjdp      fill_p = 0;
133033965Sjdp      max = 0;
133133965Sjdp    }
133233965Sjdp  else
133333965Sjdp    {
133433965Sjdp      ++input_line_pointer;
133533965Sjdp      if (*input_line_pointer == ',')
133633965Sjdp	fill_p = 0;
133733965Sjdp      else
133833965Sjdp	{
133933965Sjdp	  fill = get_absolute_expression ();
134033965Sjdp	  SKIP_WHITESPACE ();
134133965Sjdp	  fill_p = 1;
134233965Sjdp	}
134333965Sjdp
134433965Sjdp      if (*input_line_pointer != ',')
134533965Sjdp	max = 0;
134633965Sjdp      else
134733965Sjdp	{
134833965Sjdp	  ++input_line_pointer;
134933965Sjdp	  max = get_absolute_expression ();
135033965Sjdp	}
135133965Sjdp    }
135233965Sjdp
135377298Sobrien  if (!fill_p)
135433965Sjdp    {
135533965Sjdp      if (arg < 0)
135660484Sobrien	as_warn (_("expected fill pattern missing"));
135733965Sjdp      do_align (align, (char *) NULL, 0, max);
135833965Sjdp    }
135933965Sjdp  else
136033965Sjdp    {
136133965Sjdp      int fill_len;
136233965Sjdp
136333965Sjdp      if (arg >= 0)
136433965Sjdp	fill_len = 1;
136533965Sjdp      else
136677298Sobrien	fill_len = -arg;
136733965Sjdp      if (fill_len <= 1)
136833965Sjdp	{
136933965Sjdp	  char fill_char;
137033965Sjdp
137133965Sjdp	  fill_char = fill;
137233965Sjdp	  do_align (align, &fill_char, fill_len, max);
137333965Sjdp	}
137433965Sjdp      else
137533965Sjdp	{
137633965Sjdp	  char ab[16];
137733965Sjdp
137838889Sjdp	  if ((size_t) fill_len > sizeof ab)
137933965Sjdp	    abort ();
138033965Sjdp	  md_number_to_chars (ab, fill, fill_len);
138133965Sjdp	  do_align (align, ab, fill_len, max);
138233965Sjdp	}
138333965Sjdp    }
138433965Sjdp
138560484Sobrien  demand_empty_rest_of_line ();
138660484Sobrien
138733965Sjdp  if (flag_mri)
138833965Sjdp    mri_comment_end (stop, stopc);
138933965Sjdp}
139033965Sjdp
139133965Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means
139233965Sjdp   align to a 4 byte boundary.  */
139333965Sjdp
139477298Sobrienvoid
1395130561Sobriens_align_bytes (int arg)
139633965Sjdp{
139733965Sjdp  s_align (arg, 1);
139833965Sjdp}
139933965Sjdp
140038889Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means align
140133965Sjdp   to a 2**4 boundary.  */
140233965Sjdp
140377298Sobrienvoid
1404130561Sobriens_align_ptwo (int arg)
140533965Sjdp{
140633965Sjdp  s_align (arg, 0);
140733965Sjdp}
140833965Sjdp
1409218822Sdim/* Switch in and out of alternate macro mode.  */
1410218822Sdim
1411218822Sdimvoid
1412218822Sdims_altmacro (int on)
1413218822Sdim{
1414218822Sdim  demand_empty_rest_of_line ();
1415218822Sdim  macro_set_alternate (on);
1416218822Sdim}
1417218822Sdim
1418130561SobriensymbolS *
1419130561Sobriens_comm_internal (int param,
1420130561Sobrien		 symbolS *(*comm_parse_extra) (int, symbolS *, addressT))
142133965Sjdp{
1422130561Sobrien  char *name;
1423130561Sobrien  char c;
1424130561Sobrien  char *p;
1425130561Sobrien  offsetT temp, size;
1426130561Sobrien  symbolS *symbolP = NULL;
142733965Sjdp  char *stop = NULL;
1428218822Sdim  char stopc = 0;
1429130561Sobrien  expressionS exp;
143033965Sjdp
143133965Sjdp  if (flag_mri)
143233965Sjdp    stop = mri_comment_field (&stopc);
143333965Sjdp
143433965Sjdp  name = input_line_pointer;
143533965Sjdp  c = get_symbol_end ();
143677298Sobrien  /* Just after name is now '\0'.  */
143733965Sjdp  p = input_line_pointer;
143833965Sjdp  *p = c;
143989857Sobrien
144089857Sobrien  if (name == p)
144189857Sobrien    {
144289857Sobrien      as_bad (_("expected symbol name"));
1443218822Sdim      ignore_rest_of_line ();
1444130561Sobrien      goto out;
144589857Sobrien    }
144689857Sobrien
144733965Sjdp  SKIP_WHITESPACE ();
144877298Sobrien
1449130561Sobrien  /* Accept an optional comma after the name.  The comma used to be
1450130561Sobrien     required, but Irix 5 cc does not generate it for .lcomm.  */
1451130561Sobrien  if (*input_line_pointer == ',')
1452130561Sobrien    input_line_pointer++;
1453130561Sobrien
1454130561Sobrien  temp = get_absolute_expr (&exp);
1455130561Sobrien  size = temp;
1456130561Sobrien  size &= ((offsetT) 2 << (stdoutput->arch_info->bits_per_address - 1)) - 1;
1457130561Sobrien  if (exp.X_op == O_absent)
145833965Sjdp    {
1459130561Sobrien      as_bad (_("missing size expression"));
146060484Sobrien      ignore_rest_of_line ();
1461130561Sobrien      goto out;
146233965Sjdp    }
1463130561Sobrien  else if (temp != size || !exp.X_unsigned)
146433965Sjdp    {
1465130561Sobrien      as_warn (_("size (%ld) out of range, ignored"), (long) temp);
146660484Sobrien      ignore_rest_of_line ();
1467130561Sobrien      goto out;
146833965Sjdp    }
146977298Sobrien
1470218822Sdim  *p = 0;
147133965Sjdp  symbolP = symbol_find_or_make (name);
1472218822Sdim  if ((S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
1473218822Sdim      && !S_IS_COMMON (symbolP))
147433965Sjdp    {
1475218822Sdim      if (!S_IS_VOLATILE (symbolP))
1476218822Sdim	{
1477218822Sdim	  symbolP = NULL;
1478218822Sdim	  as_bad (_("symbol `%s' is already defined"), name);
1479218822Sdim	  *p = c;
1480218822Sdim	  ignore_rest_of_line ();
1481218822Sdim	  goto out;
1482218822Sdim	}
1483218822Sdim      symbolP = symbol_clone (symbolP, 1);
1484218822Sdim      S_SET_SEGMENT (symbolP, undefined_section);
1485218822Sdim      S_SET_VALUE (symbolP, 0);
1486218822Sdim      symbol_set_frag (symbolP, &zero_address_frag);
1487218822Sdim      S_CLEAR_VOLATILE (symbolP);
148833965Sjdp    }
148977298Sobrien
1490130561Sobrien  size = S_GET_VALUE (symbolP);
1491130561Sobrien  if (size == 0)
1492130561Sobrien    size = temp;
1493130561Sobrien  else if (size != temp)
1494130561Sobrien    as_warn (_("size of \"%s\" is already %ld; not changing to %ld"),
1495130561Sobrien	     name, (long) size, (long) temp);
1496130561Sobrien
1497130561Sobrien  *p = c;
1498130561Sobrien  if (comm_parse_extra != NULL)
1499130561Sobrien    symbolP = (*comm_parse_extra) (param, symbolP, size);
150033965Sjdp  else
150133965Sjdp    {
1502130561Sobrien      S_SET_VALUE (symbolP, (valueT) size);
150333965Sjdp      S_SET_EXTERNAL (symbolP);
1504218822Sdim      S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
1505130561Sobrien#ifdef OBJ_VMS
1506130561Sobrien      {
1507130561Sobrien	extern int flag_one;
1508130561Sobrien	if (size == 0 || !flag_one)
1509130561Sobrien	  S_GET_OTHER (symbolP) = const_flag;
1510130561Sobrien      }
1511130561Sobrien#endif
151233965Sjdp    }
151333965Sjdp
151460484Sobrien  demand_empty_rest_of_line ();
1515130561Sobrien out:
151633965Sjdp  if (flag_mri)
151733965Sjdp    mri_comment_end (stop, stopc);
1518130561Sobrien  return symbolP;
1519130561Sobrien}
152033965Sjdp
1521130561Sobrienvoid
1522130561Sobriens_comm (int ignore)
1523130561Sobrien{
1524130561Sobrien  s_comm_internal (ignore, NULL);
1525130561Sobrien}
1526130561Sobrien
152733965Sjdp/* The MRI COMMON pseudo-op.  We handle this by creating a common
152833965Sjdp   symbol with the appropriate name.  We make s_space do the right
152933965Sjdp   thing by increasing the size.  */
153033965Sjdp
153133965Sjdpvoid
1532130561Sobriens_mri_common (int small ATTRIBUTE_UNUSED)
153333965Sjdp{
153433965Sjdp  char *name;
153533965Sjdp  char c;
153633965Sjdp  char *alc = NULL;
153733965Sjdp  symbolS *sym;
153833965Sjdp  offsetT align;
153933965Sjdp  char *stop = NULL;
1540218822Sdim  char stopc = 0;
154133965Sjdp
154277298Sobrien  if (!flag_mri)
154333965Sjdp    {
154433965Sjdp      s_comm (0);
154533965Sjdp      return;
154633965Sjdp    }
154733965Sjdp
154833965Sjdp  stop = mri_comment_field (&stopc);
154933965Sjdp
155033965Sjdp  SKIP_WHITESPACE ();
155133965Sjdp
155233965Sjdp  name = input_line_pointer;
155389857Sobrien  if (!ISDIGIT (*name))
155433965Sjdp    c = get_symbol_end ();
155533965Sjdp  else
155633965Sjdp    {
155733965Sjdp      do
155833965Sjdp	{
155933965Sjdp	  ++input_line_pointer;
156033965Sjdp	}
156189857Sobrien      while (ISDIGIT (*input_line_pointer));
156277298Sobrien
156333965Sjdp      c = *input_line_pointer;
156433965Sjdp      *input_line_pointer = '\0';
156533965Sjdp
156633965Sjdp      if (line_label != NULL)
156733965Sjdp	{
156833965Sjdp	  alc = (char *) xmalloc (strlen (S_GET_NAME (line_label))
156933965Sjdp				  + (input_line_pointer - name)
157033965Sjdp				  + 1);
157133965Sjdp	  sprintf (alc, "%s%s", name, S_GET_NAME (line_label));
157233965Sjdp	  name = alc;
157333965Sjdp	}
157433965Sjdp    }
157533965Sjdp
157633965Sjdp  sym = symbol_find_or_make (name);
157733965Sjdp  *input_line_pointer = c;
157833965Sjdp  if (alc != NULL)
157933965Sjdp    free (alc);
158033965Sjdp
158133965Sjdp  if (*input_line_pointer != ',')
158233965Sjdp    align = 0;
158333965Sjdp  else
158433965Sjdp    {
158533965Sjdp      ++input_line_pointer;
158633965Sjdp      align = get_absolute_expression ();
158733965Sjdp    }
158833965Sjdp
158977298Sobrien  if (S_IS_DEFINED (sym) && !S_IS_COMMON (sym))
159033965Sjdp    {
159189857Sobrien      as_bad (_("symbol `%s' is already defined"), S_GET_NAME (sym));
159260484Sobrien      ignore_rest_of_line ();
159333965Sjdp      mri_comment_end (stop, stopc);
159433965Sjdp      return;
159533965Sjdp    }
159633965Sjdp
159733965Sjdp  S_SET_EXTERNAL (sym);
1598218822Sdim  S_SET_SEGMENT (sym, bfd_com_section_ptr);
159933965Sjdp  mri_common_symbol = sym;
160033965Sjdp
160133965Sjdp#ifdef S_SET_ALIGN
160233965Sjdp  if (align != 0)
160333965Sjdp    S_SET_ALIGN (sym, align);
160433965Sjdp#endif
160533965Sjdp
160633965Sjdp  if (line_label != NULL)
160733965Sjdp    {
160860484Sobrien      expressionS exp;
160960484Sobrien      exp.X_op = O_symbol;
161060484Sobrien      exp.X_add_symbol = sym;
161160484Sobrien      exp.X_add_number = 0;
161260484Sobrien      symbol_set_value_expression (line_label, &exp);
161360484Sobrien      symbol_set_frag (line_label, &zero_address_frag);
161433965Sjdp      S_SET_SEGMENT (line_label, expr_section);
161533965Sjdp    }
161633965Sjdp
161733965Sjdp  /* FIXME: We just ignore the small argument, which distinguishes
161833965Sjdp     COMMON and COMMON.S.  I don't know what we can do about it.  */
161933965Sjdp
162033965Sjdp  /* Ignore the type and hptype.  */
162133965Sjdp  if (*input_line_pointer == ',')
162233965Sjdp    input_line_pointer += 2;
162333965Sjdp  if (*input_line_pointer == ',')
162433965Sjdp    input_line_pointer += 2;
162533965Sjdp
162660484Sobrien  demand_empty_rest_of_line ();
162760484Sobrien
162833965Sjdp  mri_comment_end (stop, stopc);
162933965Sjdp}
163033965Sjdp
163133965Sjdpvoid
1632130561Sobriens_data (int ignore ATTRIBUTE_UNUSED)
163333965Sjdp{
163433965Sjdp  segT section;
163533965Sjdp  register int temp;
163633965Sjdp
163733965Sjdp  temp = get_absolute_expression ();
163833965Sjdp  if (flag_readonly_data_in_text)
163933965Sjdp    {
164033965Sjdp      section = text_section;
164133965Sjdp      temp += 1000;
164233965Sjdp    }
164333965Sjdp  else
164433965Sjdp    section = data_section;
164533965Sjdp
164633965Sjdp  subseg_set (section, (subsegT) temp);
164733965Sjdp
164833965Sjdp#ifdef OBJ_VMS
164933965Sjdp  const_flag = 0;
165033965Sjdp#endif
165133965Sjdp  demand_empty_rest_of_line ();
165233965Sjdp}
165333965Sjdp
165433965Sjdp/* Handle the .appfile pseudo-op.  This is automatically generated by
165533965Sjdp   do_scrub_chars when a preprocessor # line comment is seen with a
165633965Sjdp   file name.  This default definition may be overridden by the object
165733965Sjdp   or CPU specific pseudo-ops.  This function is also the default
165833965Sjdp   definition for .file; the APPFILE argument is 1 for .appfile, 0 for
165933965Sjdp   .file.  */
166033965Sjdp
166177298Sobrienvoid
1662218822Sdims_app_file_string (char *file, int appfile ATTRIBUTE_UNUSED)
1663104834Sobrien{
1664104834Sobrien#ifdef LISTING
1665104834Sobrien  if (listing)
1666104834Sobrien    listing_source_file (file);
1667104834Sobrien#endif
1668104834Sobrien  register_dependency (file);
1669104834Sobrien#ifdef obj_app_file
1670218822Sdim  obj_app_file (file, appfile);
1671104834Sobrien#endif
1672104834Sobrien}
1673104834Sobrien
1674104834Sobrienvoid
1675130561Sobriens_app_file (int appfile)
167633965Sjdp{
167733965Sjdp  register char *s;
167833965Sjdp  int length;
167933965Sjdp
168077298Sobrien  /* Some assemblers tolerate immediately following '"'.  */
168133965Sjdp  if ((s = demand_copy_string (&length)) != 0)
168233965Sjdp    {
168338889Sjdp      int may_omit
1684218822Sdim	= (!new_logical_line_flags (s, -1, 1) && appfile);
168533965Sjdp
168633965Sjdp      /* In MRI mode, the preprocessor may have inserted an extraneous
1687130561Sobrien	 backquote.  */
168833965Sjdp      if (flag_m68k_mri
168933965Sjdp	  && *input_line_pointer == '\''
169033965Sjdp	  && is_end_of_line[(unsigned char) input_line_pointer[1]])
169133965Sjdp	++input_line_pointer;
169233965Sjdp
169333965Sjdp      demand_empty_rest_of_line ();
169477298Sobrien      if (!may_omit)
1695218822Sdim	s_app_file_string (s, appfile);
169638889Sjdp    }
169733965Sjdp}
169833965Sjdp
1699218822Sdimstatic int
1700218822Sdimget_linefile_number (int *flag)
1701218822Sdim{
1702218822Sdim  SKIP_WHITESPACE ();
1703218822Sdim
1704218822Sdim  if (*input_line_pointer < '0' || *input_line_pointer > '9')
1705218822Sdim    return 0;
1706218822Sdim
1707218822Sdim  *flag = get_absolute_expression ();
1708218822Sdim
1709218822Sdim  return 1;
1710218822Sdim}
1711218822Sdim
171233965Sjdp/* Handle the .appline pseudo-op.  This is automatically generated by
171333965Sjdp   do_scrub_chars when a preprocessor # line comment is seen.  This
171433965Sjdp   default definition may be overridden by the object or CPU specific
171533965Sjdp   pseudo-ops.  */
171633965Sjdp
171733965Sjdpvoid
1718218822Sdims_app_line (int appline)
171933965Sjdp{
1720218822Sdim  char *file = NULL;
172133965Sjdp  int l;
172233965Sjdp
172333965Sjdp  /* The given number is that of the next line.  */
1724218822Sdim  if (appline)
1725218822Sdim    l = get_absolute_expression ();
1726218822Sdim  else if (!get_linefile_number (&l))
1727218822Sdim    {
1728218822Sdim      ignore_rest_of_line ();
1729218822Sdim      return;
1730218822Sdim    }
1731218822Sdim
1732218822Sdim  l--;
1733218822Sdim
1734218822Sdim  if (l < -1)
173533965Sjdp    /* Some of the back ends can't deal with non-positive line numbers.
1736218822Sdim       Besides, it's silly.  GCC however will generate a line number of
1737218822Sdim       zero when it is pre-processing builtins for assembler-with-cpp files:
1738218822Sdim
1739218822Sdim          # 0 "<built-in>"
1740218822Sdim
1741218822Sdim       We do not want to barf on this, especially since such files are used
1742218822Sdim       in the GCC and GDB testsuites.  So we check for negative line numbers
1743218822Sdim       rather than non-positive line numbers.  */
174489857Sobrien    as_warn (_("line numbers must be positive; line number %d rejected"),
174577298Sobrien	     l + 1);
174633965Sjdp  else
174733965Sjdp    {
1748218822Sdim      int flags = 0;
1749218822Sdim      int length = 0;
1750218822Sdim
1751218822Sdim      if (!appline)
1752218822Sdim	{
1753218822Sdim	  SKIP_WHITESPACE ();
1754218822Sdim
1755218822Sdim	  if (*input_line_pointer == '"')
1756218822Sdim	    file = demand_copy_string (&length);
1757218822Sdim
1758218822Sdim	  if (file)
1759218822Sdim	    {
1760218822Sdim	      int this_flag;
1761218822Sdim
1762218822Sdim	      while (get_linefile_number (&this_flag))
1763218822Sdim		switch (this_flag)
1764218822Sdim		  {
1765218822Sdim		    /* From GCC's cpp documentation:
1766218822Sdim		       1: start of a new file.
1767218822Sdim		       2: returning to a file after having included
1768218822Sdim		          another file.
1769218822Sdim		       3: following text comes from a system header file.
1770218822Sdim		       4: following text should be treated as extern "C".
1771218822Sdim
1772218822Sdim		       4 is nonsensical for the assembler; 3, we don't
1773218822Sdim		       care about, so we ignore it just in case a
1774218822Sdim		       system header file is included while
1775218822Sdim		       preprocessing assembly.  So 1 and 2 are all we
1776218822Sdim		       care about, and they are mutually incompatible.
1777218822Sdim		       new_logical_line_flags() demands this.  */
1778218822Sdim		  case 1:
1779218822Sdim		  case 2:
1780218822Sdim		    if (flags && flags != (1 << this_flag))
1781218822Sdim		      as_warn (_("incompatible flag %i in line directive"),
1782218822Sdim			       this_flag);
1783218822Sdim		    else
1784218822Sdim		      flags |= 1 << this_flag;
1785218822Sdim		    break;
1786218822Sdim
1787218822Sdim		  case 3:
1788218822Sdim		  case 4:
1789218822Sdim		    /* We ignore these.  */
1790218822Sdim		    break;
1791218822Sdim
1792218822Sdim		  default:
1793218822Sdim		    as_warn (_("unsupported flag %i in line directive"),
1794218822Sdim			     this_flag);
1795218822Sdim		    break;
1796218822Sdim		  }
1797218822Sdim
1798218822Sdim	      if (!is_end_of_line[(unsigned char)*input_line_pointer])
1799218822Sdim		file = 0;
1800218822Sdim	    }
1801218822Sdim	}
1802218822Sdim
1803218822Sdim      if (appline || file)
1804218822Sdim	{
1805218822Sdim	  new_logical_line_flags (file, l, flags);
180633965Sjdp#ifdef LISTING
1807218822Sdim	  if (listing)
1808218822Sdim	    listing_source_line (l);
180933965Sjdp#endif
1810218822Sdim	}
181133965Sjdp    }
1812218822Sdim  if (appline || file)
1813218822Sdim    demand_empty_rest_of_line ();
1814218822Sdim  else
1815218822Sdim    ignore_rest_of_line ();
181633965Sjdp}
181733965Sjdp
181833965Sjdp/* Handle the .end pseudo-op.  Actually, the real work is done in
181933965Sjdp   read_a_source_file.  */
182033965Sjdp
182133965Sjdpvoid
1822130561Sobriens_end (int ignore ATTRIBUTE_UNUSED)
182333965Sjdp{
182433965Sjdp  if (flag_mri)
182533965Sjdp    {
182633965Sjdp      /* The MRI assembler permits the start symbol to follow .end,
1827130561Sobrien	 but we don't support that.  */
182833965Sjdp      SKIP_WHITESPACE ();
182977298Sobrien      if (!is_end_of_line[(unsigned char) *input_line_pointer]
183033965Sjdp	  && *input_line_pointer != '*'
183133965Sjdp	  && *input_line_pointer != '!')
183260484Sobrien	as_warn (_("start address not supported"));
183333965Sjdp    }
183433965Sjdp}
183533965Sjdp
183633965Sjdp/* Handle the .err pseudo-op.  */
183733965Sjdp
183833965Sjdpvoid
1839130561Sobriens_err (int ignore ATTRIBUTE_UNUSED)
184033965Sjdp{
184160484Sobrien  as_bad (_(".err encountered"));
184233965Sjdp  demand_empty_rest_of_line ();
184333965Sjdp}
184433965Sjdp
1845218822Sdim/* Handle the .error and .warning pseudo-ops.  */
1846218822Sdim
1847218822Sdimvoid
1848218822Sdims_errwarn (int err)
1849218822Sdim{
1850218822Sdim  int len;
1851218822Sdim  /* The purpose for the conditional assignment is not to
1852218822Sdim     internationalize the directive itself, but that we need a
1853218822Sdim     self-contained message, one that can be passed like the
1854218822Sdim     demand_copy_C_string return value, and with no assumption on the
1855218822Sdim     location of the name of the directive within the message.  */
1856218822Sdim  char *msg
1857218822Sdim    = (err ? _(".error directive invoked in source file")
1858218822Sdim       : _(".warning directive invoked in source file"));
1859218822Sdim
1860218822Sdim  if (!is_it_end_of_statement ())
1861218822Sdim    {
1862218822Sdim      if (*input_line_pointer != '\"')
1863218822Sdim	{
1864218822Sdim	  as_bad (_("%s argument must be a string"),
1865218822Sdim		  err ? ".error" : ".warning");
1866218822Sdim	  ignore_rest_of_line ();
1867218822Sdim	  return;
1868218822Sdim	}
1869218822Sdim
1870218822Sdim      msg = demand_copy_C_string (&len);
1871218822Sdim      if (msg == NULL)
1872218822Sdim	return;
1873218822Sdim    }
1874218822Sdim
1875218822Sdim  if (err)
1876218822Sdim    as_bad ("%s", msg);
1877218822Sdim  else
1878218822Sdim    as_warn ("%s", msg);
1879218822Sdim  demand_empty_rest_of_line ();
1880218822Sdim}
1881218822Sdim
188233965Sjdp/* Handle the MRI fail pseudo-op.  */
188333965Sjdp
188433965Sjdpvoid
1885130561Sobriens_fail (int ignore ATTRIBUTE_UNUSED)
188633965Sjdp{
188733965Sjdp  offsetT temp;
188833965Sjdp  char *stop = NULL;
1889218822Sdim  char stopc = 0;
189033965Sjdp
189133965Sjdp  if (flag_mri)
189233965Sjdp    stop = mri_comment_field (&stopc);
189333965Sjdp
189433965Sjdp  temp = get_absolute_expression ();
189533965Sjdp  if (temp >= 500)
189660484Sobrien    as_warn (_(".fail %ld encountered"), (long) temp);
189733965Sjdp  else
189860484Sobrien    as_bad (_(".fail %ld encountered"), (long) temp);
189933965Sjdp
190060484Sobrien  demand_empty_rest_of_line ();
190160484Sobrien
190233965Sjdp  if (flag_mri)
190333965Sjdp    mri_comment_end (stop, stopc);
190433965Sjdp}
190533965Sjdp
190677298Sobrienvoid
1907130561Sobriens_fill (int ignore ATTRIBUTE_UNUSED)
190833965Sjdp{
190938889Sjdp  expressionS rep_exp;
191038889Sjdp  long size = 1;
191138889Sjdp  register long fill = 0;
191233965Sjdp  char *p;
191333965Sjdp
191433965Sjdp#ifdef md_flush_pending_output
191533965Sjdp  md_flush_pending_output ();
191633965Sjdp#endif
191733965Sjdp
191838889Sjdp  get_known_segmented_expression (&rep_exp);
191933965Sjdp  if (*input_line_pointer == ',')
192033965Sjdp    {
192133965Sjdp      input_line_pointer++;
192238889Sjdp      size = get_absolute_expression ();
192333965Sjdp      if (*input_line_pointer == ',')
192433965Sjdp	{
192533965Sjdp	  input_line_pointer++;
192638889Sjdp	  fill = get_absolute_expression ();
192733965Sjdp	}
192833965Sjdp    }
192938889Sjdp
193033965Sjdp  /* This is to be compatible with BSD 4.2 AS, not for any rational reason.  */
193133965Sjdp#define BSD_FILL_SIZE_CROCK_8 (8)
193238889Sjdp  if (size > BSD_FILL_SIZE_CROCK_8)
193333965Sjdp    {
193489857Sobrien      as_warn (_(".fill size clamped to %d"), BSD_FILL_SIZE_CROCK_8);
193538889Sjdp      size = BSD_FILL_SIZE_CROCK_8;
193633965Sjdp    }
193738889Sjdp  if (size < 0)
193833965Sjdp    {
193989857Sobrien      as_warn (_("size negative; .fill ignored"));
194038889Sjdp      size = 0;
194133965Sjdp    }
194238889Sjdp  else if (rep_exp.X_op == O_constant && rep_exp.X_add_number <= 0)
194333965Sjdp    {
194438889Sjdp      if (rep_exp.X_add_number < 0)
194589857Sobrien	as_warn (_("repeat < 0; .fill ignored"));
194638889Sjdp      size = 0;
194733965Sjdp    }
194833965Sjdp
194938889Sjdp  if (size && !need_pass_2)
195033965Sjdp    {
195138889Sjdp      if (rep_exp.X_op == O_constant)
195238889Sjdp	{
195338889Sjdp	  p = frag_var (rs_fill, (int) size, (int) size,
195438889Sjdp			(relax_substateT) 0, (symbolS *) 0,
195538889Sjdp			(offsetT) rep_exp.X_add_number,
195638889Sjdp			(char *) 0);
195738889Sjdp	}
195838889Sjdp      else
195938889Sjdp	{
196038889Sjdp	  /* We don't have a constant repeat count, so we can't use
196138889Sjdp	     rs_fill.  We can get the same results out of rs_space,
196238889Sjdp	     but its argument is in bytes, so we must multiply the
196338889Sjdp	     repeat count by size.  */
196438889Sjdp
196538889Sjdp	  symbolS *rep_sym;
196638889Sjdp	  rep_sym = make_expr_symbol (&rep_exp);
196738889Sjdp	  if (size != 1)
196838889Sjdp	    {
196938889Sjdp	      expressionS size_exp;
197038889Sjdp	      size_exp.X_op = O_constant;
197138889Sjdp	      size_exp.X_add_number = size;
197238889Sjdp
197338889Sjdp	      rep_exp.X_op = O_multiply;
197438889Sjdp	      rep_exp.X_add_symbol = rep_sym;
197538889Sjdp	      rep_exp.X_op_symbol = make_expr_symbol (&size_exp);
197638889Sjdp	      rep_exp.X_add_number = 0;
197738889Sjdp	      rep_sym = make_expr_symbol (&rep_exp);
197838889Sjdp	    }
197938889Sjdp
198038889Sjdp	  p = frag_var (rs_space, (int) size, (int) size,
198138889Sjdp			(relax_substateT) 0, rep_sym, (offsetT) 0, (char *) 0);
198238889Sjdp	}
198377298Sobrien
198438889Sjdp      memset (p, 0, (unsigned int) size);
198577298Sobrien
198633965Sjdp      /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX
1987130561Sobrien	 flavoured AS.  The following bizarre behaviour is to be
1988130561Sobrien	 compatible with above.  I guess they tried to take up to 8
1989130561Sobrien	 bytes from a 4-byte expression and they forgot to sign
1990130561Sobrien	 extend.  */
199133965Sjdp#define BSD_FILL_SIZE_CROCK_4 (4)
199238889Sjdp      md_number_to_chars (p, (valueT) fill,
199338889Sjdp			  (size > BSD_FILL_SIZE_CROCK_4
199433965Sjdp			   ? BSD_FILL_SIZE_CROCK_4
199538889Sjdp			   : (int) size));
199633965Sjdp      /* Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes)
1997130561Sobrien	 but emits no error message because it seems a legal thing to do.
1998130561Sobrien	 It is a degenerate case of .fill but could be emitted by a
199977298Sobrien	 compiler.  */
200033965Sjdp    }
200133965Sjdp  demand_empty_rest_of_line ();
200233965Sjdp}
200333965Sjdp
200477298Sobrienvoid
2005130561Sobriens_globl (int ignore ATTRIBUTE_UNUSED)
200633965Sjdp{
200733965Sjdp  char *name;
200833965Sjdp  int c;
200933965Sjdp  symbolS *symbolP;
201033965Sjdp  char *stop = NULL;
2011218822Sdim  char stopc = 0;
201233965Sjdp
201333965Sjdp  if (flag_mri)
201433965Sjdp    stop = mri_comment_field (&stopc);
201533965Sjdp
201633965Sjdp  do
201733965Sjdp    {
201833965Sjdp      name = input_line_pointer;
201933965Sjdp      c = get_symbol_end ();
202033965Sjdp      symbolP = symbol_find_or_make (name);
202160484Sobrien      S_SET_EXTERNAL (symbolP);
202260484Sobrien
202333965Sjdp      *input_line_pointer = c;
202433965Sjdp      SKIP_WHITESPACE ();
202560484Sobrien      c = *input_line_pointer;
202633965Sjdp      if (c == ',')
202733965Sjdp	{
202833965Sjdp	  input_line_pointer++;
202933965Sjdp	  SKIP_WHITESPACE ();
203089857Sobrien	  if (is_end_of_line[(unsigned char) *input_line_pointer])
203133965Sjdp	    c = '\n';
203233965Sjdp	}
203333965Sjdp    }
203433965Sjdp  while (c == ',');
203533965Sjdp
203660484Sobrien  demand_empty_rest_of_line ();
203760484Sobrien
203833965Sjdp  if (flag_mri)
203933965Sjdp    mri_comment_end (stop, stopc);
204033965Sjdp}
204133965Sjdp
2042218822Sdim#ifdef OBJ_ELF
2043218822Sdim#define skip_whitespace(str)  do { if (*(str) == ' ') ++(str); } while (0)
2044218822Sdim
2045218822Sdimstatic inline int
2046218822Sdimskip_past_char (char ** str, char c)
2047218822Sdim{
2048218822Sdim  if (**str == c)
2049218822Sdim    {
2050218822Sdim      (*str)++;
2051218822Sdim      return 0;
2052218822Sdim    }
2053218822Sdim  else
2054218822Sdim    return -1;
2055218822Sdim}
2056218822Sdim#define skip_past_comma(str) skip_past_char (str, ',')
2057218822Sdim
2058218822Sdim/* Parse an attribute directive for VENDOR.  */
2059218822Sdimvoid
2060218822Sdims_vendor_attribute (int vendor)
2061218822Sdim{
2062218822Sdim  expressionS exp;
2063218822Sdim  int type;
2064218822Sdim  int tag;
2065218822Sdim  unsigned int i = 0;
2066218822Sdim  char *s = NULL;
2067218822Sdim  char saved_char;
2068218822Sdim
2069218822Sdim  expression (& exp);
2070218822Sdim  if (exp.X_op != O_constant)
2071218822Sdim    goto bad;
2072218822Sdim
2073218822Sdim  tag = exp.X_add_number;
2074218822Sdim  type = _bfd_elf_obj_attrs_arg_type (stdoutput, vendor, tag);
2075218822Sdim
2076218822Sdim  if (skip_past_comma (&input_line_pointer) == -1)
2077218822Sdim    goto bad;
2078218822Sdim  if (type & 1)
2079218822Sdim    {
2080218822Sdim      expression (& exp);
2081218822Sdim      if (exp.X_op != O_constant)
2082218822Sdim	{
2083218822Sdim	  as_bad (_("expected numeric constant"));
2084218822Sdim	  ignore_rest_of_line ();
2085218822Sdim	  return;
2086218822Sdim	}
2087218822Sdim      i = exp.X_add_number;
2088218822Sdim    }
2089218822Sdim  if (type == 3
2090218822Sdim      && skip_past_comma (&input_line_pointer) == -1)
2091218822Sdim    {
2092218822Sdim      as_bad (_("expected comma"));
2093218822Sdim      ignore_rest_of_line ();
2094218822Sdim      return;
2095218822Sdim    }
2096218822Sdim  if (type & 2)
2097218822Sdim    {
2098218822Sdim      skip_whitespace(input_line_pointer);
2099218822Sdim      if (*input_line_pointer != '"')
2100218822Sdim	goto bad_string;
2101218822Sdim      input_line_pointer++;
2102218822Sdim      s = input_line_pointer;
2103218822Sdim      while (*input_line_pointer && *input_line_pointer != '"')
2104218822Sdim	input_line_pointer++;
2105218822Sdim      if (*input_line_pointer != '"')
2106218822Sdim	goto bad_string;
2107218822Sdim      saved_char = *input_line_pointer;
2108218822Sdim      *input_line_pointer = 0;
2109218822Sdim    }
2110218822Sdim  else
2111218822Sdim    {
2112218822Sdim      s = NULL;
2113218822Sdim      saved_char = 0;
2114218822Sdim    }
2115218822Sdim
2116218822Sdim  switch (type)
2117218822Sdim    {
2118218822Sdim    case 3:
2119218822Sdim      bfd_elf_add_obj_attr_compat (stdoutput, vendor, i, s);
2120218822Sdim      break;
2121218822Sdim    case 2:
2122218822Sdim      bfd_elf_add_obj_attr_string (stdoutput, vendor, tag, s);
2123218822Sdim      break;
2124218822Sdim    case 1:
2125218822Sdim      bfd_elf_add_obj_attr_int (stdoutput, vendor, tag, i);
2126218822Sdim      break;
2127218822Sdim    default:
2128218822Sdim      abort ();
2129218822Sdim    }
2130218822Sdim
2131218822Sdim  if (s)
2132218822Sdim    {
2133218822Sdim      *input_line_pointer = saved_char;
2134218822Sdim      input_line_pointer++;
2135218822Sdim    }
2136218822Sdim  demand_empty_rest_of_line ();
2137218822Sdim  return;
2138218822Sdimbad_string:
2139218822Sdim  as_bad (_("bad string constant"));
2140218822Sdim  ignore_rest_of_line ();
2141218822Sdim  return;
2142218822Sdimbad:
2143218822Sdim  as_bad (_("expected <tag> , <value>"));
2144218822Sdim  ignore_rest_of_line ();
2145218822Sdim}
2146218822Sdim
2147218822Sdim/* Parse a .gnu_attribute directive.  */
2148218822Sdim
2149218822Sdimstatic void
2150218822Sdims_gnu_attribute (int ignored ATTRIBUTE_UNUSED)
2151218822Sdim{
2152218822Sdim  s_vendor_attribute (OBJ_ATTR_GNU);
2153218822Sdim}
2154218822Sdim#endif /* OBJ_ELF */
2155218822Sdim
215633965Sjdp/* Handle the MRI IRP and IRPC pseudo-ops.  */
215733965Sjdp
215833965Sjdpvoid
2159130561Sobriens_irp (int irpc)
216033965Sjdp{
2161218822Sdim  char *file, *eol;
216233965Sjdp  unsigned int line;
216333965Sjdp  sb s;
216433965Sjdp  const char *err;
216533965Sjdp  sb out;
216633965Sjdp
216733965Sjdp  as_where (&file, &line);
216833965Sjdp
216933965Sjdp  sb_new (&s);
2170218822Sdim  eol = find_end_of_line (input_line_pointer, 0);
2171218822Sdim  sb_add_buffer (&s, input_line_pointer, eol - input_line_pointer);
2172218822Sdim  input_line_pointer = eol;
217333965Sjdp
217433965Sjdp  sb_new (&out);
217533965Sjdp
2176130561Sobrien  err = expand_irp (irpc, 0, &s, &out, get_line_sb);
217733965Sjdp  if (err != NULL)
217833965Sjdp    as_bad_where (file, line, "%s", err);
217933965Sjdp
218033965Sjdp  sb_kill (&s);
218133965Sjdp
218260484Sobrien  input_scrub_include_sb (&out, input_line_pointer, 1);
218333965Sjdp  sb_kill (&out);
218433965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
218533965Sjdp}
218633965Sjdp
218733965Sjdp/* Handle the .linkonce pseudo-op.  This tells the assembler to mark
218833965Sjdp   the section to only be linked once.  However, this is not supported
218933965Sjdp   by most object file formats.  This takes an optional argument,
219033965Sjdp   which is what to do about duplicates.  */
219133965Sjdp
219233965Sjdpvoid
2193130561Sobriens_linkonce (int ignore ATTRIBUTE_UNUSED)
219433965Sjdp{
219533965Sjdp  enum linkonce_type type;
219633965Sjdp
219733965Sjdp  SKIP_WHITESPACE ();
219833965Sjdp
219933965Sjdp  type = LINKONCE_DISCARD;
220033965Sjdp
220177298Sobrien  if (!is_end_of_line[(unsigned char) *input_line_pointer])
220233965Sjdp    {
220333965Sjdp      char *s;
220433965Sjdp      char c;
220533965Sjdp
220633965Sjdp      s = input_line_pointer;
220733965Sjdp      c = get_symbol_end ();
220833965Sjdp      if (strcasecmp (s, "discard") == 0)
220933965Sjdp	type = LINKONCE_DISCARD;
221033965Sjdp      else if (strcasecmp (s, "one_only") == 0)
221133965Sjdp	type = LINKONCE_ONE_ONLY;
221233965Sjdp      else if (strcasecmp (s, "same_size") == 0)
221333965Sjdp	type = LINKONCE_SAME_SIZE;
221433965Sjdp      else if (strcasecmp (s, "same_contents") == 0)
221533965Sjdp	type = LINKONCE_SAME_CONTENTS;
221633965Sjdp      else
221760484Sobrien	as_warn (_("unrecognized .linkonce type `%s'"), s);
221833965Sjdp
221933965Sjdp      *input_line_pointer = c;
222033965Sjdp    }
222133965Sjdp
222233965Sjdp#ifdef obj_handle_link_once
222333965Sjdp  obj_handle_link_once (type);
222433965Sjdp#else /* ! defined (obj_handle_link_once) */
222533965Sjdp  {
222633965Sjdp    flagword flags;
222733965Sjdp
222833965Sjdp    if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0)
222960484Sobrien      as_warn (_(".linkonce is not supported for this object file format"));
223033965Sjdp
223133965Sjdp    flags = bfd_get_section_flags (stdoutput, now_seg);
223233965Sjdp    flags |= SEC_LINK_ONCE;
223333965Sjdp    switch (type)
223433965Sjdp      {
223533965Sjdp      default:
223633965Sjdp	abort ();
223733965Sjdp      case LINKONCE_DISCARD:
223833965Sjdp	flags |= SEC_LINK_DUPLICATES_DISCARD;
223933965Sjdp	break;
224033965Sjdp      case LINKONCE_ONE_ONLY:
224133965Sjdp	flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
224233965Sjdp	break;
224333965Sjdp      case LINKONCE_SAME_SIZE:
224433965Sjdp	flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
224533965Sjdp	break;
224633965Sjdp      case LINKONCE_SAME_CONTENTS:
224733965Sjdp	flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
224833965Sjdp	break;
224933965Sjdp      }
225077298Sobrien    if (!bfd_set_section_flags (stdoutput, now_seg, flags))
225160484Sobrien      as_bad (_("bfd_set_section_flags: %s"),
225233965Sjdp	      bfd_errmsg (bfd_get_error ()));
225333965Sjdp  }
225433965Sjdp#endif /* ! defined (obj_handle_link_once) */
225533965Sjdp
225633965Sjdp  demand_empty_rest_of_line ();
225733965Sjdp}
225833965Sjdp
2259130561Sobrienvoid
2260130561Sobrienbss_alloc (symbolS *symbolP, addressT size, int align)
226133965Sjdp{
2262130561Sobrien  char *pfrag;
226333965Sjdp  segT current_seg = now_seg;
226433965Sjdp  subsegT current_subseg = now_subseg;
226533965Sjdp  segT bss_seg = bss_section;
226633965Sjdp
226733965Sjdp#if defined (TC_MIPS) || defined (TC_ALPHA)
226833965Sjdp  if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
226933965Sjdp      || OUTPUT_FLAVOR == bfd_target_elf_flavour)
227033965Sjdp    {
227133965Sjdp      /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss.  */
2272130561Sobrien      if (size <= bfd_get_gp_size (stdoutput))
227333965Sjdp	{
227433965Sjdp	  bss_seg = subseg_new (".sbss", 1);
227533965Sjdp	  seg_info (bss_seg)->bss = 1;
227677298Sobrien	  if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
227760484Sobrien	    as_warn (_("error setting flags for \".sbss\": %s"),
227833965Sjdp		     bfd_errmsg (bfd_get_error ()));
227933965Sjdp	}
228033965Sjdp    }
228133965Sjdp#endif
2282130561Sobrien  subseg_set (bss_seg, 1);
228360484Sobrien
2284130561Sobrien  if (align)
228577298Sobrien    {
2286130561Sobrien      record_alignment (bss_seg, align);
2287130561Sobrien      frag_align (align, 0, 0);
228877298Sobrien    }
228933965Sjdp
2290130561Sobrien  /* Detach from old frag.  */
2291130561Sobrien  if (S_GET_SEGMENT (symbolP) == bss_seg)
2292130561Sobrien    symbol_get_frag (symbolP)->fr_symbol = NULL;
229377298Sobrien
2294130561Sobrien  symbol_set_frag (symbolP, frag_now);
2295130561Sobrien  pfrag = frag_var (rs_org, 1, 1, 0, symbolP, size, NULL);
2296130561Sobrien  *pfrag = 0;
229777298Sobrien
2298130561Sobrien#ifdef S_SET_SIZE
2299130561Sobrien  S_SET_SIZE (symbolP, size);
2300130561Sobrien#endif
2301130561Sobrien  S_SET_SEGMENT (symbolP, bss_seg);
230277298Sobrien
2303130561Sobrien#ifdef OBJ_COFF
2304130561Sobrien  /* The symbol may already have been created with a preceding
2305130561Sobrien     ".globl" directive -- be careful not to step on storage class
2306130561Sobrien     in that case.  Otherwise, set it to static.  */
2307130561Sobrien  if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
2308130561Sobrien    S_SET_STORAGE_CLASS (symbolP, C_STAT);
2309130561Sobrien#endif /* OBJ_COFF */
231077298Sobrien
2311130561Sobrien  subseg_set (current_seg, current_subseg);
2312130561Sobrien}
231377298Sobrien
2314130561SobrienoffsetT
2315130561Sobrienparse_align (int align_bytes)
2316130561Sobrien{
2317130561Sobrien  expressionS exp;
2318130561Sobrien  addressT align;
231938889Sjdp
2320130561Sobrien  SKIP_WHITESPACE ();
2321130561Sobrien  if (*input_line_pointer != ',')
2322130561Sobrien    {
2323130561Sobrien    no_align:
2324130561Sobrien      as_bad (_("expected alignment after size"));
2325130561Sobrien      ignore_rest_of_line ();
2326130561Sobrien      return -1;
2327130561Sobrien    }
232877298Sobrien
2329130561Sobrien  input_line_pointer++;
2330130561Sobrien  SKIP_WHITESPACE ();
233177298Sobrien
2332130561Sobrien  align = get_absolute_expr (&exp);
2333130561Sobrien  if (exp.X_op == O_absent)
2334130561Sobrien    goto no_align;
2335130561Sobrien
2336130561Sobrien  if (!exp.X_unsigned)
2337130561Sobrien    {
2338130561Sobrien      as_warn (_("alignment negative; 0 assumed"));
2339130561Sobrien      align = 0;
234077298Sobrien    }
2341130561Sobrien
2342130561Sobrien  if (align_bytes && align != 0)
234333965Sjdp    {
2344130561Sobrien      /* convert to a power of 2 alignment */
2345130561Sobrien      unsigned int alignp2 = 0;
2346130561Sobrien      while ((align & 1) == 0)
2347130561Sobrien	align >>= 1, ++alignp2;
2348130561Sobrien      if (align != 1)
234933965Sjdp	{
2350130561Sobrien	  as_bad (_("alignment not a power of 2"));
2351130561Sobrien	  ignore_rest_of_line ();
2352130561Sobrien	  return -1;
235333965Sjdp	}
2354130561Sobrien      align = alignp2;
235533965Sjdp    }
2356130561Sobrien  return align;
2357130561Sobrien}
235833965Sjdp
2359130561Sobrien/* Called from s_comm_internal after symbol name and size have been
2360130561Sobrien   parsed.  NEEDS_ALIGN is 0 if it was an ".lcomm" (2 args only),
2361130561Sobrien   1 if this was a ".bss" directive which has a 3rd argument
2362130561Sobrien   (alignment as a power of 2), or 2 if this was a ".bss" directive
2363130561Sobrien   with alignment in bytes.  */
236433965Sjdp
2365130561SobriensymbolS *
2366130561Sobriens_lcomm_internal (int needs_align, symbolS *symbolP, addressT size)
2367130561Sobrien{
2368130561Sobrien  addressT align = 0;
2369130561Sobrien
2370130561Sobrien  if (needs_align)
237133965Sjdp    {
2372130561Sobrien      align = parse_align (needs_align - 1);
2373130561Sobrien      if (align == (addressT) -1)
2374130561Sobrien	return NULL;
237533965Sjdp    }
237633965Sjdp  else
2377130561Sobrien    /* Assume some objects may require alignment on some systems.  */
2378130561Sobrien    TC_IMPLICIT_LCOMM_ALIGNMENT (size, align);
237933965Sjdp
2380130561Sobrien  bss_alloc (symbolP, size, align);
2381130561Sobrien  return symbolP;
238277298Sobrien}
238333965Sjdp
238438889Sjdpvoid
2385130561Sobriens_lcomm (int needs_align)
238638889Sjdp{
2387130561Sobrien  s_comm_internal (needs_align, s_lcomm_internal);
238838889Sjdp}
238938889Sjdp
239077298Sobrienvoid
2391130561Sobriens_lcomm_bytes (int needs_align)
239238889Sjdp{
2393130561Sobrien  s_comm_internal (needs_align * 2, s_lcomm_internal);
239438889Sjdp}
239538889Sjdp
239677298Sobrienvoid
2397130561Sobriens_lsym (int ignore ATTRIBUTE_UNUSED)
239833965Sjdp{
239933965Sjdp  register char *name;
240033965Sjdp  register char c;
240133965Sjdp  register char *p;
240233965Sjdp  expressionS exp;
240333965Sjdp  register symbolS *symbolP;
240433965Sjdp
240577298Sobrien  /* We permit ANY defined expression: BSD4.2 demands constants.  */
240633965Sjdp  name = input_line_pointer;
240733965Sjdp  c = get_symbol_end ();
240833965Sjdp  p = input_line_pointer;
240933965Sjdp  *p = c;
241089857Sobrien
241189857Sobrien  if (name == p)
241289857Sobrien    {
241389857Sobrien      as_bad (_("expected symbol name"));
2414218822Sdim      ignore_rest_of_line ();
241589857Sobrien      return;
241689857Sobrien    }
241789857Sobrien
241833965Sjdp  SKIP_WHITESPACE ();
241977298Sobrien
242033965Sjdp  if (*input_line_pointer != ',')
242133965Sjdp    {
242233965Sjdp      *p = 0;
242389857Sobrien      as_bad (_("expected comma after \"%s\""), name);
242433965Sjdp      *p = c;
242533965Sjdp      ignore_rest_of_line ();
242633965Sjdp      return;
242733965Sjdp    }
242877298Sobrien
242933965Sjdp  input_line_pointer++;
2430218822Sdim  expression_and_evaluate (&exp);
243177298Sobrien
243233965Sjdp  if (exp.X_op != O_constant
243333965Sjdp      && exp.X_op != O_register)
243433965Sjdp    {
243560484Sobrien      as_bad (_("bad expression"));
243633965Sjdp      ignore_rest_of_line ();
243733965Sjdp      return;
243833965Sjdp    }
243977298Sobrien
244033965Sjdp  *p = 0;
244133965Sjdp  symbolP = symbol_find_or_make (name);
244233965Sjdp
2443218822Sdim  if (S_GET_SEGMENT (symbolP) == undefined_section)
244433965Sjdp    {
244533965Sjdp      /* The name might be an undefined .global symbol; be sure to
244677298Sobrien	 keep the "external" bit.  */
244733965Sjdp      S_SET_SEGMENT (symbolP,
244833965Sjdp		     (exp.X_op == O_constant
244933965Sjdp		      ? absolute_section
245033965Sjdp		      : reg_section));
245133965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
245233965Sjdp    }
245333965Sjdp  else
245433965Sjdp    {
245589857Sobrien      as_bad (_("symbol `%s' is already defined"), name);
245633965Sjdp    }
245777298Sobrien
245833965Sjdp  *p = c;
245933965Sjdp  demand_empty_rest_of_line ();
246077298Sobrien}
246133965Sjdp
2462130561Sobrien/* Read a line into an sb.  Returns the character that ended the line
2463130561Sobrien   or zero if there are no more lines.  */
246433965Sjdp
246533965Sjdpstatic int
2466130561Sobrienget_line_sb (sb *line)
246733965Sjdp{
2468218822Sdim  char *eol;
246933965Sjdp
247033965Sjdp  if (input_line_pointer[-1] == '\n')
247133965Sjdp    bump_line_counters ();
247233965Sjdp
247333965Sjdp  if (input_line_pointer >= buffer_limit)
247433965Sjdp    {
247533965Sjdp      buffer_limit = input_scrub_next_buffer (&input_line_pointer);
247633965Sjdp      if (buffer_limit == 0)
247733965Sjdp	return 0;
247833965Sjdp    }
247933965Sjdp
2480218822Sdim  eol = find_end_of_line (input_line_pointer, flag_m68k_mri);
2481218822Sdim  sb_add_buffer (line, input_line_pointer, eol - input_line_pointer);
2482218822Sdim  input_line_pointer = eol;
248333965Sjdp
2484130561Sobrien  /* Don't skip multiple end-of-line characters, because that breaks support
2485130561Sobrien     for the IA-64 stop bit (;;) which looks like two consecutive end-of-line
2486130561Sobrien     characters but isn't.  Instead just skip one end of line character and
2487130561Sobrien     return the character skipped so that the caller can re-insert it if
2488130561Sobrien     necessary.   */
2489218822Sdim  return *input_line_pointer++;
249033965Sjdp}
249133965Sjdp
2492130561Sobrien/* Define a macro.  This is an interface to macro.c.  */
249333965Sjdp
249433965Sjdpvoid
2495130561Sobriens_macro (int ignore ATTRIBUTE_UNUSED)
249633965Sjdp{
2497218822Sdim  char *file, *eol;
249833965Sjdp  unsigned int line;
249933965Sjdp  sb s;
250033965Sjdp  const char *err;
250133965Sjdp  const char *name;
250233965Sjdp
250333965Sjdp  as_where (&file, &line);
250433965Sjdp
250533965Sjdp  sb_new (&s);
2506218822Sdim  eol = find_end_of_line (input_line_pointer, 0);
2507218822Sdim  sb_add_buffer (&s, input_line_pointer, eol - input_line_pointer);
2508218822Sdim  input_line_pointer = eol;
250933965Sjdp
251033965Sjdp  if (line_label != NULL)
2511218822Sdim    {
2512218822Sdim      sb label;
251333965Sjdp
2514218822Sdim      sb_new (&label);
2515218822Sdim      sb_add_string (&label, S_GET_NAME (line_label));
2516218822Sdim      err = define_macro (0, &s, &label, get_line_sb, file, line, &name);
2517218822Sdim      sb_kill (&label);
2518218822Sdim    }
2519218822Sdim  else
2520218822Sdim    err = define_macro (0, &s, NULL, get_line_sb, file, line, &name);
252133965Sjdp  if (err != NULL)
2522218822Sdim    as_bad_where (file, line, err, name);
252333965Sjdp  else
252433965Sjdp    {
252533965Sjdp      if (line_label != NULL)
252633965Sjdp	{
2527218822Sdim	  S_SET_SEGMENT (line_label, absolute_section);
252833965Sjdp	  S_SET_VALUE (line_label, 0);
252960484Sobrien	  symbol_set_frag (line_label, &zero_address_frag);
253033965Sjdp	}
253133965Sjdp
253260484Sobrien      if (((NO_PSEUDO_DOT || flag_m68k_mri)
253333965Sjdp	   && hash_find (po_hash, name) != NULL)
253477298Sobrien	  || (!flag_m68k_mri
253533965Sjdp	      && *name == '.'
253633965Sjdp	      && hash_find (po_hash, name + 1) != NULL))
2537218822Sdim	as_warn_where (file,
2538218822Sdim		 line,
2539218822Sdim		 _("attempt to redefine pseudo-op `%s' ignored"),
254033965Sjdp		 name);
254133965Sjdp    }
254233965Sjdp
254333965Sjdp  sb_kill (&s);
254433965Sjdp}
254533965Sjdp
254633965Sjdp/* Handle the .mexit pseudo-op, which immediately exits a macro
254733965Sjdp   expansion.  */
254833965Sjdp
254933965Sjdpvoid
2550130561Sobriens_mexit (int ignore ATTRIBUTE_UNUSED)
255133965Sjdp{
255233965Sjdp  cond_exit_macro (macro_nest);
255333965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
255433965Sjdp}
255533965Sjdp
255633965Sjdp/* Switch in and out of MRI mode.  */
255733965Sjdp
255833965Sjdpvoid
2559130561Sobriens_mri (int ignore ATTRIBUTE_UNUSED)
256033965Sjdp{
256133965Sjdp  int on, old_flag;
256233965Sjdp
256333965Sjdp  on = get_absolute_expression ();
256433965Sjdp  old_flag = flag_mri;
256533965Sjdp  if (on != 0)
256633965Sjdp    {
256733965Sjdp      flag_mri = 1;
256833965Sjdp#ifdef TC_M68K
256933965Sjdp      flag_m68k_mri = 1;
257033965Sjdp#endif
257160484Sobrien      macro_mri_mode (1);
257233965Sjdp    }
257333965Sjdp  else
257433965Sjdp    {
257533965Sjdp      flag_mri = 0;
257660484Sobrien#ifdef TC_M68K
257733965Sjdp      flag_m68k_mri = 0;
257860484Sobrien#endif
257960484Sobrien      macro_mri_mode (0);
258033965Sjdp    }
258133965Sjdp
258260484Sobrien  /* Operator precedence changes in m68k MRI mode, so we need to
258360484Sobrien     update the operator rankings.  */
258460484Sobrien  expr_set_precedence ();
258560484Sobrien
258633965Sjdp#ifdef MRI_MODE_CHANGE
258733965Sjdp  if (on != old_flag)
258833965Sjdp    MRI_MODE_CHANGE (on);
258933965Sjdp#endif
259033965Sjdp
259133965Sjdp  demand_empty_rest_of_line ();
259233965Sjdp}
259333965Sjdp
259433965Sjdp/* Handle changing the location counter.  */
259533965Sjdp
259633965Sjdpstatic void
2597130561Sobriendo_org (segT segment, expressionS *exp, int fill)
259833965Sjdp{
259933965Sjdp  if (segment != now_seg && segment != absolute_section)
260089857Sobrien    as_bad (_("invalid segment \"%s\""), segment_name (segment));
260133965Sjdp
260233965Sjdp  if (now_seg == absolute_section)
260333965Sjdp    {
260433965Sjdp      if (fill != 0)
260560484Sobrien	as_warn (_("ignoring fill value in absolute section"));
260633965Sjdp      if (exp->X_op != O_constant)
260733965Sjdp	{
260860484Sobrien	  as_bad (_("only constant offsets supported in absolute section"));
260933965Sjdp	  exp->X_add_number = 0;
261033965Sjdp	}
261133965Sjdp      abs_section_offset = exp->X_add_number;
261233965Sjdp    }
261333965Sjdp  else
261433965Sjdp    {
261533965Sjdp      char *p;
261678828Sobrien      symbolS *sym = exp->X_add_symbol;
261778828Sobrien      offsetT off = exp->X_add_number * OCTETS_PER_BYTE;
261833965Sjdp
261978828Sobrien      if (exp->X_op != O_constant && exp->X_op != O_symbol)
262078828Sobrien	{
262178828Sobrien	  /* Handle complex expressions.  */
262278828Sobrien	  sym = make_expr_symbol (exp);
262378828Sobrien	  off = 0;
262478828Sobrien	}
262578828Sobrien
262678828Sobrien      p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0);
262733965Sjdp      *p = fill;
262833965Sjdp    }
262933965Sjdp}
263033965Sjdp
263177298Sobrienvoid
2632130561Sobriens_org (int ignore ATTRIBUTE_UNUSED)
263333965Sjdp{
263433965Sjdp  register segT segment;
263533965Sjdp  expressionS exp;
263633965Sjdp  register long temp_fill;
263733965Sjdp
263860484Sobrien#ifdef md_flush_pending_output
263960484Sobrien  md_flush_pending_output ();
264060484Sobrien#endif
264160484Sobrien
264233965Sjdp  /* The m68k MRI assembler has a different meaning for .org.  It
264333965Sjdp     means to create an absolute section at a given address.  We can't
264433965Sjdp     support that--use a linker script instead.  */
264533965Sjdp  if (flag_m68k_mri)
264633965Sjdp    {
264760484Sobrien      as_bad (_("MRI style ORG pseudo-op not supported"));
264833965Sjdp      ignore_rest_of_line ();
264933965Sjdp      return;
265033965Sjdp    }
265133965Sjdp
265233965Sjdp  /* Don't believe the documentation of BSD 4.2 AS.  There is no such
265333965Sjdp     thing as a sub-segment-relative origin.  Any absolute origin is
265433965Sjdp     given a warning, then assumed to be segment-relative.  Any
265533965Sjdp     segmented origin expression ("foo+42") had better be in the right
265633965Sjdp     segment or the .org is ignored.
265733965Sjdp
265833965Sjdp     BSD 4.2 AS warns if you try to .org backwards. We cannot because
265933965Sjdp     we never know sub-segment sizes when we are reading code.  BSD
266033965Sjdp     will crash trying to emit negative numbers of filler bytes in
266133965Sjdp     certain .orgs. We don't crash, but see as-write for that code.
266233965Sjdp
266333965Sjdp     Don't make frag if need_pass_2==1.  */
266433965Sjdp  segment = get_known_segmented_expression (&exp);
266533965Sjdp  if (*input_line_pointer == ',')
266633965Sjdp    {
266733965Sjdp      input_line_pointer++;
266833965Sjdp      temp_fill = get_absolute_expression ();
266933965Sjdp    }
267033965Sjdp  else
267133965Sjdp    temp_fill = 0;
267233965Sjdp
267333965Sjdp  if (!need_pass_2)
267433965Sjdp    do_org (segment, &exp, temp_fill);
267533965Sjdp
267633965Sjdp  demand_empty_rest_of_line ();
267777298Sobrien}
267833965Sjdp
267933965Sjdp/* Handle parsing for the MRI SECT/SECTION pseudo-op.  This should be
268033965Sjdp   called by the obj-format routine which handles section changing
268133965Sjdp   when in MRI mode.  It will create a new section, and return it.  It
268233965Sjdp   will set *TYPE to the section type: one of 'C' (code), 'D' (data),
2683218822Sdim   'M' (mixed), or 'R' (romable).  The flags will be set in the section.  */
268433965Sjdp
268533965Sjdpvoid
2686130561Sobriens_mri_sect (char *type ATTRIBUTE_UNUSED)
268733965Sjdp{
268833965Sjdp#ifdef TC_M68K
268933965Sjdp
269033965Sjdp  char *name;
269133965Sjdp  char c;
269233965Sjdp  segT seg;
269333965Sjdp
269433965Sjdp  SKIP_WHITESPACE ();
269577298Sobrien
269633965Sjdp  name = input_line_pointer;
269789857Sobrien  if (!ISDIGIT (*name))
269833965Sjdp    c = get_symbol_end ();
269933965Sjdp  else
270033965Sjdp    {
270133965Sjdp      do
270233965Sjdp	{
270333965Sjdp	  ++input_line_pointer;
270433965Sjdp	}
270589857Sobrien      while (ISDIGIT (*input_line_pointer));
270677298Sobrien
270733965Sjdp      c = *input_line_pointer;
270833965Sjdp      *input_line_pointer = '\0';
270933965Sjdp    }
271033965Sjdp
271133965Sjdp  name = xstrdup (name);
271233965Sjdp
271333965Sjdp  *input_line_pointer = c;
271433965Sjdp
271533965Sjdp  seg = subseg_new (name, 0);
271633965Sjdp
271733965Sjdp  if (*input_line_pointer == ',')
271833965Sjdp    {
271933965Sjdp      int align;
272033965Sjdp
272133965Sjdp      ++input_line_pointer;
272233965Sjdp      align = get_absolute_expression ();
272333965Sjdp      record_alignment (seg, align);
272433965Sjdp    }
272533965Sjdp
272633965Sjdp  *type = 'C';
272733965Sjdp  if (*input_line_pointer == ',')
272833965Sjdp    {
272933965Sjdp      c = *++input_line_pointer;
273089857Sobrien      c = TOUPPER (c);
273133965Sjdp      if (c == 'C' || c == 'D' || c == 'M' || c == 'R')
273233965Sjdp	*type = c;
273333965Sjdp      else
273460484Sobrien	as_bad (_("unrecognized section type"));
273533965Sjdp      ++input_line_pointer;
273633965Sjdp
273733965Sjdp      {
273833965Sjdp	flagword flags;
273933965Sjdp
274033965Sjdp	flags = SEC_NO_FLAGS;
274133965Sjdp	if (*type == 'C')
274233965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE;
274333965Sjdp	else if (*type == 'D' || *type == 'M')
274433965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_DATA;
274533965Sjdp	else if (*type == 'R')
274633965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM;
274733965Sjdp	if (flags != SEC_NO_FLAGS)
274833965Sjdp	  {
274977298Sobrien	    if (!bfd_set_section_flags (stdoutput, seg, flags))
275060484Sobrien	      as_warn (_("error setting flags for \"%s\": %s"),
275133965Sjdp		       bfd_section_name (stdoutput, seg),
275233965Sjdp		       bfd_errmsg (bfd_get_error ()));
275333965Sjdp	  }
275433965Sjdp      }
275533965Sjdp    }
275633965Sjdp
275733965Sjdp  /* Ignore the HP type.  */
275833965Sjdp  if (*input_line_pointer == ',')
275933965Sjdp    input_line_pointer += 2;
276033965Sjdp
276133965Sjdp  demand_empty_rest_of_line ();
276233965Sjdp
276333965Sjdp#else /* ! TC_M68K */
276433965Sjdp#ifdef TC_I960
276533965Sjdp
276633965Sjdp  char *name;
276733965Sjdp  char c;
276833965Sjdp  segT seg;
276933965Sjdp
277033965Sjdp  SKIP_WHITESPACE ();
277133965Sjdp
277233965Sjdp  name = input_line_pointer;
277333965Sjdp  c = get_symbol_end ();
277433965Sjdp
277533965Sjdp  name = xstrdup (name);
277633965Sjdp
277733965Sjdp  *input_line_pointer = c;
277833965Sjdp
277933965Sjdp  seg = subseg_new (name, 0);
278033965Sjdp
278133965Sjdp  if (*input_line_pointer != ',')
278233965Sjdp    *type = 'C';
278333965Sjdp  else
278433965Sjdp    {
278533965Sjdp      char *sectype;
278633965Sjdp
278733965Sjdp      ++input_line_pointer;
278833965Sjdp      SKIP_WHITESPACE ();
278933965Sjdp      sectype = input_line_pointer;
279033965Sjdp      c = get_symbol_end ();
279133965Sjdp      if (*sectype == '\0')
279233965Sjdp	*type = 'C';
279333965Sjdp      else if (strcasecmp (sectype, "text") == 0)
279433965Sjdp	*type = 'C';
279533965Sjdp      else if (strcasecmp (sectype, "data") == 0)
279633965Sjdp	*type = 'D';
279733965Sjdp      else if (strcasecmp (sectype, "romdata") == 0)
279833965Sjdp	*type = 'R';
279933965Sjdp      else
280060484Sobrien	as_warn (_("unrecognized section type `%s'"), sectype);
280133965Sjdp      *input_line_pointer = c;
280233965Sjdp    }
280333965Sjdp
280433965Sjdp  if (*input_line_pointer == ',')
280533965Sjdp    {
280633965Sjdp      char *seccmd;
280733965Sjdp
280833965Sjdp      ++input_line_pointer;
280933965Sjdp      SKIP_WHITESPACE ();
281033965Sjdp      seccmd = input_line_pointer;
281133965Sjdp      c = get_symbol_end ();
281233965Sjdp      if (strcasecmp (seccmd, "absolute") == 0)
281333965Sjdp	{
281460484Sobrien	  as_bad (_("absolute sections are not supported"));
281533965Sjdp	  *input_line_pointer = c;
281633965Sjdp	  ignore_rest_of_line ();
281733965Sjdp	  return;
281833965Sjdp	}
281933965Sjdp      else if (strcasecmp (seccmd, "align") == 0)
282033965Sjdp	{
282133965Sjdp	  int align;
282233965Sjdp
282333965Sjdp	  *input_line_pointer = c;
282433965Sjdp	  align = get_absolute_expression ();
282533965Sjdp	  record_alignment (seg, align);
282633965Sjdp	}
282733965Sjdp      else
282833965Sjdp	{
282960484Sobrien	  as_warn (_("unrecognized section command `%s'"), seccmd);
283033965Sjdp	  *input_line_pointer = c;
283133965Sjdp	}
283233965Sjdp    }
283333965Sjdp
283477298Sobrien  demand_empty_rest_of_line ();
283533965Sjdp
283633965Sjdp#else /* ! TC_I960 */
283733965Sjdp  /* The MRI assembler seems to use different forms of .sect for
283833965Sjdp     different targets.  */
283960484Sobrien  as_bad ("MRI mode not supported for this target");
284060484Sobrien  ignore_rest_of_line ();
284133965Sjdp#endif /* ! TC_I960 */
284233965Sjdp#endif /* ! TC_M68K */
284333965Sjdp}
284433965Sjdp
284533965Sjdp/* Handle the .print pseudo-op.  */
284633965Sjdp
284733965Sjdpvoid
2848130561Sobriens_print (int ignore ATTRIBUTE_UNUSED)
284933965Sjdp{
285033965Sjdp  char *s;
285133965Sjdp  int len;
285233965Sjdp
285333965Sjdp  s = demand_copy_C_string (&len);
2854130561Sobrien  if (s != NULL)
2855130561Sobrien    printf ("%s\n", s);
285633965Sjdp  demand_empty_rest_of_line ();
285733965Sjdp}
285833965Sjdp
285933965Sjdp/* Handle the .purgem pseudo-op.  */
286033965Sjdp
286133965Sjdpvoid
2862130561Sobriens_purgem (int ignore ATTRIBUTE_UNUSED)
286333965Sjdp{
286433965Sjdp  if (is_it_end_of_statement ())
286533965Sjdp    {
286633965Sjdp      demand_empty_rest_of_line ();
286733965Sjdp      return;
286833965Sjdp    }
286933965Sjdp
287033965Sjdp  do
287133965Sjdp    {
287233965Sjdp      char *name;
287333965Sjdp      char c;
287433965Sjdp
287533965Sjdp      SKIP_WHITESPACE ();
287633965Sjdp      name = input_line_pointer;
287733965Sjdp      c = get_symbol_end ();
287833965Sjdp      delete_macro (name);
287933965Sjdp      *input_line_pointer = c;
288033965Sjdp      SKIP_WHITESPACE ();
288133965Sjdp    }
288233965Sjdp  while (*input_line_pointer++ == ',');
288333965Sjdp
288433965Sjdp  --input_line_pointer;
288533965Sjdp  demand_empty_rest_of_line ();
288633965Sjdp}
288733965Sjdp
2888218822Sdim/* Handle the .endm/.endr pseudo-ops.  */
288933965Sjdp
2890218822Sdimstatic void
2891218822Sdims_bad_end (int endr)
289289857Sobrien{
2893218822Sdim  as_warn (_(".end%c encountered without preceeding %s"),
2894218822Sdim	   endr ? 'r' : 'm',
2895218822Sdim	   endr ? ".rept, .irp, or .irpc" : ".macro");
289689857Sobrien  demand_empty_rest_of_line ();
289789857Sobrien}
289889857Sobrien
289989857Sobrien/* Handle the .rept pseudo-op.  */
290089857Sobrien
290189857Sobrienvoid
2902130561Sobriens_rept (int ignore ATTRIBUTE_UNUSED)
290333965Sjdp{
290433965Sjdp  int count;
290560484Sobrien
290660484Sobrien  count = get_absolute_expression ();
290760484Sobrien
290877298Sobrien  do_repeat (count, "REPT", "ENDR");
290960484Sobrien}
291060484Sobrien
291160484Sobrien/* This function provides a generic repeat block implementation.   It allows
291277298Sobrien   different directives to be used as the start/end keys.  */
291360484Sobrien
291460484Sobrienvoid
2915130561Sobriendo_repeat (int count, const char *start, const char *end)
291660484Sobrien{
291733965Sjdp  sb one;
291833965Sjdp  sb many;
291933965Sjdp
292033965Sjdp  sb_new (&one);
292177298Sobrien  if (!buffer_and_nest (start, end, &one, get_line_sb))
292233965Sjdp    {
292360484Sobrien      as_bad (_("%s without %s"), start, end);
292433965Sjdp      return;
292533965Sjdp    }
292633965Sjdp
292733965Sjdp  sb_new (&many);
292833965Sjdp  while (count-- > 0)
292933965Sjdp    sb_add_sb (&many, &one);
293033965Sjdp
293133965Sjdp  sb_kill (&one);
293233965Sjdp
293360484Sobrien  input_scrub_include_sb (&many, input_line_pointer, 1);
293433965Sjdp  sb_kill (&many);
293533965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
293633965Sjdp}
293733965Sjdp
293860484Sobrien/* Skip to end of current repeat loop; EXTRA indicates how many additional
293960484Sobrien   input buffers to skip.  Assumes that conditionals preceding the loop end
294077298Sobrien   are properly nested.
294160484Sobrien
294260484Sobrien   This function makes it easier to implement a premature "break" out of the
294360484Sobrien   loop.  The EXTRA arg accounts for other buffers we might have inserted,
294477298Sobrien   such as line substitutions.  */
294560484Sobrien
294660484Sobrienvoid
2947130561Sobrienend_repeat (int extra)
294860484Sobrien{
294960484Sobrien  cond_exit_macro (macro_nest);
295060484Sobrien  while (extra-- >= 0)
295160484Sobrien    buffer_limit = input_scrub_next_buffer (&input_line_pointer);
295260484Sobrien}
295360484Sobrien
2954218822Sdimstatic void
2955218822Sdimassign_symbol (char *name, int mode)
295633965Sjdp{
2957218822Sdim  symbolS *symbolP;
295833965Sjdp
295933965Sjdp  if (name[0] == '.' && name[1] == '\0')
296033965Sjdp    {
296177298Sobrien      /* Turn '. = mumble' into a .org mumble.  */
2962218822Sdim      segT segment;
296333965Sjdp      expressionS exp;
296433965Sjdp
296533965Sjdp      segment = get_known_segmented_expression (&exp);
296633965Sjdp
296733965Sjdp      if (!need_pass_2)
296833965Sjdp	do_org (segment, &exp, 0);
296933965Sjdp
297033965Sjdp      return;
297133965Sjdp    }
297233965Sjdp
297333965Sjdp  if ((symbolP = symbol_find (name)) == NULL
297433965Sjdp      && (symbolP = md_undefined_symbol (name)) == NULL)
297533965Sjdp    {
2976218822Sdim      symbolP = symbol_find_or_make (name);
297738889Sjdp#ifndef NO_LISTING
297838889Sjdp      /* When doing symbol listings, play games with dummy fragments living
297938889Sjdp	 outside the normal fragment chain to record the file and line info
2980130561Sobrien	 for this symbol.  */
298138889Sjdp      if (listing & LISTING_SYMBOLS)
298238889Sjdp	{
298338889Sjdp	  extern struct list_info_struct *listing_tail;
2984218822Sdim	  fragS *dummy_frag = (fragS *) xcalloc (1, sizeof (fragS));
298538889Sjdp	  dummy_frag->line = listing_tail;
298638889Sjdp	  dummy_frag->fr_symbol = symbolP;
2987218822Sdim	  symbol_set_frag (symbolP, dummy_frag);
298838889Sjdp	}
298938889Sjdp#endif
299033965Sjdp#ifdef OBJ_COFF
299177298Sobrien      /* "set" symbols are local unless otherwise specified.  */
299233965Sjdp      SF_SET_LOCAL (symbolP);
2993218822Sdim#endif
299477298Sobrien    }
299533965Sjdp
2996218822Sdim  if (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
2997218822Sdim    {
2998218822Sdim      /* Permit register names to be redefined.  */
2999218822Sdim      if ((mode != 0 || !S_IS_VOLATILE (symbolP))
3000218822Sdim	  && S_GET_SEGMENT (symbolP) != reg_section)
3001218822Sdim	{
3002218822Sdim	  as_bad (_("symbol `%s' is already defined"), name);
3003218822Sdim	  symbolP = symbol_clone (symbolP, 0);
3004218822Sdim	}
3005218822Sdim      /* If the symbol is volatile, copy the symbol and replace the
3006218822Sdim	 original with the copy, so that previous uses of the symbol will
3007218822Sdim	 retain the value of the symbol at the point of use.  */
3008218822Sdim      else if (S_IS_VOLATILE (symbolP))
3009218822Sdim	symbolP = symbol_clone (symbolP, 1);
3010218822Sdim    }
301133965Sjdp
3012218822Sdim  if (mode == 0)
3013218822Sdim    S_SET_VOLATILE (symbolP);
3014218822Sdim  else if (mode < 0)
3015218822Sdim    S_SET_FORWARD_REF (symbolP);
3016218822Sdim
3017218822Sdim  pseudo_set (symbolP);
3018218822Sdim}
3019218822Sdim
3020218822Sdim/* Handle the .equ, .equiv, .eqv, and .set directives.  If EQUIV is 1,
3021218822Sdim   then this is .equiv, and it is an error if the symbol is already
3022218822Sdim   defined.  If EQUIV is -1, the symbol additionally is a forward
3023218822Sdim   reference.  */
3024218822Sdim
3025218822Sdimvoid
3026218822Sdims_set (int equiv)
3027218822Sdim{
3028218822Sdim  char *name;
3029218822Sdim  char delim;
3030218822Sdim  char *end_name;
3031218822Sdim
3032218822Sdim  /* Especial apologies for the random logic:
3033218822Sdim     this just grew, and could be parsed much more simply!
3034218822Sdim     Dean in haste.  */
3035218822Sdim  name = input_line_pointer;
3036218822Sdim  delim = get_symbol_end ();
3037218822Sdim  end_name = input_line_pointer;
303833965Sjdp  *end_name = delim;
303933965Sjdp
3040218822Sdim  if (name == end_name)
3041218822Sdim    {
3042218822Sdim      as_bad (_("expected symbol name"));
3043218822Sdim      ignore_rest_of_line ();
3044218822Sdim      return;
3045218822Sdim    }
304633965Sjdp
3047218822Sdim  SKIP_WHITESPACE ();
3048218822Sdim
3049218822Sdim  if (*input_line_pointer != ',')
3050218822Sdim    {
3051218822Sdim      *end_name = 0;
3052218822Sdim      as_bad (_("expected comma after \"%s\""), name);
3053218822Sdim      *end_name = delim;
3054218822Sdim      ignore_rest_of_line ();
3055218822Sdim      return;
3056218822Sdim    }
3057218822Sdim
3058218822Sdim  input_line_pointer++;
3059218822Sdim  *end_name = 0;
3060218822Sdim
3061218822Sdim  assign_symbol (name, equiv);
3062218822Sdim  *end_name = delim;
3063218822Sdim
306433965Sjdp  demand_empty_rest_of_line ();
306577298Sobrien}
306633965Sjdp
306777298Sobrienvoid
3068130561Sobriens_space (int mult)
306933965Sjdp{
307033965Sjdp  expressionS exp;
307133965Sjdp  expressionS val;
307233965Sjdp  char *p = 0;
307333965Sjdp  char *stop = NULL;
3074218822Sdim  char stopc = 0;
307533965Sjdp  int bytes;
307633965Sjdp
307733965Sjdp#ifdef md_flush_pending_output
307833965Sjdp  md_flush_pending_output ();
307933965Sjdp#endif
308033965Sjdp
308133965Sjdp  if (flag_mri)
308233965Sjdp    stop = mri_comment_field (&stopc);
308333965Sjdp
308433965Sjdp  /* In m68k MRI mode, we need to align to a word boundary, unless
308533965Sjdp     this is ds.b.  */
308633965Sjdp  if (flag_m68k_mri && mult > 1)
308733965Sjdp    {
308833965Sjdp      if (now_seg == absolute_section)
308933965Sjdp	{
309033965Sjdp	  abs_section_offset += abs_section_offset & 1;
309133965Sjdp	  if (line_label != NULL)
309233965Sjdp	    S_SET_VALUE (line_label, abs_section_offset);
309333965Sjdp	}
309433965Sjdp      else if (mri_common_symbol != NULL)
309533965Sjdp	{
309633965Sjdp	  valueT val;
309733965Sjdp
309833965Sjdp	  val = S_GET_VALUE (mri_common_symbol);
309933965Sjdp	  if ((val & 1) != 0)
310033965Sjdp	    {
310133965Sjdp	      S_SET_VALUE (mri_common_symbol, val + 1);
310233965Sjdp	      if (line_label != NULL)
310333965Sjdp		{
310460484Sobrien		  expressionS *symexp;
310560484Sobrien
310660484Sobrien		  symexp = symbol_get_value_expression (line_label);
310760484Sobrien		  know (symexp->X_op == O_symbol);
310860484Sobrien		  know (symexp->X_add_symbol == mri_common_symbol);
310960484Sobrien		  symexp->X_add_number += 1;
311033965Sjdp		}
311133965Sjdp	    }
311233965Sjdp	}
311333965Sjdp      else
311433965Sjdp	{
311533965Sjdp	  do_align (1, (char *) NULL, 0, 0);
311633965Sjdp	  if (line_label != NULL)
311733965Sjdp	    {
311860484Sobrien	      symbol_set_frag (line_label, frag_now);
311933965Sjdp	      S_SET_VALUE (line_label, frag_now_fix ());
312033965Sjdp	    }
312133965Sjdp	}
312233965Sjdp    }
312333965Sjdp
312433965Sjdp  bytes = mult;
312533965Sjdp
312633965Sjdp  expression (&exp);
312733965Sjdp
312833965Sjdp  SKIP_WHITESPACE ();
312933965Sjdp  if (*input_line_pointer == ',')
313033965Sjdp    {
313133965Sjdp      ++input_line_pointer;
313233965Sjdp      expression (&val);
313333965Sjdp    }
313433965Sjdp  else
313533965Sjdp    {
313633965Sjdp      val.X_op = O_constant;
313733965Sjdp      val.X_add_number = 0;
313833965Sjdp    }
313933965Sjdp
314033965Sjdp  if (val.X_op != O_constant
314133965Sjdp      || val.X_add_number < - 0x80
314233965Sjdp      || val.X_add_number > 0xff
314333965Sjdp      || (mult != 0 && mult != 1 && val.X_add_number != 0))
314433965Sjdp    {
3145218822Sdim      resolve_expression (&exp);
314633965Sjdp      if (exp.X_op != O_constant)
314789857Sobrien	as_bad (_("unsupported variable size or fill value"));
314833965Sjdp      else
314933965Sjdp	{
315033965Sjdp	  offsetT i;
315133965Sjdp
315233965Sjdp	  if (mult == 0)
315333965Sjdp	    mult = 1;
315433965Sjdp	  bytes = mult * exp.X_add_number;
315533965Sjdp	  for (i = 0; i < exp.X_add_number; i++)
315633965Sjdp	    emit_expr (&val, mult);
315733965Sjdp	}
315833965Sjdp    }
315933965Sjdp  else
316033965Sjdp    {
3161218822Sdim      if (now_seg == absolute_section || mri_common_symbol != NULL)
3162218822Sdim	resolve_expression (&exp);
3163218822Sdim
316433965Sjdp      if (exp.X_op == O_constant)
316533965Sjdp	{
316633965Sjdp	  long repeat;
316733965Sjdp
316833965Sjdp	  repeat = exp.X_add_number;
316933965Sjdp	  if (mult)
317033965Sjdp	    repeat *= mult;
317133965Sjdp	  bytes = repeat;
317233965Sjdp	  if (repeat <= 0)
317333965Sjdp	    {
317477298Sobrien	      if (!flag_mri)
317560484Sobrien		as_warn (_(".space repeat count is zero, ignored"));
317660484Sobrien	      else if (repeat < 0)
317760484Sobrien		as_warn (_(".space repeat count is negative, ignored"));
317833965Sjdp	      goto getout;
317933965Sjdp	    }
318033965Sjdp
318133965Sjdp	  /* If we are in the absolute section, just bump the offset.  */
318233965Sjdp	  if (now_seg == absolute_section)
318333965Sjdp	    {
318433965Sjdp	      abs_section_offset += repeat;
318533965Sjdp	      goto getout;
318633965Sjdp	    }
318733965Sjdp
318833965Sjdp	  /* If we are secretly in an MRI common section, then
318933965Sjdp	     creating space just increases the size of the common
319033965Sjdp	     symbol.  */
319133965Sjdp	  if (mri_common_symbol != NULL)
319233965Sjdp	    {
319333965Sjdp	      S_SET_VALUE (mri_common_symbol,
319433965Sjdp			   S_GET_VALUE (mri_common_symbol) + repeat);
319533965Sjdp	      goto getout;
319633965Sjdp	    }
319733965Sjdp
319833965Sjdp	  if (!need_pass_2)
319933965Sjdp	    p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
320033965Sjdp			  (offsetT) repeat, (char *) 0);
320133965Sjdp	}
320233965Sjdp      else
320333965Sjdp	{
320433965Sjdp	  if (now_seg == absolute_section)
320533965Sjdp	    {
320660484Sobrien	      as_bad (_("space allocation too complex in absolute section"));
320733965Sjdp	      subseg_set (text_section, 0);
320833965Sjdp	    }
320977298Sobrien
321033965Sjdp	  if (mri_common_symbol != NULL)
321133965Sjdp	    {
321260484Sobrien	      as_bad (_("space allocation too complex in common section"));
321333965Sjdp	      mri_common_symbol = NULL;
321433965Sjdp	    }
321577298Sobrien
321633965Sjdp	  if (!need_pass_2)
321733965Sjdp	    p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
321833965Sjdp			  make_expr_symbol (&exp), (offsetT) 0, (char *) 0);
321933965Sjdp	}
322033965Sjdp
322133965Sjdp      if (p)
322233965Sjdp	*p = val.X_add_number;
322333965Sjdp    }
322433965Sjdp
322533965Sjdp getout:
322633965Sjdp
322733965Sjdp  /* In MRI mode, after an odd number of bytes, we must align to an
322833965Sjdp     even word boundary, unless the next instruction is a dc.b, ds.b
322933965Sjdp     or dcb.b.  */
323033965Sjdp  if (flag_mri && (bytes & 1) != 0)
323133965Sjdp    mri_pending_align = 1;
323233965Sjdp
323360484Sobrien  demand_empty_rest_of_line ();
323460484Sobrien
323533965Sjdp  if (flag_mri)
323633965Sjdp    mri_comment_end (stop, stopc);
323733965Sjdp}
323833965Sjdp
323933965Sjdp/* This is like s_space, but the value is a floating point number with
324033965Sjdp   the given precision.  This is for the MRI dcb.s pseudo-op and
324133965Sjdp   friends.  */
324233965Sjdp
324333965Sjdpvoid
3244130561Sobriens_float_space (int float_type)
324533965Sjdp{
324633965Sjdp  offsetT count;
324733965Sjdp  int flen;
324833965Sjdp  char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
324933965Sjdp  char *stop = NULL;
3250218822Sdim  char stopc = 0;
325133965Sjdp
325233965Sjdp  if (flag_mri)
325333965Sjdp    stop = mri_comment_field (&stopc);
325433965Sjdp
325533965Sjdp  count = get_absolute_expression ();
325633965Sjdp
325733965Sjdp  SKIP_WHITESPACE ();
325833965Sjdp  if (*input_line_pointer != ',')
325933965Sjdp    {
326060484Sobrien      as_bad (_("missing value"));
326160484Sobrien      ignore_rest_of_line ();
326233965Sjdp      if (flag_mri)
326333965Sjdp	mri_comment_end (stop, stopc);
326433965Sjdp      return;
326533965Sjdp    }
326633965Sjdp
326733965Sjdp  ++input_line_pointer;
326833965Sjdp
326933965Sjdp  SKIP_WHITESPACE ();
327033965Sjdp
327133965Sjdp  /* Skip any 0{letter} that may be present.  Don't even check if the
327233965Sjdp   * letter is legal.  */
327338889Sjdp  if (input_line_pointer[0] == '0'
327489857Sobrien      && ISALPHA (input_line_pointer[1]))
327533965Sjdp    input_line_pointer += 2;
327633965Sjdp
327733965Sjdp  /* Accept :xxxx, where the x's are hex digits, for a floating point
327833965Sjdp     with the exact digits specified.  */
327933965Sjdp  if (input_line_pointer[0] == ':')
328033965Sjdp    {
328133965Sjdp      flen = hex_float (float_type, temp);
328233965Sjdp      if (flen < 0)
328333965Sjdp	{
328460484Sobrien	  ignore_rest_of_line ();
328533965Sjdp	  if (flag_mri)
328633965Sjdp	    mri_comment_end (stop, stopc);
328733965Sjdp	  return;
328833965Sjdp	}
328933965Sjdp    }
329033965Sjdp  else
329133965Sjdp    {
329233965Sjdp      char *err;
329333965Sjdp
329433965Sjdp      err = md_atof (float_type, temp, &flen);
329533965Sjdp      know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
329633965Sjdp      know (flen > 0);
329733965Sjdp      if (err)
329833965Sjdp	{
329989857Sobrien	  as_bad (_("bad floating literal: %s"), err);
330060484Sobrien	  ignore_rest_of_line ();
330133965Sjdp	  if (flag_mri)
330233965Sjdp	    mri_comment_end (stop, stopc);
330333965Sjdp	  return;
330433965Sjdp	}
330533965Sjdp    }
330633965Sjdp
330733965Sjdp  while (--count >= 0)
330833965Sjdp    {
330933965Sjdp      char *p;
331033965Sjdp
331133965Sjdp      p = frag_more (flen);
331233965Sjdp      memcpy (p, temp, (unsigned int) flen);
331333965Sjdp    }
331433965Sjdp
331560484Sobrien  demand_empty_rest_of_line ();
331660484Sobrien
331733965Sjdp  if (flag_mri)
331833965Sjdp    mri_comment_end (stop, stopc);
331933965Sjdp}
332033965Sjdp
332133965Sjdp/* Handle the .struct pseudo-op, as found in MIPS assemblers.  */
332233965Sjdp
332333965Sjdpvoid
3324130561Sobriens_struct (int ignore ATTRIBUTE_UNUSED)
332533965Sjdp{
332633965Sjdp  char *stop = NULL;
3327218822Sdim  char stopc = 0;
332833965Sjdp
332933965Sjdp  if (flag_mri)
333033965Sjdp    stop = mri_comment_field (&stopc);
333133965Sjdp  abs_section_offset = get_absolute_expression ();
3332218822Sdim#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
3333218822Sdim  /* The ELF backend needs to know that we are changing sections, so
3334218822Sdim     that .previous works correctly. */
3335218822Sdim  if (IS_ELF)
3336218822Sdim    obj_elf_section_change_hook ();
3337218822Sdim#endif
333833965Sjdp  subseg_set (absolute_section, 0);
333960484Sobrien  demand_empty_rest_of_line ();
334033965Sjdp  if (flag_mri)
334133965Sjdp    mri_comment_end (stop, stopc);
334233965Sjdp}
334333965Sjdp
334433965Sjdpvoid
3345130561Sobriens_text (int ignore ATTRIBUTE_UNUSED)
334633965Sjdp{
334733965Sjdp  register int temp;
334833965Sjdp
334933965Sjdp  temp = get_absolute_expression ();
335033965Sjdp  subseg_set (text_section, (subsegT) temp);
335133965Sjdp  demand_empty_rest_of_line ();
335233965Sjdp#ifdef OBJ_VMS
335333965Sjdp  const_flag &= ~IN_DEFAULT_SECTION;
335433965Sjdp#endif
335577298Sobrien}
3356218822Sdim
3357218822Sdim/* .weakref x, y sets x as an alias to y that, as long as y is not
3358218822Sdim   referenced directly, will cause y to become a weak symbol.  */
3359218822Sdimvoid
3360218822Sdims_weakref (int ignore ATTRIBUTE_UNUSED)
3361218822Sdim{
3362218822Sdim  char *name;
3363218822Sdim  char delim;
3364218822Sdim  char *end_name;
3365218822Sdim  symbolS *symbolP;
3366218822Sdim  symbolS *symbolP2;
3367218822Sdim  expressionS exp;
3368218822Sdim
3369218822Sdim  name = input_line_pointer;
3370218822Sdim  delim = get_symbol_end ();
3371218822Sdim  end_name = input_line_pointer;
3372218822Sdim
3373218822Sdim  if (name == end_name)
3374218822Sdim    {
3375218822Sdim      as_bad (_("expected symbol name"));
3376218822Sdim      *end_name = delim;
3377218822Sdim      ignore_rest_of_line ();
3378218822Sdim      return;
3379218822Sdim    }
3380218822Sdim
3381218822Sdim  symbolP = symbol_find_or_make (name);
3382218822Sdim
3383218822Sdim  if (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
3384218822Sdim    {
3385218822Sdim      if (!S_IS_VOLATILE (symbolP))
3386218822Sdim	{
3387218822Sdim	  as_bad (_("symbol `%s' is already defined"), name);
3388218822Sdim	  *end_name = delim;
3389218822Sdim	  ignore_rest_of_line ();
3390218822Sdim	  return;
3391218822Sdim	}
3392218822Sdim      symbolP = symbol_clone (symbolP, 1);
3393218822Sdim      S_CLEAR_VOLATILE (symbolP);
3394218822Sdim    }
3395218822Sdim
3396218822Sdim  *end_name = delim;
3397218822Sdim
3398218822Sdim  SKIP_WHITESPACE ();
3399218822Sdim
3400218822Sdim  if (*input_line_pointer != ',')
3401218822Sdim    {
3402218822Sdim      *end_name = 0;
3403218822Sdim      as_bad (_("expected comma after \"%s\""), name);
3404218822Sdim      *end_name = delim;
3405218822Sdim      ignore_rest_of_line ();
3406218822Sdim      return;
3407218822Sdim    }
3408218822Sdim
3409218822Sdim  input_line_pointer++;
3410218822Sdim
3411218822Sdim  SKIP_WHITESPACE ();
3412218822Sdim
3413218822Sdim  name = input_line_pointer;
3414218822Sdim  delim = get_symbol_end ();
3415218822Sdim  end_name = input_line_pointer;
3416218822Sdim
3417218822Sdim  if (name == end_name)
3418218822Sdim    {
3419218822Sdim      as_bad (_("expected symbol name"));
3420218822Sdim      ignore_rest_of_line ();
3421218822Sdim      return;
3422218822Sdim    }
3423218822Sdim
3424218822Sdim  if ((symbolP2 = symbol_find_noref (name, 1)) == NULL
3425218822Sdim      && (symbolP2 = md_undefined_symbol (name)) == NULL)
3426218822Sdim    {
3427218822Sdim      symbolP2 = symbol_find_or_make (name);
3428218822Sdim      S_SET_WEAKREFD (symbolP2);
3429218822Sdim    }
3430218822Sdim  else
3431218822Sdim    {
3432218822Sdim      symbolS *symp = symbolP2;
3433218822Sdim
3434218822Sdim      while (S_IS_WEAKREFR (symp) && symp != symbolP)
3435218822Sdim	{
3436218822Sdim	  expressionS *expP = symbol_get_value_expression (symp);
3437218822Sdim
3438218822Sdim	  assert (expP->X_op == O_symbol
3439218822Sdim		  && expP->X_add_number == 0);
3440218822Sdim	  symp = expP->X_add_symbol;
3441218822Sdim	}
3442218822Sdim      if (symp == symbolP)
3443218822Sdim	{
3444218822Sdim	  char *loop;
3445218822Sdim
3446218822Sdim	  loop = concat (S_GET_NAME (symbolP),
3447218822Sdim			 " => ", S_GET_NAME (symbolP2), NULL);
3448218822Sdim
3449218822Sdim	  symp = symbolP2;
3450218822Sdim	  while (symp != symbolP)
3451218822Sdim	    {
3452218822Sdim	      char *old_loop = loop;
3453218822Sdim	      symp = symbol_get_value_expression (symp)->X_add_symbol;
3454218822Sdim	      loop = concat (loop, " => ", S_GET_NAME (symp), NULL);
3455218822Sdim	      free (old_loop);
3456218822Sdim	    }
3457218822Sdim
3458218822Sdim	  as_bad (_("%s: would close weakref loop: %s"),
3459218822Sdim		  S_GET_NAME (symbolP), loop);
3460218822Sdim
3461218822Sdim	  free (loop);
3462218822Sdim
3463218822Sdim	  *end_name = delim;
3464218822Sdim	  ignore_rest_of_line ();
3465218822Sdim	  return;
3466218822Sdim	}
3467218822Sdim
3468218822Sdim      /* Short-circuiting instead of just checking here might speed
3469218822Sdim	 things up a tiny little bit, but loop error messages would
3470218822Sdim	 miss intermediate links.  */
3471218822Sdim      /* symbolP2 = symp; */
3472218822Sdim    }
3473218822Sdim
3474218822Sdim  *end_name = delim;
3475218822Sdim
3476218822Sdim  memset (&exp, 0, sizeof (exp));
3477218822Sdim  exp.X_op = O_symbol;
3478218822Sdim  exp.X_add_symbol = symbolP2;
3479218822Sdim
3480218822Sdim  S_SET_SEGMENT (symbolP, undefined_section);
3481218822Sdim  symbol_set_value_expression (symbolP, &exp);
3482218822Sdim  symbol_set_frag (symbolP, &zero_address_frag);
3483218822Sdim  S_SET_WEAKREFR (symbolP);
3484218822Sdim
3485218822Sdim  demand_empty_rest_of_line ();
3486218822Sdim}
348733965Sjdp
3488130561Sobrien
3489130561Sobrien/* Verify that we are at the end of a line.  If not, issue an error and
3490130561Sobrien   skip to EOL.  */
3491130561Sobrien
349277298Sobrienvoid
3493130561Sobriendemand_empty_rest_of_line (void)
349433965Sjdp{
349533965Sjdp  SKIP_WHITESPACE ();
349633965Sjdp  if (is_end_of_line[(unsigned char) *input_line_pointer])
349777298Sobrien    input_line_pointer++;
349833965Sjdp  else
349933965Sjdp    {
350089857Sobrien      if (ISPRINT (*input_line_pointer))
3501130561Sobrien	as_bad (_("junk at end of line, first unrecognized character is `%c'"),
350289857Sobrien		 *input_line_pointer);
350333965Sjdp      else
3504130561Sobrien	as_bad (_("junk at end of line, first unrecognized character valued 0x%x"),
350589857Sobrien		 *input_line_pointer);
3506130561Sobrien      ignore_rest_of_line ();
350733965Sjdp    }
3508130561Sobrien
3509130561Sobrien  /* Return pointing just after end-of-line.  */
3510130561Sobrien  know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
3511130561Sobrien}
351277298Sobrien
3513130561Sobrien/* Silently advance to the end of line.  Use this after already having
3514130561Sobrien   issued an error about something bad.  */
3515130561Sobrien
3516130561Sobrienvoid
3517130561Sobrienignore_rest_of_line (void)
3518130561Sobrien{
3519130561Sobrien  while (input_line_pointer < buffer_limit
3520130561Sobrien	 && !is_end_of_line[(unsigned char) *input_line_pointer])
3521130561Sobrien    input_line_pointer++;
3522130561Sobrien
352377298Sobrien  input_line_pointer++;
352477298Sobrien
352577298Sobrien  /* Return pointing just after end-of-line.  */
352633965Sjdp  know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
352733965Sjdp}
352833965Sjdp
3529218822Sdim/* Sets frag for given symbol to zero_address_frag, except when the
3530218822Sdim   symbol frag is already set to a dummy listing frag.  */
3531218822Sdim
3532218822Sdimstatic void
3533218822Sdimset_zero_frag (symbolS *symbolP)
353460484Sobrien{
3535218822Sdim  if (symbol_get_frag (symbolP)->fr_type != rs_dummy)
3536218822Sdim    symbol_set_frag (symbolP, &zero_address_frag);
353760484Sobrien}
353860484Sobrien
353977298Sobrien/* In:	Pointer to a symbol.
3540130561Sobrien	Input_line_pointer->expression.
354177298Sobrien
354277298Sobrien   Out:	Input_line_pointer->just after any whitespace after expression.
3543130561Sobrien	Tried to set symbol to value of expression.
3544130561Sobrien	Will change symbols type, value, and frag;  */
354577298Sobrien
354633965Sjdpvoid
3547130561Sobrienpseudo_set (symbolS *symbolP)
354833965Sjdp{
354933965Sjdp  expressionS exp;
3550218822Sdim  segT seg;
355133965Sjdp
355277298Sobrien  know (symbolP);		/* NULL pointer is logic error.  */
355333965Sjdp
3554218822Sdim  if (!S_IS_FORWARD_REF (symbolP))
3555218822Sdim    (void) expression (&exp);
3556218822Sdim  else
3557218822Sdim    (void) deferred_expression (&exp);
355833965Sjdp
355933965Sjdp  if (exp.X_op == O_illegal)
356089857Sobrien    as_bad (_("illegal expression"));
356133965Sjdp  else if (exp.X_op == O_absent)
356289857Sobrien    as_bad (_("missing expression"));
356333965Sjdp  else if (exp.X_op == O_big)
356460484Sobrien    {
356560484Sobrien      if (exp.X_add_number > 0)
356689857Sobrien	as_bad (_("bignum invalid"));
356760484Sobrien      else
356889857Sobrien	as_bad (_("floating point number invalid"));
356960484Sobrien    }
357033965Sjdp  else if (exp.X_op == O_subtract
3571218822Sdim	   && !S_IS_FORWARD_REF (symbolP)
357233965Sjdp	   && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol))
357360484Sobrien	   && (symbol_get_frag (exp.X_add_symbol)
357460484Sobrien	       == symbol_get_frag (exp.X_op_symbol)))
357533965Sjdp    {
357633965Sjdp      exp.X_op = O_constant;
357733965Sjdp      exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol)
357833965Sjdp			  - S_GET_VALUE (exp.X_op_symbol));
357933965Sjdp    }
358033965Sjdp
3581218822Sdim  if (symbol_section_p (symbolP))
3582218822Sdim    {
3583218822Sdim      as_bad ("attempt to set value of section symbol");
3584218822Sdim      return;
3585218822Sdim    }
3586218822Sdim
358733965Sjdp  switch (exp.X_op)
358833965Sjdp    {
358933965Sjdp    case O_illegal:
359033965Sjdp    case O_absent:
359133965Sjdp    case O_big:
359233965Sjdp      exp.X_add_number = 0;
359333965Sjdp      /* Fall through.  */
359433965Sjdp    case O_constant:
359533965Sjdp      S_SET_SEGMENT (symbolP, absolute_section);
359633965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
3597218822Sdim      set_zero_frag (symbolP);
359833965Sjdp      break;
359933965Sjdp
360033965Sjdp    case O_register:
360133965Sjdp      S_SET_SEGMENT (symbolP, reg_section);
360233965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
3603218822Sdim      set_zero_frag (symbolP);
3604218822Sdim      symbol_get_value_expression (symbolP)->X_op = O_register;
360533965Sjdp      break;
360633965Sjdp
360733965Sjdp    case O_symbol:
3608218822Sdim      seg = S_GET_SEGMENT (exp.X_add_symbol);
3609218822Sdim      /* For x=undef+const, create an expression symbol.
3610218822Sdim	 For x=x+const, just update x except when x is an undefined symbol
3611218822Sdim	 For x=defined+const, evaluate x.  */
3612218822Sdim      if (symbolP == exp.X_add_symbol
3613218822Sdim	  && (seg != undefined_section
3614218822Sdim	      || !symbol_constant_p (symbolP)))
361533965Sjdp	{
3616218822Sdim	  *symbol_X_add_number (symbolP) += exp.X_add_number;
3617218822Sdim	  break;
3618218822Sdim	}
3619218822Sdim      else if (!S_IS_FORWARD_REF (symbolP) && seg != undefined_section)
3620218822Sdim	{
362133965Sjdp	  symbolS *s = exp.X_add_symbol;
362233965Sjdp
3623218822Sdim	  if (S_IS_COMMON (s))
3624218822Sdim	    as_bad (_("`%s' can't be equated to common symbol '%s'"),
3625218822Sdim		    S_GET_NAME (symbolP), S_GET_NAME (s));
3626218822Sdim
3627218822Sdim	  S_SET_SEGMENT (symbolP, seg);
3628218822Sdim	  S_SET_VALUE (symbolP, exp.X_add_number + S_GET_VALUE (s));
362960484Sobrien	  symbol_set_frag (symbolP, symbol_get_frag (s));
363033965Sjdp	  copy_symbol_attributes (symbolP, s);
3631218822Sdim	  break;
363233965Sjdp	}
3633218822Sdim      S_SET_SEGMENT (symbolP, undefined_section);
3634218822Sdim      symbol_set_value_expression (symbolP, &exp);
3635218822Sdim      set_zero_frag (symbolP);
363633965Sjdp      break;
363733965Sjdp
363833965Sjdp    default:
3639218822Sdim      /* The value is some complex expression.  */
3640218822Sdim      S_SET_SEGMENT (symbolP, expr_section);
364160484Sobrien      symbol_set_value_expression (symbolP, &exp);
3642218822Sdim      set_zero_frag (symbolP);
364333965Sjdp      break;
364433965Sjdp    }
364533965Sjdp}
364633965Sjdp
3647130561Sobrien/*			cons()
364833965Sjdp
364977298Sobrien   CONStruct more frag of .bytes, or .words etc.
365077298Sobrien   Should need_pass_2 be 1 then emit no frag(s).
365177298Sobrien   This understands EXPRESSIONS.
365277298Sobrien
365377298Sobrien   Bug (?)
365477298Sobrien
365577298Sobrien   This has a split personality. We use expression() to read the
365677298Sobrien   value. We can detect if the value won't fit in a byte or word.
365777298Sobrien   But we can't detect if expression() discarded significant digits
365877298Sobrien   in the case of a long. Not worth the crocks required to fix it.  */
365977298Sobrien
366033965Sjdp/* Select a parser for cons expressions.  */
366133965Sjdp
366233965Sjdp/* Some targets need to parse the expression in various fancy ways.
366333965Sjdp   You can define TC_PARSE_CONS_EXPRESSION to do whatever you like
366433965Sjdp   (for example, the HPPA does this).  Otherwise, you can define
366533965Sjdp   BITFIELD_CONS_EXPRESSIONS to permit bitfields to be specified, or
366633965Sjdp   REPEAT_CONS_EXPRESSIONS to permit repeat counts.  If none of these
366733965Sjdp   are defined, which is the normal case, then only simple expressions
366833965Sjdp   are permitted.  */
366933965Sjdp
367060484Sobrien#ifdef TC_M68K
367133965Sjdpstatic void
3672130561Sobrienparse_mri_cons (expressionS *exp, unsigned int nbytes);
367360484Sobrien#endif
367433965Sjdp
367533965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION
367633965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS
367733965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES)
367877298Sobrienstatic void
3679130561Sobrienparse_bitfield_cons (expressionS *exp, unsigned int nbytes);
368033965Sjdp#endif
368133965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
368233965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES)
368333965Sjdpstatic void
3684130561Sobrienparse_repeat_cons (expressionS *exp, unsigned int nbytes);
368533965Sjdp#endif
368633965Sjdp
368733965Sjdp/* If we haven't gotten one yet, just call expression.  */
368833965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION
368933965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP)
369033965Sjdp#endif
369133965Sjdp#endif
369233965Sjdp
3693130561Sobrienvoid
3694130561Sobriendo_parse_cons_expression (expressionS *exp,
3695130561Sobrien			  int nbytes ATTRIBUTE_UNUSED)
3696130561Sobrien{
3697130561Sobrien  TC_PARSE_CONS_EXPRESSION (exp, nbytes);
3698130561Sobrien}
3699130561Sobrien
3700130561Sobrien
370177298Sobrien/* Worker to do .byte etc statements.
370277298Sobrien   Clobbers input_line_pointer and checks end-of-line.  */
370377298Sobrien
370477298Sobrienstatic void
3705130561Sobriencons_worker (register int nbytes,	/* 1=.byte, 2=.word, 4=.long.  */
3706130561Sobrien	     int rva)
370733965Sjdp{
370833965Sjdp  int c;
370933965Sjdp  expressionS exp;
371033965Sjdp  char *stop = NULL;
3711218822Sdim  char stopc = 0;
371233965Sjdp
371333965Sjdp#ifdef md_flush_pending_output
371433965Sjdp  md_flush_pending_output ();
371533965Sjdp#endif
371633965Sjdp
371733965Sjdp  if (flag_mri)
371833965Sjdp    stop = mri_comment_field (&stopc);
371933965Sjdp
372033965Sjdp  if (is_it_end_of_statement ())
372133965Sjdp    {
372260484Sobrien      demand_empty_rest_of_line ();
372333965Sjdp      if (flag_mri)
372433965Sjdp	mri_comment_end (stop, stopc);
372533965Sjdp      return;
372633965Sjdp    }
372733965Sjdp
3728218822Sdim#ifdef TC_ADDRESS_BYTES
3729218822Sdim  if (nbytes == 0)
3730218822Sdim    nbytes = TC_ADDRESS_BYTES ();
3731218822Sdim#endif
3732218822Sdim
373333965Sjdp#ifdef md_cons_align
373433965Sjdp  md_cons_align (nbytes);
373533965Sjdp#endif
373633965Sjdp
373733965Sjdp  c = 0;
373833965Sjdp  do
373933965Sjdp    {
374060484Sobrien#ifdef TC_M68K
374133965Sjdp      if (flag_m68k_mri)
374233965Sjdp	parse_mri_cons (&exp, (unsigned int) nbytes);
374333965Sjdp      else
374460484Sobrien#endif
374533965Sjdp	TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
374633965Sjdp
374733965Sjdp      if (rva)
374833965Sjdp	{
374933965Sjdp	  if (exp.X_op == O_symbol)
375033965Sjdp	    exp.X_op = O_symbol_rva;
375133965Sjdp	  else
375260484Sobrien	    as_fatal (_("rva without symbol"));
375333965Sjdp	}
375433965Sjdp      emit_expr (&exp, (unsigned int) nbytes);
375533965Sjdp      ++c;
375633965Sjdp    }
375733965Sjdp  while (*input_line_pointer++ == ',');
375833965Sjdp
375933965Sjdp  /* In MRI mode, after an odd number of bytes, we must align to an
376033965Sjdp     even word boundary, unless the next instruction is a dc.b, ds.b
376133965Sjdp     or dcb.b.  */
376233965Sjdp  if (flag_mri && nbytes == 1 && (c & 1) != 0)
376333965Sjdp    mri_pending_align = 1;
376433965Sjdp
376577298Sobrien  input_line_pointer--;		/* Put terminator back into stream.  */
376633965Sjdp
376760484Sobrien  demand_empty_rest_of_line ();
376860484Sobrien
376933965Sjdp  if (flag_mri)
377033965Sjdp    mri_comment_end (stop, stopc);
377133965Sjdp}
377233965Sjdp
377333965Sjdpvoid
3774130561Sobriencons (int size)
377533965Sjdp{
377633965Sjdp  cons_worker (size, 0);
377733965Sjdp}
377833965Sjdp
377977298Sobrienvoid
3780130561Sobriens_rva (int size)
378133965Sjdp{
378233965Sjdp  cons_worker (size, 1);
378333965Sjdp}
378433965Sjdp
3785218822Sdim/* .reloc offset, reloc_name, symbol+addend.  */
3786218822Sdim
3787218822Sdimvoid
3788218822Sdims_reloc (int ignore ATTRIBUTE_UNUSED)
3789218822Sdim{
3790218822Sdim  char *stop = NULL;
3791218822Sdim  char stopc = 0;
3792218822Sdim  expressionS exp;
3793218822Sdim  char *r_name;
3794218822Sdim  int c;
3795218822Sdim  struct reloc_list *reloc;
3796218822Sdim
3797218822Sdim  reloc = xmalloc (sizeof (*reloc));
3798218822Sdim
3799218822Sdim  if (flag_mri)
3800218822Sdim    stop = mri_comment_field (&stopc);
3801218822Sdim
3802218822Sdim  expression (&exp);
3803218822Sdim  switch (exp.X_op)
3804218822Sdim    {
3805218822Sdim    case O_illegal:
3806218822Sdim    case O_absent:
3807218822Sdim    case O_big:
3808218822Sdim    case O_register:
3809218822Sdim      as_bad (_("missing or bad offset expression"));
3810218822Sdim      goto err_out;
3811218822Sdim    case O_constant:
3812218822Sdim      exp.X_add_symbol = section_symbol (now_seg);
3813218822Sdim      exp.X_op = O_symbol;
3814218822Sdim      /* Fall thru */
3815218822Sdim    case O_symbol:
3816218822Sdim      if (exp.X_add_number == 0)
3817218822Sdim	{
3818218822Sdim	  reloc->u.a.offset_sym = exp.X_add_symbol;
3819218822Sdim	  break;
3820218822Sdim	}
3821218822Sdim      /* Fall thru */
3822218822Sdim    default:
3823218822Sdim      reloc->u.a.offset_sym = make_expr_symbol (&exp);
3824218822Sdim      break;
3825218822Sdim    }
3826218822Sdim
3827218822Sdim  SKIP_WHITESPACE ();
3828218822Sdim  if (*input_line_pointer != ',')
3829218822Sdim    {
3830218822Sdim      as_bad (_("missing reloc type"));
3831218822Sdim      goto err_out;
3832218822Sdim    }
3833218822Sdim
3834218822Sdim  ++input_line_pointer;
3835218822Sdim  SKIP_WHITESPACE ();
3836218822Sdim  r_name = input_line_pointer;
3837218822Sdim  c = get_symbol_end ();
3838218822Sdim  reloc->u.a.howto = bfd_reloc_name_lookup (stdoutput, r_name);
3839218822Sdim  *input_line_pointer = c;
3840218822Sdim  if (reloc->u.a.howto == NULL)
3841218822Sdim    {
3842218822Sdim      as_bad (_("unrecognized reloc type"));
3843218822Sdim      goto err_out;
3844218822Sdim    }
3845218822Sdim
3846218822Sdim  exp.X_op = O_absent;
3847218822Sdim  SKIP_WHITESPACE ();
3848218822Sdim  if (*input_line_pointer == ',')
3849218822Sdim    {
3850218822Sdim      ++input_line_pointer;
3851218822Sdim      expression_and_evaluate (&exp);
3852218822Sdim    }
3853218822Sdim  switch (exp.X_op)
3854218822Sdim    {
3855218822Sdim    case O_illegal:
3856218822Sdim    case O_big:
3857218822Sdim    case O_register:
3858218822Sdim      as_bad (_("bad reloc expression"));
3859218822Sdim    err_out:
3860218822Sdim      ignore_rest_of_line ();
3861218822Sdim      free (reloc);
3862218822Sdim      if (flag_mri)
3863218822Sdim	mri_comment_end (stop, stopc);
3864218822Sdim      return;
3865218822Sdim    case O_absent:
3866218822Sdim      reloc->u.a.sym = NULL;
3867218822Sdim      reloc->u.a.addend = 0;
3868218822Sdim      break;
3869218822Sdim    case O_constant:
3870218822Sdim      reloc->u.a.sym = NULL;
3871218822Sdim      reloc->u.a.addend = exp.X_add_number;
3872218822Sdim      break;
3873218822Sdim    case O_symbol:
3874218822Sdim      reloc->u.a.sym = exp.X_add_symbol;
3875218822Sdim      reloc->u.a.addend = exp.X_add_number;
3876218822Sdim      break;
3877218822Sdim    default:
3878218822Sdim      reloc->u.a.sym = make_expr_symbol (&exp);
3879218822Sdim      reloc->u.a.addend = 0;
3880218822Sdim      break;
3881218822Sdim    }
3882218822Sdim
3883218822Sdim  as_where (&reloc->file, &reloc->line);
3884218822Sdim  reloc->next = reloc_list;
3885218822Sdim  reloc_list = reloc;
3886218822Sdim
3887218822Sdim  demand_empty_rest_of_line ();
3888218822Sdim  if (flag_mri)
3889218822Sdim    mri_comment_end (stop, stopc);
3890218822Sdim}
3891218822Sdim
389233965Sjdp/* Put the contents of expression EXP into the object file using
389333965Sjdp   NBYTES bytes.  If need_pass_2 is 1, this does nothing.  */
389433965Sjdp
389533965Sjdpvoid
3896130561Sobrienemit_expr (expressionS *exp, unsigned int nbytes)
389733965Sjdp{
389833965Sjdp  operatorT op;
389933965Sjdp  register char *p;
390033965Sjdp  valueT extra_digit = 0;
390133965Sjdp
390233965Sjdp  /* Don't do anything if we are going to make another pass.  */
390333965Sjdp  if (need_pass_2)
390433965Sjdp    return;
390533965Sjdp
3906130561Sobrien  dot_value = frag_now_fix ();
3907130561Sobrien
390838889Sjdp#ifndef NO_LISTING
390938889Sjdp#ifdef OBJ_ELF
391038889Sjdp  /* When gcc emits DWARF 1 debugging pseudo-ops, a line number will
391138889Sjdp     appear as a four byte positive constant in the .line section,
391238889Sjdp     followed by a 2 byte 0xffff.  Look for that case here.  */
391338889Sjdp  {
391438889Sjdp    static int dwarf_line = -1;
391538889Sjdp
391638889Sjdp    if (strcmp (segment_name (now_seg), ".line") != 0)
391738889Sjdp      dwarf_line = -1;
391838889Sjdp    else if (dwarf_line >= 0
391938889Sjdp	     && nbytes == 2
392038889Sjdp	     && exp->X_op == O_constant
392138889Sjdp	     && (exp->X_add_number == -1 || exp->X_add_number == 0xffff))
392238889Sjdp      listing_source_line ((unsigned int) dwarf_line);
392338889Sjdp    else if (nbytes == 4
392438889Sjdp	     && exp->X_op == O_constant
392538889Sjdp	     && exp->X_add_number >= 0)
392638889Sjdp      dwarf_line = exp->X_add_number;
392738889Sjdp    else
392838889Sjdp      dwarf_line = -1;
392938889Sjdp  }
393038889Sjdp
393138889Sjdp  /* When gcc emits DWARF 1 debugging pseudo-ops, a file name will
393238889Sjdp     appear as a 2 byte TAG_compile_unit (0x11) followed by a 2 byte
393338889Sjdp     AT_sibling (0x12) followed by a four byte address of the sibling
393438889Sjdp     followed by a 2 byte AT_name (0x38) followed by the name of the
393538889Sjdp     file.  We look for that case here.  */
393638889Sjdp  {
393738889Sjdp    static int dwarf_file = 0;
393838889Sjdp
393938889Sjdp    if (strcmp (segment_name (now_seg), ".debug") != 0)
394038889Sjdp      dwarf_file = 0;
394138889Sjdp    else if (dwarf_file == 0
394238889Sjdp	     && nbytes == 2
394338889Sjdp	     && exp->X_op == O_constant
394438889Sjdp	     && exp->X_add_number == 0x11)
394538889Sjdp      dwarf_file = 1;
394638889Sjdp    else if (dwarf_file == 1
394738889Sjdp	     && nbytes == 2
394838889Sjdp	     && exp->X_op == O_constant
394938889Sjdp	     && exp->X_add_number == 0x12)
395038889Sjdp      dwarf_file = 2;
395138889Sjdp    else if (dwarf_file == 2
395238889Sjdp	     && nbytes == 4)
395338889Sjdp      dwarf_file = 3;
395438889Sjdp    else if (dwarf_file == 3
395538889Sjdp	     && nbytes == 2
395638889Sjdp	     && exp->X_op == O_constant
395738889Sjdp	     && exp->X_add_number == 0x38)
395838889Sjdp      dwarf_file = 4;
395938889Sjdp    else
396038889Sjdp      dwarf_file = 0;
396138889Sjdp
396238889Sjdp    /* The variable dwarf_file_string tells stringer that the string
396338889Sjdp       may be the name of the source file.  */
396438889Sjdp    if (dwarf_file == 4)
396538889Sjdp      dwarf_file_string = 1;
396638889Sjdp    else
396738889Sjdp      dwarf_file_string = 0;
396838889Sjdp  }
396938889Sjdp#endif
397038889Sjdp#endif
397138889Sjdp
397238889Sjdp  if (check_eh_frame (exp, &nbytes))
397338889Sjdp    return;
397438889Sjdp
397533965Sjdp  op = exp->X_op;
397633965Sjdp
397733965Sjdp  /* Allow `.word 0' in the absolute section.  */
397833965Sjdp  if (now_seg == absolute_section)
397933965Sjdp    {
398033965Sjdp      if (op != O_constant || exp->X_add_number != 0)
398160484Sobrien	as_bad (_("attempt to store value in absolute section"));
398233965Sjdp      abs_section_offset += nbytes;
398333965Sjdp      return;
398433965Sjdp    }
398533965Sjdp
398633965Sjdp  /* Handle a negative bignum.  */
398733965Sjdp  if (op == O_uminus
398833965Sjdp      && exp->X_add_number == 0
398960484Sobrien      && symbol_get_value_expression (exp->X_add_symbol)->X_op == O_big
399060484Sobrien      && symbol_get_value_expression (exp->X_add_symbol)->X_add_number > 0)
399133965Sjdp    {
399233965Sjdp      int i;
399333965Sjdp      unsigned long carry;
399433965Sjdp
399560484Sobrien      exp = symbol_get_value_expression (exp->X_add_symbol);
399633965Sjdp
399733965Sjdp      /* Negate the bignum: one's complement each digit and add 1.  */
399833965Sjdp      carry = 1;
399933965Sjdp      for (i = 0; i < exp->X_add_number; i++)
400033965Sjdp	{
400133965Sjdp	  unsigned long next;
400233965Sjdp
400377298Sobrien	  next = (((~(generic_bignum[i] & LITTLENUM_MASK))
400433965Sjdp		   & LITTLENUM_MASK)
400533965Sjdp		  + carry);
400633965Sjdp	  generic_bignum[i] = next & LITTLENUM_MASK;
400733965Sjdp	  carry = next >> LITTLENUM_NUMBER_OF_BITS;
400833965Sjdp	}
400933965Sjdp
401033965Sjdp      /* We can ignore any carry out, because it will be handled by
401133965Sjdp	 extra_digit if it is needed.  */
401233965Sjdp
401333965Sjdp      extra_digit = (valueT) -1;
401433965Sjdp      op = O_big;
401533965Sjdp    }
401633965Sjdp
401733965Sjdp  if (op == O_absent || op == O_illegal)
401833965Sjdp    {
401960484Sobrien      as_warn (_("zero assumed for missing expression"));
402033965Sjdp      exp->X_add_number = 0;
402133965Sjdp      op = O_constant;
402233965Sjdp    }
402333965Sjdp  else if (op == O_big && exp->X_add_number <= 0)
402433965Sjdp    {
402589857Sobrien      as_bad (_("floating point number invalid"));
402633965Sjdp      exp->X_add_number = 0;
402733965Sjdp      op = O_constant;
402833965Sjdp    }
402933965Sjdp  else if (op == O_register)
403033965Sjdp    {
403160484Sobrien      as_warn (_("register value used as expression"));
403233965Sjdp      op = O_constant;
403333965Sjdp    }
403433965Sjdp
403533965Sjdp  p = frag_more ((int) nbytes);
403633965Sjdp
403733965Sjdp#ifndef WORKING_DOT_WORD
403833965Sjdp  /* If we have the difference of two symbols in a word, save it on
403933965Sjdp     the broken_words list.  See the code in write.c.  */
404033965Sjdp  if (op == O_subtract && nbytes == 2)
404133965Sjdp    {
404233965Sjdp      struct broken_word *x;
404333965Sjdp
404433965Sjdp      x = (struct broken_word *) xmalloc (sizeof (struct broken_word));
404533965Sjdp      x->next_broken_word = broken_words;
404633965Sjdp      broken_words = x;
404760484Sobrien      x->seg = now_seg;
404860484Sobrien      x->subseg = now_subseg;
404933965Sjdp      x->frag = frag_now;
405033965Sjdp      x->word_goes_here = p;
405133965Sjdp      x->dispfrag = 0;
405233965Sjdp      x->add = exp->X_add_symbol;
405333965Sjdp      x->sub = exp->X_op_symbol;
405433965Sjdp      x->addnum = exp->X_add_number;
405533965Sjdp      x->added = 0;
4056130561Sobrien      x->use_jump = 0;
405733965Sjdp      new_broken_words++;
405833965Sjdp      return;
405933965Sjdp    }
406033965Sjdp#endif
406133965Sjdp
406233965Sjdp  /* If we have an integer, but the number of bytes is too large to
406333965Sjdp     pass to md_number_to_chars, handle it as a bignum.  */
406433965Sjdp  if (op == O_constant && nbytes > sizeof (valueT))
406533965Sjdp    {
4066218822Sdim      extra_digit = exp->X_unsigned ? 0 : -1;
4067218822Sdim      convert_to_bignum (exp);
4068218822Sdim      op = O_big;
406933965Sjdp    }
407033965Sjdp
407133965Sjdp  if (op == O_constant)
407233965Sjdp    {
407333965Sjdp      register valueT get;
407433965Sjdp      register valueT use;
407533965Sjdp      register valueT mask;
407633965Sjdp      valueT hibit;
407733965Sjdp      register valueT unmask;
407833965Sjdp
407933965Sjdp      /* JF << of >= number of bits in the object is undefined.  In
408077298Sobrien	 particular SPARC (Sun 4) has problems.  */
408133965Sjdp      if (nbytes >= sizeof (valueT))
408233965Sjdp	{
408333965Sjdp	  mask = 0;
408433965Sjdp	  if (nbytes > sizeof (valueT))
408533965Sjdp	    hibit = 0;
408633965Sjdp	  else
408733965Sjdp	    hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
408833965Sjdp	}
408933965Sjdp      else
409033965Sjdp	{
409177298Sobrien	  /* Don't store these bits.  */
409233965Sjdp	  mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes);
409333965Sjdp	  hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
409433965Sjdp	}
409533965Sjdp
409677298Sobrien      unmask = ~mask;		/* Do store these bits.  */
409733965Sjdp
409833965Sjdp#ifdef NEVER
409933965Sjdp      "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
410077298Sobrien      mask = ~(unmask >> 1);	/* Includes sign bit now.  */
410133965Sjdp#endif
410233965Sjdp
410333965Sjdp      get = exp->X_add_number;
410433965Sjdp      use = get & unmask;
410533965Sjdp      if ((get & mask) != 0
410633965Sjdp	  && ((get & mask) != mask
410733965Sjdp	      || (get & hibit) == 0))
410877298Sobrien	{		/* Leading bits contain both 0s & 1s.  */
410989857Sobrien	  as_warn (_("value 0x%lx truncated to 0x%lx"),
411033965Sjdp		   (unsigned long) get, (unsigned long) use);
411133965Sjdp	}
411277298Sobrien      /* Put bytes in right order.  */
411333965Sjdp      md_number_to_chars (p, use, (int) nbytes);
411433965Sjdp    }
411533965Sjdp  else if (op == O_big)
411633965Sjdp    {
411738889Sjdp      unsigned int size;
411833965Sjdp      LITTLENUM_TYPE *nums;
411933965Sjdp
412033965Sjdp      size = exp->X_add_number * CHARS_PER_LITTLENUM;
412133965Sjdp      if (nbytes < size)
412233965Sjdp	{
4123276448Spfg	  int i = nbytes / CHARS_PER_LITTLENUM;
4124276448Spfg	  if (i != 0)
4125276448Spfg	    {
4126276448Spfg	      LITTLENUM_TYPE sign = 0;
4127276448Spfg	      if ((generic_bignum[--i]
4128276448Spfg		   & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) != 0)
4129276448Spfg		sign = ~(LITTLENUM_TYPE) 0;
4130276448Spfg	      while (++i < exp->X_add_number)
4131276448Spfg		if (generic_bignum[i] != sign)
4132276448Spfg		  break;
4133276448Spfg	    }
4134276448Spfg	  if (i < exp->X_add_number)
4135276448Spfg	    as_warn (_("bignum truncated to %d bytes"), nbytes);
413633965Sjdp	  size = nbytes;
413733965Sjdp	}
413833965Sjdp
4139276448Spfg      if (nbytes == 1)
4140276448Spfg	{
4141276448Spfg	  md_number_to_chars (p, (valueT) generic_bignum[0], 1);
4142276448Spfg	  return;
4143276448Spfg	}
4144276448Spfg      know (nbytes % CHARS_PER_LITTLENUM == 0);
4145276448Spfg
414633965Sjdp      if (target_big_endian)
414733965Sjdp	{
414833965Sjdp	  while (nbytes > size)
414933965Sjdp	    {
415033965Sjdp	      md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
415133965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
415233965Sjdp	      p += CHARS_PER_LITTLENUM;
415333965Sjdp	    }
415433965Sjdp
415533965Sjdp	  nums = generic_bignum + size / CHARS_PER_LITTLENUM;
415689857Sobrien	  while (size >= CHARS_PER_LITTLENUM)
415733965Sjdp	    {
415833965Sjdp	      --nums;
415933965Sjdp	      md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
416033965Sjdp	      size -= CHARS_PER_LITTLENUM;
416133965Sjdp	      p += CHARS_PER_LITTLENUM;
416233965Sjdp	    }
416333965Sjdp	}
416433965Sjdp      else
416533965Sjdp	{
416633965Sjdp	  nums = generic_bignum;
416789857Sobrien	  while (size >= CHARS_PER_LITTLENUM)
416833965Sjdp	    {
416933965Sjdp	      md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
417033965Sjdp	      ++nums;
417133965Sjdp	      size -= CHARS_PER_LITTLENUM;
417233965Sjdp	      p += CHARS_PER_LITTLENUM;
417333965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
417433965Sjdp	    }
417533965Sjdp
417689857Sobrien	  while (nbytes >= CHARS_PER_LITTLENUM)
417733965Sjdp	    {
417833965Sjdp	      md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
417933965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
418033965Sjdp	      p += CHARS_PER_LITTLENUM;
418133965Sjdp	    }
418233965Sjdp	}
418333965Sjdp    }
418433965Sjdp  else
418533965Sjdp    {
418633965Sjdp      memset (p, 0, nbytes);
418733965Sjdp
4188218822Sdim      /* Now we need to generate a fixS to record the symbol value.  */
418933965Sjdp
419033965Sjdp#ifdef TC_CONS_FIX_NEW
419133965Sjdp      TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
419233965Sjdp#else
419333965Sjdp      {
419433965Sjdp	bfd_reloc_code_real_type r;
419533965Sjdp
419633965Sjdp	switch (nbytes)
419733965Sjdp	  {
419833965Sjdp	  case 1:
419933965Sjdp	    r = BFD_RELOC_8;
420033965Sjdp	    break;
420133965Sjdp	  case 2:
420233965Sjdp	    r = BFD_RELOC_16;
420333965Sjdp	    break;
420433965Sjdp	  case 4:
420533965Sjdp	    r = BFD_RELOC_32;
420633965Sjdp	    break;
420733965Sjdp	  case 8:
420833965Sjdp	    r = BFD_RELOC_64;
420933965Sjdp	    break;
421033965Sjdp	  default:
421160484Sobrien	    as_bad (_("unsupported BFD relocation size %u"), nbytes);
421233965Sjdp	    r = BFD_RELOC_32;
421333965Sjdp	    break;
421433965Sjdp	  }
421533965Sjdp	fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp,
421633965Sjdp		     0, r);
421733965Sjdp      }
421833965Sjdp#endif
421933965Sjdp    }
422033965Sjdp}
422133965Sjdp
422233965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS
422333965Sjdp
422433965Sjdp/* i960 assemblers, (eg, asm960), allow bitfields after ".byte" as
422533965Sjdp   w:x,y:z, where w and y are bitwidths and x and y are values.  They
422633965Sjdp   then pack them all together. We do a little better in that we allow
422733965Sjdp   them in words, longs, etc. and we'll pack them in target byte order
422833965Sjdp   for you.
422933965Sjdp
4230130561Sobrien   The rules are: pack least significant bit first, if a field doesn't
423133965Sjdp   entirely fit, put it in the next unit.  Overflowing the bitfield is
423233965Sjdp   explicitly *not* even a warning.  The bitwidth should be considered
423333965Sjdp   a "mask".
423433965Sjdp
423533965Sjdp   To use this function the tc-XXX.h file should define
423633965Sjdp   BITFIELD_CONS_EXPRESSIONS.  */
423733965Sjdp
423877298Sobrienstatic void
423933965Sjdpparse_bitfield_cons (exp, nbytes)
424033965Sjdp     expressionS *exp;
424133965Sjdp     unsigned int nbytes;
424233965Sjdp{
424333965Sjdp  unsigned int bits_available = BITS_PER_CHAR * nbytes;
424433965Sjdp  char *hold = input_line_pointer;
424533965Sjdp
424633965Sjdp  (void) expression (exp);
424733965Sjdp
424833965Sjdp  if (*input_line_pointer == ':')
424977298Sobrien    {
425077298Sobrien      /* Bitfields.  */
425133965Sjdp      long value = 0;
425233965Sjdp
425333965Sjdp      for (;;)
425433965Sjdp	{
425533965Sjdp	  unsigned long width;
425633965Sjdp
425733965Sjdp	  if (*input_line_pointer != ':')
425833965Sjdp	    {
425933965Sjdp	      input_line_pointer = hold;
426033965Sjdp	      break;
426177298Sobrien	    }			/* Next piece is not a bitfield.  */
426233965Sjdp
426333965Sjdp	  /* In the general case, we can't allow
426433965Sjdp	     full expressions with symbol
426533965Sjdp	     differences and such.  The relocation
426633965Sjdp	     entries for symbols not defined in this
426733965Sjdp	     assembly would require arbitrary field
426833965Sjdp	     widths, positions, and masks which most
426933965Sjdp	     of our current object formats don't
427033965Sjdp	     support.
427133965Sjdp
427233965Sjdp	     In the specific case where a symbol
427333965Sjdp	     *is* defined in this assembly, we
427433965Sjdp	     *could* build fixups and track it, but
427533965Sjdp	     this could lead to confusion for the
427633965Sjdp	     backends.  I'm lazy. I'll take any
427733965Sjdp	     SEG_ABSOLUTE. I think that means that
427833965Sjdp	     you can use a previous .set or
427977298Sobrien	     .equ type symbol.  xoxorich.  */
428033965Sjdp
428133965Sjdp	  if (exp->X_op == O_absent)
428233965Sjdp	    {
428360484Sobrien	      as_warn (_("using a bit field width of zero"));
428433965Sjdp	      exp->X_add_number = 0;
428533965Sjdp	      exp->X_op = O_constant;
428677298Sobrien	    }			/* Implied zero width bitfield.  */
428733965Sjdp
428833965Sjdp	  if (exp->X_op != O_constant)
428933965Sjdp	    {
429033965Sjdp	      *input_line_pointer = '\0';
429160484Sobrien	      as_bad (_("field width \"%s\" too complex for a bitfield"), hold);
429233965Sjdp	      *input_line_pointer = ':';
429333965Sjdp	      demand_empty_rest_of_line ();
429433965Sjdp	      return;
429577298Sobrien	    }			/* Too complex.  */
429633965Sjdp
429733965Sjdp	  if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes))
429833965Sjdp	    {
429960484Sobrien	      as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"),
430033965Sjdp		       width, nbytes, (BITS_PER_CHAR * nbytes));
430133965Sjdp	      width = BITS_PER_CHAR * nbytes;
430277298Sobrien	    }			/* Too big.  */
430333965Sjdp
430433965Sjdp	  if (width > bits_available)
430533965Sjdp	    {
430633965Sjdp	      /* FIXME-SOMEDAY: backing up and reparsing is wasteful.  */
430733965Sjdp	      input_line_pointer = hold;
430833965Sjdp	      exp->X_add_number = value;
430933965Sjdp	      break;
431077298Sobrien	    }			/* Won't fit.  */
431133965Sjdp
431277298Sobrien	  /* Skip ':'.  */
431377298Sobrien	  hold = ++input_line_pointer;
431433965Sjdp
431533965Sjdp	  (void) expression (exp);
431633965Sjdp	  if (exp->X_op != O_constant)
431733965Sjdp	    {
431833965Sjdp	      char cache = *input_line_pointer;
431933965Sjdp
432033965Sjdp	      *input_line_pointer = '\0';
432160484Sobrien	      as_bad (_("field value \"%s\" too complex for a bitfield"), hold);
432233965Sjdp	      *input_line_pointer = cache;
432333965Sjdp	      demand_empty_rest_of_line ();
432433965Sjdp	      return;
432577298Sobrien	    }			/* Too complex.  */
432633965Sjdp
432733965Sjdp	  value |= ((~(-1 << width) & exp->X_add_number)
432833965Sjdp		    << ((BITS_PER_CHAR * nbytes) - bits_available));
432933965Sjdp
433033965Sjdp	  if ((bits_available -= width) == 0
433133965Sjdp	      || is_it_end_of_statement ()
433233965Sjdp	      || *input_line_pointer != ',')
433333965Sjdp	    {
433433965Sjdp	      break;
433577298Sobrien	    }			/* All the bitfields we're gonna get.  */
433633965Sjdp
433733965Sjdp	  hold = ++input_line_pointer;
433833965Sjdp	  (void) expression (exp);
433977298Sobrien	}
434033965Sjdp
434133965Sjdp      exp->X_add_number = value;
434233965Sjdp      exp->X_op = O_constant;
434333965Sjdp      exp->X_unsigned = 1;
434477298Sobrien    }
434577298Sobrien}
434633965Sjdp
434733965Sjdp#endif /* BITFIELD_CONS_EXPRESSIONS */
434833965Sjdp
434933965Sjdp/* Handle an MRI style string expression.  */
435033965Sjdp
435160484Sobrien#ifdef TC_M68K
435233965Sjdpstatic void
435333965Sjdpparse_mri_cons (exp, nbytes)
435433965Sjdp     expressionS *exp;
435533965Sjdp     unsigned int nbytes;
435633965Sjdp{
435733965Sjdp  if (*input_line_pointer != '\''
435833965Sjdp      && (input_line_pointer[1] != '\''
435933965Sjdp	  || (*input_line_pointer != 'A'
436033965Sjdp	      && *input_line_pointer != 'E')))
436133965Sjdp    TC_PARSE_CONS_EXPRESSION (exp, nbytes);
436233965Sjdp  else
436333965Sjdp    {
436438889Sjdp      unsigned int scan;
436533965Sjdp      unsigned int result = 0;
436633965Sjdp
436733965Sjdp      /* An MRI style string.  Cut into as many bytes as will fit into
436833965Sjdp	 a nbyte chunk, left justify if necessary, and separate with
436933965Sjdp	 commas so we can try again later.  */
437033965Sjdp      if (*input_line_pointer == 'A')
437133965Sjdp	++input_line_pointer;
437233965Sjdp      else if (*input_line_pointer == 'E')
437333965Sjdp	{
437460484Sobrien	  as_bad (_("EBCDIC constants are not supported"));
437533965Sjdp	  ++input_line_pointer;
437633965Sjdp	}
437733965Sjdp
437833965Sjdp      input_line_pointer++;
437933965Sjdp      for (scan = 0; scan < nbytes; scan++)
438033965Sjdp	{
438133965Sjdp	  if (*input_line_pointer == '\'')
438233965Sjdp	    {
438333965Sjdp	      if (input_line_pointer[1] == '\'')
438433965Sjdp		{
438533965Sjdp		  input_line_pointer++;
438633965Sjdp		}
438733965Sjdp	      else
438833965Sjdp		break;
438933965Sjdp	    }
439033965Sjdp	  result = (result << 8) | (*input_line_pointer++);
439133965Sjdp	}
439233965Sjdp
439377298Sobrien      /* Left justify.  */
439433965Sjdp      while (scan < nbytes)
439533965Sjdp	{
439633965Sjdp	  result <<= 8;
439733965Sjdp	  scan++;
439833965Sjdp	}
439977298Sobrien
440077298Sobrien      /* Create correct expression.  */
440133965Sjdp      exp->X_op = O_constant;
440233965Sjdp      exp->X_add_number = result;
440377298Sobrien
440477298Sobrien      /* Fake it so that we can read the next char too.  */
440533965Sjdp      if (input_line_pointer[0] != '\'' ||
440633965Sjdp	  (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\''))
440733965Sjdp	{
440833965Sjdp	  input_line_pointer -= 2;
440933965Sjdp	  input_line_pointer[0] = ',';
441033965Sjdp	  input_line_pointer[1] = '\'';
441133965Sjdp	}
441233965Sjdp      else
441333965Sjdp	input_line_pointer++;
441433965Sjdp    }
441533965Sjdp}
441660484Sobrien#endif /* TC_M68K */
441733965Sjdp
441833965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
441933965Sjdp
442033965Sjdp/* Parse a repeat expression for cons.  This is used by the MIPS
442133965Sjdp   assembler.  The format is NUMBER:COUNT; NUMBER appears in the
442233965Sjdp   object file COUNT times.
442333965Sjdp
442433965Sjdp   To use this for a target, define REPEAT_CONS_EXPRESSIONS.  */
442533965Sjdp
442633965Sjdpstatic void
442733965Sjdpparse_repeat_cons (exp, nbytes)
442833965Sjdp     expressionS *exp;
442933965Sjdp     unsigned int nbytes;
443033965Sjdp{
443133965Sjdp  expressionS count;
443233965Sjdp  register int i;
443333965Sjdp
443433965Sjdp  expression (exp);
443533965Sjdp
443633965Sjdp  if (*input_line_pointer != ':')
443733965Sjdp    {
443833965Sjdp      /* No repeat count.  */
443933965Sjdp      return;
444033965Sjdp    }
444133965Sjdp
444233965Sjdp  ++input_line_pointer;
444333965Sjdp  expression (&count);
444433965Sjdp  if (count.X_op != O_constant
444533965Sjdp      || count.X_add_number <= 0)
444633965Sjdp    {
444789857Sobrien      as_warn (_("unresolvable or nonpositive repeat count; using 1"));
444833965Sjdp      return;
444933965Sjdp    }
445033965Sjdp
445133965Sjdp  /* The cons function is going to output this expression once.  So we
445233965Sjdp     output it count - 1 times.  */
445333965Sjdp  for (i = count.X_add_number - 1; i > 0; i--)
445433965Sjdp    emit_expr (exp, nbytes);
445533965Sjdp}
445633965Sjdp
445733965Sjdp#endif /* REPEAT_CONS_EXPRESSIONS */
445833965Sjdp
445933965Sjdp/* Parse a floating point number represented as a hex constant.  This
446033965Sjdp   permits users to specify the exact bits they want in the floating
446133965Sjdp   point number.  */
446233965Sjdp
446333965Sjdpstatic int
4464130561Sobrienhex_float (int float_type, char *bytes)
446533965Sjdp{
446633965Sjdp  int length;
446733965Sjdp  int i;
446833965Sjdp
446933965Sjdp  switch (float_type)
447033965Sjdp    {
447133965Sjdp    case 'f':
447233965Sjdp    case 'F':
447333965Sjdp    case 's':
447433965Sjdp    case 'S':
447533965Sjdp      length = 4;
447633965Sjdp      break;
447733965Sjdp
447833965Sjdp    case 'd':
447933965Sjdp    case 'D':
448033965Sjdp    case 'r':
448133965Sjdp    case 'R':
448233965Sjdp      length = 8;
448333965Sjdp      break;
448433965Sjdp
448533965Sjdp    case 'x':
448633965Sjdp    case 'X':
448733965Sjdp      length = 12;
448833965Sjdp      break;
448933965Sjdp
449033965Sjdp    case 'p':
449133965Sjdp    case 'P':
449233965Sjdp      length = 12;
449333965Sjdp      break;
449433965Sjdp
449533965Sjdp    default:
449689857Sobrien      as_bad (_("unknown floating type type '%c'"), float_type);
449733965Sjdp      return -1;
449833965Sjdp    }
449933965Sjdp
450033965Sjdp  /* It would be nice if we could go through expression to parse the
450133965Sjdp     hex constant, but if we get a bignum it's a pain to sort it into
450233965Sjdp     the buffer correctly.  */
450333965Sjdp  i = 0;
450433965Sjdp  while (hex_p (*input_line_pointer) || *input_line_pointer == '_')
450533965Sjdp    {
450633965Sjdp      int d;
450733965Sjdp
450833965Sjdp      /* The MRI assembler accepts arbitrary underscores strewn about
450977298Sobrien	 through the hex constant, so we ignore them as well.  */
451033965Sjdp      if (*input_line_pointer == '_')
451133965Sjdp	{
451233965Sjdp	  ++input_line_pointer;
451333965Sjdp	  continue;
451433965Sjdp	}
451533965Sjdp
451633965Sjdp      if (i >= length)
451733965Sjdp	{
451889857Sobrien	  as_warn (_("floating point constant too large"));
451933965Sjdp	  return -1;
452033965Sjdp	}
452133965Sjdp      d = hex_value (*input_line_pointer) << 4;
452233965Sjdp      ++input_line_pointer;
452333965Sjdp      while (*input_line_pointer == '_')
452433965Sjdp	++input_line_pointer;
452533965Sjdp      if (hex_p (*input_line_pointer))
452633965Sjdp	{
452733965Sjdp	  d += hex_value (*input_line_pointer);
452833965Sjdp	  ++input_line_pointer;
452933965Sjdp	}
453033965Sjdp      if (target_big_endian)
453133965Sjdp	bytes[i] = d;
453233965Sjdp      else
453333965Sjdp	bytes[length - i - 1] = d;
453433965Sjdp      ++i;
453533965Sjdp    }
453633965Sjdp
453733965Sjdp  if (i < length)
453833965Sjdp    {
453933965Sjdp      if (target_big_endian)
454033965Sjdp	memset (bytes + i, 0, length - i);
454133965Sjdp      else
454233965Sjdp	memset (bytes, 0, length - i);
454333965Sjdp    }
454433965Sjdp
454533965Sjdp  return length;
454633965Sjdp}
454733965Sjdp
4548130561Sobrien/*			float_cons()
454933965Sjdp
455077298Sobrien   CONStruct some more frag chars of .floats .ffloats etc.
455177298Sobrien   Makes 0 or more new frags.
455277298Sobrien   If need_pass_2 == 1, no frags are emitted.
455377298Sobrien   This understands only floating literals, not expressions. Sorry.
455477298Sobrien
455577298Sobrien   A floating constant is defined by atof_generic(), except it is preceded
455677298Sobrien   by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its
455777298Sobrien   reading, I decided to be incompatible. This always tries to give you
455877298Sobrien   rounded bits to the precision of the pseudo-op. Former AS did premature
4559130561Sobrien   truncation, restored noisy bits instead of trailing 0s AND gave you
456077298Sobrien   a choice of 2 flavours of noise according to which of 2 floating-point
456177298Sobrien   scanners you directed AS to use.
456277298Sobrien
456377298Sobrien   In:	input_line_pointer->whitespace before, or '0' of flonum.  */
456477298Sobrien
456533965Sjdpvoid
4566130561Sobrienfloat_cons (/* Clobbers input_line-pointer, checks end-of-line.  */
4567130561Sobrien	    register int float_type	/* 'f':.ffloat ... 'F':.float ...  */)
456833965Sjdp{
456933965Sjdp  register char *p;
457077298Sobrien  int length;			/* Number of chars in an object.  */
457177298Sobrien  register char *err;		/* Error from scanning floating literal.  */
457233965Sjdp  char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
457333965Sjdp
457433965Sjdp  if (is_it_end_of_statement ())
457533965Sjdp    {
457633965Sjdp      demand_empty_rest_of_line ();
457733965Sjdp      return;
457833965Sjdp    }
457933965Sjdp
458033965Sjdp#ifdef md_flush_pending_output
458133965Sjdp  md_flush_pending_output ();
458233965Sjdp#endif
458333965Sjdp
458433965Sjdp  do
458533965Sjdp    {
458677298Sobrien      /* input_line_pointer->1st char of a flonum (we hope!).  */
458733965Sjdp      SKIP_WHITESPACE ();
458833965Sjdp
458933965Sjdp      /* Skip any 0{letter} that may be present. Don't even check if the
4590130561Sobrien	 letter is legal. Someone may invent a "z" format and this routine
4591130561Sobrien	 has no use for such information. Lusers beware: you get
4592130561Sobrien	 diagnostics if your input is ill-conditioned.  */
459338889Sjdp      if (input_line_pointer[0] == '0'
459489857Sobrien	  && ISALPHA (input_line_pointer[1]))
459533965Sjdp	input_line_pointer += 2;
459633965Sjdp
459733965Sjdp      /* Accept :xxxx, where the x's are hex digits, for a floating
4598130561Sobrien	 point with the exact digits specified.  */
459933965Sjdp      if (input_line_pointer[0] == ':')
460033965Sjdp	{
460133965Sjdp	  ++input_line_pointer;
460233965Sjdp	  length = hex_float (float_type, temp);
460333965Sjdp	  if (length < 0)
460433965Sjdp	    {
460533965Sjdp	      ignore_rest_of_line ();
460633965Sjdp	      return;
460733965Sjdp	    }
460833965Sjdp	}
460933965Sjdp      else
461033965Sjdp	{
461133965Sjdp	  err = md_atof (float_type, temp, &length);
461233965Sjdp	  know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
461333965Sjdp	  know (length > 0);
461433965Sjdp	  if (err)
461533965Sjdp	    {
461689857Sobrien	      as_bad (_("bad floating literal: %s"), err);
461733965Sjdp	      ignore_rest_of_line ();
461833965Sjdp	      return;
461933965Sjdp	    }
462033965Sjdp	}
462133965Sjdp
462233965Sjdp      if (!need_pass_2)
462333965Sjdp	{
462433965Sjdp	  int count;
462533965Sjdp
462633965Sjdp	  count = 1;
462733965Sjdp
462833965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
462933965Sjdp	  if (*input_line_pointer == ':')
463033965Sjdp	    {
463133965Sjdp	      expressionS count_exp;
463233965Sjdp
463333965Sjdp	      ++input_line_pointer;
463433965Sjdp	      expression (&count_exp);
463577298Sobrien
463633965Sjdp	      if (count_exp.X_op != O_constant
463733965Sjdp		  || count_exp.X_add_number <= 0)
463877298Sobrien		as_warn (_("unresolvable or nonpositive repeat count; using 1"));
463933965Sjdp	      else
464033965Sjdp		count = count_exp.X_add_number;
464133965Sjdp	    }
464233965Sjdp#endif
464333965Sjdp
464433965Sjdp	  while (--count >= 0)
464533965Sjdp	    {
464633965Sjdp	      p = frag_more (length);
464733965Sjdp	      memcpy (p, temp, (unsigned int) length);
464833965Sjdp	    }
464933965Sjdp	}
465033965Sjdp      SKIP_WHITESPACE ();
465133965Sjdp    }
465233965Sjdp  while (*input_line_pointer++ == ',');
465333965Sjdp
465477298Sobrien  /* Put terminator back into stream.  */
465577298Sobrien  --input_line_pointer;
465633965Sjdp  demand_empty_rest_of_line ();
465777298Sobrien}
465833965Sjdp
465977298Sobrien/* Return the size of a LEB128 value.  */
466038889Sjdp
466138889Sjdpstatic inline int
4662130561Sobriensizeof_sleb128 (offsetT value)
466338889Sjdp{
466438889Sjdp  register int size = 0;
466538889Sjdp  register unsigned byte;
466638889Sjdp
466738889Sjdp  do
466838889Sjdp    {
466938889Sjdp      byte = (value & 0x7f);
467038889Sjdp      /* Sadly, we cannot rely on typical arithmetic right shift behaviour.
467138889Sjdp	 Fortunately, we can structure things so that the extra work reduces
467238889Sjdp	 to a noop on systems that do things "properly".  */
467338889Sjdp      value = (value >> 7) | ~(-(offsetT)1 >> 7);
467438889Sjdp      size += 1;
467538889Sjdp    }
467638889Sjdp  while (!(((value == 0) && ((byte & 0x40) == 0))
467738889Sjdp	   || ((value == -1) && ((byte & 0x40) != 0))));
467838889Sjdp
467938889Sjdp  return size;
468038889Sjdp}
468138889Sjdp
468238889Sjdpstatic inline int
4683130561Sobriensizeof_uleb128 (valueT value)
468438889Sjdp{
468538889Sjdp  register int size = 0;
468638889Sjdp  register unsigned byte;
468738889Sjdp
468838889Sjdp  do
468938889Sjdp    {
469038889Sjdp      byte = (value & 0x7f);
469138889Sjdp      value >>= 7;
469238889Sjdp      size += 1;
469338889Sjdp    }
469438889Sjdp  while (value != 0);
469538889Sjdp
469638889Sjdp  return size;
469738889Sjdp}
469838889Sjdp
469960484Sobrienint
4700130561Sobriensizeof_leb128 (valueT value, int sign)
470138889Sjdp{
470238889Sjdp  if (sign)
470338889Sjdp    return sizeof_sleb128 ((offsetT) value);
470438889Sjdp  else
470538889Sjdp    return sizeof_uleb128 (value);
470638889Sjdp}
470738889Sjdp
470838889Sjdp/* Output a LEB128 value.  */
470938889Sjdp
471038889Sjdpstatic inline int
4711130561Sobrienoutput_sleb128 (char *p, offsetT value)
471238889Sjdp{
471338889Sjdp  register char *orig = p;
471438889Sjdp  register int more;
471538889Sjdp
471638889Sjdp  do
471738889Sjdp    {
471838889Sjdp      unsigned byte = (value & 0x7f);
471938889Sjdp
472038889Sjdp      /* Sadly, we cannot rely on typical arithmetic right shift behaviour.
472138889Sjdp	 Fortunately, we can structure things so that the extra work reduces
472238889Sjdp	 to a noop on systems that do things "properly".  */
472338889Sjdp      value = (value >> 7) | ~(-(offsetT)1 >> 7);
472438889Sjdp
472538889Sjdp      more = !((((value == 0) && ((byte & 0x40) == 0))
472638889Sjdp		|| ((value == -1) && ((byte & 0x40) != 0))));
472738889Sjdp      if (more)
472838889Sjdp	byte |= 0x80;
472938889Sjdp
473038889Sjdp      *p++ = byte;
473138889Sjdp    }
473238889Sjdp  while (more);
473338889Sjdp
473438889Sjdp  return p - orig;
473538889Sjdp}
473638889Sjdp
473738889Sjdpstatic inline int
4738130561Sobrienoutput_uleb128 (char *p, valueT value)
473938889Sjdp{
474038889Sjdp  char *orig = p;
474138889Sjdp
474238889Sjdp  do
474338889Sjdp    {
474438889Sjdp      unsigned byte = (value & 0x7f);
474538889Sjdp      value >>= 7;
474638889Sjdp      if (value != 0)
474738889Sjdp	/* More bytes to follow.  */
474838889Sjdp	byte |= 0x80;
474938889Sjdp
475038889Sjdp      *p++ = byte;
475138889Sjdp    }
475238889Sjdp  while (value != 0);
475338889Sjdp
475438889Sjdp  return p - orig;
475538889Sjdp}
475638889Sjdp
475760484Sobrienint
4758130561Sobrienoutput_leb128 (char *p, valueT value, int sign)
475938889Sjdp{
476038889Sjdp  if (sign)
476138889Sjdp    return output_sleb128 (p, (offsetT) value);
476238889Sjdp  else
476338889Sjdp    return output_uleb128 (p, value);
476438889Sjdp}
476538889Sjdp
476638889Sjdp/* Do the same for bignums.  We combine sizeof with output here in that
476738889Sjdp   we don't output for NULL values of P.  It isn't really as critical as
476838889Sjdp   for "normal" values that this be streamlined.  */
476938889Sjdp
477060484Sobrienstatic inline int
4771130561Sobrienoutput_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
477238889Sjdp{
477338889Sjdp  char *orig = p;
477438889Sjdp  valueT val = 0;
477538889Sjdp  int loaded = 0;
477638889Sjdp  unsigned byte;
477738889Sjdp
477838889Sjdp  /* Strip leading sign extensions off the bignum.  */
4779218822Sdim  while (size > 1
4780218822Sdim	 && bignum[size - 1] == LITTLENUM_MASK
4781218822Sdim	 && bignum[size - 2] > LITTLENUM_MASK / 2)
478238889Sjdp    size--;
478338889Sjdp
478438889Sjdp  do
478538889Sjdp    {
4786218822Sdim      /* OR in the next part of the littlenum.  */
4787218822Sdim      val |= (*bignum << loaded);
4788218822Sdim      loaded += LITTLENUM_NUMBER_OF_BITS;
4789218822Sdim      size--;
4790218822Sdim      bignum++;
479138889Sjdp
4792218822Sdim      /* Add bytes until there are less than 7 bits left in VAL
4793218822Sdim	 or until every non-sign bit has been written.  */
4794218822Sdim      do
479538889Sjdp	{
4796218822Sdim	  byte = val & 0x7f;
4797218822Sdim	  loaded -= 7;
4798218822Sdim	  val >>= 7;
4799218822Sdim	  if (size > 0
4800218822Sdim	      || val != ((byte & 0x40) == 0 ? 0 : ((valueT) 1 << loaded) - 1))
480138889Sjdp	    byte |= 0x80;
4802218822Sdim
4803218822Sdim	  if (orig)
4804218822Sdim	    *p = byte;
4805218822Sdim	  p++;
480638889Sjdp	}
4807218822Sdim      while ((byte & 0x80) != 0 && loaded >= 7);
4808218822Sdim    }
4809218822Sdim  while (size > 0);
481038889Sjdp
4811218822Sdim  /* Mop up any left-over bits (of which there will be less than 7).  */
4812218822Sdim  if ((byte & 0x80) != 0)
4813218822Sdim    {
4814218822Sdim      /* Sign-extend VAL.  */
4815218822Sdim      if (val & (1 << (loaded - 1)))
4816218822Sdim	val |= ~0 << loaded;
481738889Sjdp      if (orig)
4818218822Sdim	*p = val & 0x7f;
481938889Sjdp      p++;
482038889Sjdp    }
482138889Sjdp
482238889Sjdp  return p - orig;
482338889Sjdp}
482438889Sjdp
482560484Sobrienstatic inline int
4826130561Sobrienoutput_big_uleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
482738889Sjdp{
482838889Sjdp  char *orig = p;
482938889Sjdp  valueT val = 0;
483038889Sjdp  int loaded = 0;
483138889Sjdp  unsigned byte;
483238889Sjdp
483338889Sjdp  /* Strip leading zeros off the bignum.  */
483438889Sjdp  /* XXX: Is this needed?  */
483577298Sobrien  while (size > 0 && bignum[size - 1] == 0)
483638889Sjdp    size--;
483738889Sjdp
483838889Sjdp  do
483938889Sjdp    {
484038889Sjdp      if (loaded < 7 && size > 0)
484138889Sjdp	{
484238889Sjdp	  val |= (*bignum << loaded);
484338889Sjdp	  loaded += 8 * CHARS_PER_LITTLENUM;
484438889Sjdp	  size--;
484538889Sjdp	  bignum++;
484638889Sjdp	}
484738889Sjdp
484838889Sjdp      byte = val & 0x7f;
484938889Sjdp      loaded -= 7;
485038889Sjdp      val >>= 7;
485138889Sjdp
485238889Sjdp      if (size > 0 || val)
485338889Sjdp	byte |= 0x80;
485438889Sjdp
485538889Sjdp      if (orig)
485638889Sjdp	*p = byte;
485738889Sjdp      p++;
485838889Sjdp    }
485938889Sjdp  while (byte & 0x80);
486038889Sjdp
486138889Sjdp  return p - orig;
486238889Sjdp}
486338889Sjdp
486460484Sobrienstatic int
4865130561Sobrienoutput_big_leb128 (char *p, LITTLENUM_TYPE *bignum, int size, int sign)
486638889Sjdp{
486738889Sjdp  if (sign)
486838889Sjdp    return output_big_sleb128 (p, bignum, size);
486938889Sjdp  else
487038889Sjdp    return output_big_uleb128 (p, bignum, size);
487138889Sjdp}
487238889Sjdp
487338889Sjdp/* Generate the appropriate fragments for a given expression to emit a
487438889Sjdp   leb128 value.  */
487538889Sjdp
4876218822Sdimstatic void
4877130561Sobrienemit_leb128_expr (expressionS *exp, int sign)
487838889Sjdp{
487938889Sjdp  operatorT op = exp->X_op;
4880218822Sdim  unsigned int nbytes;
488138889Sjdp
488238889Sjdp  if (op == O_absent || op == O_illegal)
488338889Sjdp    {
488460484Sobrien      as_warn (_("zero assumed for missing expression"));
488538889Sjdp      exp->X_add_number = 0;
488638889Sjdp      op = O_constant;
488738889Sjdp    }
488838889Sjdp  else if (op == O_big && exp->X_add_number <= 0)
488938889Sjdp    {
489089857Sobrien      as_bad (_("floating point number invalid"));
489138889Sjdp      exp->X_add_number = 0;
489238889Sjdp      op = O_constant;
489338889Sjdp    }
489438889Sjdp  else if (op == O_register)
489538889Sjdp    {
489660484Sobrien      as_warn (_("register value used as expression"));
489738889Sjdp      op = O_constant;
489838889Sjdp    }
4899218822Sdim  else if (op == O_constant
4900218822Sdim	   && sign
4901218822Sdim	   && (exp->X_add_number < 0) != !exp->X_unsigned)
4902218822Sdim    {
4903218822Sdim      /* We're outputting a signed leb128 and the sign of X_add_number
4904218822Sdim	 doesn't reflect the sign of the original value.  Convert EXP
4905218822Sdim	 to a correctly-extended bignum instead.  */
4906218822Sdim      convert_to_bignum (exp);
4907218822Sdim      op = O_big;
4908218822Sdim    }
490938889Sjdp
491078828Sobrien  /* Let check_eh_frame know that data is being emitted.  nbytes == -1 is
491178828Sobrien     a signal that this is leb128 data.  It shouldn't optimize this away.  */
4912218822Sdim  nbytes = (unsigned int) -1;
491378828Sobrien  if (check_eh_frame (exp, &nbytes))
491478828Sobrien    abort ();
491578828Sobrien
491678828Sobrien  /* Let the backend know that subsequent data may be byte aligned.  */
491778828Sobrien#ifdef md_cons_align
491878828Sobrien  md_cons_align (1);
491978828Sobrien#endif
492078828Sobrien
492138889Sjdp  if (op == O_constant)
492238889Sjdp    {
492338889Sjdp      /* If we've got a constant, emit the thing directly right now.  */
492438889Sjdp
492538889Sjdp      valueT value = exp->X_add_number;
492638889Sjdp      int size;
492738889Sjdp      char *p;
492838889Sjdp
492938889Sjdp      size = sizeof_leb128 (value, sign);
493038889Sjdp      p = frag_more (size);
493138889Sjdp      output_leb128 (p, value, sign);
493238889Sjdp    }
493338889Sjdp  else if (op == O_big)
493438889Sjdp    {
493538889Sjdp      /* O_big is a different sort of constant.  */
493638889Sjdp
493738889Sjdp      int size;
493838889Sjdp      char *p;
493938889Sjdp
494038889Sjdp      size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign);
494138889Sjdp      p = frag_more (size);
494238889Sjdp      output_big_leb128 (p, generic_bignum, exp->X_add_number, sign);
494338889Sjdp    }
494438889Sjdp  else
494538889Sjdp    {
494677298Sobrien      /* Otherwise, we have to create a variable sized fragment and
494738889Sjdp	 resolve things later.  */
494838889Sjdp
494977298Sobrien      frag_var (rs_leb128, sizeof_uleb128 (~(valueT) 0), 0, sign,
495038889Sjdp		make_expr_symbol (exp), 0, (char *) NULL);
495138889Sjdp    }
495238889Sjdp}
495338889Sjdp
495438889Sjdp/* Parse the .sleb128 and .uleb128 pseudos.  */
495538889Sjdp
495638889Sjdpvoid
4957130561Sobriens_leb128 (int sign)
495838889Sjdp{
495938889Sjdp  expressionS exp;
496038889Sjdp
4961130561Sobrien#ifdef md_flush_pending_output
4962130561Sobrien  md_flush_pending_output ();
4963130561Sobrien#endif
4964130561Sobrien
496577298Sobrien  do
496677298Sobrien    {
496777298Sobrien      expression (&exp);
496877298Sobrien      emit_leb128_expr (&exp, sign);
496977298Sobrien    }
497077298Sobrien  while (*input_line_pointer++ == ',');
497138889Sjdp
497238889Sjdp  input_line_pointer--;
497338889Sjdp  demand_empty_rest_of_line ();
497438889Sjdp}
497538889Sjdp
497677298Sobrien/* We read 0 or more ',' separated, double-quoted strings.
497777298Sobrien   Caller should have checked need_pass_2 is FALSE because we don't
497877298Sobrien   check it.  */
497933965Sjdp
498077298Sobrienvoid
4981130561Sobrienstringer (/* Worker to do .ascii etc statements.  */
4982130561Sobrien	  /* Checks end-of-line.  */
4983130561Sobrien	  register int append_zero	/* 0: don't append '\0', else 1.  */)
498433965Sjdp{
498533965Sjdp  register unsigned int c;
498638889Sjdp  char *start;
498733965Sjdp
498833965Sjdp#ifdef md_flush_pending_output
498933965Sjdp  md_flush_pending_output ();
499033965Sjdp#endif
499133965Sjdp
499277298Sobrien  /* The following awkward logic is to parse ZERO or more strings,
499377298Sobrien     comma separated. Recall a string expression includes spaces
499477298Sobrien     before the opening '\"' and spaces after the closing '\"'.
499577298Sobrien     We fake a leading ',' if there is (supposed to be)
499677298Sobrien     a 1st, expression. We keep demanding expressions for each ','.  */
499733965Sjdp  if (is_it_end_of_statement ())
499833965Sjdp    {
499977298Sobrien      c = 0;			/* Skip loop.  */
500077298Sobrien      ++input_line_pointer;	/* Compensate for end of loop.  */
500133965Sjdp    }
500233965Sjdp  else
500333965Sjdp    {
500477298Sobrien      c = ',';			/* Do loop.  */
500533965Sjdp    }
5006104834Sobrien  /* If we have been switched into the abs_section then we
5007104834Sobrien     will not have an obstack onto which we can hang strings.  */
5008104834Sobrien  if (now_seg == absolute_section)
5009104834Sobrien    {
5010104834Sobrien      as_bad (_("strings must be placed into a section"));
5011104834Sobrien      c = 0;
5012104834Sobrien      ignore_rest_of_line ();
5013104834Sobrien    }
5014130561Sobrien
501533965Sjdp  while (c == ',' || c == '<' || c == '"')
501633965Sjdp    {
501733965Sjdp      SKIP_WHITESPACE ();
501833965Sjdp      switch (*input_line_pointer)
501933965Sjdp	{
502033965Sjdp	case '\"':
502177298Sobrien	  ++input_line_pointer;	/*->1st char of string.  */
502238889Sjdp	  start = input_line_pointer;
502333965Sjdp	  while (is_a_char (c = next_char_of_string ()))
502433965Sjdp	    {
502533965Sjdp	      FRAG_APPEND_1_CHAR (c);
502633965Sjdp	    }
502733965Sjdp	  if (append_zero)
502833965Sjdp	    {
502933965Sjdp	      FRAG_APPEND_1_CHAR (0);
503033965Sjdp	    }
503133965Sjdp	  know (input_line_pointer[-1] == '\"');
503238889Sjdp
503338889Sjdp#ifndef NO_LISTING
503438889Sjdp#ifdef OBJ_ELF
503538889Sjdp	  /* In ELF, when gcc is emitting DWARF 1 debugging output, it
5036130561Sobrien	     will emit .string with a filename in the .debug section
5037130561Sobrien	     after a sequence of constants.  See the comment in
5038130561Sobrien	     emit_expr for the sequence.  emit_expr will set
5039130561Sobrien	     dwarf_file_string to non-zero if this string might be a
5040130561Sobrien	     source file name.  */
504138889Sjdp	  if (strcmp (segment_name (now_seg), ".debug") != 0)
504238889Sjdp	    dwarf_file_string = 0;
504338889Sjdp	  else if (dwarf_file_string)
504438889Sjdp	    {
504538889Sjdp	      c = input_line_pointer[-1];
504638889Sjdp	      input_line_pointer[-1] = '\0';
504738889Sjdp	      listing_source_file (start);
504838889Sjdp	      input_line_pointer[-1] = c;
504938889Sjdp	    }
505038889Sjdp#endif
505138889Sjdp#endif
505238889Sjdp
505333965Sjdp	  break;
505433965Sjdp	case '<':
505533965Sjdp	  input_line_pointer++;
505633965Sjdp	  c = get_single_number ();
505733965Sjdp	  FRAG_APPEND_1_CHAR (c);
505833965Sjdp	  if (*input_line_pointer != '>')
505933965Sjdp	    {
506089857Sobrien	      as_bad (_("expected <nn>"));
506133965Sjdp	    }
506233965Sjdp	  input_line_pointer++;
506333965Sjdp	  break;
506433965Sjdp	case ',':
506533965Sjdp	  input_line_pointer++;
506633965Sjdp	  break;
506733965Sjdp	}
506833965Sjdp      SKIP_WHITESPACE ();
506933965Sjdp      c = *input_line_pointer;
507033965Sjdp    }
507133965Sjdp
507233965Sjdp  demand_empty_rest_of_line ();
507333965Sjdp}				/* stringer() */
507433965Sjdp
507533965Sjdp/* FIXME-SOMEDAY: I had trouble here on characters with the
507633965Sjdp    high bits set.  We'll probably also have trouble with
507733965Sjdp    multibyte chars, wide chars, etc.  Also be careful about
507877298Sobrien    returning values bigger than 1 byte.  xoxorich.  */
507933965Sjdp
508077298Sobrienunsigned int
5081130561Sobriennext_char_of_string (void)
508233965Sjdp{
508333965Sjdp  register unsigned int c;
508433965Sjdp
508533965Sjdp  c = *input_line_pointer++ & CHAR_MASK;
508633965Sjdp  switch (c)
508733965Sjdp    {
508833965Sjdp    case '\"':
508933965Sjdp      c = NOT_A_CHAR;
509033965Sjdp      break;
509133965Sjdp
509233965Sjdp    case '\n':
509389857Sobrien      as_warn (_("unterminated string; newline inserted"));
509433965Sjdp      bump_line_counters ();
509533965Sjdp      break;
509633965Sjdp
509733965Sjdp#ifndef NO_STRING_ESCAPES
509833965Sjdp    case '\\':
509933965Sjdp      switch (c = *input_line_pointer++)
510033965Sjdp	{
510133965Sjdp	case 'b':
510233965Sjdp	  c = '\b';
510333965Sjdp	  break;
510433965Sjdp
510533965Sjdp	case 'f':
510633965Sjdp	  c = '\f';
510733965Sjdp	  break;
510833965Sjdp
510933965Sjdp	case 'n':
511033965Sjdp	  c = '\n';
511133965Sjdp	  break;
511233965Sjdp
511333965Sjdp	case 'r':
511433965Sjdp	  c = '\r';
511533965Sjdp	  break;
511633965Sjdp
511733965Sjdp	case 't':
511833965Sjdp	  c = '\t';
511933965Sjdp	  break;
512033965Sjdp
512133965Sjdp	case 'v':
512233965Sjdp	  c = '\013';
512333965Sjdp	  break;
512433965Sjdp
512533965Sjdp	case '\\':
512633965Sjdp	case '"':
512777298Sobrien	  break;		/* As itself.  */
512833965Sjdp
512933965Sjdp	case '0':
513033965Sjdp	case '1':
513133965Sjdp	case '2':
513233965Sjdp	case '3':
513333965Sjdp	case '4':
513433965Sjdp	case '5':
513533965Sjdp	case '6':
513633965Sjdp	case '7':
513733965Sjdp	case '8':
513833965Sjdp	case '9':
513933965Sjdp	  {
514033965Sjdp	    long number;
514133965Sjdp	    int i;
514233965Sjdp
514377298Sobrien	    for (i = 0, number = 0;
514489857Sobrien		 ISDIGIT (c) && i < 3;
514577298Sobrien		 c = *input_line_pointer++, i++)
514633965Sjdp	      {
514733965Sjdp		number = number * 8 + c - '0';
514833965Sjdp	      }
514977298Sobrien
515033965Sjdp	    c = number & 0xff;
515133965Sjdp	  }
515233965Sjdp	  --input_line_pointer;
515333965Sjdp	  break;
515433965Sjdp
515533965Sjdp	case 'x':
515633965Sjdp	case 'X':
515733965Sjdp	  {
515833965Sjdp	    long number;
515933965Sjdp
516033965Sjdp	    number = 0;
516133965Sjdp	    c = *input_line_pointer++;
516289857Sobrien	    while (ISXDIGIT (c))
516333965Sjdp	      {
516489857Sobrien		if (ISDIGIT (c))
516533965Sjdp		  number = number * 16 + c - '0';
516689857Sobrien		else if (ISUPPER (c))
516733965Sjdp		  number = number * 16 + c - 'A' + 10;
516833965Sjdp		else
516933965Sjdp		  number = number * 16 + c - 'a' + 10;
517033965Sjdp		c = *input_line_pointer++;
517133965Sjdp	      }
517233965Sjdp	    c = number & 0xff;
517333965Sjdp	    --input_line_pointer;
517433965Sjdp	  }
517533965Sjdp	  break;
517633965Sjdp
517733965Sjdp	case '\n':
517877298Sobrien	  /* To be compatible with BSD 4.2 as: give the luser a linefeed!!  */
517989857Sobrien	  as_warn (_("unterminated string; newline inserted"));
518033965Sjdp	  c = '\n';
518133965Sjdp	  bump_line_counters ();
518233965Sjdp	  break;
518333965Sjdp
518433965Sjdp	default:
518533965Sjdp
518633965Sjdp#ifdef ONLY_STANDARD_ESCAPES
518789857Sobrien	  as_bad (_("bad escaped character in string"));
518833965Sjdp	  c = '?';
518933965Sjdp#endif /* ONLY_STANDARD_ESCAPES */
519033965Sjdp
519133965Sjdp	  break;
519277298Sobrien	}
519333965Sjdp      break;
519433965Sjdp#endif /* ! defined (NO_STRING_ESCAPES) */
519533965Sjdp
519633965Sjdp    default:
519733965Sjdp      break;
519877298Sobrien    }
519933965Sjdp  return (c);
520077298Sobrien}
520133965Sjdp
520233965Sjdpstatic segT
5203130561Sobrienget_segmented_expression (register expressionS *expP)
520433965Sjdp{
520533965Sjdp  register segT retval;
520633965Sjdp
520733965Sjdp  retval = expression (expP);
520833965Sjdp  if (expP->X_op == O_illegal
520933965Sjdp      || expP->X_op == O_absent
521033965Sjdp      || expP->X_op == O_big)
521133965Sjdp    {
521289857Sobrien      as_bad (_("expected address expression"));
521333965Sjdp      expP->X_op = O_constant;
521433965Sjdp      expP->X_add_number = 0;
521533965Sjdp      retval = absolute_section;
521633965Sjdp    }
521733965Sjdp  return retval;
521833965Sjdp}
521933965Sjdp
522077298Sobrienstatic segT
5221130561Sobrienget_known_segmented_expression (register expressionS *expP)
522233965Sjdp{
522333965Sjdp  register segT retval;
522433965Sjdp
522533965Sjdp  if ((retval = get_segmented_expression (expP)) == undefined_section)
522633965Sjdp    {
522733965Sjdp      /* There is no easy way to extract the undefined symbol from the
522833965Sjdp	 expression.  */
522933965Sjdp      if (expP->X_add_symbol != NULL
523033965Sjdp	  && S_GET_SEGMENT (expP->X_add_symbol) != expr_section)
523160484Sobrien	as_warn (_("symbol \"%s\" undefined; zero assumed"),
523233965Sjdp		 S_GET_NAME (expP->X_add_symbol));
523333965Sjdp      else
523460484Sobrien	as_warn (_("some symbol undefined; zero assumed"));
523533965Sjdp      retval = absolute_section;
523633965Sjdp      expP->X_op = O_constant;
523733965Sjdp      expP->X_add_number = 0;
523833965Sjdp    }
523933965Sjdp  know (retval == absolute_section || SEG_NORMAL (retval));
524033965Sjdp  return (retval);
524177298Sobrien}
524233965Sjdp
524377298Sobrienchar				/* Return terminator.  */
5244130561Sobrienget_absolute_expression_and_terminator (long *val_pointer /* Return value of expression.  */)
524533965Sjdp{
524633965Sjdp  /* FIXME: val_pointer should probably be offsetT *.  */
524733965Sjdp  *val_pointer = (long) get_absolute_expression ();
524833965Sjdp  return (*input_line_pointer++);
524933965Sjdp}
525033965Sjdp
525177298Sobrien/* Like demand_copy_string, but return NULL if the string contains any '\0's.
525277298Sobrien   Give a warning if that happens.  */
525377298Sobrien
525433965Sjdpchar *
5255130561Sobriendemand_copy_C_string (int *len_pointer)
525633965Sjdp{
525733965Sjdp  register char *s;
525833965Sjdp
525933965Sjdp  if ((s = demand_copy_string (len_pointer)) != 0)
526033965Sjdp    {
526133965Sjdp      register int len;
526233965Sjdp
526333965Sjdp      for (len = *len_pointer; len > 0; len--)
526433965Sjdp	{
526533965Sjdp	  if (*s == 0)
526633965Sjdp	    {
526733965Sjdp	      s = 0;
526833965Sjdp	      len = 1;
526933965Sjdp	      *len_pointer = 0;
527089857Sobrien	      as_bad (_("this string may not contain \'\\0\'"));
527133965Sjdp	    }
527233965Sjdp	}
527333965Sjdp    }
527477298Sobrien
527533965Sjdp  return s;
527633965Sjdp}
527733965Sjdp
527877298Sobrien/* Demand string, but return a safe (=private) copy of the string.
527977298Sobrien   Return NULL if we can't read a string here.  */
528077298Sobrien
528133965Sjdpchar *
5282130561Sobriendemand_copy_string (int *lenP)
528333965Sjdp{
528433965Sjdp  register unsigned int c;
528533965Sjdp  register int len;
528633965Sjdp  char *retval;
528733965Sjdp
528833965Sjdp  len = 0;
528933965Sjdp  SKIP_WHITESPACE ();
529033965Sjdp  if (*input_line_pointer == '\"')
529133965Sjdp    {
529277298Sobrien      input_line_pointer++;	/* Skip opening quote.  */
529333965Sjdp
529433965Sjdp      while (is_a_char (c = next_char_of_string ()))
529533965Sjdp	{
529633965Sjdp	  obstack_1grow (&notes, c);
529733965Sjdp	  len++;
529833965Sjdp	}
529933965Sjdp      /* JF this next line is so demand_copy_C_string will return a
530077298Sobrien	 null terminated string.  */
530133965Sjdp      obstack_1grow (&notes, '\0');
530233965Sjdp      retval = obstack_finish (&notes);
530333965Sjdp    }
530433965Sjdp  else
530533965Sjdp    {
5306130561Sobrien      as_bad (_("missing string"));
530733965Sjdp      retval = NULL;
530833965Sjdp      ignore_rest_of_line ();
530933965Sjdp    }
531033965Sjdp  *lenP = len;
531133965Sjdp  return (retval);
531277298Sobrien}
531333965Sjdp
531477298Sobrien/* In:	Input_line_pointer->next character.
531577298Sobrien
531677298Sobrien   Do:	Skip input_line_pointer over all whitespace.
531777298Sobrien
531877298Sobrien   Out:	1 if input_line_pointer->end-of-line.  */
531977298Sobrien
532077298Sobrienint
5321130561Sobrienis_it_end_of_statement (void)
532233965Sjdp{
532333965Sjdp  SKIP_WHITESPACE ();
532433965Sjdp  return (is_end_of_line[(unsigned char) *input_line_pointer]);
532577298Sobrien}
532633965Sjdp
532777298Sobrienvoid
5328130561Sobrienequals (char *sym_name, int reassign)
532933965Sjdp{
533038889Sjdp  char *stop = NULL;
5331218822Sdim  char stopc = 0;
533233965Sjdp
533333965Sjdp  input_line_pointer++;
533433965Sjdp  if (*input_line_pointer == '=')
533533965Sjdp    input_line_pointer++;
5336218822Sdim  if (reassign < 0 && *input_line_pointer == '=')
5337218822Sdim    input_line_pointer++;
533833965Sjdp
533933965Sjdp  while (*input_line_pointer == ' ' || *input_line_pointer == '\t')
534033965Sjdp    input_line_pointer++;
534133965Sjdp
534233965Sjdp  if (flag_mri)
534333965Sjdp    stop = mri_comment_field (&stopc);
534433965Sjdp
5345218822Sdim  assign_symbol (sym_name, reassign >= 0 ? !reassign : reassign);
534633965Sjdp
534733965Sjdp  if (flag_mri)
534877298Sobrien    {
5349130561Sobrien      demand_empty_rest_of_line ();
535077298Sobrien      mri_comment_end (stop, stopc);
535177298Sobrien    }
535277298Sobrien}
535333965Sjdp
535489857Sobrien/* .incbin -- include a file verbatim at the current location.  */
535589857Sobrien
535689857Sobrienvoid
5357130561Sobriens_incbin (int x ATTRIBUTE_UNUSED)
535889857Sobrien{
535989857Sobrien  FILE * binfile;
536089857Sobrien  char * path;
536189857Sobrien  char * filename;
536289857Sobrien  char * binfrag;
536389857Sobrien  long   skip = 0;
536489857Sobrien  long   count = 0;
536589857Sobrien  long   bytes;
536689857Sobrien  int    len;
536789857Sobrien
536889857Sobrien#ifdef md_flush_pending_output
536989857Sobrien  md_flush_pending_output ();
537089857Sobrien#endif
537189857Sobrien
537289857Sobrien  SKIP_WHITESPACE ();
537389857Sobrien  filename = demand_copy_string (& len);
537489857Sobrien  if (filename == NULL)
537589857Sobrien    return;
537689857Sobrien
537789857Sobrien  SKIP_WHITESPACE ();
537889857Sobrien
537989857Sobrien  /* Look for optional skip and count.  */
538089857Sobrien  if (* input_line_pointer == ',')
538189857Sobrien    {
538289857Sobrien      ++ input_line_pointer;
538389857Sobrien      skip = get_absolute_expression ();
538489857Sobrien
538589857Sobrien      SKIP_WHITESPACE ();
538689857Sobrien
538789857Sobrien      if (* input_line_pointer == ',')
538889857Sobrien	{
538989857Sobrien	  ++ input_line_pointer;
539089857Sobrien
539189857Sobrien	  count = get_absolute_expression ();
539289857Sobrien	  if (count == 0)
539389857Sobrien	    as_warn (_(".incbin count zero, ignoring `%s'"), filename);
539489857Sobrien
539589857Sobrien	  SKIP_WHITESPACE ();
539689857Sobrien	}
539789857Sobrien    }
539889857Sobrien
539989857Sobrien  demand_empty_rest_of_line ();
540089857Sobrien
540189857Sobrien  /* Try opening absolute path first, then try include dirs.  */
540289857Sobrien  binfile = fopen (filename, FOPEN_RB);
540389857Sobrien  if (binfile == NULL)
540489857Sobrien    {
540589857Sobrien      int i;
540689857Sobrien
540789857Sobrien      path = xmalloc ((unsigned long) len + include_dir_maxlen + 5);
540889857Sobrien
540989857Sobrien      for (i = 0; i < include_dir_count; i++)
541089857Sobrien	{
541189857Sobrien	  sprintf (path, "%s/%s", include_dirs[i], filename);
541289857Sobrien
541389857Sobrien	  binfile = fopen (path, FOPEN_RB);
541489857Sobrien	  if (binfile != NULL)
541589857Sobrien	    break;
541689857Sobrien	}
541789857Sobrien
541889857Sobrien      if (binfile == NULL)
541989857Sobrien	as_bad (_("file not found: %s"), filename);
542089857Sobrien    }
542189857Sobrien  else
542289857Sobrien    path = xstrdup (filename);
542389857Sobrien
542489857Sobrien  if (binfile)
542589857Sobrien    {
542689857Sobrien      long   file_len;
542789857Sobrien
542889857Sobrien      register_dependency (path);
542989857Sobrien
543089857Sobrien      /* Compute the length of the file.  */
543189857Sobrien      if (fseek (binfile, 0, SEEK_END) != 0)
543289857Sobrien	{
543389857Sobrien	  as_bad (_("seek to end of .incbin file failed `%s'"), path);
543489857Sobrien	  goto done;
543589857Sobrien	}
543689857Sobrien      file_len = ftell (binfile);
543789857Sobrien
5438218822Sdim      /* If a count was not specified use the remainder of the file.  */
543989857Sobrien      if (count == 0)
5440218822Sdim	count = file_len - skip;
544189857Sobrien
5442218822Sdim      if (skip < 0 || count < 0 || file_len < 0 || skip + count > file_len)
544389857Sobrien	{
5444218822Sdim	  as_bad (_("skip (%ld) or count (%ld) invalid for file size (%ld)"),
544589857Sobrien		  skip, count, file_len);
544689857Sobrien	  goto done;
544789857Sobrien	}
544889857Sobrien
544989857Sobrien      if (fseek (binfile, skip, SEEK_SET) != 0)
545089857Sobrien	{
545189857Sobrien	  as_bad (_("could not skip to %ld in file `%s'"), skip, path);
545289857Sobrien	  goto done;
545389857Sobrien	}
545489857Sobrien
545589857Sobrien      /* Allocate frag space and store file contents in it.  */
545689857Sobrien      binfrag = frag_more (count);
545789857Sobrien
545889857Sobrien      bytes = fread (binfrag, 1, count, binfile);
545989857Sobrien      if (bytes < count)
546089857Sobrien	as_warn (_("truncated file `%s', %ld of %ld bytes read"),
546189857Sobrien		 path, bytes, count);
546289857Sobrien    }
546389857Sobriendone:
546489857Sobrien  if (binfile != NULL)
546589857Sobrien    fclose (binfile);
546689857Sobrien  if (path)
546789857Sobrien    free (path);
546889857Sobrien}
546989857Sobrien
547077298Sobrien/* .include -- include a file at this point.  */
547133965Sjdp
547277298Sobrienvoid
5473130561Sobriens_include (int arg ATTRIBUTE_UNUSED)
547433965Sjdp{
547533965Sjdp  char *filename;
547633965Sjdp  int i;
547733965Sjdp  FILE *try;
547833965Sjdp  char *path;
547933965Sjdp
548077298Sobrien  if (!flag_m68k_mri)
548138889Sjdp    {
548238889Sjdp      filename = demand_copy_string (&i);
548338889Sjdp      if (filename == NULL)
548438889Sjdp	{
548538889Sjdp	  /* demand_copy_string has already printed an error and
5486130561Sobrien	     called ignore_rest_of_line.  */
548738889Sjdp	  return;
548838889Sjdp	}
548938889Sjdp    }
549033965Sjdp  else
549133965Sjdp    {
549233965Sjdp      SKIP_WHITESPACE ();
549333965Sjdp      i = 0;
549477298Sobrien      while (!is_end_of_line[(unsigned char) *input_line_pointer]
549533965Sjdp	     && *input_line_pointer != ' '
549633965Sjdp	     && *input_line_pointer != '\t')
549733965Sjdp	{
549833965Sjdp	  obstack_1grow (&notes, *input_line_pointer);
549933965Sjdp	  ++input_line_pointer;
550033965Sjdp	  ++i;
550133965Sjdp	}
550277298Sobrien
550333965Sjdp      obstack_1grow (&notes, '\0');
550433965Sjdp      filename = obstack_finish (&notes);
550577298Sobrien      while (!is_end_of_line[(unsigned char) *input_line_pointer])
550633965Sjdp	++input_line_pointer;
550733965Sjdp    }
550877298Sobrien
550933965Sjdp  demand_empty_rest_of_line ();
551033965Sjdp  path = xmalloc ((unsigned long) i + include_dir_maxlen + 5 /* slop */ );
551177298Sobrien
551233965Sjdp  for (i = 0; i < include_dir_count; i++)
551333965Sjdp    {
551433965Sjdp      strcpy (path, include_dirs[i]);
551533965Sjdp      strcat (path, "/");
551633965Sjdp      strcat (path, filename);
551789857Sobrien      if (0 != (try = fopen (path, FOPEN_RT)))
551833965Sjdp	{
551933965Sjdp	  fclose (try);
552033965Sjdp	  goto gotit;
552133965Sjdp	}
552233965Sjdp    }
552377298Sobrien
552433965Sjdp  free (path);
552533965Sjdp  path = filename;
552633965Sjdpgotit:
552777298Sobrien  /* malloc Storage leak when file is found on path.  FIXME-SOMEDAY.  */
552838889Sjdp  register_dependency (path);
552960484Sobrien  input_scrub_insert_file (path);
553077298Sobrien}
553133965Sjdp
553277298Sobrienvoid
5533130561Sobrienadd_include_dir (char *path)
553433965Sjdp{
553533965Sjdp  int i;
553633965Sjdp
553733965Sjdp  if (include_dir_count == 0)
553833965Sjdp    {
553933965Sjdp      include_dirs = (char **) xmalloc (2 * sizeof (*include_dirs));
554077298Sobrien      include_dirs[0] = ".";	/* Current dir.  */
554133965Sjdp      include_dir_count = 2;
554233965Sjdp    }
554333965Sjdp  else
554433965Sjdp    {
554533965Sjdp      include_dir_count++;
554677298Sobrien      include_dirs =
554777298Sobrien	(char **) realloc (include_dirs,
554877298Sobrien			   include_dir_count * sizeof (*include_dirs));
554933965Sjdp    }
555033965Sjdp
555177298Sobrien  include_dirs[include_dir_count - 1] = path;	/* New one.  */
555233965Sjdp
555333965Sjdp  i = strlen (path);
555433965Sjdp  if (i > include_dir_maxlen)
555533965Sjdp    include_dir_maxlen = i;
555677298Sobrien}
555760484Sobrien
555860484Sobrien/* Output debugging information to denote the source file.  */
555933965Sjdp
556060484Sobrienstatic void
5561130561Sobriengenerate_file_debug (void)
556260484Sobrien{
556360484Sobrien  if (debug_type == DEBUG_STABS)
556460484Sobrien    stabs_generate_asm_file ();
556560484Sobrien}
556660484Sobrien
556760484Sobrien/* Output line number debugging information for the current source line.  */
556860484Sobrien
556960484Sobrienvoid
5570130561Sobriengenerate_lineno_debug (void)
557160484Sobrien{
557260484Sobrien  switch (debug_type)
557360484Sobrien    {
557460484Sobrien    case DEBUG_UNSPECIFIED:
557560484Sobrien    case DEBUG_NONE:
557677298Sobrien    case DEBUG_DWARF:
557760484Sobrien      break;
557860484Sobrien    case DEBUG_STABS:
557960484Sobrien      stabs_generate_asm_lineno ();
558060484Sobrien      break;
558160484Sobrien    case DEBUG_ECOFF:
558260484Sobrien      ecoff_generate_asm_lineno ();
558360484Sobrien      break;
558460484Sobrien    case DEBUG_DWARF2:
558577298Sobrien      /* ??? We could here indicate to dwarf2dbg.c that something
558677298Sobrien	 has changed.  However, since there is additional backend
558777298Sobrien	 support that is required (calling dwarf2_emit_insn), we
558877298Sobrien	 let dwarf2dbg.c call as_where on its own.  */
558960484Sobrien      break;
559060484Sobrien    }
559160484Sobrien}
559260484Sobrien
559360484Sobrien/* Output debugging information to mark a function entry point or end point.
559460484Sobrien   END_P is zero for .func, and non-zero for .endfunc.  */
559560484Sobrien
559660484Sobrienvoid
5597130561Sobriens_func (int end_p)
559860484Sobrien{
559960484Sobrien  do_s_func (end_p, NULL);
560060484Sobrien}
560160484Sobrien
560260484Sobrien/* Subroutine of s_func so targets can choose a different default prefix.
560360484Sobrien   If DEFAULT_PREFIX is NULL, use the target's "leading char".  */
560460484Sobrien
5605218822Sdimstatic void
5606130561Sobriendo_s_func (int end_p, const char *default_prefix)
560760484Sobrien{
560860484Sobrien  /* Record the current function so that we can issue an error message for
560960484Sobrien     misplaced .func,.endfunc, and also so that .endfunc needs no
561060484Sobrien     arguments.  */
561160484Sobrien  static char *current_name;
561260484Sobrien  static char *current_label;
561360484Sobrien
561460484Sobrien  if (end_p)
561560484Sobrien    {
561660484Sobrien      if (current_name == NULL)
561760484Sobrien	{
561860484Sobrien	  as_bad (_("missing .func"));
561960484Sobrien	  ignore_rest_of_line ();
562060484Sobrien	  return;
562160484Sobrien	}
562260484Sobrien
562360484Sobrien      if (debug_type == DEBUG_STABS)
562460484Sobrien	stabs_generate_asm_endfunc (current_name, current_label);
562560484Sobrien
562660484Sobrien      current_name = current_label = NULL;
562760484Sobrien    }
562860484Sobrien  else /* ! end_p */
562960484Sobrien    {
563077298Sobrien      char *name, *label;
563177298Sobrien      char delim1, delim2;
563260484Sobrien
563360484Sobrien      if (current_name != NULL)
563460484Sobrien	{
563560484Sobrien	  as_bad (_(".endfunc missing for previous .func"));
563660484Sobrien	  ignore_rest_of_line ();
563760484Sobrien	  return;
563860484Sobrien	}
563960484Sobrien
564060484Sobrien      name = input_line_pointer;
564160484Sobrien      delim1 = get_symbol_end ();
564260484Sobrien      name = xstrdup (name);
564360484Sobrien      *input_line_pointer = delim1;
564460484Sobrien      SKIP_WHITESPACE ();
564560484Sobrien      if (*input_line_pointer != ',')
564660484Sobrien	{
564760484Sobrien	  if (default_prefix)
564860484Sobrien	    asprintf (&label, "%s%s", default_prefix, name);
564960484Sobrien	  else
565060484Sobrien	    {
5651218822Sdim	      char leading_char = bfd_get_symbol_leading_char (stdoutput);
565260484Sobrien	      /* Missing entry point, use function's name with the leading
565360484Sobrien		 char prepended.  */
565460484Sobrien	      if (leading_char)
565560484Sobrien		asprintf (&label, "%c%s", leading_char, name);
565660484Sobrien	      else
565760484Sobrien		label = name;
565860484Sobrien	    }
565960484Sobrien	}
566060484Sobrien      else
566160484Sobrien	{
566260484Sobrien	  ++input_line_pointer;
566360484Sobrien	  SKIP_WHITESPACE ();
566460484Sobrien	  label = input_line_pointer;
566560484Sobrien	  delim2 = get_symbol_end ();
566660484Sobrien	  label = xstrdup (label);
566760484Sobrien	  *input_line_pointer = delim2;
566860484Sobrien	}
566960484Sobrien
567060484Sobrien      if (debug_type == DEBUG_STABS)
567160484Sobrien	stabs_generate_asm_func (name, label);
567260484Sobrien
567360484Sobrien      current_name = name;
567460484Sobrien      current_label = label;
567560484Sobrien    }
567660484Sobrien
567760484Sobrien  demand_empty_rest_of_line ();
567860484Sobrien}
567960484Sobrien
568077298Sobrienvoid
5681130561Sobriens_ignore (int arg ATTRIBUTE_UNUSED)
568233965Sjdp{
5683218822Sdim  ignore_rest_of_line ();
568433965Sjdp}
568533965Sjdp
568633965Sjdpvoid
5687130561Sobrienread_print_statistics (FILE *file)
568833965Sjdp{
568933965Sjdp  hash_print_statistics (file, "pseudo-op table", po_hash);
569033965Sjdp}
569133965Sjdp
569277298Sobrien/* Inserts the given line into the input stream.
569377298Sobrien
569460484Sobrien   This call avoids macro/conditionals nesting checking, since the contents of
569560484Sobrien   the line are assumed to replace the contents of a line already scanned.
569660484Sobrien
5697130561Sobrien   An appropriate use of this function would be substitution of input lines when
569860484Sobrien   called by md_start_line_hook().  The given line is assumed to already be
569960484Sobrien   properly scrubbed.  */
570060484Sobrien
570160484Sobrienvoid
5702130561Sobrieninput_scrub_insert_line (const char *line)
570360484Sobrien{
570460484Sobrien  sb newline;
570560484Sobrien  sb_new (&newline);
570660484Sobrien  sb_add_string (&newline, line);
570760484Sobrien  input_scrub_include_sb (&newline, input_line_pointer, 0);
570860484Sobrien  sb_kill (&newline);
570960484Sobrien  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
571060484Sobrien}
571160484Sobrien
571260484Sobrien/* Insert a file into the input stream; the path must resolve to an actual
571377298Sobrien   file; no include path searching or dependency registering is performed.  */
571460484Sobrien
571560484Sobrienvoid
5716130561Sobrieninput_scrub_insert_file (char *path)
571760484Sobrien{
571860484Sobrien  input_scrub_include_file (path, input_line_pointer);
571960484Sobrien  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
572060484Sobrien}
5721218822Sdim
5722218822Sdim/* Find the end of a line, considering quotation and escaping of quotes.  */
5723218822Sdim
5724218822Sdim#if !defined(TC_SINGLE_QUOTE_STRINGS) && defined(SINGLE_QUOTE_STRINGS)
5725218822Sdim# define TC_SINGLE_QUOTE_STRINGS 1
5726218822Sdim#endif
5727218822Sdim
5728218822Sdimstatic char *
5729218822Sdim_find_end_of_line (char *s, int mri_string, int insn ATTRIBUTE_UNUSED)
5730218822Sdim{
5731218822Sdim  char inquote = '\0';
5732218822Sdim  int inescape = 0;
5733218822Sdim
5734218822Sdim  while (!is_end_of_line[(unsigned char) *s]
5735218822Sdim	 || (inquote && !ISCNTRL (*s))
5736218822Sdim	 || (inquote == '\'' && flag_mri)
5737218822Sdim#ifdef TC_EOL_IN_INSN
5738218822Sdim	 || (insn && TC_EOL_IN_INSN (s))
5739218822Sdim#endif
5740218822Sdim	)
5741218822Sdim    {
5742218822Sdim      if (mri_string && *s == '\'')
5743218822Sdim	inquote ^= *s;
5744218822Sdim      else if (inescape)
5745218822Sdim	inescape = 0;
5746218822Sdim      else if (*s == '\\')
5747218822Sdim	inescape = 1;
5748218822Sdim      else if (!inquote
5749218822Sdim	       ? *s == '"'
5750218822Sdim#ifdef TC_SINGLE_QUOTE_STRINGS
5751218822Sdim		 || (TC_SINGLE_QUOTE_STRINGS && *s == '\'')
5752218822Sdim#endif
5753218822Sdim	       : *s == inquote)
5754218822Sdim	inquote ^= *s;
5755218822Sdim      ++s;
5756218822Sdim    }
5757218822Sdim  if (inquote)
5758218822Sdim    as_warn (_("missing closing `%c'"), inquote);
5759218822Sdim  if (inescape)
5760218822Sdim    as_warn (_("stray `\\'"));
5761218822Sdim  return s;
5762218822Sdim}
5763218822Sdim
5764218822Sdimchar *
5765218822Sdimfind_end_of_line (char *s, int mri_string)
5766218822Sdim{
5767218822Sdim  return _find_end_of_line (s, mri_string, 0);
5768218822Sdim}
5769