read.c revision 130561
133965Sjdp/* read.c - read a source file -
278828Sobrien   Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
3130561Sobrien   1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
433965Sjdp
533965SjdpThis file is part of GAS, the GNU Assembler.
633965Sjdp
733965SjdpGAS is free software; you can redistribute it and/or modify
833965Sjdpit under the terms of the GNU General Public License as published by
933965Sjdpthe Free Software Foundation; either version 2, or (at your option)
1033965Sjdpany later version.
1133965Sjdp
1233965SjdpGAS is distributed in the hope that it will be useful,
1333965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
1433965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1533965SjdpGNU General Public License for more details.
1633965Sjdp
1733965SjdpYou should have received a copy of the GNU General Public License
1833965Sjdpalong with GAS; see the file COPYING.  If not, write to the Free
1933965SjdpSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2077298Sobrien02111-1307, USA.  */
2133965Sjdp
2233965Sjdp#if 0
2377298Sobrien/* If your chars aren't 8 bits, you will change this a bit.
2477298Sobrien   But then, GNU isn't spozed to run on your machine anyway.
2577298Sobrien   (RMS is so shortsighted sometimes.)  */
2677298Sobrien#define MASK_CHAR (0xFF)
2733965Sjdp#else
2877298Sobrien#define MASK_CHAR ((int)(unsigned char) -1)
2933965Sjdp#endif
3033965Sjdp
3133965Sjdp/* This is the largest known floating point format (for now). It will
3277298Sobrien   grow when we do 4361 style flonums.  */
3333965Sjdp#define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)
3433965Sjdp
35130561Sobrien/* Routines that read assembler source text to build spaghetti in memory.
3633965Sjdp   Another group of these functions is in the expr.c module.  */
3733965Sjdp
3833965Sjdp#include "as.h"
3989857Sobrien#include "safe-ctype.h"
4033965Sjdp#include "subsegs.h"
4133965Sjdp#include "sb.h"
4233965Sjdp#include "macro.h"
4333965Sjdp#include "obstack.h"
4433965Sjdp#include "listing.h"
4533965Sjdp#include "ecoff.h"
46130561Sobrien#include "dw2gencfi.h"
4733965Sjdp
4833965Sjdp#ifndef TC_START_LABEL
49104834Sobrien#define TC_START_LABEL(x,y) (x == ':')
5033965Sjdp#endif
5133965Sjdp
5260484Sobrien/* Set by the object-format or the target.  */
5360484Sobrien#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
54130561Sobrien#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR)		\
5577298Sobrien  do								\
56130561Sobrien    {								\
57130561Sobrien      if ((SIZE) >= 8)						\
58130561Sobrien	(P2VAR) = 3;						\
59130561Sobrien      else if ((SIZE) >= 4)					\
60130561Sobrien	(P2VAR) = 2;						\
61130561Sobrien      else if ((SIZE) >= 2)					\
62130561Sobrien	(P2VAR) = 1;						\
63130561Sobrien      else							\
64130561Sobrien	(P2VAR) = 0;						\
6577298Sobrien    }								\
6677298Sobrien  while (0)
6760484Sobrien#endif
6860484Sobrien
6977298Sobrienchar *input_line_pointer;	/*->next char of source file to parse.  */
7033965Sjdp
7133965Sjdp#if BITS_PER_CHAR != 8
7233965Sjdp/*  The following table is indexed by[(char)] and will break if
7333965Sjdp    a char does not have exactly 256 states (hopefully 0:255!)!  */
7433965Sjdpdie horribly;
7533965Sjdp#endif
7633965Sjdp
7733965Sjdp#ifndef LEX_AT
7833965Sjdp/* The m88k unfortunately uses @ as a label beginner.  */
7933965Sjdp#define LEX_AT 0
8033965Sjdp#endif
8133965Sjdp
8233965Sjdp#ifndef LEX_BR
8333965Sjdp/* The RS/6000 assembler uses {,},[,] as parts of symbol names.  */
8433965Sjdp#define LEX_BR 0
8533965Sjdp#endif
8633965Sjdp
8733965Sjdp#ifndef LEX_PCT
8833965Sjdp/* The Delta 68k assembler permits % inside label names.  */
8933965Sjdp#define LEX_PCT 0
9033965Sjdp#endif
9133965Sjdp
9233965Sjdp#ifndef LEX_QM
9333965Sjdp/* The PowerPC Windows NT assemblers permits ? inside label names.  */
9433965Sjdp#define LEX_QM 0
9533965Sjdp#endif
9633965Sjdp
9760484Sobrien#ifndef LEX_HASH
9877298Sobrien/* The IA-64 assembler uses # as a suffix designating a symbol.  We include
9977298Sobrien   it in the symbol and strip it out in tc_canonicalize_symbol_name.  */
10060484Sobrien#define LEX_HASH 0
10160484Sobrien#endif
10260484Sobrien
10333965Sjdp#ifndef LEX_DOLLAR
10433965Sjdp/* The a29k assembler does not permits labels to start with $.  */
10533965Sjdp#define LEX_DOLLAR 3
10633965Sjdp#endif
10733965Sjdp
10833965Sjdp#ifndef LEX_TILDE
10933965Sjdp/* The Delta 68k assembler permits ~ at start of label names.  */
11033965Sjdp#define LEX_TILDE 0
11133965Sjdp#endif
11233965Sjdp
11377298Sobrien/* Used by is_... macros. our ctype[].  */
11477298Sobrienchar lex_type[256] = {
11533965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* @ABCDEFGHIJKLMNO */
11633965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* PQRSTUVWXYZ[\]^_ */
11760484Sobrien  0, 0, 0, LEX_HASH, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
11833965Sjdp  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM,	/* 0123456789:;<=>? */
11933965Sjdp  LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,	/* @ABCDEFGHIJKLMNO */
12033965Sjdp  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
12133965Sjdp  0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,	/* `abcdefghijklmno */
12277298Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~.  */
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,
12560484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12660484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12760484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12860484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12960484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
13060484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
13133965Sjdp};
13233965Sjdp
13377298Sobrien/* In: a character.
13477298Sobrien   Out: 1 if this character ends a line.  */
13577298Sobrienchar is_end_of_line[256] = {
13633965Sjdp#ifdef CR_EOL
13777298Sobrien  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,	/* @abcdefghijklmno */
13833965Sjdp#else
13977298Sobrien  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,	/* @abcdefghijklmno */
14033965Sjdp#endif
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,	/* 0123456789:;<=>? */
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,	/* */
15077298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
15177298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
15277298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
15377298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
15477298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
15577298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0	/* */
15633965Sjdp};
15733965Sjdp
158130561Sobrien#ifndef TC_CASE_SENSITIVE
15977298Sobrienchar original_case_string[128];
16077298Sobrien#endif
16133965Sjdp
16277298Sobrien/* Functions private to this file.  */
16333965Sjdp
16477298Sobrienstatic char *buffer;	/* 1st char of each buffer of lines is here.  */
16577298Sobrienstatic char *buffer_limit;	/*->1 + last char in buffer.  */
16677298Sobrien
16777298Sobrien/* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1
16877298Sobrien   in the tc-<CPU>.h file.  See the "Porting GAS" section of the
16977298Sobrien   internals manual.  */
17033965Sjdpint target_big_endian = TARGET_BYTES_BIG_ENDIAN;
17133965Sjdp
17277298Sobrien/* Variables for handling include file directory table.  */
17333965Sjdp
17477298Sobrien/* Table of pointers to directories to search for .include's.  */
17577298Sobrienchar **include_dirs;
17633965Sjdp
17777298Sobrien/* How many are in the table.  */
17877298Sobrienint include_dir_count;
17977298Sobrien
18077298Sobrien/* Length of longest in table.  */
18177298Sobrienint include_dir_maxlen = 1;
18277298Sobrien
18333965Sjdp#ifndef WORKING_DOT_WORD
18433965Sjdpstruct broken_word *broken_words;
18533965Sjdpint new_broken_words;
18633965Sjdp#endif
18733965Sjdp
18833965Sjdp/* The current offset into the absolute section.  We don't try to
18933965Sjdp   build frags in the absolute section, since no data can be stored
19033965Sjdp   there.  We just keep track of the current offset.  */
19133965SjdpaddressT abs_section_offset;
19233965Sjdp
19333965Sjdp/* If this line had an MRI style label, it is stored in this variable.
19433965Sjdp   This is used by some of the MRI pseudo-ops.  */
19533965SjdpsymbolS *line_label;
19633965Sjdp
19733965Sjdp/* This global variable is used to support MRI common sections.  We
19833965Sjdp   translate such sections into a common symbol.  This variable is
19933965Sjdp   non-NULL when we are in an MRI common section.  */
20033965SjdpsymbolS *mri_common_symbol;
20133965Sjdp
20233965Sjdp/* In MRI mode, after a dc.b pseudo-op with an odd number of bytes, we
20333965Sjdp   need to align to an even byte boundary unless the next pseudo-op is
20433965Sjdp   dc.b, ds.b, or dcb.b.  This variable is set to 1 if an alignment
20533965Sjdp   may be needed.  */
20633965Sjdpstatic int mri_pending_align;
20733965Sjdp
20838889Sjdp#ifndef NO_LISTING
20938889Sjdp#ifdef OBJ_ELF
21038889Sjdp/* This variable is set to be non-zero if the next string we see might
21138889Sjdp   be the name of the source file in DWARF debugging information.  See
21238889Sjdp   the comment in emit_expr for the format we look for.  */
21338889Sjdpstatic int dwarf_file_string;
21438889Sjdp#endif
21538889Sjdp#endif
21638889Sjdp
217130561Sobrienstatic void do_align (int, char *, int, int);
218130561Sobrienstatic void s_align (int, int);
219130561Sobrienstatic int hex_float (int, char *);
220130561Sobrienstatic segT get_known_segmented_expression (expressionS * expP);
221130561Sobrienstatic void pobegin (void);
222130561Sobrienstatic int get_line_sb (sb *);
223130561Sobrienstatic void generate_file_debug (void);
22433965Sjdp
22533965Sjdpvoid
226130561Sobrienread_begin (void)
22733965Sjdp{
22833965Sjdp  const char *p;
22933965Sjdp
23033965Sjdp  pobegin ();
23133965Sjdp  obj_read_begin_hook ();
23233965Sjdp
23333965Sjdp  /* Something close -- but not too close -- to a multiple of 1024.
23433965Sjdp     The debugging malloc I'm using has 24 bytes of overhead.  */
23533965Sjdp  obstack_begin (&notes, chunksize);
23633965Sjdp  obstack_begin (&cond_obstack, chunksize);
23733965Sjdp
23877298Sobrien  /* Use machine dependent syntax.  */
23933965Sjdp  for (p = line_separator_chars; *p; p++)
24033965Sjdp    is_end_of_line[(unsigned char) *p] = 1;
24177298Sobrien  /* Use more.  FIXME-SOMEDAY.  */
24233965Sjdp
24333965Sjdp  if (flag_mri)
24433965Sjdp    lex_type['?'] = 3;
24533965Sjdp}
24633965Sjdp
24777298Sobrien/* Set up pseudo-op tables.  */
24833965Sjdp
24933965Sjdpstatic struct hash_control *po_hash;
25033965Sjdp
25177298Sobrienstatic const pseudo_typeS potable[] = {
25233965Sjdp  {"abort", s_abort, 0},
25333965Sjdp  {"align", s_align_ptwo, 0},
25433965Sjdp  {"ascii", stringer, 0},
25533965Sjdp  {"asciz", stringer, 1},
25633965Sjdp  {"balign", s_align_bytes, 0},
25733965Sjdp  {"balignw", s_align_bytes, -2},
25833965Sjdp  {"balignl", s_align_bytes, -4},
25977298Sobrien/* block  */
26033965Sjdp  {"byte", cons, 1},
26133965Sjdp  {"comm", s_comm, 0},
26233965Sjdp  {"common", s_mri_common, 0},
26333965Sjdp  {"common.s", s_mri_common, 1},
26433965Sjdp  {"data", s_data, 0},
26533965Sjdp  {"dc", cons, 2},
26633965Sjdp  {"dc.b", cons, 1},
26733965Sjdp  {"dc.d", float_cons, 'd'},
26833965Sjdp  {"dc.l", cons, 4},
26933965Sjdp  {"dc.s", float_cons, 'f'},
27033965Sjdp  {"dc.w", cons, 2},
27133965Sjdp  {"dc.x", float_cons, 'x'},
27233965Sjdp  {"dcb", s_space, 2},
27333965Sjdp  {"dcb.b", s_space, 1},
27433965Sjdp  {"dcb.d", s_float_space, 'd'},
27533965Sjdp  {"dcb.l", s_space, 4},
27633965Sjdp  {"dcb.s", s_float_space, 'f'},
27733965Sjdp  {"dcb.w", s_space, 2},
27833965Sjdp  {"dcb.x", s_float_space, 'x'},
27933965Sjdp  {"ds", s_space, 2},
28033965Sjdp  {"ds.b", s_space, 1},
28133965Sjdp  {"ds.d", s_space, 8},
28233965Sjdp  {"ds.l", s_space, 4},
28333965Sjdp  {"ds.p", s_space, 12},
28433965Sjdp  {"ds.s", s_space, 4},
28533965Sjdp  {"ds.w", s_space, 2},
28633965Sjdp  {"ds.x", s_space, 12},
28733965Sjdp  {"debug", s_ignore, 0},
28833965Sjdp#ifdef S_SET_DESC
28933965Sjdp  {"desc", s_desc, 0},
29033965Sjdp#endif
29177298Sobrien/* dim  */
29233965Sjdp  {"double", float_cons, 'd'},
29377298Sobrien/* dsect  */
29477298Sobrien  {"eject", listing_eject, 0},	/* Formfeed listing.  */
29533965Sjdp  {"else", s_else, 0},
29633965Sjdp  {"elsec", s_else, 0},
29760484Sobrien  {"elseif", s_elseif, (int) O_ne},
29833965Sjdp  {"end", s_end, 0},
29933965Sjdp  {"endc", s_endif, 0},
30060484Sobrien  {"endfunc", s_func, 1},
30133965Sjdp  {"endif", s_endif, 0},
30289857Sobrien  {"endr", s_bad_endr, 0},
30377298Sobrien/* endef  */
30433965Sjdp  {"equ", s_set, 0},
30533965Sjdp  {"equiv", s_set, 1},
30633965Sjdp  {"err", s_err, 0},
30733965Sjdp  {"exitm", s_mexit, 0},
30877298Sobrien/* extend  */
30977298Sobrien  {"extern", s_ignore, 0},	/* We treat all undef as ext.  */
31033965Sjdp  {"appfile", s_app_file, 1},
31133965Sjdp  {"appline", s_app_line, 0},
31233965Sjdp  {"fail", s_fail, 0},
31333965Sjdp  {"file", s_app_file, 0},
31433965Sjdp  {"fill", s_fill, 0},
31533965Sjdp  {"float", float_cons, 'f'},
31633965Sjdp  {"format", s_ignore, 0},
31760484Sobrien  {"func", s_func, 0},
31833965Sjdp  {"global", s_globl, 0},
31933965Sjdp  {"globl", s_globl, 0},
32033965Sjdp  {"hword", cons, 2},
32133965Sjdp  {"if", s_if, (int) O_ne},
32233965Sjdp  {"ifc", s_ifc, 0},
32333965Sjdp  {"ifdef", s_ifdef, 0},
32433965Sjdp  {"ifeq", s_if, (int) O_eq},
32533965Sjdp  {"ifeqs", s_ifeqs, 0},
32633965Sjdp  {"ifge", s_if, (int) O_ge},
32733965Sjdp  {"ifgt", s_if, (int) O_gt},
32833965Sjdp  {"ifle", s_if, (int) O_le},
32933965Sjdp  {"iflt", s_if, (int) O_lt},
33033965Sjdp  {"ifnc", s_ifc, 1},
33133965Sjdp  {"ifndef", s_ifdef, 1},
33233965Sjdp  {"ifne", s_if, (int) O_ne},
33333965Sjdp  {"ifnes", s_ifeqs, 1},
33433965Sjdp  {"ifnotdef", s_ifdef, 1},
33589857Sobrien  {"incbin", s_incbin, 0},
33633965Sjdp  {"include", s_include, 0},
33733965Sjdp  {"int", cons, 4},
33833965Sjdp  {"irp", s_irp, 0},
33933965Sjdp  {"irep", s_irp, 0},
34033965Sjdp  {"irpc", s_irp, 1},
34133965Sjdp  {"irepc", s_irp, 1},
34233965Sjdp  {"lcomm", s_lcomm, 0},
34377298Sobrien  {"lflags", listing_flags, 0},	/* Listing flags.  */
34433965Sjdp  {"linkonce", s_linkonce, 0},
34577298Sobrien  {"list", listing_list, 1},	/* Turn listing on.  */
34633965Sjdp  {"llen", listing_psize, 1},
34733965Sjdp  {"long", cons, 4},
34833965Sjdp  {"lsym", s_lsym, 0},
34933965Sjdp  {"macro", s_macro, 0},
35033965Sjdp  {"mexit", s_mexit, 0},
35133965Sjdp  {"mri", s_mri, 0},
35233965Sjdp  {".mri", s_mri, 0},	/* Special case so .mri works in MRI mode.  */
35333965Sjdp  {"name", s_ignore, 0},
35433965Sjdp  {"noformat", s_ignore, 0},
35577298Sobrien  {"nolist", listing_list, 0},	/* Turn listing off.  */
35633965Sjdp  {"nopage", listing_nopage, 0},
35733965Sjdp  {"octa", cons, 16},
35833965Sjdp  {"offset", s_struct, 0},
35933965Sjdp  {"org", s_org, 0},
36033965Sjdp  {"p2align", s_align_ptwo, 0},
36133965Sjdp  {"p2alignw", s_align_ptwo, -2},
36233965Sjdp  {"p2alignl", s_align_ptwo, -4},
36333965Sjdp  {"page", listing_eject, 0},
36433965Sjdp  {"plen", listing_psize, 0},
36533965Sjdp  {"print", s_print, 0},
36677298Sobrien  {"psize", listing_psize, 0},	/* Set paper size.  */
36733965Sjdp  {"purgem", s_purgem, 0},
36833965Sjdp  {"quad", cons, 8},
36933965Sjdp  {"rep", s_rept, 0},
37033965Sjdp  {"rept", s_rept, 0},
37133965Sjdp  {"rva", s_rva, 4},
37277298Sobrien  {"sbttl", listing_title, 1},	/* Subtitle of listing.  */
37377298Sobrien/* scl  */
37477298Sobrien/* sect  */
37533965Sjdp  {"set", s_set, 0},
37633965Sjdp  {"short", cons, 2},
37733965Sjdp  {"single", float_cons, 'f'},
37877298Sobrien/* size  */
37933965Sjdp  {"space", s_space, 0},
38033965Sjdp  {"skip", s_space, 0},
38138889Sjdp  {"sleb128", s_leb128, 1},
38233965Sjdp  {"spc", s_ignore, 0},
38333965Sjdp  {"stabd", s_stab, 'd'},
38433965Sjdp  {"stabn", s_stab, 'n'},
38533965Sjdp  {"stabs", s_stab, 's'},
38633965Sjdp  {"string", stringer, 1},
38733965Sjdp  {"struct", s_struct, 0},
38877298Sobrien/* tag  */
38933965Sjdp  {"text", s_text, 0},
39033965Sjdp
39133965Sjdp  /* This is for gcc to use.  It's only just been added (2/94), so gcc
39233965Sjdp     won't be able to use it for a while -- probably a year or more.
39333965Sjdp     But once this has been released, check with gcc maintainers
39433965Sjdp     before deleting it or even changing the spelling.  */
39533965Sjdp  {"this_GCC_requires_the_GNU_assembler", s_ignore, 0},
39633965Sjdp  /* If we're folding case -- done for some targets, not necessarily
39733965Sjdp     all -- the above string in an input file will be converted to
39833965Sjdp     this one.  Match it either way...  */
39933965Sjdp  {"this_gcc_requires_the_gnu_assembler", s_ignore, 0},
40033965Sjdp
40177298Sobrien  {"title", listing_title, 0},	/* Listing title.  */
40233965Sjdp  {"ttl", listing_title, 0},
40377298Sobrien/* type  */
40438889Sjdp  {"uleb128", s_leb128, 0},
40577298Sobrien/* use  */
40677298Sobrien/* val  */
40733965Sjdp  {"xcom", s_comm, 0},
40833965Sjdp  {"xdef", s_globl, 0},
40933965Sjdp  {"xref", s_ignore, 0},
41033965Sjdp  {"xstabs", s_xstab, 's'},
41133965Sjdp  {"word", cons, 2},
41233965Sjdp  {"zero", s_space, 0},
41377298Sobrien  {NULL, NULL, 0}			/* End sentinel.  */
41433965Sjdp};
41533965Sjdp
41633965Sjdpstatic int pop_override_ok = 0;
41733965Sjdpstatic const char *pop_table_name;
41833965Sjdp
41933965Sjdpvoid
420130561Sobrienpop_insert (const pseudo_typeS *table)
42133965Sjdp{
42233965Sjdp  const char *errtxt;
42333965Sjdp  const pseudo_typeS *pop;
42433965Sjdp  for (pop = table; pop->poc_name; pop++)
42533965Sjdp    {
42633965Sjdp      errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
42733965Sjdp      if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists")))
42860484Sobrien	as_fatal (_("error constructing %s pseudo-op table: %s"), pop_table_name,
42933965Sjdp		  errtxt);
43033965Sjdp    }
43133965Sjdp}
43233965Sjdp
43333965Sjdp#ifndef md_pop_insert
43433965Sjdp#define md_pop_insert()		pop_insert(md_pseudo_table)
43533965Sjdp#endif
43633965Sjdp
43733965Sjdp#ifndef obj_pop_insert
43833965Sjdp#define obj_pop_insert()	pop_insert(obj_pseudo_table)
43933965Sjdp#endif
44033965Sjdp
441130561Sobrien#ifndef cfi_pop_insert
442130561Sobrien#define cfi_pop_insert()	pop_insert(cfi_pseudo_table)
443130561Sobrien#endif
444130561Sobrien
44577298Sobrienstatic void
446130561Sobrienpobegin (void)
44733965Sjdp{
44833965Sjdp  po_hash = hash_new ();
44933965Sjdp
45077298Sobrien  /* Do the target-specific pseudo ops.  */
45133965Sjdp  pop_table_name = "md";
45233965Sjdp  md_pop_insert ();
45333965Sjdp
45477298Sobrien  /* Now object specific.  Skip any that were in the target table.  */
45533965Sjdp  pop_table_name = "obj";
45633965Sjdp  pop_override_ok = 1;
45733965Sjdp  obj_pop_insert ();
45833965Sjdp
45977298Sobrien  /* Now portable ones.  Skip any that we've seen already.  */
46033965Sjdp  pop_table_name = "standard";
46133965Sjdp  pop_insert (potable);
462130561Sobrien
463130561Sobrien#ifdef TARGET_USE_CFIPOP
464130561Sobrien  pop_table_name = "cfi";
465130561Sobrien  pop_override_ok = 1;
466130561Sobrien  cfi_pop_insert ();
467130561Sobrien#endif
46833965Sjdp}
46933965Sjdp
47033965Sjdp#define HANDLE_CONDITIONAL_ASSEMBLY()					\
47133965Sjdp  if (ignore_input ())							\
47233965Sjdp    {									\
47377298Sobrien      while (!is_end_of_line[(unsigned char) *input_line_pointer++])	\
47433965Sjdp	if (input_line_pointer == buffer_limit)				\
47533965Sjdp	  break;							\
47633965Sjdp      continue;								\
47733965Sjdp    }
47833965Sjdp
47933965Sjdp/* This function is used when scrubbing the characters between #APP
48033965Sjdp   and #NO_APP.  */
48133965Sjdp
48233965Sjdpstatic char *scrub_string;
48333965Sjdpstatic char *scrub_string_end;
48433965Sjdp
48533965Sjdpstatic int
486130561Sobrienscrub_from_string (char *buf, int buflen)
48733965Sjdp{
48860484Sobrien  int copy;
48933965Sjdp
49060484Sobrien  copy = scrub_string_end - scrub_string;
49160484Sobrien  if (copy > buflen)
49260484Sobrien    copy = buflen;
49360484Sobrien  memcpy (buf, scrub_string, copy);
49460484Sobrien  scrub_string += copy;
49560484Sobrien  return copy;
49633965Sjdp}
49733965Sjdp
49877298Sobrien/* We read the file, putting things into a web that represents what we
49977298Sobrien   have been reading.  */
50077298Sobrienvoid
501130561Sobrienread_a_source_file (char *name)
50233965Sjdp{
50333965Sjdp  register char c;
50477298Sobrien  register char *s;		/* String of symbol, '\0' appended.  */
50533965Sjdp  register int temp;
50633965Sjdp  pseudo_typeS *pop;
50733965Sjdp
50877298Sobrien#ifdef WARN_COMMENTS
50977298Sobrien  found_comment = 0;
51077298Sobrien#endif
51177298Sobrien
51233965Sjdp  buffer = input_scrub_new_file (name);
51333965Sjdp
51433965Sjdp  listing_file (name);
51538889Sjdp  listing_newline (NULL);
51638889Sjdp  register_dependency (name);
51733965Sjdp
51860484Sobrien  /* Generate debugging information before we've read anything in to denote
51960484Sobrien     this file as the "main" source file and not a subordinate one
52060484Sobrien     (e.g. N_SO vs N_SOL in stabs).  */
52160484Sobrien  generate_file_debug ();
52260484Sobrien
52333965Sjdp  while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0)
52477298Sobrien    {				/* We have another line to parse.  */
52577298Sobrien      know (buffer_limit[-1] == '\n');	/* Must have a sentinel.  */
526130561Sobrien
52733965Sjdp      while (input_line_pointer < buffer_limit)
52833965Sjdp	{
52977298Sobrien	  /* We have more of this buffer to parse.  */
53033965Sjdp
53177298Sobrien	  /* We now have input_line_pointer->1st char of next line.
53277298Sobrien	     If input_line_pointer [-1] == '\n' then we just
53377298Sobrien	     scanned another line: so bump line counters.  */
53433965Sjdp	  if (is_end_of_line[(unsigned char) input_line_pointer[-1]])
53533965Sjdp	    {
53633965Sjdp#ifdef md_start_line_hook
53733965Sjdp	      md_start_line_hook ();
53833965Sjdp#endif
53933965Sjdp	      if (input_line_pointer[-1] == '\n')
54033965Sjdp		bump_line_counters ();
54133965Sjdp
54233965Sjdp	      line_label = NULL;
54333965Sjdp
54460484Sobrien	      if (LABELS_WITHOUT_COLONS || flag_m68k_mri)
54533965Sjdp		{
54633965Sjdp		  /* Text at the start of a line must be a label, we
54733965Sjdp		     run down and stick a colon in.  */
54833965Sjdp		  if (is_name_beginner (*input_line_pointer))
54933965Sjdp		    {
55033965Sjdp		      char *line_start = input_line_pointer;
55133965Sjdp		      char c;
55233965Sjdp		      int mri_line_macro;
55333965Sjdp
55433965Sjdp		      LISTING_NEWLINE ();
55533965Sjdp		      HANDLE_CONDITIONAL_ASSEMBLY ();
55633965Sjdp
55733965Sjdp		      c = get_symbol_end ();
55833965Sjdp
55933965Sjdp		      /* In MRI mode, the EQU and MACRO pseudoops must
56033965Sjdp			 be handled specially.  */
56133965Sjdp		      mri_line_macro = 0;
56233965Sjdp		      if (flag_m68k_mri)
56333965Sjdp			{
56433965Sjdp			  char *rest = input_line_pointer + 1;
56533965Sjdp
56633965Sjdp			  if (*rest == ':')
56733965Sjdp			    ++rest;
56833965Sjdp			  if (*rest == ' ' || *rest == '\t')
56933965Sjdp			    ++rest;
57033965Sjdp			  if ((strncasecmp (rest, "EQU", 3) == 0
57133965Sjdp			       || strncasecmp (rest, "SET", 3) == 0)
57233965Sjdp			      && (rest[3] == ' ' || rest[3] == '\t'))
57333965Sjdp			    {
57433965Sjdp			      input_line_pointer = rest + 3;
57533965Sjdp			      equals (line_start,
57633965Sjdp				      strncasecmp (rest, "SET", 3) == 0);
57733965Sjdp			      continue;
57833965Sjdp			    }
57933965Sjdp			  if (strncasecmp (rest, "MACRO", 5) == 0
58033965Sjdp			      && (rest[5] == ' '
58133965Sjdp				  || rest[5] == '\t'
58233965Sjdp				  || is_end_of_line[(unsigned char) rest[5]]))
58333965Sjdp			    mri_line_macro = 1;
58433965Sjdp			}
58533965Sjdp
58633965Sjdp		      /* In MRI mode, we need to handle the MACRO
587130561Sobrien			 pseudo-op specially: we don't want to put the
588130561Sobrien			 symbol in the symbol table.  */
58977298Sobrien		      if (!mri_line_macro
59060484Sobrien#ifdef TC_START_LABEL_WITHOUT_COLON
59177298Sobrien			  && TC_START_LABEL_WITHOUT_COLON(c,
59277298Sobrien							  input_line_pointer)
59360484Sobrien#endif
59477298Sobrien			  )
59533965Sjdp			line_label = colon (line_start);
59633965Sjdp		      else
59733965Sjdp			line_label = symbol_create (line_start,
59833965Sjdp						    absolute_section,
59933965Sjdp						    (valueT) 0,
60033965Sjdp						    &zero_address_frag);
60133965Sjdp
60233965Sjdp		      *input_line_pointer = c;
60333965Sjdp		      if (c == ':')
60433965Sjdp			input_line_pointer++;
60533965Sjdp		    }
60633965Sjdp		}
60733965Sjdp	    }
60833965Sjdp
609130561Sobrien	  /* We are at the beginning of a line, or similar place.
61077298Sobrien	     We expect a well-formed assembler statement.
61177298Sobrien	     A "symbol-name:" is a statement.
61277298Sobrien
61377298Sobrien	     Depending on what compiler is used, the order of these tests
61477298Sobrien	     may vary to catch most common case 1st.
61577298Sobrien	     Each test is independent of all other tests at the (top) level.
61677298Sobrien	     PLEASE make a compiler that doesn't use this assembler.
61777298Sobrien	     It is crufty to waste a compiler's time encoding things for this
61877298Sobrien	     assembler, which then wastes more time decoding it.
61977298Sobrien	     (And communicating via (linear) files is silly!
62077298Sobrien	     If you must pass stuff, please pass a tree!)  */
62133965Sjdp	  if ((c = *input_line_pointer++) == '\t'
62233965Sjdp	      || c == ' '
62333965Sjdp	      || c == '\f'
62433965Sjdp	      || c == 0)
62577298Sobrien	    c = *input_line_pointer++;
62638889Sjdp
62777298Sobrien	  know (c != ' ');	/* No further leading whitespace.  */
62877298Sobrien
62938889Sjdp#ifndef NO_LISTING
63038889Sjdp	  /* If listing is on, and we are expanding a macro, then give
63138889Sjdp	     the listing code the contents of the expanded line.  */
63238889Sjdp	  if (listing)
63338889Sjdp	    {
63438889Sjdp	      if ((listing & LISTING_MACEXP) && macro_nest > 0)
63538889Sjdp		{
63638889Sjdp		  char *copy;
63738889Sjdp		  int len;
63838889Sjdp
63938889Sjdp		  /* Find the end of the current expanded macro line.  */
64077298Sobrien		  for (s = input_line_pointer - 1; *s; ++s)
64138889Sjdp		    if (is_end_of_line[(unsigned char) *s])
64238889Sjdp		      break;
64338889Sjdp
64438889Sjdp		  /* Copy it for safe keeping.  Also give an indication of
64538889Sjdp		     how much macro nesting is involved at this point.  */
64677298Sobrien		  len = s - (input_line_pointer - 1);
64738889Sjdp		  copy = (char *) xmalloc (len + macro_nest + 2);
64838889Sjdp		  memset (copy, '>', macro_nest);
64938889Sjdp		  copy[macro_nest] = ' ';
65077298Sobrien		  memcpy (copy + macro_nest + 1, input_line_pointer - 1, len);
65177298Sobrien		  copy[macro_nest + 1 + len] = '\0';
65238889Sjdp
65338889Sjdp		  /* Install the line with the listing facility.  */
65438889Sjdp		  listing_newline (copy);
65538889Sjdp		}
65638889Sjdp	      else
65738889Sjdp		listing_newline (NULL);
65838889Sjdp	    }
65938889Sjdp#endif
66077298Sobrien	  /* C is the 1st significant character.
66177298Sobrien	     Input_line_pointer points after that character.  */
66233965Sjdp	  if (is_name_beginner (c))
66333965Sjdp	    {
66477298Sobrien	      /* Want user-defined label or pseudo/opcode.  */
66533965Sjdp	      HANDLE_CONDITIONAL_ASSEMBLY ();
66633965Sjdp
66733965Sjdp	      s = --input_line_pointer;
66877298Sobrien	      c = get_symbol_end ();	/* name's delimiter.  */
66977298Sobrien
67077298Sobrien	      /* C is character after symbol.
671130561Sobrien		 That character's place in the input line is now '\0'.
672130561Sobrien		 S points to the beginning of the symbol.
673130561Sobrien		   [In case of pseudo-op, s->'.'.]
674130561Sobrien		 Input_line_pointer->'\0' where c was.  */
67577298Sobrien	      if (TC_START_LABEL (c, input_line_pointer))
67633965Sjdp		{
67733965Sjdp		  if (flag_m68k_mri)
67833965Sjdp		    {
67933965Sjdp		      char *rest = input_line_pointer + 1;
68033965Sjdp
68133965Sjdp		      /* In MRI mode, \tsym: set 0 is permitted.  */
68233965Sjdp		      if (*rest == ':')
68333965Sjdp			++rest;
68477298Sobrien
68533965Sjdp		      if (*rest == ' ' || *rest == '\t')
68633965Sjdp			++rest;
68777298Sobrien
68833965Sjdp		      if ((strncasecmp (rest, "EQU", 3) == 0
68933965Sjdp			   || strncasecmp (rest, "SET", 3) == 0)
69033965Sjdp			  && (rest[3] == ' ' || rest[3] == '\t'))
69133965Sjdp			{
69233965Sjdp			  input_line_pointer = rest + 3;
69333965Sjdp			  equals (s, 1);
69433965Sjdp			  continue;
69533965Sjdp			}
69633965Sjdp		    }
69733965Sjdp
69877298Sobrien		  line_label = colon (s);	/* User-defined label.  */
69977298Sobrien		  /* Put ':' back for error messages' sake.  */
70077298Sobrien		  *input_line_pointer++ = ':';
701130561Sobrien#ifdef tc_check_label
702130561Sobrien		  tc_check_label (line_label);
703130561Sobrien#endif
70477298Sobrien		  /* Input_line_pointer->after ':'.  */
70533965Sjdp		  SKIP_WHITESPACE ();
70633965Sjdp		}
70733965Sjdp	      else if (c == '='
70833965Sjdp		       || ((c == ' ' || c == '\t')
70933965Sjdp			   && input_line_pointer[1] == '='
71033965Sjdp#ifdef TC_EQUAL_IN_INSN
71177298Sobrien			   && !TC_EQUAL_IN_INSN (c, input_line_pointer)
71233965Sjdp#endif
71333965Sjdp			   ))
71433965Sjdp		{
71533965Sjdp		  equals (s, 1);
71633965Sjdp		  demand_empty_rest_of_line ();
71733965Sjdp		}
71833965Sjdp	      else
71977298Sobrien		{
72077298Sobrien		  /* Expect pseudo-op or machine instruction.  */
72133965Sjdp		  pop = NULL;
72233965Sjdp
723130561Sobrien#ifndef TC_CASE_SENSITIVE
72433965Sjdp		  {
72533965Sjdp		    char *s2 = s;
72677298Sobrien
72777298Sobrien		    strncpy (original_case_string, s2, sizeof (original_case_string));
72877298Sobrien		    original_case_string[sizeof (original_case_string) - 1] = 0;
72977298Sobrien
73033965Sjdp		    while (*s2)
73133965Sjdp		      {
73289857Sobrien			*s2 = TOLOWER (*s2);
73333965Sjdp			s2++;
73433965Sjdp		      }
73533965Sjdp		  }
73633965Sjdp#endif
73760484Sobrien		  if (NO_PSEUDO_DOT || flag_m68k_mri)
73833965Sjdp		    {
73933965Sjdp		      /* The MRI assembler and the m88k use pseudo-ops
740130561Sobrien			 without a period.  */
74133965Sjdp		      pop = (pseudo_typeS *) hash_find (po_hash, s);
74233965Sjdp		      if (pop != NULL && pop->poc_handler == NULL)
74333965Sjdp			pop = NULL;
74433965Sjdp		    }
74533965Sjdp
74633965Sjdp		  if (pop != NULL
74777298Sobrien		      || (!flag_m68k_mri && *s == '.'))
74833965Sjdp		    {
74977298Sobrien		      /* PSEUDO - OP.
75033965Sjdp
751130561Sobrien			 WARNING: c has next char, which may be end-of-line.
752130561Sobrien			 We lookup the pseudo-op table with s+1 because we
753130561Sobrien			 already know that the pseudo-op begins with a '.'.  */
75477298Sobrien
75533965Sjdp		      if (pop == NULL)
75633965Sjdp			pop = (pseudo_typeS *) hash_find (po_hash, s + 1);
757130561Sobrien		      if (pop && !pop->poc_handler)
758130561Sobrien			pop = NULL;
75933965Sjdp
76033965Sjdp		      /* In MRI mode, we may need to insert an
761130561Sobrien			 automatic alignment directive.  What a hack
762130561Sobrien			 this is.  */
76333965Sjdp		      if (mri_pending_align
76433965Sjdp			  && (pop == NULL
76577298Sobrien			      || !((pop->poc_handler == cons
76677298Sobrien				    && pop->poc_val == 1)
76777298Sobrien				   || (pop->poc_handler == s_space
76877298Sobrien				       && pop->poc_val == 1)
76933965Sjdp#ifdef tc_conditional_pseudoop
77077298Sobrien				   || tc_conditional_pseudoop (pop)
77133965Sjdp#endif
77277298Sobrien				   || pop->poc_handler == s_if
77377298Sobrien				   || pop->poc_handler == s_ifdef
77477298Sobrien				   || pop->poc_handler == s_ifc
77577298Sobrien				   || pop->poc_handler == s_ifeqs
77677298Sobrien				   || pop->poc_handler == s_else
77777298Sobrien				   || pop->poc_handler == s_endif
77877298Sobrien				   || pop->poc_handler == s_globl
77977298Sobrien				   || pop->poc_handler == s_ignore)))
78033965Sjdp			{
78133965Sjdp			  do_align (1, (char *) NULL, 0, 0);
78233965Sjdp			  mri_pending_align = 0;
78377298Sobrien
78433965Sjdp			  if (line_label != NULL)
78533965Sjdp			    {
78660484Sobrien			      symbol_set_frag (line_label, frag_now);
78733965Sjdp			      S_SET_VALUE (line_label, frag_now_fix ());
78833965Sjdp			    }
78933965Sjdp			}
79033965Sjdp
79177298Sobrien		      /* Print the error msg now, while we still can.  */
79233965Sjdp		      if (pop == NULL)
79333965Sjdp			{
79489857Sobrien			  as_bad (_("unknown pseudo-op: `%s'"), s);
79533965Sjdp			  *input_line_pointer = c;
79633965Sjdp			  s_ignore (0);
79733965Sjdp			  continue;
79833965Sjdp			}
79933965Sjdp
80077298Sobrien		      /* Put it back for error messages etc.  */
80133965Sjdp		      *input_line_pointer = c;
80233965Sjdp		      /* The following skip of whitespace is compulsory.
80333965Sjdp			 A well shaped space is sometimes all that separates
80477298Sobrien			 keyword from operands.  */
80533965Sjdp		      if (c == ' ' || c == '\t')
80633965Sjdp			input_line_pointer++;
80777298Sobrien
80877298Sobrien		      /* Input_line is restored.
809130561Sobrien			 Input_line_pointer->1st non-blank char
810130561Sobrien			 after pseudo-operation.  */
81133965Sjdp		      (*pop->poc_handler) (pop->poc_val);
81233965Sjdp
81333965Sjdp		      /* If that was .end, just get out now.  */
81433965Sjdp		      if (pop->poc_handler == s_end)
81533965Sjdp			goto quit;
81633965Sjdp		    }
81733965Sjdp		  else
81833965Sjdp		    {
81933965Sjdp		      int inquote = 0;
82060484Sobrien#ifdef QUOTES_IN_INSN
82160484Sobrien		      int inescape = 0;
82260484Sobrien#endif
82333965Sjdp
82477298Sobrien		      /* WARNING: c has char, which may be end-of-line.  */
82577298Sobrien		      /* Also: input_line_pointer->`\0` where c was.  */
82633965Sjdp		      *input_line_pointer = c;
82733965Sjdp		      while (!is_end_of_line[(unsigned char) *input_line_pointer]
82833965Sjdp			     || inquote
82933965Sjdp#ifdef TC_EOL_IN_INSN
83033965Sjdp			     || TC_EOL_IN_INSN (input_line_pointer)
83133965Sjdp#endif
83233965Sjdp			     )
83333965Sjdp			{
83433965Sjdp			  if (flag_m68k_mri && *input_line_pointer == '\'')
83577298Sobrien			    inquote = !inquote;
83660484Sobrien#ifdef QUOTES_IN_INSN
83760484Sobrien			  if (inescape)
83860484Sobrien			    inescape = 0;
83960484Sobrien			  else if (*input_line_pointer == '"')
84077298Sobrien			    inquote = !inquote;
84160484Sobrien			  else if (*input_line_pointer == '\\')
84260484Sobrien			    inescape = 1;
84360484Sobrien#endif
84433965Sjdp			  input_line_pointer++;
84533965Sjdp			}
84633965Sjdp
84733965Sjdp		      c = *input_line_pointer;
84833965Sjdp		      *input_line_pointer = '\0';
84933965Sjdp
85060484Sobrien		      generate_lineno_debug ();
85138889Sjdp
85233965Sjdp		      if (macro_defined)
85333965Sjdp			{
85433965Sjdp			  sb out;
85533965Sjdp			  const char *err;
85677298Sobrien			  macro_entry *macro;
85733965Sjdp
858130561Sobrien			  if (check_macro (s, &out, &err, &macro))
85933965Sjdp			    {
86033965Sjdp			      if (err != NULL)
86160484Sobrien				as_bad ("%s", err);
86233965Sjdp			      *input_line_pointer++ = c;
86333965Sjdp			      input_scrub_include_sb (&out,
86460484Sobrien						      input_line_pointer, 1);
86533965Sjdp			      sb_kill (&out);
86633965Sjdp			      buffer_limit =
86733965Sjdp				input_scrub_next_buffer (&input_line_pointer);
86860484Sobrien#ifdef md_macro_info
86977298Sobrien			      md_macro_info (macro);
87060484Sobrien#endif
87133965Sjdp			      continue;
87233965Sjdp			    }
87333965Sjdp			}
87433965Sjdp
87533965Sjdp		      if (mri_pending_align)
87633965Sjdp			{
87733965Sjdp			  do_align (1, (char *) NULL, 0, 0);
87833965Sjdp			  mri_pending_align = 0;
87933965Sjdp			  if (line_label != NULL)
88033965Sjdp			    {
88160484Sobrien			      symbol_set_frag (line_label, frag_now);
88233965Sjdp			      S_SET_VALUE (line_label, frag_now_fix ());
88333965Sjdp			    }
88433965Sjdp			}
88533965Sjdp
88677298Sobrien		      md_assemble (s);	/* Assemble 1 instruction.  */
88733965Sjdp
88833965Sjdp		      *input_line_pointer++ = c;
88933965Sjdp
89033965Sjdp		      /* We resume loop AFTER the end-of-line from
89177298Sobrien			 this instruction.  */
89277298Sobrien		    }
89377298Sobrien		}
89433965Sjdp	      continue;
89577298Sobrien	    }
89633965Sjdp
89733965Sjdp	  /* Empty statement?  */
89833965Sjdp	  if (is_end_of_line[(unsigned char) c])
89933965Sjdp	    continue;
90033965Sjdp
90189857Sobrien	  if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (c))
90233965Sjdp	    {
90377298Sobrien	      /* local label  ("4:")  */
90433965Sjdp	      char *backup = input_line_pointer;
90533965Sjdp
90633965Sjdp	      HANDLE_CONDITIONAL_ASSEMBLY ();
90733965Sjdp
90833965Sjdp	      temp = c - '0';
90933965Sjdp
91077298Sobrien	      /* Read the whole number.  */
91189857Sobrien	      while (ISDIGIT (*input_line_pointer))
91233965Sjdp		{
91333965Sjdp		  temp = (temp * 10) + *input_line_pointer - '0';
91433965Sjdp		  ++input_line_pointer;
91577298Sobrien		}
91633965Sjdp
91733965Sjdp	      if (LOCAL_LABELS_DOLLAR
91833965Sjdp		  && *input_line_pointer == '$'
91933965Sjdp		  && *(input_line_pointer + 1) == ':')
92033965Sjdp		{
92133965Sjdp		  input_line_pointer += 2;
92233965Sjdp
92333965Sjdp		  if (dollar_label_defined (temp))
92433965Sjdp		    {
92560484Sobrien		      as_fatal (_("label \"%d$\" redefined"), temp);
92633965Sjdp		    }
92733965Sjdp
92833965Sjdp		  define_dollar_label (temp);
92933965Sjdp		  colon (dollar_label_name (temp, 0));
93033965Sjdp		  continue;
93133965Sjdp		}
93233965Sjdp
93333965Sjdp	      if (LOCAL_LABELS_FB
93433965Sjdp		  && *input_line_pointer++ == ':')
93533965Sjdp		{
93633965Sjdp		  fb_label_instance_inc (temp);
93733965Sjdp		  colon (fb_label_name (temp, 0));
93833965Sjdp		  continue;
93933965Sjdp		}
94033965Sjdp
94133965Sjdp	      input_line_pointer = backup;
94233965Sjdp	    }			/* local label  ("4:") */
94333965Sjdp
94433965Sjdp	  if (c && strchr (line_comment_chars, c))
94577298Sobrien	    {			/* Its a comment.  Better say APP or NO_APP.  */
946130561Sobrien	      sb sbuf;
94733965Sjdp	      char *ends;
94833965Sjdp	      char *new_buf;
94933965Sjdp	      char *new_tmp;
95033965Sjdp	      unsigned int new_length;
95133965Sjdp	      char *tmp_buf = 0;
95233965Sjdp
95333965Sjdp	      bump_line_counters ();
95433965Sjdp	      s = input_line_pointer;
95533965Sjdp	      if (strncmp (s, "APP\n", 4))
95633965Sjdp		continue;	/* We ignore it */
95733965Sjdp	      s += 4;
95833965Sjdp
959130561Sobrien	      sb_new (&sbuf);
96033965Sjdp	      ends = strstr (s, "#NO_APP\n");
96133965Sjdp
96233965Sjdp	      if (!ends)
96333965Sjdp		{
96433965Sjdp		  unsigned int tmp_len;
96533965Sjdp		  unsigned int num;
96633965Sjdp
96733965Sjdp		  /* The end of the #APP wasn't in this buffer.  We
96833965Sjdp		     keep reading in buffers until we find the #NO_APP
96933965Sjdp		     that goes with this #APP  There is one.  The specs
970130561Sobrien		     guarantee it...  */
97133965Sjdp		  tmp_len = buffer_limit - s;
97233965Sjdp		  tmp_buf = xmalloc (tmp_len + 1);
97333965Sjdp		  memcpy (tmp_buf, s, tmp_len);
97433965Sjdp		  do
97533965Sjdp		    {
97633965Sjdp		      new_tmp = input_scrub_next_buffer (&buffer);
97733965Sjdp		      if (!new_tmp)
97833965Sjdp			break;
97933965Sjdp		      else
98033965Sjdp			buffer_limit = new_tmp;
98133965Sjdp		      input_line_pointer = buffer;
98233965Sjdp		      ends = strstr (buffer, "#NO_APP\n");
98333965Sjdp		      if (ends)
98433965Sjdp			num = ends - buffer;
98533965Sjdp		      else
98633965Sjdp			num = buffer_limit - buffer;
98733965Sjdp
98833965Sjdp		      tmp_buf = xrealloc (tmp_buf, tmp_len + num);
98933965Sjdp		      memcpy (tmp_buf + tmp_len, buffer, num);
99033965Sjdp		      tmp_len += num;
99133965Sjdp		    }
99233965Sjdp		  while (!ends);
99333965Sjdp
99433965Sjdp		  input_line_pointer = ends ? ends + 8 : NULL;
99533965Sjdp
99633965Sjdp		  s = tmp_buf;
99733965Sjdp		  ends = s + tmp_len;
99833965Sjdp
99933965Sjdp		}
100033965Sjdp	      else
100133965Sjdp		{
100233965Sjdp		  input_line_pointer = ends + 8;
100333965Sjdp		}
100433965Sjdp
100533965Sjdp	      scrub_string = s;
100633965Sjdp	      scrub_string_end = ends;
100733965Sjdp
100833965Sjdp	      new_length = ends - s;
100933965Sjdp	      new_buf = (char *) xmalloc (new_length);
101033965Sjdp	      new_tmp = new_buf;
101133965Sjdp	      for (;;)
101233965Sjdp		{
101333965Sjdp		  int space;
101433965Sjdp		  int size;
101533965Sjdp
101633965Sjdp		  space = (new_buf + new_length) - new_tmp;
101733965Sjdp		  size = do_scrub_chars (scrub_from_string, new_tmp, space);
101833965Sjdp
101933965Sjdp		  if (size < space)
102033965Sjdp		    {
1021130561Sobrien		      new_tmp[size] = 0;
102233965Sjdp		      break;
102333965Sjdp		    }
102433965Sjdp
102533965Sjdp		  new_buf = xrealloc (new_buf, new_length + 100);
102633965Sjdp		  new_tmp = new_buf + new_length;
102733965Sjdp		  new_length += 100;
102833965Sjdp		}
102933965Sjdp
103033965Sjdp	      if (tmp_buf)
103133965Sjdp		free (tmp_buf);
103277298Sobrien
1033130561Sobrien	      /* We've "scrubbed" input to the preferred format.  In the
1034130561Sobrien		 process we may have consumed the whole of the remaining
1035130561Sobrien		 file (and included files).  We handle this formatted
1036130561Sobrien		 input similar to that of macro expansion, letting
1037130561Sobrien		 actual macro expansion (possibly nested) and other
1038130561Sobrien		 input expansion work.  Beware that in messages, line
1039130561Sobrien		 numbers and possibly file names will be incorrect.  */
1040130561Sobrien	      sb_add_string (&sbuf, new_buf);
1041130561Sobrien	      input_scrub_include_sb (&sbuf, input_line_pointer, 0);
1042130561Sobrien	      sb_kill (&sbuf);
1043130561Sobrien	      buffer_limit = input_scrub_next_buffer (&input_line_pointer);
1044130561Sobrien	      free (new_buf);
104533965Sjdp	      continue;
104633965Sjdp	    }
104733965Sjdp
104833965Sjdp	  HANDLE_CONDITIONAL_ASSEMBLY ();
104933965Sjdp
105033965Sjdp#ifdef tc_unrecognized_line
105133965Sjdp	  if (tc_unrecognized_line (c))
105233965Sjdp	    continue;
105333965Sjdp#endif
105489857Sobrien	  input_line_pointer--;
105589857Sobrien	  /* Report unknown char as ignored.  */
1056130561Sobrien	  demand_empty_rest_of_line ();
105777298Sobrien	}
105833965Sjdp
105933965Sjdp#ifdef md_after_pass_hook
106033965Sjdp      md_after_pass_hook ();
106133965Sjdp#endif
106277298Sobrien    }
106333965Sjdp
106433965Sjdp quit:
106533965Sjdp
106633965Sjdp#ifdef md_cleanup
106777298Sobrien  md_cleanup ();
106833965Sjdp#endif
106977298Sobrien  /* Close the input file.  */
107077298Sobrien  input_scrub_close ();
107177298Sobrien#ifdef WARN_COMMENTS
107277298Sobrien  {
107377298Sobrien    if (warn_comment && found_comment)
107477298Sobrien      as_warn_where (found_comment_file, found_comment,
107577298Sobrien		     "first comment found here");
107677298Sobrien  }
107777298Sobrien#endif
107833965Sjdp}
107933965Sjdp
108033965Sjdp/* For most MRI pseudo-ops, the line actually ends at the first
108133965Sjdp   nonquoted space.  This function looks for that point, stuffs a null
108233965Sjdp   in, and sets *STOPCP to the character that used to be there, and
108333965Sjdp   returns the location.
108433965Sjdp
108533965Sjdp   Until I hear otherwise, I am going to assume that this is only true
108633965Sjdp   for the m68k MRI assembler.  */
108733965Sjdp
108833965Sjdpchar *
1089130561Sobrienmri_comment_field (char *stopcp)
109033965Sjdp{
109177298Sobrien  char *s;
109233965Sjdp#ifdef TC_M68K
109333965Sjdp  int inquote = 0;
109433965Sjdp
109533965Sjdp  know (flag_m68k_mri);
109633965Sjdp
109733965Sjdp  for (s = input_line_pointer;
109877298Sobrien       ((!is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t')
109933965Sjdp	|| inquote);
110033965Sjdp       s++)
110133965Sjdp    {
110233965Sjdp      if (*s == '\'')
110377298Sobrien	inquote = !inquote;
110433965Sjdp    }
110533965Sjdp#else
110677298Sobrien  for (s = input_line_pointer;
110777298Sobrien       !is_end_of_line[(unsigned char) *s];
110877298Sobrien       s++)
110933965Sjdp    ;
111077298Sobrien#endif
111133965Sjdp  *stopcp = *s;
111233965Sjdp  *s = '\0';
111377298Sobrien
111433965Sjdp  return s;
111533965Sjdp}
111633965Sjdp
111733965Sjdp/* Skip to the end of an MRI comment field.  */
111833965Sjdp
111933965Sjdpvoid
1120130561Sobrienmri_comment_end (char *stop, int stopc)
112133965Sjdp{
112233965Sjdp  know (flag_mri);
112333965Sjdp
112433965Sjdp  input_line_pointer = stop;
112533965Sjdp  *stop = stopc;
112677298Sobrien  while (!is_end_of_line[(unsigned char) *input_line_pointer])
112733965Sjdp    ++input_line_pointer;
112833965Sjdp}
112933965Sjdp
113077298Sobrienvoid
1131130561Sobriens_abort (int ignore ATTRIBUTE_UNUSED)
113233965Sjdp{
113360484Sobrien  as_fatal (_(".abort detected.  Abandoning ship."));
113433965Sjdp}
113533965Sjdp
113633965Sjdp/* Guts of .align directive.  N is the power of two to which to align.
113733965Sjdp   FILL may be NULL, or it may point to the bytes of the fill pattern.
113833965Sjdp   LEN is the length of whatever FILL points to, if anything.  MAX is
113933965Sjdp   the maximum number of characters to skip when doing the alignment,
114033965Sjdp   or 0 if there is no maximum.  */
114133965Sjdp
114277298Sobrienstatic void
1143130561Sobriendo_align (int n, char *fill, int len, int max)
114433965Sjdp{
114589857Sobrien  if (now_seg == absolute_section)
114689857Sobrien    {
114789857Sobrien      if (fill != NULL)
114889857Sobrien	while (len-- > 0)
114989857Sobrien	  if (*fill++ != '\0')
115089857Sobrien	    {
115189857Sobrien	      as_warn (_("ignoring fill value in absolute section"));
115289857Sobrien	      break;
115389857Sobrien	    }
115489857Sobrien      fill = NULL;
115589857Sobrien      len = 0;
115689857Sobrien    }
115789857Sobrien
115833965Sjdp#ifdef md_do_align
115933965Sjdp  md_do_align (n, fill, len, max, just_record_alignment);
116033965Sjdp#endif
116133965Sjdp
116277298Sobrien  /* Only make a frag if we HAVE to...  */
116333965Sjdp  if (n != 0 && !need_pass_2)
116433965Sjdp    {
116577298Sobrien      if (fill == NULL)
116677298Sobrien	{
116777298Sobrien	  if (subseg_text_p (now_seg))
116877298Sobrien	    frag_align_code (n, max);
116977298Sobrien	  else
117077298Sobrien	    frag_align (n, 0, max);
117177298Sobrien	}
117277298Sobrien      else if (len <= 1)
117333965Sjdp	frag_align (n, *fill, max);
117433965Sjdp      else
117533965Sjdp	frag_align_pattern (n, fill, len, max);
117633965Sjdp    }
117733965Sjdp
117833965Sjdp#ifdef md_do_align
1179130561Sobrien just_record_alignment: ATTRIBUTE_UNUSED_LABEL
118033965Sjdp#endif
118133965Sjdp
118260484Sobrien  record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
118333965Sjdp}
118433965Sjdp
118533965Sjdp/* Handle the .align pseudo-op.  A positive ARG is a default alignment
118633965Sjdp   (in bytes).  A negative ARG is the negative of the length of the
118733965Sjdp   fill pattern.  BYTES_P is non-zero if the alignment value should be
118833965Sjdp   interpreted as the byte boundary, rather than the power of 2.  */
118933965Sjdp
119033965Sjdpstatic void
1191130561Sobriens_align (int arg, int bytes_p)
119233965Sjdp{
119333965Sjdp  register unsigned int align;
119433965Sjdp  char *stop = NULL;
119533965Sjdp  char stopc;
119633965Sjdp  offsetT fill = 0;
119733965Sjdp  int max;
119833965Sjdp  int fill_p;
119933965Sjdp
120033965Sjdp  if (flag_mri)
120133965Sjdp    stop = mri_comment_field (&stopc);
120233965Sjdp
120333965Sjdp  if (is_end_of_line[(unsigned char) *input_line_pointer])
120433965Sjdp    {
120533965Sjdp      if (arg < 0)
120633965Sjdp	align = 0;
120733965Sjdp      else
120877298Sobrien	align = arg;	/* Default value from pseudo-op table.  */
120933965Sjdp    }
121033965Sjdp  else
121133965Sjdp    {
121233965Sjdp      align = get_absolute_expression ();
121333965Sjdp      SKIP_WHITESPACE ();
121433965Sjdp    }
121533965Sjdp
121633965Sjdp  if (bytes_p)
121733965Sjdp    {
121833965Sjdp      /* Convert to a power of 2.  */
121933965Sjdp      if (align != 0)
122033965Sjdp	{
122133965Sjdp	  unsigned int i;
122233965Sjdp
122333965Sjdp	  for (i = 0; (align & 1) == 0; align >>= 1, ++i)
122433965Sjdp	    ;
122533965Sjdp	  if (align != 1)
122689857Sobrien	    as_bad (_("alignment not a power of 2"));
122777298Sobrien
122833965Sjdp	  align = i;
122933965Sjdp	}
123033965Sjdp    }
123133965Sjdp
123233965Sjdp  if (align > 15)
123333965Sjdp    {
123433965Sjdp      align = 15;
123589857Sobrien      as_warn (_("alignment too large: %u assumed"), align);
123633965Sjdp    }
123733965Sjdp
123833965Sjdp  if (*input_line_pointer != ',')
123933965Sjdp    {
124033965Sjdp      fill_p = 0;
124133965Sjdp      max = 0;
124233965Sjdp    }
124333965Sjdp  else
124433965Sjdp    {
124533965Sjdp      ++input_line_pointer;
124633965Sjdp      if (*input_line_pointer == ',')
124733965Sjdp	fill_p = 0;
124833965Sjdp      else
124933965Sjdp	{
125033965Sjdp	  fill = get_absolute_expression ();
125133965Sjdp	  SKIP_WHITESPACE ();
125233965Sjdp	  fill_p = 1;
125333965Sjdp	}
125433965Sjdp
125533965Sjdp      if (*input_line_pointer != ',')
125633965Sjdp	max = 0;
125733965Sjdp      else
125833965Sjdp	{
125933965Sjdp	  ++input_line_pointer;
126033965Sjdp	  max = get_absolute_expression ();
126133965Sjdp	}
126233965Sjdp    }
126333965Sjdp
126477298Sobrien  if (!fill_p)
126533965Sjdp    {
126633965Sjdp      if (arg < 0)
126760484Sobrien	as_warn (_("expected fill pattern missing"));
126833965Sjdp      do_align (align, (char *) NULL, 0, max);
126933965Sjdp    }
127033965Sjdp  else
127133965Sjdp    {
127233965Sjdp      int fill_len;
127333965Sjdp
127433965Sjdp      if (arg >= 0)
127533965Sjdp	fill_len = 1;
127633965Sjdp      else
127777298Sobrien	fill_len = -arg;
127833965Sjdp      if (fill_len <= 1)
127933965Sjdp	{
128033965Sjdp	  char fill_char;
128133965Sjdp
128233965Sjdp	  fill_char = fill;
128333965Sjdp	  do_align (align, &fill_char, fill_len, max);
128433965Sjdp	}
128533965Sjdp      else
128633965Sjdp	{
128733965Sjdp	  char ab[16];
128833965Sjdp
128938889Sjdp	  if ((size_t) fill_len > sizeof ab)
129033965Sjdp	    abort ();
129133965Sjdp	  md_number_to_chars (ab, fill, fill_len);
129233965Sjdp	  do_align (align, ab, fill_len, max);
129333965Sjdp	}
129433965Sjdp    }
129533965Sjdp
129660484Sobrien  demand_empty_rest_of_line ();
129760484Sobrien
129833965Sjdp  if (flag_mri)
129933965Sjdp    mri_comment_end (stop, stopc);
130033965Sjdp}
130133965Sjdp
130233965Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means
130333965Sjdp   align to a 4 byte boundary.  */
130433965Sjdp
130577298Sobrienvoid
1306130561Sobriens_align_bytes (int arg)
130733965Sjdp{
130833965Sjdp  s_align (arg, 1);
130933965Sjdp}
131033965Sjdp
131138889Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means align
131233965Sjdp   to a 2**4 boundary.  */
131333965Sjdp
131477298Sobrienvoid
1315130561Sobriens_align_ptwo (int arg)
131633965Sjdp{
131733965Sjdp  s_align (arg, 0);
131833965Sjdp}
131933965Sjdp
1320130561SobriensymbolS *
1321130561Sobriens_comm_internal (int param,
1322130561Sobrien		 symbolS *(*comm_parse_extra) (int, symbolS *, addressT))
132333965Sjdp{
1324130561Sobrien  char *name;
1325130561Sobrien  char c;
1326130561Sobrien  char *p;
1327130561Sobrien  offsetT temp, size;
1328130561Sobrien  symbolS *symbolP = NULL;
132933965Sjdp  char *stop = NULL;
133033965Sjdp  char stopc;
1331130561Sobrien  expressionS exp;
133233965Sjdp
133333965Sjdp  if (flag_mri)
133433965Sjdp    stop = mri_comment_field (&stopc);
133533965Sjdp
133633965Sjdp  name = input_line_pointer;
133733965Sjdp  c = get_symbol_end ();
133877298Sobrien  /* Just after name is now '\0'.  */
133933965Sjdp  p = input_line_pointer;
134033965Sjdp  *p = c;
134189857Sobrien
134289857Sobrien  if (name == p)
134389857Sobrien    {
134489857Sobrien      as_bad (_("expected symbol name"));
134589857Sobrien      discard_rest_of_line ();
1346130561Sobrien      goto out;
134789857Sobrien    }
134889857Sobrien
134933965Sjdp  SKIP_WHITESPACE ();
135077298Sobrien
1351130561Sobrien  /* Accept an optional comma after the name.  The comma used to be
1352130561Sobrien     required, but Irix 5 cc does not generate it for .lcomm.  */
1353130561Sobrien  if (*input_line_pointer == ',')
1354130561Sobrien    input_line_pointer++;
1355130561Sobrien
1356130561Sobrien  *p = 0;
1357130561Sobrien  temp = get_absolute_expr (&exp);
1358130561Sobrien  size = temp;
1359130561Sobrien#ifdef BFD_ASSEMBLER
1360130561Sobrien  size &= ((offsetT) 2 << (stdoutput->arch_info->bits_per_address - 1)) - 1;
1361130561Sobrien#endif
1362130561Sobrien  if (exp.X_op == O_absent)
136333965Sjdp    {
1364130561Sobrien      as_bad (_("missing size expression"));
136589857Sobrien      *p = c;
136660484Sobrien      ignore_rest_of_line ();
1367130561Sobrien      goto out;
136833965Sjdp    }
1369130561Sobrien  else if (temp != size || !exp.X_unsigned)
137033965Sjdp    {
1371130561Sobrien      as_warn (_("size (%ld) out of range, ignored"), (long) temp);
1372130561Sobrien      *p = c;
137360484Sobrien      ignore_rest_of_line ();
1374130561Sobrien      goto out;
137533965Sjdp    }
137677298Sobrien
137733965Sjdp  symbolP = symbol_find_or_make (name);
137877298Sobrien  if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP))
137933965Sjdp    {
1380130561Sobrien      symbolP = NULL;
1381130561Sobrien      as_bad (_("symbol `%s' is already defined"), name);
1382130561Sobrien      *p = c;
138360484Sobrien      ignore_rest_of_line ();
1384130561Sobrien      goto out;
138533965Sjdp    }
138677298Sobrien
1387130561Sobrien  size = S_GET_VALUE (symbolP);
1388130561Sobrien  if (size == 0)
1389130561Sobrien    size = temp;
1390130561Sobrien  else if (size != temp)
1391130561Sobrien    as_warn (_("size of \"%s\" is already %ld; not changing to %ld"),
1392130561Sobrien	     name, (long) size, (long) temp);
1393130561Sobrien
1394130561Sobrien  *p = c;
1395130561Sobrien  if (comm_parse_extra != NULL)
1396130561Sobrien    symbolP = (*comm_parse_extra) (param, symbolP, size);
139733965Sjdp  else
139833965Sjdp    {
1399130561Sobrien      S_SET_VALUE (symbolP, (valueT) size);
140033965Sjdp      S_SET_EXTERNAL (symbolP);
1401130561Sobrien#ifdef OBJ_VMS
1402130561Sobrien      {
1403130561Sobrien	extern int flag_one;
1404130561Sobrien	if (size == 0 || !flag_one)
1405130561Sobrien	  S_GET_OTHER (symbolP) = const_flag;
1406130561Sobrien      }
1407130561Sobrien#endif
140833965Sjdp    }
140933965Sjdp
1410130561Sobrien  know (symbolP == NULL || symbolP->sy_frag == &zero_address_frag);
141160484Sobrien  demand_empty_rest_of_line ();
1412130561Sobrien out:
141333965Sjdp  if (flag_mri)
141433965Sjdp    mri_comment_end (stop, stopc);
1415130561Sobrien  return symbolP;
1416130561Sobrien}
141733965Sjdp
1418130561Sobrienvoid
1419130561Sobriens_comm (int ignore)
1420130561Sobrien{
1421130561Sobrien  s_comm_internal (ignore, NULL);
1422130561Sobrien}
1423130561Sobrien
142433965Sjdp/* The MRI COMMON pseudo-op.  We handle this by creating a common
142533965Sjdp   symbol with the appropriate name.  We make s_space do the right
142633965Sjdp   thing by increasing the size.  */
142733965Sjdp
142833965Sjdpvoid
1429130561Sobriens_mri_common (int small ATTRIBUTE_UNUSED)
143033965Sjdp{
143133965Sjdp  char *name;
143233965Sjdp  char c;
143333965Sjdp  char *alc = NULL;
143433965Sjdp  symbolS *sym;
143533965Sjdp  offsetT align;
143633965Sjdp  char *stop = NULL;
143733965Sjdp  char stopc;
143833965Sjdp
143977298Sobrien  if (!flag_mri)
144033965Sjdp    {
144133965Sjdp      s_comm (0);
144233965Sjdp      return;
144333965Sjdp    }
144433965Sjdp
144533965Sjdp  stop = mri_comment_field (&stopc);
144633965Sjdp
144733965Sjdp  SKIP_WHITESPACE ();
144833965Sjdp
144933965Sjdp  name = input_line_pointer;
145089857Sobrien  if (!ISDIGIT (*name))
145133965Sjdp    c = get_symbol_end ();
145233965Sjdp  else
145333965Sjdp    {
145433965Sjdp      do
145533965Sjdp	{
145633965Sjdp	  ++input_line_pointer;
145733965Sjdp	}
145889857Sobrien      while (ISDIGIT (*input_line_pointer));
145977298Sobrien
146033965Sjdp      c = *input_line_pointer;
146133965Sjdp      *input_line_pointer = '\0';
146233965Sjdp
146333965Sjdp      if (line_label != NULL)
146433965Sjdp	{
146533965Sjdp	  alc = (char *) xmalloc (strlen (S_GET_NAME (line_label))
146633965Sjdp				  + (input_line_pointer - name)
146733965Sjdp				  + 1);
146833965Sjdp	  sprintf (alc, "%s%s", name, S_GET_NAME (line_label));
146933965Sjdp	  name = alc;
147033965Sjdp	}
147133965Sjdp    }
147233965Sjdp
147333965Sjdp  sym = symbol_find_or_make (name);
147433965Sjdp  *input_line_pointer = c;
147533965Sjdp  if (alc != NULL)
147633965Sjdp    free (alc);
147733965Sjdp
147833965Sjdp  if (*input_line_pointer != ',')
147933965Sjdp    align = 0;
148033965Sjdp  else
148133965Sjdp    {
148233965Sjdp      ++input_line_pointer;
148333965Sjdp      align = get_absolute_expression ();
148433965Sjdp    }
148533965Sjdp
148677298Sobrien  if (S_IS_DEFINED (sym) && !S_IS_COMMON (sym))
148733965Sjdp    {
148889857Sobrien      as_bad (_("symbol `%s' is already defined"), S_GET_NAME (sym));
148960484Sobrien      ignore_rest_of_line ();
149033965Sjdp      mri_comment_end (stop, stopc);
149133965Sjdp      return;
149233965Sjdp    }
149333965Sjdp
149433965Sjdp  S_SET_EXTERNAL (sym);
149533965Sjdp  mri_common_symbol = sym;
149633965Sjdp
149733965Sjdp#ifdef S_SET_ALIGN
149833965Sjdp  if (align != 0)
149933965Sjdp    S_SET_ALIGN (sym, align);
150033965Sjdp#endif
150133965Sjdp
150233965Sjdp  if (line_label != NULL)
150333965Sjdp    {
150460484Sobrien      expressionS exp;
150560484Sobrien      exp.X_op = O_symbol;
150660484Sobrien      exp.X_add_symbol = sym;
150760484Sobrien      exp.X_add_number = 0;
150860484Sobrien      symbol_set_value_expression (line_label, &exp);
150960484Sobrien      symbol_set_frag (line_label, &zero_address_frag);
151033965Sjdp      S_SET_SEGMENT (line_label, expr_section);
151133965Sjdp    }
151233965Sjdp
151333965Sjdp  /* FIXME: We just ignore the small argument, which distinguishes
151433965Sjdp     COMMON and COMMON.S.  I don't know what we can do about it.  */
151533965Sjdp
151633965Sjdp  /* Ignore the type and hptype.  */
151733965Sjdp  if (*input_line_pointer == ',')
151833965Sjdp    input_line_pointer += 2;
151933965Sjdp  if (*input_line_pointer == ',')
152033965Sjdp    input_line_pointer += 2;
152133965Sjdp
152260484Sobrien  demand_empty_rest_of_line ();
152360484Sobrien
152433965Sjdp  mri_comment_end (stop, stopc);
152533965Sjdp}
152633965Sjdp
152733965Sjdpvoid
1528130561Sobriens_data (int ignore ATTRIBUTE_UNUSED)
152933965Sjdp{
153033965Sjdp  segT section;
153133965Sjdp  register int temp;
153233965Sjdp
153333965Sjdp  temp = get_absolute_expression ();
153433965Sjdp  if (flag_readonly_data_in_text)
153533965Sjdp    {
153633965Sjdp      section = text_section;
153733965Sjdp      temp += 1000;
153833965Sjdp    }
153933965Sjdp  else
154033965Sjdp    section = data_section;
154133965Sjdp
154233965Sjdp  subseg_set (section, (subsegT) temp);
154333965Sjdp
154433965Sjdp#ifdef OBJ_VMS
154533965Sjdp  const_flag = 0;
154633965Sjdp#endif
154733965Sjdp  demand_empty_rest_of_line ();
154833965Sjdp}
154933965Sjdp
155033965Sjdp/* Handle the .appfile pseudo-op.  This is automatically generated by
155133965Sjdp   do_scrub_chars when a preprocessor # line comment is seen with a
155233965Sjdp   file name.  This default definition may be overridden by the object
155333965Sjdp   or CPU specific pseudo-ops.  This function is also the default
155433965Sjdp   definition for .file; the APPFILE argument is 1 for .appfile, 0 for
155533965Sjdp   .file.  */
155633965Sjdp
155777298Sobrienvoid
1558130561Sobriens_app_file_string (char *file)
1559104834Sobrien{
1560104834Sobrien#ifdef LISTING
1561104834Sobrien  if (listing)
1562104834Sobrien    listing_source_file (file);
1563104834Sobrien#endif
1564104834Sobrien  register_dependency (file);
1565104834Sobrien#ifdef obj_app_file
1566104834Sobrien  obj_app_file (file);
1567104834Sobrien#endif
1568104834Sobrien}
1569104834Sobrien
1570104834Sobrienvoid
1571130561Sobriens_app_file (int appfile)
157233965Sjdp{
157333965Sjdp  register char *s;
157433965Sjdp  int length;
157533965Sjdp
157677298Sobrien  /* Some assemblers tolerate immediately following '"'.  */
157733965Sjdp  if ((s = demand_copy_string (&length)) != 0)
157833965Sjdp    {
157933965Sjdp      /* If this is a fake .appfile, a fake newline was inserted into
158033965Sjdp	 the buffer.  Passing -2 to new_logical_line tells it to
158133965Sjdp	 account for it.  */
158238889Sjdp      int may_omit
158377298Sobrien	= (!new_logical_line (s, appfile ? -2 : -1) && appfile);
158433965Sjdp
158533965Sjdp      /* In MRI mode, the preprocessor may have inserted an extraneous
1586130561Sobrien	 backquote.  */
158733965Sjdp      if (flag_m68k_mri
158833965Sjdp	  && *input_line_pointer == '\''
158933965Sjdp	  && is_end_of_line[(unsigned char) input_line_pointer[1]])
159033965Sjdp	++input_line_pointer;
159133965Sjdp
159233965Sjdp      demand_empty_rest_of_line ();
159377298Sobrien      if (!may_omit)
1594104834Sobrien	s_app_file_string (s);
159538889Sjdp    }
159633965Sjdp}
159733965Sjdp
159833965Sjdp/* Handle the .appline pseudo-op.  This is automatically generated by
159933965Sjdp   do_scrub_chars when a preprocessor # line comment is seen.  This
160033965Sjdp   default definition may be overridden by the object or CPU specific
160133965Sjdp   pseudo-ops.  */
160233965Sjdp
160333965Sjdpvoid
1604130561Sobriens_app_line (int ignore ATTRIBUTE_UNUSED)
160533965Sjdp{
160633965Sjdp  int l;
160733965Sjdp
160833965Sjdp  /* The given number is that of the next line.  */
160933965Sjdp  l = get_absolute_expression () - 1;
161033965Sjdp  if (l < 0)
161133965Sjdp    /* Some of the back ends can't deal with non-positive line numbers.
161233965Sjdp       Besides, it's silly.  */
161389857Sobrien    as_warn (_("line numbers must be positive; line number %d rejected"),
161477298Sobrien	     l + 1);
161533965Sjdp  else
161633965Sjdp    {
161733965Sjdp      new_logical_line ((char *) NULL, l);
161833965Sjdp#ifdef LISTING
161933965Sjdp      if (listing)
162033965Sjdp	listing_source_line (l);
162133965Sjdp#endif
162233965Sjdp    }
162333965Sjdp  demand_empty_rest_of_line ();
162433965Sjdp}
162533965Sjdp
162633965Sjdp/* Handle the .end pseudo-op.  Actually, the real work is done in
162733965Sjdp   read_a_source_file.  */
162833965Sjdp
162933965Sjdpvoid
1630130561Sobriens_end (int ignore ATTRIBUTE_UNUSED)
163133965Sjdp{
163233965Sjdp  if (flag_mri)
163333965Sjdp    {
163433965Sjdp      /* The MRI assembler permits the start symbol to follow .end,
1635130561Sobrien	 but we don't support that.  */
163633965Sjdp      SKIP_WHITESPACE ();
163777298Sobrien      if (!is_end_of_line[(unsigned char) *input_line_pointer]
163833965Sjdp	  && *input_line_pointer != '*'
163933965Sjdp	  && *input_line_pointer != '!')
164060484Sobrien	as_warn (_("start address not supported"));
164133965Sjdp    }
164233965Sjdp}
164333965Sjdp
164433965Sjdp/* Handle the .err pseudo-op.  */
164533965Sjdp
164633965Sjdpvoid
1647130561Sobriens_err (int ignore ATTRIBUTE_UNUSED)
164833965Sjdp{
164960484Sobrien  as_bad (_(".err encountered"));
165033965Sjdp  demand_empty_rest_of_line ();
165133965Sjdp}
165233965Sjdp
165333965Sjdp/* Handle the MRI fail pseudo-op.  */
165433965Sjdp
165533965Sjdpvoid
1656130561Sobriens_fail (int ignore ATTRIBUTE_UNUSED)
165733965Sjdp{
165833965Sjdp  offsetT temp;
165933965Sjdp  char *stop = NULL;
166033965Sjdp  char stopc;
166133965Sjdp
166233965Sjdp  if (flag_mri)
166333965Sjdp    stop = mri_comment_field (&stopc);
166433965Sjdp
166533965Sjdp  temp = get_absolute_expression ();
166633965Sjdp  if (temp >= 500)
166760484Sobrien    as_warn (_(".fail %ld encountered"), (long) temp);
166833965Sjdp  else
166960484Sobrien    as_bad (_(".fail %ld encountered"), (long) temp);
167033965Sjdp
167160484Sobrien  demand_empty_rest_of_line ();
167260484Sobrien
167333965Sjdp  if (flag_mri)
167433965Sjdp    mri_comment_end (stop, stopc);
167533965Sjdp}
167633965Sjdp
167777298Sobrienvoid
1678130561Sobriens_fill (int ignore ATTRIBUTE_UNUSED)
167933965Sjdp{
168038889Sjdp  expressionS rep_exp;
168138889Sjdp  long size = 1;
168238889Sjdp  register long fill = 0;
168333965Sjdp  char *p;
168433965Sjdp
168533965Sjdp#ifdef md_flush_pending_output
168633965Sjdp  md_flush_pending_output ();
168733965Sjdp#endif
168833965Sjdp
168938889Sjdp  get_known_segmented_expression (&rep_exp);
169033965Sjdp  if (*input_line_pointer == ',')
169133965Sjdp    {
169233965Sjdp      input_line_pointer++;
169338889Sjdp      size = get_absolute_expression ();
169433965Sjdp      if (*input_line_pointer == ',')
169533965Sjdp	{
169633965Sjdp	  input_line_pointer++;
169738889Sjdp	  fill = get_absolute_expression ();
169833965Sjdp	}
169933965Sjdp    }
170038889Sjdp
170133965Sjdp  /* This is to be compatible with BSD 4.2 AS, not for any rational reason.  */
170233965Sjdp#define BSD_FILL_SIZE_CROCK_8 (8)
170338889Sjdp  if (size > BSD_FILL_SIZE_CROCK_8)
170433965Sjdp    {
170589857Sobrien      as_warn (_(".fill size clamped to %d"), BSD_FILL_SIZE_CROCK_8);
170638889Sjdp      size = BSD_FILL_SIZE_CROCK_8;
170733965Sjdp    }
170838889Sjdp  if (size < 0)
170933965Sjdp    {
171089857Sobrien      as_warn (_("size negative; .fill ignored"));
171138889Sjdp      size = 0;
171233965Sjdp    }
171338889Sjdp  else if (rep_exp.X_op == O_constant && rep_exp.X_add_number <= 0)
171433965Sjdp    {
171538889Sjdp      if (rep_exp.X_add_number < 0)
171689857Sobrien	as_warn (_("repeat < 0; .fill ignored"));
171738889Sjdp      size = 0;
171833965Sjdp    }
171933965Sjdp
172038889Sjdp  if (size && !need_pass_2)
172133965Sjdp    {
172238889Sjdp      if (rep_exp.X_op == O_constant)
172338889Sjdp	{
172438889Sjdp	  p = frag_var (rs_fill, (int) size, (int) size,
172538889Sjdp			(relax_substateT) 0, (symbolS *) 0,
172638889Sjdp			(offsetT) rep_exp.X_add_number,
172738889Sjdp			(char *) 0);
172838889Sjdp	}
172938889Sjdp      else
173038889Sjdp	{
173138889Sjdp	  /* We don't have a constant repeat count, so we can't use
173238889Sjdp	     rs_fill.  We can get the same results out of rs_space,
173338889Sjdp	     but its argument is in bytes, so we must multiply the
173438889Sjdp	     repeat count by size.  */
173538889Sjdp
173638889Sjdp	  symbolS *rep_sym;
173738889Sjdp	  rep_sym = make_expr_symbol (&rep_exp);
173838889Sjdp	  if (size != 1)
173938889Sjdp	    {
174038889Sjdp	      expressionS size_exp;
174138889Sjdp	      size_exp.X_op = O_constant;
174238889Sjdp	      size_exp.X_add_number = size;
174338889Sjdp
174438889Sjdp	      rep_exp.X_op = O_multiply;
174538889Sjdp	      rep_exp.X_add_symbol = rep_sym;
174638889Sjdp	      rep_exp.X_op_symbol = make_expr_symbol (&size_exp);
174738889Sjdp	      rep_exp.X_add_number = 0;
174838889Sjdp	      rep_sym = make_expr_symbol (&rep_exp);
174938889Sjdp	    }
175038889Sjdp
175138889Sjdp	  p = frag_var (rs_space, (int) size, (int) size,
175238889Sjdp			(relax_substateT) 0, rep_sym, (offsetT) 0, (char *) 0);
175338889Sjdp	}
175477298Sobrien
175538889Sjdp      memset (p, 0, (unsigned int) size);
175677298Sobrien
175733965Sjdp      /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX
1758130561Sobrien	 flavoured AS.  The following bizarre behaviour is to be
1759130561Sobrien	 compatible with above.  I guess they tried to take up to 8
1760130561Sobrien	 bytes from a 4-byte expression and they forgot to sign
1761130561Sobrien	 extend.  */
176233965Sjdp#define BSD_FILL_SIZE_CROCK_4 (4)
176338889Sjdp      md_number_to_chars (p, (valueT) fill,
176438889Sjdp			  (size > BSD_FILL_SIZE_CROCK_4
176533965Sjdp			   ? BSD_FILL_SIZE_CROCK_4
176638889Sjdp			   : (int) size));
176733965Sjdp      /* Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes)
1768130561Sobrien	 but emits no error message because it seems a legal thing to do.
1769130561Sobrien	 It is a degenerate case of .fill but could be emitted by a
177077298Sobrien	 compiler.  */
177133965Sjdp    }
177233965Sjdp  demand_empty_rest_of_line ();
177333965Sjdp}
177433965Sjdp
177577298Sobrienvoid
1776130561Sobriens_globl (int ignore ATTRIBUTE_UNUSED)
177733965Sjdp{
177833965Sjdp  char *name;
177933965Sjdp  int c;
178033965Sjdp  symbolS *symbolP;
178133965Sjdp  char *stop = NULL;
178233965Sjdp  char stopc;
178333965Sjdp
178433965Sjdp  if (flag_mri)
178533965Sjdp    stop = mri_comment_field (&stopc);
178633965Sjdp
178733965Sjdp  do
178833965Sjdp    {
178933965Sjdp      name = input_line_pointer;
179033965Sjdp      c = get_symbol_end ();
179133965Sjdp      symbolP = symbol_find_or_make (name);
179260484Sobrien      S_SET_EXTERNAL (symbolP);
179360484Sobrien
179433965Sjdp      *input_line_pointer = c;
179533965Sjdp      SKIP_WHITESPACE ();
179660484Sobrien      c = *input_line_pointer;
179733965Sjdp      if (c == ',')
179833965Sjdp	{
179933965Sjdp	  input_line_pointer++;
180033965Sjdp	  SKIP_WHITESPACE ();
180189857Sobrien	  if (is_end_of_line[(unsigned char) *input_line_pointer])
180233965Sjdp	    c = '\n';
180333965Sjdp	}
180433965Sjdp    }
180533965Sjdp  while (c == ',');
180633965Sjdp
180760484Sobrien  demand_empty_rest_of_line ();
180860484Sobrien
180933965Sjdp  if (flag_mri)
181033965Sjdp    mri_comment_end (stop, stopc);
181133965Sjdp}
181233965Sjdp
181333965Sjdp/* Handle the MRI IRP and IRPC pseudo-ops.  */
181433965Sjdp
181533965Sjdpvoid
1816130561Sobriens_irp (int irpc)
181733965Sjdp{
181833965Sjdp  char *file;
181933965Sjdp  unsigned int line;
182033965Sjdp  sb s;
182133965Sjdp  const char *err;
182233965Sjdp  sb out;
182333965Sjdp
182433965Sjdp  as_where (&file, &line);
182533965Sjdp
182633965Sjdp  sb_new (&s);
182777298Sobrien  while (!is_end_of_line[(unsigned char) *input_line_pointer])
182833965Sjdp    sb_add_char (&s, *input_line_pointer++);
182933965Sjdp
183033965Sjdp  sb_new (&out);
183133965Sjdp
1832130561Sobrien  err = expand_irp (irpc, 0, &s, &out, get_line_sb);
183333965Sjdp  if (err != NULL)
183433965Sjdp    as_bad_where (file, line, "%s", err);
183533965Sjdp
183633965Sjdp  sb_kill (&s);
183733965Sjdp
183860484Sobrien  input_scrub_include_sb (&out, input_line_pointer, 1);
183933965Sjdp  sb_kill (&out);
184033965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
184133965Sjdp}
184233965Sjdp
184333965Sjdp/* Handle the .linkonce pseudo-op.  This tells the assembler to mark
184433965Sjdp   the section to only be linked once.  However, this is not supported
184533965Sjdp   by most object file formats.  This takes an optional argument,
184633965Sjdp   which is what to do about duplicates.  */
184733965Sjdp
184833965Sjdpvoid
1849130561Sobriens_linkonce (int ignore ATTRIBUTE_UNUSED)
185033965Sjdp{
185133965Sjdp  enum linkonce_type type;
185233965Sjdp
185333965Sjdp  SKIP_WHITESPACE ();
185433965Sjdp
185533965Sjdp  type = LINKONCE_DISCARD;
185633965Sjdp
185777298Sobrien  if (!is_end_of_line[(unsigned char) *input_line_pointer])
185833965Sjdp    {
185933965Sjdp      char *s;
186033965Sjdp      char c;
186133965Sjdp
186233965Sjdp      s = input_line_pointer;
186333965Sjdp      c = get_symbol_end ();
186433965Sjdp      if (strcasecmp (s, "discard") == 0)
186533965Sjdp	type = LINKONCE_DISCARD;
186633965Sjdp      else if (strcasecmp (s, "one_only") == 0)
186733965Sjdp	type = LINKONCE_ONE_ONLY;
186833965Sjdp      else if (strcasecmp (s, "same_size") == 0)
186933965Sjdp	type = LINKONCE_SAME_SIZE;
187033965Sjdp      else if (strcasecmp (s, "same_contents") == 0)
187133965Sjdp	type = LINKONCE_SAME_CONTENTS;
187233965Sjdp      else
187360484Sobrien	as_warn (_("unrecognized .linkonce type `%s'"), s);
187433965Sjdp
187533965Sjdp      *input_line_pointer = c;
187633965Sjdp    }
187733965Sjdp
187833965Sjdp#ifdef obj_handle_link_once
187933965Sjdp  obj_handle_link_once (type);
188033965Sjdp#else /* ! defined (obj_handle_link_once) */
188133965Sjdp#ifdef BFD_ASSEMBLER
188233965Sjdp  {
188333965Sjdp    flagword flags;
188433965Sjdp
188533965Sjdp    if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0)
188660484Sobrien      as_warn (_(".linkonce is not supported for this object file format"));
188733965Sjdp
188833965Sjdp    flags = bfd_get_section_flags (stdoutput, now_seg);
188933965Sjdp    flags |= SEC_LINK_ONCE;
189033965Sjdp    switch (type)
189133965Sjdp      {
189233965Sjdp      default:
189333965Sjdp	abort ();
189433965Sjdp      case LINKONCE_DISCARD:
189533965Sjdp	flags |= SEC_LINK_DUPLICATES_DISCARD;
189633965Sjdp	break;
189733965Sjdp      case LINKONCE_ONE_ONLY:
189833965Sjdp	flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
189933965Sjdp	break;
190033965Sjdp      case LINKONCE_SAME_SIZE:
190133965Sjdp	flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
190233965Sjdp	break;
190333965Sjdp      case LINKONCE_SAME_CONTENTS:
190433965Sjdp	flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
190533965Sjdp	break;
190633965Sjdp      }
190777298Sobrien    if (!bfd_set_section_flags (stdoutput, now_seg, flags))
190860484Sobrien      as_bad (_("bfd_set_section_flags: %s"),
190933965Sjdp	      bfd_errmsg (bfd_get_error ()));
191033965Sjdp  }
191133965Sjdp#else /* ! defined (BFD_ASSEMBLER) */
191260484Sobrien  as_warn (_(".linkonce is not supported for this object file format"));
191333965Sjdp#endif /* ! defined (BFD_ASSEMBLER) */
191433965Sjdp#endif /* ! defined (obj_handle_link_once) */
191533965Sjdp
191633965Sjdp  demand_empty_rest_of_line ();
191733965Sjdp}
191833965Sjdp
1919130561Sobrienvoid
1920130561Sobrienbss_alloc (symbolS *symbolP, addressT size, int align)
192133965Sjdp{
1922130561Sobrien  char *pfrag;
192333965Sjdp  segT current_seg = now_seg;
192433965Sjdp  subsegT current_subseg = now_subseg;
192533965Sjdp  segT bss_seg = bss_section;
192633965Sjdp
192733965Sjdp#if defined (TC_MIPS) || defined (TC_ALPHA)
192833965Sjdp  if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
192933965Sjdp      || OUTPUT_FLAVOR == bfd_target_elf_flavour)
193033965Sjdp    {
193133965Sjdp      /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss.  */
1932130561Sobrien      if (size <= bfd_get_gp_size (stdoutput))
193333965Sjdp	{
193433965Sjdp	  bss_seg = subseg_new (".sbss", 1);
193533965Sjdp	  seg_info (bss_seg)->bss = 1;
193633965Sjdp#ifdef BFD_ASSEMBLER
193777298Sobrien	  if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
193860484Sobrien	    as_warn (_("error setting flags for \".sbss\": %s"),
193933965Sjdp		     bfd_errmsg (bfd_get_error ()));
194033965Sjdp#endif
194133965Sjdp	}
194233965Sjdp    }
194333965Sjdp#endif
1944130561Sobrien  subseg_set (bss_seg, 1);
194560484Sobrien
1946130561Sobrien  if (align)
194777298Sobrien    {
1948130561Sobrien      record_alignment (bss_seg, align);
1949130561Sobrien      frag_align (align, 0, 0);
195077298Sobrien    }
195133965Sjdp
1952130561Sobrien  /* Detach from old frag.  */
1953130561Sobrien  if (S_GET_SEGMENT (symbolP) == bss_seg)
1954130561Sobrien    symbol_get_frag (symbolP)->fr_symbol = NULL;
195577298Sobrien
1956130561Sobrien  symbol_set_frag (symbolP, frag_now);
1957130561Sobrien  pfrag = frag_var (rs_org, 1, 1, 0, symbolP, size, NULL);
1958130561Sobrien  *pfrag = 0;
195977298Sobrien
1960130561Sobrien#ifdef S_SET_SIZE
1961130561Sobrien  S_SET_SIZE (symbolP, size);
1962130561Sobrien#endif
1963130561Sobrien  S_SET_SEGMENT (symbolP, bss_seg);
196477298Sobrien
1965130561Sobrien#ifdef OBJ_COFF
1966130561Sobrien  /* The symbol may already have been created with a preceding
1967130561Sobrien     ".globl" directive -- be careful not to step on storage class
1968130561Sobrien     in that case.  Otherwise, set it to static.  */
1969130561Sobrien  if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
1970130561Sobrien    S_SET_STORAGE_CLASS (symbolP, C_STAT);
1971130561Sobrien#endif /* OBJ_COFF */
197277298Sobrien
1973130561Sobrien  subseg_set (current_seg, current_subseg);
1974130561Sobrien}
197577298Sobrien
1976130561SobrienoffsetT
1977130561Sobrienparse_align (int align_bytes)
1978130561Sobrien{
1979130561Sobrien  expressionS exp;
1980130561Sobrien  addressT align;
198138889Sjdp
1982130561Sobrien  SKIP_WHITESPACE ();
1983130561Sobrien  if (*input_line_pointer != ',')
1984130561Sobrien    {
1985130561Sobrien    no_align:
1986130561Sobrien      as_bad (_("expected alignment after size"));
1987130561Sobrien      ignore_rest_of_line ();
1988130561Sobrien      return -1;
1989130561Sobrien    }
199077298Sobrien
1991130561Sobrien  input_line_pointer++;
1992130561Sobrien  SKIP_WHITESPACE ();
199377298Sobrien
1994130561Sobrien  align = get_absolute_expr (&exp);
1995130561Sobrien  if (exp.X_op == O_absent)
1996130561Sobrien    goto no_align;
1997130561Sobrien
1998130561Sobrien  if (!exp.X_unsigned)
1999130561Sobrien    {
2000130561Sobrien      as_warn (_("alignment negative; 0 assumed"));
2001130561Sobrien      align = 0;
200277298Sobrien    }
2003130561Sobrien
2004130561Sobrien  if (align_bytes && align != 0)
200533965Sjdp    {
2006130561Sobrien      /* convert to a power of 2 alignment */
2007130561Sobrien      unsigned int alignp2 = 0;
2008130561Sobrien      while ((align & 1) == 0)
2009130561Sobrien	align >>= 1, ++alignp2;
2010130561Sobrien      if (align != 1)
201133965Sjdp	{
2012130561Sobrien	  as_bad (_("alignment not a power of 2"));
2013130561Sobrien	  ignore_rest_of_line ();
2014130561Sobrien	  return -1;
201533965Sjdp	}
2016130561Sobrien      align = alignp2;
201733965Sjdp    }
2018130561Sobrien  return align;
2019130561Sobrien}
202033965Sjdp
2021130561Sobrien/* Called from s_comm_internal after symbol name and size have been
2022130561Sobrien   parsed.  NEEDS_ALIGN is 0 if it was an ".lcomm" (2 args only),
2023130561Sobrien   1 if this was a ".bss" directive which has a 3rd argument
2024130561Sobrien   (alignment as a power of 2), or 2 if this was a ".bss" directive
2025130561Sobrien   with alignment in bytes.  */
202633965Sjdp
2027130561SobriensymbolS *
2028130561Sobriens_lcomm_internal (int needs_align, symbolS *symbolP, addressT size)
2029130561Sobrien{
2030130561Sobrien  addressT align = 0;
2031130561Sobrien
2032130561Sobrien  if (needs_align)
203333965Sjdp    {
2034130561Sobrien      align = parse_align (needs_align - 1);
2035130561Sobrien      if (align == (addressT) -1)
2036130561Sobrien	return NULL;
203733965Sjdp    }
203833965Sjdp  else
2039130561Sobrien    /* Assume some objects may require alignment on some systems.  */
2040130561Sobrien    TC_IMPLICIT_LCOMM_ALIGNMENT (size, align);
204133965Sjdp
2042130561Sobrien  bss_alloc (symbolP, size, align);
2043130561Sobrien  return symbolP;
204477298Sobrien}
204533965Sjdp
204638889Sjdpvoid
2047130561Sobriens_lcomm (int needs_align)
204838889Sjdp{
2049130561Sobrien  s_comm_internal (needs_align, s_lcomm_internal);
205038889Sjdp}
205138889Sjdp
205277298Sobrienvoid
2053130561Sobriens_lcomm_bytes (int needs_align)
205438889Sjdp{
2055130561Sobrien  s_comm_internal (needs_align * 2, s_lcomm_internal);
205638889Sjdp}
205738889Sjdp
205877298Sobrienvoid
2059130561Sobriens_lsym (int ignore ATTRIBUTE_UNUSED)
206033965Sjdp{
206133965Sjdp  register char *name;
206233965Sjdp  register char c;
206333965Sjdp  register char *p;
206433965Sjdp  expressionS exp;
206533965Sjdp  register symbolS *symbolP;
206633965Sjdp
206777298Sobrien  /* We permit ANY defined expression: BSD4.2 demands constants.  */
206833965Sjdp  name = input_line_pointer;
206933965Sjdp  c = get_symbol_end ();
207033965Sjdp  p = input_line_pointer;
207133965Sjdp  *p = c;
207289857Sobrien
207389857Sobrien  if (name == p)
207489857Sobrien    {
207589857Sobrien      as_bad (_("expected symbol name"));
207689857Sobrien      discard_rest_of_line ();
207789857Sobrien      return;
207889857Sobrien    }
207989857Sobrien
208033965Sjdp  SKIP_WHITESPACE ();
208177298Sobrien
208233965Sjdp  if (*input_line_pointer != ',')
208333965Sjdp    {
208433965Sjdp      *p = 0;
208589857Sobrien      as_bad (_("expected comma after \"%s\""), name);
208633965Sjdp      *p = c;
208733965Sjdp      ignore_rest_of_line ();
208833965Sjdp      return;
208933965Sjdp    }
209077298Sobrien
209133965Sjdp  input_line_pointer++;
209233965Sjdp  expression (&exp);
209377298Sobrien
209433965Sjdp  if (exp.X_op != O_constant
209533965Sjdp      && exp.X_op != O_register)
209633965Sjdp    {
209760484Sobrien      as_bad (_("bad expression"));
209833965Sjdp      ignore_rest_of_line ();
209933965Sjdp      return;
210033965Sjdp    }
210177298Sobrien
210233965Sjdp  *p = 0;
210333965Sjdp  symbolP = symbol_find_or_make (name);
210433965Sjdp
210533965Sjdp  /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0 &&
210633965Sjdp     symbolP->sy_desc == 0) out of this test because coff doesn't have
210733965Sjdp     those fields, and I can't see when they'd ever be tripped.  I
210833965Sjdp     don't think I understand why they were here so I may have
210933965Sjdp     introduced a bug. As recently as 1.37 didn't have this test
211077298Sobrien     anyway.  xoxorich.  */
211133965Sjdp
211233965Sjdp  if (S_GET_SEGMENT (symbolP) == undefined_section
211333965Sjdp      && S_GET_VALUE (symbolP) == 0)
211433965Sjdp    {
211533965Sjdp      /* The name might be an undefined .global symbol; be sure to
211677298Sobrien	 keep the "external" bit.  */
211733965Sjdp      S_SET_SEGMENT (symbolP,
211833965Sjdp		     (exp.X_op == O_constant
211933965Sjdp		      ? absolute_section
212033965Sjdp		      : reg_section));
212133965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
212233965Sjdp    }
212333965Sjdp  else
212433965Sjdp    {
212589857Sobrien      as_bad (_("symbol `%s' is already defined"), name);
212633965Sjdp    }
212777298Sobrien
212833965Sjdp  *p = c;
212933965Sjdp  demand_empty_rest_of_line ();
213077298Sobrien}
213133965Sjdp
2132130561Sobrien/* Read a line into an sb.  Returns the character that ended the line
2133130561Sobrien   or zero if there are no more lines.  */
213433965Sjdp
213533965Sjdpstatic int
2136130561Sobrienget_line_sb (sb *line)
213733965Sjdp{
213833965Sjdp  char quote1, quote2, inquote;
2139130561Sobrien  unsigned char c;
214033965Sjdp
214133965Sjdp  if (input_line_pointer[-1] == '\n')
214233965Sjdp    bump_line_counters ();
214333965Sjdp
214433965Sjdp  if (input_line_pointer >= buffer_limit)
214533965Sjdp    {
214633965Sjdp      buffer_limit = input_scrub_next_buffer (&input_line_pointer);
214733965Sjdp      if (buffer_limit == 0)
214833965Sjdp	return 0;
214933965Sjdp    }
215033965Sjdp
215133965Sjdp  /* If app.c sets any other characters to LEX_IS_STRINGQUOTE, this
215233965Sjdp     code needs to be changed.  */
215377298Sobrien  if (!flag_m68k_mri)
215433965Sjdp    quote1 = '"';
215533965Sjdp  else
215633965Sjdp    quote1 = '\0';
215733965Sjdp
215833965Sjdp  quote2 = '\0';
215933965Sjdp  if (flag_m68k_mri)
216033965Sjdp    quote2 = '\'';
216133965Sjdp#ifdef LEX_IS_STRINGQUOTE
216233965Sjdp  quote2 = '\'';
216333965Sjdp#endif
216433965Sjdp
216533965Sjdp  inquote = '\0';
216677298Sobrien
2167130561Sobrien  while ((c = * input_line_pointer ++) != 0
2168130561Sobrien	 && (!is_end_of_line[c]
2169130561Sobrien	     || (inquote != '\0' && c != '\n')))
217033965Sjdp    {
2171130561Sobrien      if (inquote == c)
217233965Sjdp	inquote = '\0';
217333965Sjdp      else if (inquote == '\0')
217433965Sjdp	{
2175130561Sobrien	  if (c == quote1)
217633965Sjdp	    inquote = quote1;
2177130561Sobrien	  else if (c == quote2)
217833965Sjdp	    inquote = quote2;
217933965Sjdp	}
218077298Sobrien
2181130561Sobrien      sb_add_char (line, c);
218233965Sjdp    }
218377298Sobrien
2184130561Sobrien  /* Don't skip multiple end-of-line characters, because that breaks support
2185130561Sobrien     for the IA-64 stop bit (;;) which looks like two consecutive end-of-line
2186130561Sobrien     characters but isn't.  Instead just skip one end of line character and
2187130561Sobrien     return the character skipped so that the caller can re-insert it if
2188130561Sobrien     necessary.   */
2189130561Sobrien  return c;
219033965Sjdp}
219133965Sjdp
2192130561Sobrien/* Define a macro.  This is an interface to macro.c.  */
219333965Sjdp
219433965Sjdpvoid
2195130561Sobriens_macro (int ignore ATTRIBUTE_UNUSED)
219633965Sjdp{
219733965Sjdp  char *file;
219833965Sjdp  unsigned int line;
219933965Sjdp  sb s;
220033965Sjdp  sb label;
220133965Sjdp  const char *err;
220233965Sjdp  const char *name;
220333965Sjdp
220433965Sjdp  as_where (&file, &line);
220533965Sjdp
220633965Sjdp  sb_new (&s);
220777298Sobrien  while (!is_end_of_line[(unsigned char) *input_line_pointer])
220833965Sjdp    sb_add_char (&s, *input_line_pointer++);
220933965Sjdp
221033965Sjdp  sb_new (&label);
221133965Sjdp  if (line_label != NULL)
221233965Sjdp    sb_add_string (&label, S_GET_NAME (line_label));
221333965Sjdp
221433965Sjdp  err = define_macro (0, &s, &label, get_line_sb, &name);
221533965Sjdp  if (err != NULL)
221633965Sjdp    as_bad_where (file, line, "%s", err);
221733965Sjdp  else
221833965Sjdp    {
221933965Sjdp      if (line_label != NULL)
222033965Sjdp	{
222133965Sjdp	  S_SET_SEGMENT (line_label, undefined_section);
222233965Sjdp	  S_SET_VALUE (line_label, 0);
222360484Sobrien	  symbol_set_frag (line_label, &zero_address_frag);
222433965Sjdp	}
222533965Sjdp
222660484Sobrien      if (((NO_PSEUDO_DOT || flag_m68k_mri)
222733965Sjdp	   && hash_find (po_hash, name) != NULL)
222877298Sobrien	  || (!flag_m68k_mri
222933965Sjdp	      && *name == '.'
223033965Sjdp	      && hash_find (po_hash, name + 1) != NULL))
223160484Sobrien	as_warn (_("attempt to redefine pseudo-op `%s' ignored"),
223233965Sjdp		 name);
223333965Sjdp    }
223433965Sjdp
223533965Sjdp  sb_kill (&s);
223633965Sjdp}
223733965Sjdp
223833965Sjdp/* Handle the .mexit pseudo-op, which immediately exits a macro
223933965Sjdp   expansion.  */
224033965Sjdp
224133965Sjdpvoid
2242130561Sobriens_mexit (int ignore ATTRIBUTE_UNUSED)
224333965Sjdp{
224433965Sjdp  cond_exit_macro (macro_nest);
224533965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
224633965Sjdp}
224733965Sjdp
224833965Sjdp/* Switch in and out of MRI mode.  */
224933965Sjdp
225033965Sjdpvoid
2251130561Sobriens_mri (int ignore ATTRIBUTE_UNUSED)
225233965Sjdp{
225333965Sjdp  int on, old_flag;
225433965Sjdp
225533965Sjdp  on = get_absolute_expression ();
225633965Sjdp  old_flag = flag_mri;
225733965Sjdp  if (on != 0)
225833965Sjdp    {
225933965Sjdp      flag_mri = 1;
226033965Sjdp#ifdef TC_M68K
226133965Sjdp      flag_m68k_mri = 1;
226233965Sjdp#endif
226360484Sobrien      macro_mri_mode (1);
226433965Sjdp    }
226533965Sjdp  else
226633965Sjdp    {
226733965Sjdp      flag_mri = 0;
226860484Sobrien#ifdef TC_M68K
226933965Sjdp      flag_m68k_mri = 0;
227060484Sobrien#endif
227160484Sobrien      macro_mri_mode (0);
227233965Sjdp    }
227333965Sjdp
227460484Sobrien  /* Operator precedence changes in m68k MRI mode, so we need to
227560484Sobrien     update the operator rankings.  */
227660484Sobrien  expr_set_precedence ();
227760484Sobrien
227833965Sjdp#ifdef MRI_MODE_CHANGE
227933965Sjdp  if (on != old_flag)
228033965Sjdp    MRI_MODE_CHANGE (on);
228133965Sjdp#endif
228233965Sjdp
228333965Sjdp  demand_empty_rest_of_line ();
228433965Sjdp}
228533965Sjdp
228633965Sjdp/* Handle changing the location counter.  */
228733965Sjdp
228833965Sjdpstatic void
2289130561Sobriendo_org (segT segment, expressionS *exp, int fill)
229033965Sjdp{
229133965Sjdp  if (segment != now_seg && segment != absolute_section)
229289857Sobrien    as_bad (_("invalid segment \"%s\""), segment_name (segment));
229333965Sjdp
229433965Sjdp  if (now_seg == absolute_section)
229533965Sjdp    {
229633965Sjdp      if (fill != 0)
229760484Sobrien	as_warn (_("ignoring fill value in absolute section"));
229833965Sjdp      if (exp->X_op != O_constant)
229933965Sjdp	{
230060484Sobrien	  as_bad (_("only constant offsets supported in absolute section"));
230133965Sjdp	  exp->X_add_number = 0;
230233965Sjdp	}
230333965Sjdp      abs_section_offset = exp->X_add_number;
230433965Sjdp    }
230533965Sjdp  else
230633965Sjdp    {
230733965Sjdp      char *p;
230878828Sobrien      symbolS *sym = exp->X_add_symbol;
230978828Sobrien      offsetT off = exp->X_add_number * OCTETS_PER_BYTE;
231033965Sjdp
231178828Sobrien      if (exp->X_op != O_constant && exp->X_op != O_symbol)
231278828Sobrien	{
231378828Sobrien	  /* Handle complex expressions.  */
231478828Sobrien	  sym = make_expr_symbol (exp);
231578828Sobrien	  off = 0;
231678828Sobrien	}
231778828Sobrien
231878828Sobrien      p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0);
231933965Sjdp      *p = fill;
232033965Sjdp    }
232133965Sjdp}
232233965Sjdp
232377298Sobrienvoid
2324130561Sobriens_org (int ignore ATTRIBUTE_UNUSED)
232533965Sjdp{
232633965Sjdp  register segT segment;
232733965Sjdp  expressionS exp;
232833965Sjdp  register long temp_fill;
232933965Sjdp
233060484Sobrien#ifdef md_flush_pending_output
233160484Sobrien  md_flush_pending_output ();
233260484Sobrien#endif
233360484Sobrien
233433965Sjdp  /* The m68k MRI assembler has a different meaning for .org.  It
233533965Sjdp     means to create an absolute section at a given address.  We can't
233633965Sjdp     support that--use a linker script instead.  */
233733965Sjdp  if (flag_m68k_mri)
233833965Sjdp    {
233960484Sobrien      as_bad (_("MRI style ORG pseudo-op not supported"));
234033965Sjdp      ignore_rest_of_line ();
234133965Sjdp      return;
234233965Sjdp    }
234333965Sjdp
234433965Sjdp  /* Don't believe the documentation of BSD 4.2 AS.  There is no such
234533965Sjdp     thing as a sub-segment-relative origin.  Any absolute origin is
234633965Sjdp     given a warning, then assumed to be segment-relative.  Any
234733965Sjdp     segmented origin expression ("foo+42") had better be in the right
234833965Sjdp     segment or the .org is ignored.
234933965Sjdp
235033965Sjdp     BSD 4.2 AS warns if you try to .org backwards. We cannot because
235133965Sjdp     we never know sub-segment sizes when we are reading code.  BSD
235233965Sjdp     will crash trying to emit negative numbers of filler bytes in
235333965Sjdp     certain .orgs. We don't crash, but see as-write for that code.
235433965Sjdp
235533965Sjdp     Don't make frag if need_pass_2==1.  */
235633965Sjdp  segment = get_known_segmented_expression (&exp);
235733965Sjdp  if (*input_line_pointer == ',')
235833965Sjdp    {
235933965Sjdp      input_line_pointer++;
236033965Sjdp      temp_fill = get_absolute_expression ();
236133965Sjdp    }
236233965Sjdp  else
236333965Sjdp    temp_fill = 0;
236433965Sjdp
236533965Sjdp  if (!need_pass_2)
236633965Sjdp    do_org (segment, &exp, temp_fill);
236733965Sjdp
236833965Sjdp  demand_empty_rest_of_line ();
236977298Sobrien}
237033965Sjdp
237133965Sjdp/* Handle parsing for the MRI SECT/SECTION pseudo-op.  This should be
237233965Sjdp   called by the obj-format routine which handles section changing
237333965Sjdp   when in MRI mode.  It will create a new section, and return it.  It
237433965Sjdp   will set *TYPE to the section type: one of 'C' (code), 'D' (data),
237533965Sjdp   'M' (mixed), or 'R' (romable).  If BFD_ASSEMBLER is defined, the
237633965Sjdp   flags will be set in the section.  */
237733965Sjdp
237833965Sjdpvoid
2379130561Sobriens_mri_sect (char *type ATTRIBUTE_UNUSED)
238033965Sjdp{
238133965Sjdp#ifdef TC_M68K
238233965Sjdp
238333965Sjdp  char *name;
238433965Sjdp  char c;
238533965Sjdp  segT seg;
238633965Sjdp
238733965Sjdp  SKIP_WHITESPACE ();
238877298Sobrien
238933965Sjdp  name = input_line_pointer;
239089857Sobrien  if (!ISDIGIT (*name))
239133965Sjdp    c = get_symbol_end ();
239233965Sjdp  else
239333965Sjdp    {
239433965Sjdp      do
239533965Sjdp	{
239633965Sjdp	  ++input_line_pointer;
239733965Sjdp	}
239889857Sobrien      while (ISDIGIT (*input_line_pointer));
239977298Sobrien
240033965Sjdp      c = *input_line_pointer;
240133965Sjdp      *input_line_pointer = '\0';
240233965Sjdp    }
240333965Sjdp
240433965Sjdp  name = xstrdup (name);
240533965Sjdp
240633965Sjdp  *input_line_pointer = c;
240733965Sjdp
240833965Sjdp  seg = subseg_new (name, 0);
240933965Sjdp
241033965Sjdp  if (*input_line_pointer == ',')
241133965Sjdp    {
241233965Sjdp      int align;
241333965Sjdp
241433965Sjdp      ++input_line_pointer;
241533965Sjdp      align = get_absolute_expression ();
241633965Sjdp      record_alignment (seg, align);
241733965Sjdp    }
241833965Sjdp
241933965Sjdp  *type = 'C';
242033965Sjdp  if (*input_line_pointer == ',')
242133965Sjdp    {
242233965Sjdp      c = *++input_line_pointer;
242389857Sobrien      c = TOUPPER (c);
242433965Sjdp      if (c == 'C' || c == 'D' || c == 'M' || c == 'R')
242533965Sjdp	*type = c;
242633965Sjdp      else
242760484Sobrien	as_bad (_("unrecognized section type"));
242833965Sjdp      ++input_line_pointer;
242933965Sjdp
243033965Sjdp#ifdef BFD_ASSEMBLER
243133965Sjdp      {
243233965Sjdp	flagword flags;
243333965Sjdp
243433965Sjdp	flags = SEC_NO_FLAGS;
243533965Sjdp	if (*type == 'C')
243633965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE;
243733965Sjdp	else if (*type == 'D' || *type == 'M')
243833965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_DATA;
243933965Sjdp	else if (*type == 'R')
244033965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM;
244133965Sjdp	if (flags != SEC_NO_FLAGS)
244233965Sjdp	  {
244377298Sobrien	    if (!bfd_set_section_flags (stdoutput, seg, flags))
244460484Sobrien	      as_warn (_("error setting flags for \"%s\": %s"),
244533965Sjdp		       bfd_section_name (stdoutput, seg),
244633965Sjdp		       bfd_errmsg (bfd_get_error ()));
244733965Sjdp	  }
244833965Sjdp      }
244933965Sjdp#endif
245033965Sjdp    }
245133965Sjdp
245233965Sjdp  /* Ignore the HP type.  */
245333965Sjdp  if (*input_line_pointer == ',')
245433965Sjdp    input_line_pointer += 2;
245533965Sjdp
245633965Sjdp  demand_empty_rest_of_line ();
245733965Sjdp
245833965Sjdp#else /* ! TC_M68K */
245933965Sjdp#ifdef TC_I960
246033965Sjdp
246133965Sjdp  char *name;
246233965Sjdp  char c;
246333965Sjdp  segT seg;
246433965Sjdp
246533965Sjdp  SKIP_WHITESPACE ();
246633965Sjdp
246733965Sjdp  name = input_line_pointer;
246833965Sjdp  c = get_symbol_end ();
246933965Sjdp
247033965Sjdp  name = xstrdup (name);
247133965Sjdp
247233965Sjdp  *input_line_pointer = c;
247333965Sjdp
247433965Sjdp  seg = subseg_new (name, 0);
247533965Sjdp
247633965Sjdp  if (*input_line_pointer != ',')
247733965Sjdp    *type = 'C';
247833965Sjdp  else
247933965Sjdp    {
248033965Sjdp      char *sectype;
248133965Sjdp
248233965Sjdp      ++input_line_pointer;
248333965Sjdp      SKIP_WHITESPACE ();
248433965Sjdp      sectype = input_line_pointer;
248533965Sjdp      c = get_symbol_end ();
248633965Sjdp      if (*sectype == '\0')
248733965Sjdp	*type = 'C';
248833965Sjdp      else if (strcasecmp (sectype, "text") == 0)
248933965Sjdp	*type = 'C';
249033965Sjdp      else if (strcasecmp (sectype, "data") == 0)
249133965Sjdp	*type = 'D';
249233965Sjdp      else if (strcasecmp (sectype, "romdata") == 0)
249333965Sjdp	*type = 'R';
249433965Sjdp      else
249560484Sobrien	as_warn (_("unrecognized section type `%s'"), sectype);
249633965Sjdp      *input_line_pointer = c;
249733965Sjdp    }
249833965Sjdp
249933965Sjdp  if (*input_line_pointer == ',')
250033965Sjdp    {
250133965Sjdp      char *seccmd;
250233965Sjdp
250333965Sjdp      ++input_line_pointer;
250433965Sjdp      SKIP_WHITESPACE ();
250533965Sjdp      seccmd = input_line_pointer;
250633965Sjdp      c = get_symbol_end ();
250733965Sjdp      if (strcasecmp (seccmd, "absolute") == 0)
250833965Sjdp	{
250960484Sobrien	  as_bad (_("absolute sections are not supported"));
251033965Sjdp	  *input_line_pointer = c;
251133965Sjdp	  ignore_rest_of_line ();
251233965Sjdp	  return;
251333965Sjdp	}
251433965Sjdp      else if (strcasecmp (seccmd, "align") == 0)
251533965Sjdp	{
251633965Sjdp	  int align;
251733965Sjdp
251833965Sjdp	  *input_line_pointer = c;
251933965Sjdp	  align = get_absolute_expression ();
252033965Sjdp	  record_alignment (seg, align);
252133965Sjdp	}
252233965Sjdp      else
252333965Sjdp	{
252460484Sobrien	  as_warn (_("unrecognized section command `%s'"), seccmd);
252533965Sjdp	  *input_line_pointer = c;
252633965Sjdp	}
252733965Sjdp    }
252833965Sjdp
252977298Sobrien  demand_empty_rest_of_line ();
253033965Sjdp
253133965Sjdp#else /* ! TC_I960 */
253233965Sjdp  /* The MRI assembler seems to use different forms of .sect for
253333965Sjdp     different targets.  */
253460484Sobrien  as_bad ("MRI mode not supported for this target");
253560484Sobrien  ignore_rest_of_line ();
253633965Sjdp#endif /* ! TC_I960 */
253733965Sjdp#endif /* ! TC_M68K */
253833965Sjdp}
253933965Sjdp
254033965Sjdp/* Handle the .print pseudo-op.  */
254133965Sjdp
254233965Sjdpvoid
2543130561Sobriens_print (int ignore ATTRIBUTE_UNUSED)
254433965Sjdp{
254533965Sjdp  char *s;
254633965Sjdp  int len;
254733965Sjdp
254833965Sjdp  s = demand_copy_C_string (&len);
2549130561Sobrien  if (s != NULL)
2550130561Sobrien    printf ("%s\n", s);
255133965Sjdp  demand_empty_rest_of_line ();
255233965Sjdp}
255333965Sjdp
255433965Sjdp/* Handle the .purgem pseudo-op.  */
255533965Sjdp
255633965Sjdpvoid
2557130561Sobriens_purgem (int ignore ATTRIBUTE_UNUSED)
255833965Sjdp{
255933965Sjdp  if (is_it_end_of_statement ())
256033965Sjdp    {
256133965Sjdp      demand_empty_rest_of_line ();
256233965Sjdp      return;
256333965Sjdp    }
256433965Sjdp
256533965Sjdp  do
256633965Sjdp    {
256733965Sjdp      char *name;
256833965Sjdp      char c;
256933965Sjdp
257033965Sjdp      SKIP_WHITESPACE ();
257133965Sjdp      name = input_line_pointer;
257233965Sjdp      c = get_symbol_end ();
257333965Sjdp      delete_macro (name);
257433965Sjdp      *input_line_pointer = c;
257533965Sjdp      SKIP_WHITESPACE ();
257633965Sjdp    }
257733965Sjdp  while (*input_line_pointer++ == ',');
257833965Sjdp
257933965Sjdp  --input_line_pointer;
258033965Sjdp  demand_empty_rest_of_line ();
258133965Sjdp}
258233965Sjdp
258333965Sjdp/* Handle the .rept pseudo-op.  */
258433965Sjdp
258533965Sjdpvoid
2586130561Sobriens_bad_endr (int ignore ATTRIBUTE_UNUSED)
258789857Sobrien{
258889857Sobrien  as_warn (_(".endr encountered without preceeding .rept, .irc, or .irp"));
258989857Sobrien  demand_empty_rest_of_line ();
259089857Sobrien}
259189857Sobrien
259289857Sobrien/* Handle the .rept pseudo-op.  */
259389857Sobrien
259489857Sobrienvoid
2595130561Sobriens_rept (int ignore ATTRIBUTE_UNUSED)
259633965Sjdp{
259733965Sjdp  int count;
259860484Sobrien
259960484Sobrien  count = get_absolute_expression ();
260060484Sobrien
260177298Sobrien  do_repeat (count, "REPT", "ENDR");
260260484Sobrien}
260360484Sobrien
260460484Sobrien/* This function provides a generic repeat block implementation.   It allows
260577298Sobrien   different directives to be used as the start/end keys.  */
260660484Sobrien
260760484Sobrienvoid
2608130561Sobriendo_repeat (int count, const char *start, const char *end)
260960484Sobrien{
261033965Sjdp  sb one;
261133965Sjdp  sb many;
261233965Sjdp
261333965Sjdp  sb_new (&one);
261477298Sobrien  if (!buffer_and_nest (start, end, &one, get_line_sb))
261533965Sjdp    {
261660484Sobrien      as_bad (_("%s without %s"), start, end);
261733965Sjdp      return;
261833965Sjdp    }
261933965Sjdp
262033965Sjdp  sb_new (&many);
262133965Sjdp  while (count-- > 0)
262233965Sjdp    sb_add_sb (&many, &one);
262333965Sjdp
262433965Sjdp  sb_kill (&one);
262533965Sjdp
262660484Sobrien  input_scrub_include_sb (&many, input_line_pointer, 1);
262733965Sjdp  sb_kill (&many);
262833965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
262933965Sjdp}
263033965Sjdp
263160484Sobrien/* Skip to end of current repeat loop; EXTRA indicates how many additional
263260484Sobrien   input buffers to skip.  Assumes that conditionals preceding the loop end
263377298Sobrien   are properly nested.
263460484Sobrien
263560484Sobrien   This function makes it easier to implement a premature "break" out of the
263660484Sobrien   loop.  The EXTRA arg accounts for other buffers we might have inserted,
263777298Sobrien   such as line substitutions.  */
263860484Sobrien
263960484Sobrienvoid
2640130561Sobrienend_repeat (int extra)
264160484Sobrien{
264260484Sobrien  cond_exit_macro (macro_nest);
264360484Sobrien  while (extra-- >= 0)
264460484Sobrien    buffer_limit = input_scrub_next_buffer (&input_line_pointer);
264560484Sobrien}
264660484Sobrien
264733965Sjdp/* Handle the .equ, .equiv and .set directives.  If EQUIV is 1, then
264833965Sjdp   this is .equiv, and it is an error if the symbol is already
264933965Sjdp   defined.  */
265033965Sjdp
265177298Sobrienvoid
2652130561Sobriens_set (int equiv)
265333965Sjdp{
265433965Sjdp  register char *name;
265533965Sjdp  register char delim;
265633965Sjdp  register char *end_name;
265733965Sjdp  register symbolS *symbolP;
265833965Sjdp
265977298Sobrien  /* Especial apologies for the random logic:
266077298Sobrien     this just grew, and could be parsed much more simply!
266177298Sobrien     Dean in haste.  */
266233965Sjdp  name = input_line_pointer;
266333965Sjdp  delim = get_symbol_end ();
266433965Sjdp  end_name = input_line_pointer;
266533965Sjdp  *end_name = delim;
266689857Sobrien
266789857Sobrien  if (name == end_name)
266889857Sobrien    {
266989857Sobrien      as_bad (_("expected symbol name"));
267089857Sobrien      discard_rest_of_line ();
267189857Sobrien      return;
267289857Sobrien    }
267389857Sobrien
267433965Sjdp  SKIP_WHITESPACE ();
267533965Sjdp
267633965Sjdp  if (*input_line_pointer != ',')
267733965Sjdp    {
267833965Sjdp      *end_name = 0;
267989857Sobrien      as_bad (_("expected comma after \"%s\""), name);
268033965Sjdp      *end_name = delim;
268133965Sjdp      ignore_rest_of_line ();
268233965Sjdp      return;
268333965Sjdp    }
268433965Sjdp
268533965Sjdp  input_line_pointer++;
268633965Sjdp  *end_name = 0;
268733965Sjdp
268833965Sjdp  if (name[0] == '.' && name[1] == '\0')
268933965Sjdp    {
269077298Sobrien      /* Turn '. = mumble' into a .org mumble.  */
269133965Sjdp      register segT segment;
269233965Sjdp      expressionS exp;
269333965Sjdp
269433965Sjdp      segment = get_known_segmented_expression (&exp);
269533965Sjdp
269633965Sjdp      if (!need_pass_2)
269733965Sjdp	do_org (segment, &exp, 0);
269833965Sjdp
269933965Sjdp      *end_name = delim;
270033965Sjdp      return;
270133965Sjdp    }
270233965Sjdp
270333965Sjdp  if ((symbolP = symbol_find (name)) == NULL
270433965Sjdp      && (symbolP = md_undefined_symbol (name)) == NULL)
270533965Sjdp    {
270638889Sjdp#ifndef NO_LISTING
270738889Sjdp      /* When doing symbol listings, play games with dummy fragments living
270838889Sjdp	 outside the normal fragment chain to record the file and line info
2709130561Sobrien	 for this symbol.  */
271038889Sjdp      if (listing & LISTING_SYMBOLS)
271138889Sjdp	{
271238889Sjdp	  extern struct list_info_struct *listing_tail;
271377298Sobrien	  fragS *dummy_frag = (fragS *) xmalloc (sizeof (fragS));
271477298Sobrien	  memset (dummy_frag, 0, sizeof (fragS));
271538889Sjdp	  dummy_frag->fr_type = rs_fill;
271638889Sjdp	  dummy_frag->line = listing_tail;
271738889Sjdp	  symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
271838889Sjdp	  dummy_frag->fr_symbol = symbolP;
271938889Sjdp	}
272038889Sjdp      else
272138889Sjdp#endif
272277298Sobrien	symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
272377298Sobrien
272433965Sjdp#ifdef OBJ_COFF
272577298Sobrien      /* "set" symbols are local unless otherwise specified.  */
272633965Sjdp      SF_SET_LOCAL (symbolP);
272733965Sjdp#endif /* OBJ_COFF */
272877298Sobrien    }
272933965Sjdp
273033965Sjdp  symbol_table_insert (symbolP);
273133965Sjdp
273233965Sjdp  *end_name = delim;
273333965Sjdp
273433965Sjdp  if (equiv
273533965Sjdp      && S_IS_DEFINED (symbolP)
273633965Sjdp      && S_GET_SEGMENT (symbolP) != reg_section)
273789857Sobrien    as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
273833965Sjdp
273933965Sjdp  pseudo_set (symbolP);
274033965Sjdp  demand_empty_rest_of_line ();
274177298Sobrien}
274233965Sjdp
274377298Sobrienvoid
2744130561Sobriens_space (int mult)
274533965Sjdp{
274633965Sjdp  expressionS exp;
274733965Sjdp  expressionS val;
274833965Sjdp  char *p = 0;
274933965Sjdp  char *stop = NULL;
275033965Sjdp  char stopc;
275133965Sjdp  int bytes;
275233965Sjdp
275333965Sjdp#ifdef md_flush_pending_output
275433965Sjdp  md_flush_pending_output ();
275533965Sjdp#endif
275633965Sjdp
275733965Sjdp  if (flag_mri)
275833965Sjdp    stop = mri_comment_field (&stopc);
275933965Sjdp
276033965Sjdp  /* In m68k MRI mode, we need to align to a word boundary, unless
276133965Sjdp     this is ds.b.  */
276233965Sjdp  if (flag_m68k_mri && mult > 1)
276333965Sjdp    {
276433965Sjdp      if (now_seg == absolute_section)
276533965Sjdp	{
276633965Sjdp	  abs_section_offset += abs_section_offset & 1;
276733965Sjdp	  if (line_label != NULL)
276833965Sjdp	    S_SET_VALUE (line_label, abs_section_offset);
276933965Sjdp	}
277033965Sjdp      else if (mri_common_symbol != NULL)
277133965Sjdp	{
277233965Sjdp	  valueT val;
277333965Sjdp
277433965Sjdp	  val = S_GET_VALUE (mri_common_symbol);
277533965Sjdp	  if ((val & 1) != 0)
277633965Sjdp	    {
277733965Sjdp	      S_SET_VALUE (mri_common_symbol, val + 1);
277833965Sjdp	      if (line_label != NULL)
277933965Sjdp		{
278060484Sobrien		  expressionS *symexp;
278160484Sobrien
278260484Sobrien		  symexp = symbol_get_value_expression (line_label);
278360484Sobrien		  know (symexp->X_op == O_symbol);
278460484Sobrien		  know (symexp->X_add_symbol == mri_common_symbol);
278560484Sobrien		  symexp->X_add_number += 1;
278633965Sjdp		}
278733965Sjdp	    }
278833965Sjdp	}
278933965Sjdp      else
279033965Sjdp	{
279133965Sjdp	  do_align (1, (char *) NULL, 0, 0);
279233965Sjdp	  if (line_label != NULL)
279333965Sjdp	    {
279460484Sobrien	      symbol_set_frag (line_label, frag_now);
279533965Sjdp	      S_SET_VALUE (line_label, frag_now_fix ());
279633965Sjdp	    }
279733965Sjdp	}
279833965Sjdp    }
279933965Sjdp
280033965Sjdp  bytes = mult;
280133965Sjdp
280233965Sjdp  expression (&exp);
280333965Sjdp
280433965Sjdp  SKIP_WHITESPACE ();
280533965Sjdp  if (*input_line_pointer == ',')
280633965Sjdp    {
280733965Sjdp      ++input_line_pointer;
280833965Sjdp      expression (&val);
280933965Sjdp    }
281033965Sjdp  else
281133965Sjdp    {
281233965Sjdp      val.X_op = O_constant;
281333965Sjdp      val.X_add_number = 0;
281433965Sjdp    }
281533965Sjdp
281633965Sjdp  if (val.X_op != O_constant
281733965Sjdp      || val.X_add_number < - 0x80
281833965Sjdp      || val.X_add_number > 0xff
281933965Sjdp      || (mult != 0 && mult != 1 && val.X_add_number != 0))
282033965Sjdp    {
282133965Sjdp      if (exp.X_op != O_constant)
282289857Sobrien	as_bad (_("unsupported variable size or fill value"));
282333965Sjdp      else
282433965Sjdp	{
282533965Sjdp	  offsetT i;
282633965Sjdp
282733965Sjdp	  if (mult == 0)
282833965Sjdp	    mult = 1;
282933965Sjdp	  bytes = mult * exp.X_add_number;
283033965Sjdp	  for (i = 0; i < exp.X_add_number; i++)
283133965Sjdp	    emit_expr (&val, mult);
283233965Sjdp	}
283333965Sjdp    }
283433965Sjdp  else
283533965Sjdp    {
283633965Sjdp      if (exp.X_op == O_constant)
283733965Sjdp	{
283833965Sjdp	  long repeat;
283933965Sjdp
284033965Sjdp	  repeat = exp.X_add_number;
284133965Sjdp	  if (mult)
284233965Sjdp	    repeat *= mult;
284333965Sjdp	  bytes = repeat;
284433965Sjdp	  if (repeat <= 0)
284533965Sjdp	    {
284677298Sobrien	      if (!flag_mri)
284760484Sobrien		as_warn (_(".space repeat count is zero, ignored"));
284860484Sobrien	      else if (repeat < 0)
284960484Sobrien		as_warn (_(".space repeat count is negative, ignored"));
285033965Sjdp	      goto getout;
285133965Sjdp	    }
285233965Sjdp
285333965Sjdp	  /* If we are in the absolute section, just bump the offset.  */
285433965Sjdp	  if (now_seg == absolute_section)
285533965Sjdp	    {
285633965Sjdp	      abs_section_offset += repeat;
285733965Sjdp	      goto getout;
285833965Sjdp	    }
285933965Sjdp
286033965Sjdp	  /* If we are secretly in an MRI common section, then
286133965Sjdp	     creating space just increases the size of the common
286233965Sjdp	     symbol.  */
286333965Sjdp	  if (mri_common_symbol != NULL)
286433965Sjdp	    {
286533965Sjdp	      S_SET_VALUE (mri_common_symbol,
286633965Sjdp			   S_GET_VALUE (mri_common_symbol) + repeat);
286733965Sjdp	      goto getout;
286833965Sjdp	    }
286933965Sjdp
287033965Sjdp	  if (!need_pass_2)
287133965Sjdp	    p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
287233965Sjdp			  (offsetT) repeat, (char *) 0);
287333965Sjdp	}
287433965Sjdp      else
287533965Sjdp	{
287633965Sjdp	  if (now_seg == absolute_section)
287733965Sjdp	    {
287860484Sobrien	      as_bad (_("space allocation too complex in absolute section"));
287933965Sjdp	      subseg_set (text_section, 0);
288033965Sjdp	    }
288177298Sobrien
288233965Sjdp	  if (mri_common_symbol != NULL)
288333965Sjdp	    {
288460484Sobrien	      as_bad (_("space allocation too complex in common section"));
288533965Sjdp	      mri_common_symbol = NULL;
288633965Sjdp	    }
288777298Sobrien
288833965Sjdp	  if (!need_pass_2)
288933965Sjdp	    p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
289033965Sjdp			  make_expr_symbol (&exp), (offsetT) 0, (char *) 0);
289133965Sjdp	}
289233965Sjdp
289333965Sjdp      if (p)
289433965Sjdp	*p = val.X_add_number;
289533965Sjdp    }
289633965Sjdp
289733965Sjdp getout:
289833965Sjdp
289933965Sjdp  /* In MRI mode, after an odd number of bytes, we must align to an
290033965Sjdp     even word boundary, unless the next instruction is a dc.b, ds.b
290133965Sjdp     or dcb.b.  */
290233965Sjdp  if (flag_mri && (bytes & 1) != 0)
290333965Sjdp    mri_pending_align = 1;
290433965Sjdp
290560484Sobrien  demand_empty_rest_of_line ();
290660484Sobrien
290733965Sjdp  if (flag_mri)
290833965Sjdp    mri_comment_end (stop, stopc);
290933965Sjdp}
291033965Sjdp
291133965Sjdp/* This is like s_space, but the value is a floating point number with
291233965Sjdp   the given precision.  This is for the MRI dcb.s pseudo-op and
291333965Sjdp   friends.  */
291433965Sjdp
291533965Sjdpvoid
2916130561Sobriens_float_space (int float_type)
291733965Sjdp{
291833965Sjdp  offsetT count;
291933965Sjdp  int flen;
292033965Sjdp  char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
292133965Sjdp  char *stop = NULL;
292233965Sjdp  char stopc;
292333965Sjdp
292433965Sjdp  if (flag_mri)
292533965Sjdp    stop = mri_comment_field (&stopc);
292633965Sjdp
292733965Sjdp  count = get_absolute_expression ();
292833965Sjdp
292933965Sjdp  SKIP_WHITESPACE ();
293033965Sjdp  if (*input_line_pointer != ',')
293133965Sjdp    {
293260484Sobrien      as_bad (_("missing value"));
293360484Sobrien      ignore_rest_of_line ();
293433965Sjdp      if (flag_mri)
293533965Sjdp	mri_comment_end (stop, stopc);
293633965Sjdp      return;
293733965Sjdp    }
293833965Sjdp
293933965Sjdp  ++input_line_pointer;
294033965Sjdp
294133965Sjdp  SKIP_WHITESPACE ();
294233965Sjdp
294333965Sjdp  /* Skip any 0{letter} that may be present.  Don't even check if the
294433965Sjdp   * letter is legal.  */
294538889Sjdp  if (input_line_pointer[0] == '0'
294689857Sobrien      && ISALPHA (input_line_pointer[1]))
294733965Sjdp    input_line_pointer += 2;
294833965Sjdp
294933965Sjdp  /* Accept :xxxx, where the x's are hex digits, for a floating point
295033965Sjdp     with the exact digits specified.  */
295133965Sjdp  if (input_line_pointer[0] == ':')
295233965Sjdp    {
295333965Sjdp      flen = hex_float (float_type, temp);
295433965Sjdp      if (flen < 0)
295533965Sjdp	{
295660484Sobrien	  ignore_rest_of_line ();
295733965Sjdp	  if (flag_mri)
295833965Sjdp	    mri_comment_end (stop, stopc);
295933965Sjdp	  return;
296033965Sjdp	}
296133965Sjdp    }
296233965Sjdp  else
296333965Sjdp    {
296433965Sjdp      char *err;
296533965Sjdp
296633965Sjdp      err = md_atof (float_type, temp, &flen);
296733965Sjdp      know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
296833965Sjdp      know (flen > 0);
296933965Sjdp      if (err)
297033965Sjdp	{
297189857Sobrien	  as_bad (_("bad floating literal: %s"), err);
297260484Sobrien	  ignore_rest_of_line ();
297333965Sjdp	  if (flag_mri)
297433965Sjdp	    mri_comment_end (stop, stopc);
297533965Sjdp	  return;
297633965Sjdp	}
297733965Sjdp    }
297833965Sjdp
297933965Sjdp  while (--count >= 0)
298033965Sjdp    {
298133965Sjdp      char *p;
298233965Sjdp
298333965Sjdp      p = frag_more (flen);
298433965Sjdp      memcpy (p, temp, (unsigned int) flen);
298533965Sjdp    }
298633965Sjdp
298760484Sobrien  demand_empty_rest_of_line ();
298860484Sobrien
298933965Sjdp  if (flag_mri)
299033965Sjdp    mri_comment_end (stop, stopc);
299133965Sjdp}
299233965Sjdp
299333965Sjdp/* Handle the .struct pseudo-op, as found in MIPS assemblers.  */
299433965Sjdp
299533965Sjdpvoid
2996130561Sobriens_struct (int ignore ATTRIBUTE_UNUSED)
299733965Sjdp{
299833965Sjdp  char *stop = NULL;
299933965Sjdp  char stopc;
300033965Sjdp
300133965Sjdp  if (flag_mri)
300233965Sjdp    stop = mri_comment_field (&stopc);
300333965Sjdp  abs_section_offset = get_absolute_expression ();
300433965Sjdp  subseg_set (absolute_section, 0);
300560484Sobrien  demand_empty_rest_of_line ();
300633965Sjdp  if (flag_mri)
300733965Sjdp    mri_comment_end (stop, stopc);
300833965Sjdp}
300933965Sjdp
301033965Sjdpvoid
3011130561Sobriens_text (int ignore ATTRIBUTE_UNUSED)
301233965Sjdp{
301333965Sjdp  register int temp;
301433965Sjdp
301533965Sjdp  temp = get_absolute_expression ();
301633965Sjdp  subseg_set (text_section, (subsegT) temp);
301733965Sjdp  demand_empty_rest_of_line ();
301833965Sjdp#ifdef OBJ_VMS
301933965Sjdp  const_flag &= ~IN_DEFAULT_SECTION;
302033965Sjdp#endif
302177298Sobrien}
302233965Sjdp
3023130561Sobrien
3024130561Sobrien/* Verify that we are at the end of a line.  If not, issue an error and
3025130561Sobrien   skip to EOL.  */
3026130561Sobrien
302777298Sobrienvoid
3028130561Sobriendemand_empty_rest_of_line (void)
302933965Sjdp{
303033965Sjdp  SKIP_WHITESPACE ();
303133965Sjdp  if (is_end_of_line[(unsigned char) *input_line_pointer])
303277298Sobrien    input_line_pointer++;
303333965Sjdp  else
303433965Sjdp    {
303589857Sobrien      if (ISPRINT (*input_line_pointer))
3036130561Sobrien	as_bad (_("junk at end of line, first unrecognized character is `%c'"),
303789857Sobrien		 *input_line_pointer);
303833965Sjdp      else
3039130561Sobrien	as_bad (_("junk at end of line, first unrecognized character valued 0x%x"),
304089857Sobrien		 *input_line_pointer);
3041130561Sobrien      ignore_rest_of_line ();
304233965Sjdp    }
3043130561Sobrien
3044130561Sobrien  /* Return pointing just after end-of-line.  */
3045130561Sobrien  know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
3046130561Sobrien}
304777298Sobrien
3048130561Sobrien/* Silently advance to the end of line.  Use this after already having
3049130561Sobrien   issued an error about something bad.  */
3050130561Sobrien
3051130561Sobrienvoid
3052130561Sobrienignore_rest_of_line (void)
3053130561Sobrien{
3054130561Sobrien  while (input_line_pointer < buffer_limit
3055130561Sobrien	 && !is_end_of_line[(unsigned char) *input_line_pointer])
3056130561Sobrien    input_line_pointer++;
3057130561Sobrien
305877298Sobrien  input_line_pointer++;
305977298Sobrien
306077298Sobrien  /* Return pointing just after end-of-line.  */
306133965Sjdp  know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
306233965Sjdp}
306333965Sjdp
306460484Sobrienvoid
3065130561Sobriendiscard_rest_of_line (void)
306660484Sobrien{
306760484Sobrien  while (input_line_pointer < buffer_limit
306877298Sobrien	 && !is_end_of_line[(unsigned char) *input_line_pointer])
306977298Sobrien    input_line_pointer++;
307077298Sobrien
307177298Sobrien  input_line_pointer++;
307277298Sobrien
307377298Sobrien  /* Return pointing just after end-of-line.  */
307460484Sobrien  know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
307560484Sobrien}
307660484Sobrien
307777298Sobrien/* In:	Pointer to a symbol.
3078130561Sobrien	Input_line_pointer->expression.
307977298Sobrien
308077298Sobrien   Out:	Input_line_pointer->just after any whitespace after expression.
3081130561Sobrien	Tried to set symbol to value of expression.
3082130561Sobrien	Will change symbols type, value, and frag;  */
308377298Sobrien
308433965Sjdpvoid
3085130561Sobrienpseudo_set (symbolS *symbolP)
308633965Sjdp{
308733965Sjdp  expressionS exp;
308833965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
308933965Sjdp  int ext;
309033965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
309133965Sjdp
309277298Sobrien  know (symbolP);		/* NULL pointer is logic error.  */
309333965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
309433965Sjdp  ext = S_IS_EXTERNAL (symbolP);
309533965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
309633965Sjdp
309733965Sjdp  (void) expression (&exp);
309833965Sjdp
309933965Sjdp  if (exp.X_op == O_illegal)
310089857Sobrien    as_bad (_("illegal expression"));
310133965Sjdp  else if (exp.X_op == O_absent)
310289857Sobrien    as_bad (_("missing expression"));
310333965Sjdp  else if (exp.X_op == O_big)
310460484Sobrien    {
310560484Sobrien      if (exp.X_add_number > 0)
310689857Sobrien	as_bad (_("bignum invalid"));
310760484Sobrien      else
310889857Sobrien	as_bad (_("floating point number invalid"));
310960484Sobrien    }
311033965Sjdp  else if (exp.X_op == O_subtract
311133965Sjdp	   && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol))
311260484Sobrien	   && (symbol_get_frag (exp.X_add_symbol)
311360484Sobrien	       == symbol_get_frag (exp.X_op_symbol)))
311433965Sjdp    {
311533965Sjdp      exp.X_op = O_constant;
311633965Sjdp      exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol)
311733965Sjdp			  - S_GET_VALUE (exp.X_op_symbol));
311833965Sjdp    }
311933965Sjdp
312033965Sjdp  switch (exp.X_op)
312133965Sjdp    {
312233965Sjdp    case O_illegal:
312333965Sjdp    case O_absent:
312433965Sjdp    case O_big:
312533965Sjdp      exp.X_add_number = 0;
312633965Sjdp      /* Fall through.  */
312733965Sjdp    case O_constant:
312833965Sjdp      S_SET_SEGMENT (symbolP, absolute_section);
312933965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
313033965Sjdp      if (ext)
313133965Sjdp	S_SET_EXTERNAL (symbolP);
313233965Sjdp      else
313333965Sjdp	S_CLEAR_EXTERNAL (symbolP);
313433965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
313533965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
313638889Sjdp      if (exp.X_op != O_constant)
313777298Sobrien	symbol_set_frag (symbolP, &zero_address_frag);
313833965Sjdp      break;
313933965Sjdp
314033965Sjdp    case O_register:
314133965Sjdp      S_SET_SEGMENT (symbolP, reg_section);
314233965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
314360484Sobrien      symbol_set_frag (symbolP, &zero_address_frag);
314433965Sjdp      break;
314533965Sjdp
314633965Sjdp    case O_symbol:
314733965Sjdp      if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section
314833965Sjdp	  || exp.X_add_number != 0)
314960484Sobrien	symbol_set_value_expression (symbolP, &exp);
315060484Sobrien      else if (symbol_section_p (symbolP))
315189857Sobrien	as_bad ("attempt to set value of section symbol");
315233965Sjdp      else
315333965Sjdp	{
315433965Sjdp	  symbolS *s = exp.X_add_symbol;
315533965Sjdp
315633965Sjdp	  S_SET_SEGMENT (symbolP, S_GET_SEGMENT (s));
315733965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
315833965Sjdp	  if (ext)
315933965Sjdp	    S_SET_EXTERNAL (symbolP);
316033965Sjdp	  else
316133965Sjdp	    S_CLEAR_EXTERNAL (symbolP);
316233965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
316333965Sjdp	  S_SET_VALUE (symbolP,
316433965Sjdp		       exp.X_add_number + S_GET_VALUE (s));
316560484Sobrien	  symbol_set_frag (symbolP, symbol_get_frag (s));
316633965Sjdp	  copy_symbol_attributes (symbolP, s);
316733965Sjdp	}
316833965Sjdp      break;
316933965Sjdp
317033965Sjdp    default:
317133965Sjdp      /* The value is some complex expression.
317233965Sjdp	 FIXME: Should we set the segment to anything?  */
317360484Sobrien      symbol_set_value_expression (symbolP, &exp);
317433965Sjdp      break;
317533965Sjdp    }
317633965Sjdp}
317733965Sjdp
3178130561Sobrien/*			cons()
317933965Sjdp
318077298Sobrien   CONStruct more frag of .bytes, or .words etc.
318177298Sobrien   Should need_pass_2 be 1 then emit no frag(s).
318277298Sobrien   This understands EXPRESSIONS.
318377298Sobrien
318477298Sobrien   Bug (?)
318577298Sobrien
318677298Sobrien   This has a split personality. We use expression() to read the
318777298Sobrien   value. We can detect if the value won't fit in a byte or word.
318877298Sobrien   But we can't detect if expression() discarded significant digits
318977298Sobrien   in the case of a long. Not worth the crocks required to fix it.  */
319077298Sobrien
319133965Sjdp/* Select a parser for cons expressions.  */
319233965Sjdp
319333965Sjdp/* Some targets need to parse the expression in various fancy ways.
319433965Sjdp   You can define TC_PARSE_CONS_EXPRESSION to do whatever you like
319533965Sjdp   (for example, the HPPA does this).  Otherwise, you can define
319633965Sjdp   BITFIELD_CONS_EXPRESSIONS to permit bitfields to be specified, or
319733965Sjdp   REPEAT_CONS_EXPRESSIONS to permit repeat counts.  If none of these
319833965Sjdp   are defined, which is the normal case, then only simple expressions
319933965Sjdp   are permitted.  */
320033965Sjdp
320160484Sobrien#ifdef TC_M68K
320233965Sjdpstatic void
3203130561Sobrienparse_mri_cons (expressionS *exp, unsigned int nbytes);
320460484Sobrien#endif
320533965Sjdp
320633965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION
320733965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS
320833965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES)
320977298Sobrienstatic void
3210130561Sobrienparse_bitfield_cons (expressionS *exp, unsigned int nbytes);
321133965Sjdp#endif
321233965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
321333965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES)
321433965Sjdpstatic void
3215130561Sobrienparse_repeat_cons (expressionS *exp, unsigned int nbytes);
321633965Sjdp#endif
321733965Sjdp
321833965Sjdp/* If we haven't gotten one yet, just call expression.  */
321933965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION
322033965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP)
322133965Sjdp#endif
322233965Sjdp#endif
322333965Sjdp
3224130561Sobrienvoid
3225130561Sobriendo_parse_cons_expression (expressionS *exp,
3226130561Sobrien			  int nbytes ATTRIBUTE_UNUSED)
3227130561Sobrien{
3228130561Sobrien  TC_PARSE_CONS_EXPRESSION (exp, nbytes);
3229130561Sobrien}
3230130561Sobrien
3231130561Sobrien
323277298Sobrien/* Worker to do .byte etc statements.
323377298Sobrien   Clobbers input_line_pointer and checks end-of-line.  */
323477298Sobrien
323577298Sobrienstatic void
3236130561Sobriencons_worker (register int nbytes,	/* 1=.byte, 2=.word, 4=.long.  */
3237130561Sobrien	     int rva)
323833965Sjdp{
323933965Sjdp  int c;
324033965Sjdp  expressionS exp;
324133965Sjdp  char *stop = NULL;
324233965Sjdp  char stopc;
324333965Sjdp
324433965Sjdp#ifdef md_flush_pending_output
324533965Sjdp  md_flush_pending_output ();
324633965Sjdp#endif
324733965Sjdp
324833965Sjdp  if (flag_mri)
324933965Sjdp    stop = mri_comment_field (&stopc);
325033965Sjdp
325133965Sjdp  if (is_it_end_of_statement ())
325233965Sjdp    {
325360484Sobrien      demand_empty_rest_of_line ();
325433965Sjdp      if (flag_mri)
325533965Sjdp	mri_comment_end (stop, stopc);
325633965Sjdp      return;
325733965Sjdp    }
325833965Sjdp
325933965Sjdp#ifdef md_cons_align
326033965Sjdp  md_cons_align (nbytes);
326133965Sjdp#endif
326233965Sjdp
326333965Sjdp  c = 0;
326433965Sjdp  do
326533965Sjdp    {
326660484Sobrien#ifdef TC_M68K
326733965Sjdp      if (flag_m68k_mri)
326833965Sjdp	parse_mri_cons (&exp, (unsigned int) nbytes);
326933965Sjdp      else
327060484Sobrien#endif
327133965Sjdp	TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
327233965Sjdp
327333965Sjdp      if (rva)
327433965Sjdp	{
327533965Sjdp	  if (exp.X_op == O_symbol)
327633965Sjdp	    exp.X_op = O_symbol_rva;
327733965Sjdp	  else
327860484Sobrien	    as_fatal (_("rva without symbol"));
327933965Sjdp	}
328033965Sjdp      emit_expr (&exp, (unsigned int) nbytes);
328133965Sjdp      ++c;
328233965Sjdp    }
328333965Sjdp  while (*input_line_pointer++ == ',');
328433965Sjdp
328533965Sjdp  /* In MRI mode, after an odd number of bytes, we must align to an
328633965Sjdp     even word boundary, unless the next instruction is a dc.b, ds.b
328733965Sjdp     or dcb.b.  */
328833965Sjdp  if (flag_mri && nbytes == 1 && (c & 1) != 0)
328933965Sjdp    mri_pending_align = 1;
329033965Sjdp
329177298Sobrien  input_line_pointer--;		/* Put terminator back into stream.  */
329233965Sjdp
329360484Sobrien  demand_empty_rest_of_line ();
329460484Sobrien
329533965Sjdp  if (flag_mri)
329633965Sjdp    mri_comment_end (stop, stopc);
329733965Sjdp}
329833965Sjdp
329933965Sjdpvoid
3300130561Sobriencons (int size)
330133965Sjdp{
330233965Sjdp  cons_worker (size, 0);
330333965Sjdp}
330433965Sjdp
330577298Sobrienvoid
3306130561Sobriens_rva (int size)
330733965Sjdp{
330833965Sjdp  cons_worker (size, 1);
330933965Sjdp}
331033965Sjdp
331133965Sjdp/* Put the contents of expression EXP into the object file using
331233965Sjdp   NBYTES bytes.  If need_pass_2 is 1, this does nothing.  */
331333965Sjdp
331433965Sjdpvoid
3315130561Sobrienemit_expr (expressionS *exp, unsigned int nbytes)
331633965Sjdp{
331733965Sjdp  operatorT op;
331833965Sjdp  register char *p;
331933965Sjdp  valueT extra_digit = 0;
332033965Sjdp
332133965Sjdp  /* Don't do anything if we are going to make another pass.  */
332233965Sjdp  if (need_pass_2)
332333965Sjdp    return;
332433965Sjdp
3325130561Sobrien  dot_value = frag_now_fix ();
3326130561Sobrien
332738889Sjdp#ifndef NO_LISTING
332838889Sjdp#ifdef OBJ_ELF
332938889Sjdp  /* When gcc emits DWARF 1 debugging pseudo-ops, a line number will
333038889Sjdp     appear as a four byte positive constant in the .line section,
333138889Sjdp     followed by a 2 byte 0xffff.  Look for that case here.  */
333238889Sjdp  {
333338889Sjdp    static int dwarf_line = -1;
333438889Sjdp
333538889Sjdp    if (strcmp (segment_name (now_seg), ".line") != 0)
333638889Sjdp      dwarf_line = -1;
333738889Sjdp    else if (dwarf_line >= 0
333838889Sjdp	     && nbytes == 2
333938889Sjdp	     && exp->X_op == O_constant
334038889Sjdp	     && (exp->X_add_number == -1 || exp->X_add_number == 0xffff))
334138889Sjdp      listing_source_line ((unsigned int) dwarf_line);
334238889Sjdp    else if (nbytes == 4
334338889Sjdp	     && exp->X_op == O_constant
334438889Sjdp	     && exp->X_add_number >= 0)
334538889Sjdp      dwarf_line = exp->X_add_number;
334638889Sjdp    else
334738889Sjdp      dwarf_line = -1;
334838889Sjdp  }
334938889Sjdp
335038889Sjdp  /* When gcc emits DWARF 1 debugging pseudo-ops, a file name will
335138889Sjdp     appear as a 2 byte TAG_compile_unit (0x11) followed by a 2 byte
335238889Sjdp     AT_sibling (0x12) followed by a four byte address of the sibling
335338889Sjdp     followed by a 2 byte AT_name (0x38) followed by the name of the
335438889Sjdp     file.  We look for that case here.  */
335538889Sjdp  {
335638889Sjdp    static int dwarf_file = 0;
335738889Sjdp
335838889Sjdp    if (strcmp (segment_name (now_seg), ".debug") != 0)
335938889Sjdp      dwarf_file = 0;
336038889Sjdp    else if (dwarf_file == 0
336138889Sjdp	     && nbytes == 2
336238889Sjdp	     && exp->X_op == O_constant
336338889Sjdp	     && exp->X_add_number == 0x11)
336438889Sjdp      dwarf_file = 1;
336538889Sjdp    else if (dwarf_file == 1
336638889Sjdp	     && nbytes == 2
336738889Sjdp	     && exp->X_op == O_constant
336838889Sjdp	     && exp->X_add_number == 0x12)
336938889Sjdp      dwarf_file = 2;
337038889Sjdp    else if (dwarf_file == 2
337138889Sjdp	     && nbytes == 4)
337238889Sjdp      dwarf_file = 3;
337338889Sjdp    else if (dwarf_file == 3
337438889Sjdp	     && nbytes == 2
337538889Sjdp	     && exp->X_op == O_constant
337638889Sjdp	     && exp->X_add_number == 0x38)
337738889Sjdp      dwarf_file = 4;
337838889Sjdp    else
337938889Sjdp      dwarf_file = 0;
338038889Sjdp
338138889Sjdp    /* The variable dwarf_file_string tells stringer that the string
338238889Sjdp       may be the name of the source file.  */
338338889Sjdp    if (dwarf_file == 4)
338438889Sjdp      dwarf_file_string = 1;
338538889Sjdp    else
338638889Sjdp      dwarf_file_string = 0;
338738889Sjdp  }
338838889Sjdp#endif
338938889Sjdp#endif
339038889Sjdp
339138889Sjdp  if (check_eh_frame (exp, &nbytes))
339238889Sjdp    return;
339338889Sjdp
339433965Sjdp  op = exp->X_op;
339533965Sjdp
339633965Sjdp  /* Allow `.word 0' in the absolute section.  */
339733965Sjdp  if (now_seg == absolute_section)
339833965Sjdp    {
339933965Sjdp      if (op != O_constant || exp->X_add_number != 0)
340060484Sobrien	as_bad (_("attempt to store value in absolute section"));
340133965Sjdp      abs_section_offset += nbytes;
340233965Sjdp      return;
340333965Sjdp    }
340433965Sjdp
340533965Sjdp  /* Handle a negative bignum.  */
340633965Sjdp  if (op == O_uminus
340733965Sjdp      && exp->X_add_number == 0
340860484Sobrien      && symbol_get_value_expression (exp->X_add_symbol)->X_op == O_big
340960484Sobrien      && symbol_get_value_expression (exp->X_add_symbol)->X_add_number > 0)
341033965Sjdp    {
341133965Sjdp      int i;
341233965Sjdp      unsigned long carry;
341333965Sjdp
341460484Sobrien      exp = symbol_get_value_expression (exp->X_add_symbol);
341533965Sjdp
341633965Sjdp      /* Negate the bignum: one's complement each digit and add 1.  */
341733965Sjdp      carry = 1;
341833965Sjdp      for (i = 0; i < exp->X_add_number; i++)
341933965Sjdp	{
342033965Sjdp	  unsigned long next;
342133965Sjdp
342277298Sobrien	  next = (((~(generic_bignum[i] & LITTLENUM_MASK))
342333965Sjdp		   & LITTLENUM_MASK)
342433965Sjdp		  + carry);
342533965Sjdp	  generic_bignum[i] = next & LITTLENUM_MASK;
342633965Sjdp	  carry = next >> LITTLENUM_NUMBER_OF_BITS;
342733965Sjdp	}
342833965Sjdp
342933965Sjdp      /* We can ignore any carry out, because it will be handled by
343033965Sjdp	 extra_digit if it is needed.  */
343133965Sjdp
343233965Sjdp      extra_digit = (valueT) -1;
343333965Sjdp      op = O_big;
343433965Sjdp    }
343533965Sjdp
343633965Sjdp  if (op == O_absent || op == O_illegal)
343733965Sjdp    {
343860484Sobrien      as_warn (_("zero assumed for missing expression"));
343933965Sjdp      exp->X_add_number = 0;
344033965Sjdp      op = O_constant;
344133965Sjdp    }
344233965Sjdp  else if (op == O_big && exp->X_add_number <= 0)
344333965Sjdp    {
344489857Sobrien      as_bad (_("floating point number invalid"));
344533965Sjdp      exp->X_add_number = 0;
344633965Sjdp      op = O_constant;
344733965Sjdp    }
344833965Sjdp  else if (op == O_register)
344933965Sjdp    {
345060484Sobrien      as_warn (_("register value used as expression"));
345133965Sjdp      op = O_constant;
345233965Sjdp    }
345333965Sjdp
345433965Sjdp  p = frag_more ((int) nbytes);
345533965Sjdp
345633965Sjdp#ifndef WORKING_DOT_WORD
345733965Sjdp  /* If we have the difference of two symbols in a word, save it on
345833965Sjdp     the broken_words list.  See the code in write.c.  */
345933965Sjdp  if (op == O_subtract && nbytes == 2)
346033965Sjdp    {
346133965Sjdp      struct broken_word *x;
346233965Sjdp
346333965Sjdp      x = (struct broken_word *) xmalloc (sizeof (struct broken_word));
346433965Sjdp      x->next_broken_word = broken_words;
346533965Sjdp      broken_words = x;
346660484Sobrien      x->seg = now_seg;
346760484Sobrien      x->subseg = now_subseg;
346833965Sjdp      x->frag = frag_now;
346933965Sjdp      x->word_goes_here = p;
347033965Sjdp      x->dispfrag = 0;
347133965Sjdp      x->add = exp->X_add_symbol;
347233965Sjdp      x->sub = exp->X_op_symbol;
347333965Sjdp      x->addnum = exp->X_add_number;
347433965Sjdp      x->added = 0;
3475130561Sobrien      x->use_jump = 0;
347633965Sjdp      new_broken_words++;
347733965Sjdp      return;
347833965Sjdp    }
347933965Sjdp#endif
348033965Sjdp
348133965Sjdp  /* If we have an integer, but the number of bytes is too large to
348233965Sjdp     pass to md_number_to_chars, handle it as a bignum.  */
348333965Sjdp  if (op == O_constant && nbytes > sizeof (valueT))
348433965Sjdp    {
348533965Sjdp      valueT val;
348633965Sjdp      int gencnt;
348733965Sjdp
348877298Sobrien      if (!exp->X_unsigned && exp->X_add_number < 0)
348933965Sjdp	extra_digit = (valueT) -1;
349033965Sjdp      val = (valueT) exp->X_add_number;
349133965Sjdp      gencnt = 0;
349233965Sjdp      do
349333965Sjdp	{
349433965Sjdp	  generic_bignum[gencnt] = val & LITTLENUM_MASK;
349533965Sjdp	  val >>= LITTLENUM_NUMBER_OF_BITS;
349633965Sjdp	  ++gencnt;
349733965Sjdp	}
349833965Sjdp      while (val != 0);
349933965Sjdp      op = exp->X_op = O_big;
350033965Sjdp      exp->X_add_number = gencnt;
350133965Sjdp    }
350233965Sjdp
350333965Sjdp  if (op == O_constant)
350433965Sjdp    {
350533965Sjdp      register valueT get;
350633965Sjdp      register valueT use;
350733965Sjdp      register valueT mask;
350833965Sjdp      valueT hibit;
350933965Sjdp      register valueT unmask;
351033965Sjdp
351133965Sjdp      /* JF << of >= number of bits in the object is undefined.  In
351277298Sobrien	 particular SPARC (Sun 4) has problems.  */
351333965Sjdp      if (nbytes >= sizeof (valueT))
351433965Sjdp	{
351533965Sjdp	  mask = 0;
351633965Sjdp	  if (nbytes > sizeof (valueT))
351733965Sjdp	    hibit = 0;
351833965Sjdp	  else
351933965Sjdp	    hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
352033965Sjdp	}
352133965Sjdp      else
352233965Sjdp	{
352377298Sobrien	  /* Don't store these bits.  */
352433965Sjdp	  mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes);
352533965Sjdp	  hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
352633965Sjdp	}
352733965Sjdp
352877298Sobrien      unmask = ~mask;		/* Do store these bits.  */
352933965Sjdp
353033965Sjdp#ifdef NEVER
353133965Sjdp      "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
353277298Sobrien      mask = ~(unmask >> 1);	/* Includes sign bit now.  */
353333965Sjdp#endif
353433965Sjdp
353533965Sjdp      get = exp->X_add_number;
353633965Sjdp      use = get & unmask;
353733965Sjdp      if ((get & mask) != 0
353833965Sjdp	  && ((get & mask) != mask
353933965Sjdp	      || (get & hibit) == 0))
354077298Sobrien	{		/* Leading bits contain both 0s & 1s.  */
354189857Sobrien	  as_warn (_("value 0x%lx truncated to 0x%lx"),
354233965Sjdp		   (unsigned long) get, (unsigned long) use);
354333965Sjdp	}
354477298Sobrien      /* Put bytes in right order.  */
354533965Sjdp      md_number_to_chars (p, use, (int) nbytes);
354633965Sjdp    }
354733965Sjdp  else if (op == O_big)
354833965Sjdp    {
354938889Sjdp      unsigned int size;
355033965Sjdp      LITTLENUM_TYPE *nums;
355133965Sjdp
355233965Sjdp      know (nbytes % CHARS_PER_LITTLENUM == 0);
355333965Sjdp
355433965Sjdp      size = exp->X_add_number * CHARS_PER_LITTLENUM;
355533965Sjdp      if (nbytes < size)
355633965Sjdp	{
355789857Sobrien	  as_warn (_("bignum truncated to %d bytes"), nbytes);
355833965Sjdp	  size = nbytes;
355933965Sjdp	}
356033965Sjdp
356133965Sjdp      if (target_big_endian)
356233965Sjdp	{
356333965Sjdp	  while (nbytes > size)
356433965Sjdp	    {
356533965Sjdp	      md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
356633965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
356733965Sjdp	      p += CHARS_PER_LITTLENUM;
356833965Sjdp	    }
356933965Sjdp
357033965Sjdp	  nums = generic_bignum + size / CHARS_PER_LITTLENUM;
357189857Sobrien	  while (size >= CHARS_PER_LITTLENUM)
357233965Sjdp	    {
357333965Sjdp	      --nums;
357433965Sjdp	      md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
357533965Sjdp	      size -= CHARS_PER_LITTLENUM;
357633965Sjdp	      p += CHARS_PER_LITTLENUM;
357733965Sjdp	    }
357833965Sjdp	}
357933965Sjdp      else
358033965Sjdp	{
358133965Sjdp	  nums = generic_bignum;
358289857Sobrien	  while (size >= CHARS_PER_LITTLENUM)
358333965Sjdp	    {
358433965Sjdp	      md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
358533965Sjdp	      ++nums;
358633965Sjdp	      size -= CHARS_PER_LITTLENUM;
358733965Sjdp	      p += CHARS_PER_LITTLENUM;
358833965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
358933965Sjdp	    }
359033965Sjdp
359189857Sobrien	  while (nbytes >= CHARS_PER_LITTLENUM)
359233965Sjdp	    {
359333965Sjdp	      md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
359433965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
359533965Sjdp	      p += CHARS_PER_LITTLENUM;
359633965Sjdp	    }
359733965Sjdp	}
359833965Sjdp    }
359933965Sjdp  else
360033965Sjdp    {
360133965Sjdp      memset (p, 0, nbytes);
360233965Sjdp
360333965Sjdp      /* Now we need to generate a fixS to record the symbol value.
360433965Sjdp	 This is easy for BFD.  For other targets it can be more
360533965Sjdp	 complex.  For very complex cases (currently, the HPPA and
360633965Sjdp	 NS32K), you can define TC_CONS_FIX_NEW to do whatever you
360733965Sjdp	 want.  For simpler cases, you can define TC_CONS_RELOC to be
360833965Sjdp	 the name of the reloc code that should be stored in the fixS.
360933965Sjdp	 If neither is defined, the code uses NO_RELOC if it is
361033965Sjdp	 defined, and otherwise uses 0.  */
361133965Sjdp
361233965Sjdp#ifdef BFD_ASSEMBLER
361333965Sjdp#ifdef TC_CONS_FIX_NEW
361433965Sjdp      TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
361533965Sjdp#else
361633965Sjdp      {
361733965Sjdp	bfd_reloc_code_real_type r;
361833965Sjdp
361933965Sjdp	switch (nbytes)
362033965Sjdp	  {
362133965Sjdp	  case 1:
362233965Sjdp	    r = BFD_RELOC_8;
362333965Sjdp	    break;
362433965Sjdp	  case 2:
362533965Sjdp	    r = BFD_RELOC_16;
362633965Sjdp	    break;
362733965Sjdp	  case 4:
362833965Sjdp	    r = BFD_RELOC_32;
362933965Sjdp	    break;
363033965Sjdp	  case 8:
363133965Sjdp	    r = BFD_RELOC_64;
363233965Sjdp	    break;
363333965Sjdp	  default:
363460484Sobrien	    as_bad (_("unsupported BFD relocation size %u"), nbytes);
363533965Sjdp	    r = BFD_RELOC_32;
363633965Sjdp	    break;
363733965Sjdp	  }
363833965Sjdp	fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp,
363933965Sjdp		     0, r);
364033965Sjdp      }
364133965Sjdp#endif
364233965Sjdp#else
364333965Sjdp#ifdef TC_CONS_FIX_NEW
364433965Sjdp      TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
364533965Sjdp#else
364633965Sjdp      /* Figure out which reloc number to use.  Use TC_CONS_RELOC if
364733965Sjdp	 it is defined, otherwise use NO_RELOC if it is defined,
364833965Sjdp	 otherwise use 0.  */
364933965Sjdp#ifndef TC_CONS_RELOC
365033965Sjdp#ifdef NO_RELOC
365133965Sjdp#define TC_CONS_RELOC NO_RELOC
365233965Sjdp#else
365333965Sjdp#define TC_CONS_RELOC 0
365433965Sjdp#endif
365533965Sjdp#endif
365633965Sjdp      fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0,
365733965Sjdp		   TC_CONS_RELOC);
365833965Sjdp#endif /* TC_CONS_FIX_NEW */
365933965Sjdp#endif /* BFD_ASSEMBLER */
366033965Sjdp    }
366133965Sjdp}
366233965Sjdp
366333965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS
366433965Sjdp
366533965Sjdp/* i960 assemblers, (eg, asm960), allow bitfields after ".byte" as
366633965Sjdp   w:x,y:z, where w and y are bitwidths and x and y are values.  They
366733965Sjdp   then pack them all together. We do a little better in that we allow
366833965Sjdp   them in words, longs, etc. and we'll pack them in target byte order
366933965Sjdp   for you.
367033965Sjdp
3671130561Sobrien   The rules are: pack least significant bit first, if a field doesn't
367233965Sjdp   entirely fit, put it in the next unit.  Overflowing the bitfield is
367333965Sjdp   explicitly *not* even a warning.  The bitwidth should be considered
367433965Sjdp   a "mask".
367533965Sjdp
367633965Sjdp   To use this function the tc-XXX.h file should define
367733965Sjdp   BITFIELD_CONS_EXPRESSIONS.  */
367833965Sjdp
367977298Sobrienstatic void
368033965Sjdpparse_bitfield_cons (exp, nbytes)
368133965Sjdp     expressionS *exp;
368233965Sjdp     unsigned int nbytes;
368333965Sjdp{
368433965Sjdp  unsigned int bits_available = BITS_PER_CHAR * nbytes;
368533965Sjdp  char *hold = input_line_pointer;
368633965Sjdp
368733965Sjdp  (void) expression (exp);
368833965Sjdp
368933965Sjdp  if (*input_line_pointer == ':')
369077298Sobrien    {
369177298Sobrien      /* Bitfields.  */
369233965Sjdp      long value = 0;
369333965Sjdp
369433965Sjdp      for (;;)
369533965Sjdp	{
369633965Sjdp	  unsigned long width;
369733965Sjdp
369833965Sjdp	  if (*input_line_pointer != ':')
369933965Sjdp	    {
370033965Sjdp	      input_line_pointer = hold;
370133965Sjdp	      break;
370277298Sobrien	    }			/* Next piece is not a bitfield.  */
370333965Sjdp
370433965Sjdp	  /* In the general case, we can't allow
370533965Sjdp	     full expressions with symbol
370633965Sjdp	     differences and such.  The relocation
370733965Sjdp	     entries for symbols not defined in this
370833965Sjdp	     assembly would require arbitrary field
370933965Sjdp	     widths, positions, and masks which most
371033965Sjdp	     of our current object formats don't
371133965Sjdp	     support.
371233965Sjdp
371333965Sjdp	     In the specific case where a symbol
371433965Sjdp	     *is* defined in this assembly, we
371533965Sjdp	     *could* build fixups and track it, but
371633965Sjdp	     this could lead to confusion for the
371733965Sjdp	     backends.  I'm lazy. I'll take any
371833965Sjdp	     SEG_ABSOLUTE. I think that means that
371933965Sjdp	     you can use a previous .set or
372077298Sobrien	     .equ type symbol.  xoxorich.  */
372133965Sjdp
372233965Sjdp	  if (exp->X_op == O_absent)
372333965Sjdp	    {
372460484Sobrien	      as_warn (_("using a bit field width of zero"));
372533965Sjdp	      exp->X_add_number = 0;
372633965Sjdp	      exp->X_op = O_constant;
372777298Sobrien	    }			/* Implied zero width bitfield.  */
372833965Sjdp
372933965Sjdp	  if (exp->X_op != O_constant)
373033965Sjdp	    {
373133965Sjdp	      *input_line_pointer = '\0';
373260484Sobrien	      as_bad (_("field width \"%s\" too complex for a bitfield"), hold);
373333965Sjdp	      *input_line_pointer = ':';
373433965Sjdp	      demand_empty_rest_of_line ();
373533965Sjdp	      return;
373677298Sobrien	    }			/* Too complex.  */
373733965Sjdp
373833965Sjdp	  if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes))
373933965Sjdp	    {
374060484Sobrien	      as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"),
374133965Sjdp		       width, nbytes, (BITS_PER_CHAR * nbytes));
374233965Sjdp	      width = BITS_PER_CHAR * nbytes;
374377298Sobrien	    }			/* Too big.  */
374433965Sjdp
374533965Sjdp	  if (width > bits_available)
374633965Sjdp	    {
374733965Sjdp	      /* FIXME-SOMEDAY: backing up and reparsing is wasteful.  */
374833965Sjdp	      input_line_pointer = hold;
374933965Sjdp	      exp->X_add_number = value;
375033965Sjdp	      break;
375177298Sobrien	    }			/* Won't fit.  */
375233965Sjdp
375377298Sobrien	  /* Skip ':'.  */
375477298Sobrien	  hold = ++input_line_pointer;
375533965Sjdp
375633965Sjdp	  (void) expression (exp);
375733965Sjdp	  if (exp->X_op != O_constant)
375833965Sjdp	    {
375933965Sjdp	      char cache = *input_line_pointer;
376033965Sjdp
376133965Sjdp	      *input_line_pointer = '\0';
376260484Sobrien	      as_bad (_("field value \"%s\" too complex for a bitfield"), hold);
376333965Sjdp	      *input_line_pointer = cache;
376433965Sjdp	      demand_empty_rest_of_line ();
376533965Sjdp	      return;
376677298Sobrien	    }			/* Too complex.  */
376733965Sjdp
376833965Sjdp	  value |= ((~(-1 << width) & exp->X_add_number)
376933965Sjdp		    << ((BITS_PER_CHAR * nbytes) - bits_available));
377033965Sjdp
377133965Sjdp	  if ((bits_available -= width) == 0
377233965Sjdp	      || is_it_end_of_statement ()
377333965Sjdp	      || *input_line_pointer != ',')
377433965Sjdp	    {
377533965Sjdp	      break;
377677298Sobrien	    }			/* All the bitfields we're gonna get.  */
377733965Sjdp
377833965Sjdp	  hold = ++input_line_pointer;
377933965Sjdp	  (void) expression (exp);
378077298Sobrien	}
378133965Sjdp
378233965Sjdp      exp->X_add_number = value;
378333965Sjdp      exp->X_op = O_constant;
378433965Sjdp      exp->X_unsigned = 1;
378577298Sobrien    }
378677298Sobrien}
378733965Sjdp
378833965Sjdp#endif /* BITFIELD_CONS_EXPRESSIONS */
378933965Sjdp
379033965Sjdp/* Handle an MRI style string expression.  */
379133965Sjdp
379260484Sobrien#ifdef TC_M68K
379333965Sjdpstatic void
379433965Sjdpparse_mri_cons (exp, nbytes)
379533965Sjdp     expressionS *exp;
379633965Sjdp     unsigned int nbytes;
379733965Sjdp{
379833965Sjdp  if (*input_line_pointer != '\''
379933965Sjdp      && (input_line_pointer[1] != '\''
380033965Sjdp	  || (*input_line_pointer != 'A'
380133965Sjdp	      && *input_line_pointer != 'E')))
380233965Sjdp    TC_PARSE_CONS_EXPRESSION (exp, nbytes);
380333965Sjdp  else
380433965Sjdp    {
380538889Sjdp      unsigned int scan;
380633965Sjdp      unsigned int result = 0;
380733965Sjdp
380833965Sjdp      /* An MRI style string.  Cut into as many bytes as will fit into
380933965Sjdp	 a nbyte chunk, left justify if necessary, and separate with
381033965Sjdp	 commas so we can try again later.  */
381133965Sjdp      if (*input_line_pointer == 'A')
381233965Sjdp	++input_line_pointer;
381333965Sjdp      else if (*input_line_pointer == 'E')
381433965Sjdp	{
381560484Sobrien	  as_bad (_("EBCDIC constants are not supported"));
381633965Sjdp	  ++input_line_pointer;
381733965Sjdp	}
381833965Sjdp
381933965Sjdp      input_line_pointer++;
382033965Sjdp      for (scan = 0; scan < nbytes; scan++)
382133965Sjdp	{
382233965Sjdp	  if (*input_line_pointer == '\'')
382333965Sjdp	    {
382433965Sjdp	      if (input_line_pointer[1] == '\'')
382533965Sjdp		{
382633965Sjdp		  input_line_pointer++;
382733965Sjdp		}
382833965Sjdp	      else
382933965Sjdp		break;
383033965Sjdp	    }
383133965Sjdp	  result = (result << 8) | (*input_line_pointer++);
383233965Sjdp	}
383333965Sjdp
383477298Sobrien      /* Left justify.  */
383533965Sjdp      while (scan < nbytes)
383633965Sjdp	{
383733965Sjdp	  result <<= 8;
383833965Sjdp	  scan++;
383933965Sjdp	}
384077298Sobrien
384177298Sobrien      /* Create correct expression.  */
384233965Sjdp      exp->X_op = O_constant;
384333965Sjdp      exp->X_add_number = result;
384477298Sobrien
384577298Sobrien      /* Fake it so that we can read the next char too.  */
384633965Sjdp      if (input_line_pointer[0] != '\'' ||
384733965Sjdp	  (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\''))
384833965Sjdp	{
384933965Sjdp	  input_line_pointer -= 2;
385033965Sjdp	  input_line_pointer[0] = ',';
385133965Sjdp	  input_line_pointer[1] = '\'';
385233965Sjdp	}
385333965Sjdp      else
385433965Sjdp	input_line_pointer++;
385533965Sjdp    }
385633965Sjdp}
385760484Sobrien#endif /* TC_M68K */
385833965Sjdp
385933965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
386033965Sjdp
386133965Sjdp/* Parse a repeat expression for cons.  This is used by the MIPS
386233965Sjdp   assembler.  The format is NUMBER:COUNT; NUMBER appears in the
386333965Sjdp   object file COUNT times.
386433965Sjdp
386533965Sjdp   To use this for a target, define REPEAT_CONS_EXPRESSIONS.  */
386633965Sjdp
386733965Sjdpstatic void
386833965Sjdpparse_repeat_cons (exp, nbytes)
386933965Sjdp     expressionS *exp;
387033965Sjdp     unsigned int nbytes;
387133965Sjdp{
387233965Sjdp  expressionS count;
387333965Sjdp  register int i;
387433965Sjdp
387533965Sjdp  expression (exp);
387633965Sjdp
387733965Sjdp  if (*input_line_pointer != ':')
387833965Sjdp    {
387933965Sjdp      /* No repeat count.  */
388033965Sjdp      return;
388133965Sjdp    }
388233965Sjdp
388333965Sjdp  ++input_line_pointer;
388433965Sjdp  expression (&count);
388533965Sjdp  if (count.X_op != O_constant
388633965Sjdp      || count.X_add_number <= 0)
388733965Sjdp    {
388889857Sobrien      as_warn (_("unresolvable or nonpositive repeat count; using 1"));
388933965Sjdp      return;
389033965Sjdp    }
389133965Sjdp
389233965Sjdp  /* The cons function is going to output this expression once.  So we
389333965Sjdp     output it count - 1 times.  */
389433965Sjdp  for (i = count.X_add_number - 1; i > 0; i--)
389533965Sjdp    emit_expr (exp, nbytes);
389633965Sjdp}
389733965Sjdp
389833965Sjdp#endif /* REPEAT_CONS_EXPRESSIONS */
389933965Sjdp
390033965Sjdp/* Parse a floating point number represented as a hex constant.  This
390133965Sjdp   permits users to specify the exact bits they want in the floating
390233965Sjdp   point number.  */
390333965Sjdp
390433965Sjdpstatic int
3905130561Sobrienhex_float (int float_type, char *bytes)
390633965Sjdp{
390733965Sjdp  int length;
390833965Sjdp  int i;
390933965Sjdp
391033965Sjdp  switch (float_type)
391133965Sjdp    {
391233965Sjdp    case 'f':
391333965Sjdp    case 'F':
391433965Sjdp    case 's':
391533965Sjdp    case 'S':
391633965Sjdp      length = 4;
391733965Sjdp      break;
391833965Sjdp
391933965Sjdp    case 'd':
392033965Sjdp    case 'D':
392133965Sjdp    case 'r':
392233965Sjdp    case 'R':
392333965Sjdp      length = 8;
392433965Sjdp      break;
392533965Sjdp
392633965Sjdp    case 'x':
392733965Sjdp    case 'X':
392833965Sjdp      length = 12;
392933965Sjdp      break;
393033965Sjdp
393133965Sjdp    case 'p':
393233965Sjdp    case 'P':
393333965Sjdp      length = 12;
393433965Sjdp      break;
393533965Sjdp
393633965Sjdp    default:
393789857Sobrien      as_bad (_("unknown floating type type '%c'"), float_type);
393833965Sjdp      return -1;
393933965Sjdp    }
394033965Sjdp
394133965Sjdp  /* It would be nice if we could go through expression to parse the
394233965Sjdp     hex constant, but if we get a bignum it's a pain to sort it into
394333965Sjdp     the buffer correctly.  */
394433965Sjdp  i = 0;
394533965Sjdp  while (hex_p (*input_line_pointer) || *input_line_pointer == '_')
394633965Sjdp    {
394733965Sjdp      int d;
394833965Sjdp
394933965Sjdp      /* The MRI assembler accepts arbitrary underscores strewn about
395077298Sobrien	 through the hex constant, so we ignore them as well.  */
395133965Sjdp      if (*input_line_pointer == '_')
395233965Sjdp	{
395333965Sjdp	  ++input_line_pointer;
395433965Sjdp	  continue;
395533965Sjdp	}
395633965Sjdp
395733965Sjdp      if (i >= length)
395833965Sjdp	{
395989857Sobrien	  as_warn (_("floating point constant too large"));
396033965Sjdp	  return -1;
396133965Sjdp	}
396233965Sjdp      d = hex_value (*input_line_pointer) << 4;
396333965Sjdp      ++input_line_pointer;
396433965Sjdp      while (*input_line_pointer == '_')
396533965Sjdp	++input_line_pointer;
396633965Sjdp      if (hex_p (*input_line_pointer))
396733965Sjdp	{
396833965Sjdp	  d += hex_value (*input_line_pointer);
396933965Sjdp	  ++input_line_pointer;
397033965Sjdp	}
397133965Sjdp      if (target_big_endian)
397233965Sjdp	bytes[i] = d;
397333965Sjdp      else
397433965Sjdp	bytes[length - i - 1] = d;
397533965Sjdp      ++i;
397633965Sjdp    }
397733965Sjdp
397833965Sjdp  if (i < length)
397933965Sjdp    {
398033965Sjdp      if (target_big_endian)
398133965Sjdp	memset (bytes + i, 0, length - i);
398233965Sjdp      else
398333965Sjdp	memset (bytes, 0, length - i);
398433965Sjdp    }
398533965Sjdp
398633965Sjdp  return length;
398733965Sjdp}
398833965Sjdp
3989130561Sobrien/*			float_cons()
399033965Sjdp
399177298Sobrien   CONStruct some more frag chars of .floats .ffloats etc.
399277298Sobrien   Makes 0 or more new frags.
399377298Sobrien   If need_pass_2 == 1, no frags are emitted.
399477298Sobrien   This understands only floating literals, not expressions. Sorry.
399577298Sobrien
399677298Sobrien   A floating constant is defined by atof_generic(), except it is preceded
399777298Sobrien   by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its
399877298Sobrien   reading, I decided to be incompatible. This always tries to give you
399977298Sobrien   rounded bits to the precision of the pseudo-op. Former AS did premature
4000130561Sobrien   truncation, restored noisy bits instead of trailing 0s AND gave you
400177298Sobrien   a choice of 2 flavours of noise according to which of 2 floating-point
400277298Sobrien   scanners you directed AS to use.
400377298Sobrien
400477298Sobrien   In:	input_line_pointer->whitespace before, or '0' of flonum.  */
400577298Sobrien
400633965Sjdpvoid
4007130561Sobrienfloat_cons (/* Clobbers input_line-pointer, checks end-of-line.  */
4008130561Sobrien	    register int float_type	/* 'f':.ffloat ... 'F':.float ...  */)
400933965Sjdp{
401033965Sjdp  register char *p;
401177298Sobrien  int length;			/* Number of chars in an object.  */
401277298Sobrien  register char *err;		/* Error from scanning floating literal.  */
401333965Sjdp  char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
401433965Sjdp
401533965Sjdp  if (is_it_end_of_statement ())
401633965Sjdp    {
401733965Sjdp      demand_empty_rest_of_line ();
401833965Sjdp      return;
401933965Sjdp    }
402033965Sjdp
402133965Sjdp#ifdef md_flush_pending_output
402233965Sjdp  md_flush_pending_output ();
402333965Sjdp#endif
402433965Sjdp
402533965Sjdp  do
402633965Sjdp    {
402777298Sobrien      /* input_line_pointer->1st char of a flonum (we hope!).  */
402833965Sjdp      SKIP_WHITESPACE ();
402933965Sjdp
403033965Sjdp      /* Skip any 0{letter} that may be present. Don't even check if the
4031130561Sobrien	 letter is legal. Someone may invent a "z" format and this routine
4032130561Sobrien	 has no use for such information. Lusers beware: you get
4033130561Sobrien	 diagnostics if your input is ill-conditioned.  */
403438889Sjdp      if (input_line_pointer[0] == '0'
403589857Sobrien	  && ISALPHA (input_line_pointer[1]))
403633965Sjdp	input_line_pointer += 2;
403733965Sjdp
403833965Sjdp      /* Accept :xxxx, where the x's are hex digits, for a floating
4039130561Sobrien	 point with the exact digits specified.  */
404033965Sjdp      if (input_line_pointer[0] == ':')
404133965Sjdp	{
404233965Sjdp	  ++input_line_pointer;
404333965Sjdp	  length = hex_float (float_type, temp);
404433965Sjdp	  if (length < 0)
404533965Sjdp	    {
404633965Sjdp	      ignore_rest_of_line ();
404733965Sjdp	      return;
404833965Sjdp	    }
404933965Sjdp	}
405033965Sjdp      else
405133965Sjdp	{
405233965Sjdp	  err = md_atof (float_type, temp, &length);
405333965Sjdp	  know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
405433965Sjdp	  know (length > 0);
405533965Sjdp	  if (err)
405633965Sjdp	    {
405789857Sobrien	      as_bad (_("bad floating literal: %s"), err);
405833965Sjdp	      ignore_rest_of_line ();
405933965Sjdp	      return;
406033965Sjdp	    }
406133965Sjdp	}
406233965Sjdp
406333965Sjdp      if (!need_pass_2)
406433965Sjdp	{
406533965Sjdp	  int count;
406633965Sjdp
406733965Sjdp	  count = 1;
406833965Sjdp
406933965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
407033965Sjdp	  if (*input_line_pointer == ':')
407133965Sjdp	    {
407233965Sjdp	      expressionS count_exp;
407333965Sjdp
407433965Sjdp	      ++input_line_pointer;
407533965Sjdp	      expression (&count_exp);
407677298Sobrien
407733965Sjdp	      if (count_exp.X_op != O_constant
407833965Sjdp		  || count_exp.X_add_number <= 0)
407977298Sobrien		as_warn (_("unresolvable or nonpositive repeat count; using 1"));
408033965Sjdp	      else
408133965Sjdp		count = count_exp.X_add_number;
408233965Sjdp	    }
408333965Sjdp#endif
408433965Sjdp
408533965Sjdp	  while (--count >= 0)
408633965Sjdp	    {
408733965Sjdp	      p = frag_more (length);
408833965Sjdp	      memcpy (p, temp, (unsigned int) length);
408933965Sjdp	    }
409033965Sjdp	}
409133965Sjdp      SKIP_WHITESPACE ();
409233965Sjdp    }
409333965Sjdp  while (*input_line_pointer++ == ',');
409433965Sjdp
409577298Sobrien  /* Put terminator back into stream.  */
409677298Sobrien  --input_line_pointer;
409733965Sjdp  demand_empty_rest_of_line ();
409877298Sobrien}
409933965Sjdp
410077298Sobrien/* Return the size of a LEB128 value.  */
410138889Sjdp
410238889Sjdpstatic inline int
4103130561Sobriensizeof_sleb128 (offsetT value)
410438889Sjdp{
410538889Sjdp  register int size = 0;
410638889Sjdp  register unsigned byte;
410738889Sjdp
410838889Sjdp  do
410938889Sjdp    {
411038889Sjdp      byte = (value & 0x7f);
411138889Sjdp      /* Sadly, we cannot rely on typical arithmetic right shift behaviour.
411238889Sjdp	 Fortunately, we can structure things so that the extra work reduces
411338889Sjdp	 to a noop on systems that do things "properly".  */
411438889Sjdp      value = (value >> 7) | ~(-(offsetT)1 >> 7);
411538889Sjdp      size += 1;
411638889Sjdp    }
411738889Sjdp  while (!(((value == 0) && ((byte & 0x40) == 0))
411838889Sjdp	   || ((value == -1) && ((byte & 0x40) != 0))));
411938889Sjdp
412038889Sjdp  return size;
412138889Sjdp}
412238889Sjdp
412338889Sjdpstatic inline int
4124130561Sobriensizeof_uleb128 (valueT value)
412538889Sjdp{
412638889Sjdp  register int size = 0;
412738889Sjdp  register unsigned byte;
412838889Sjdp
412938889Sjdp  do
413038889Sjdp    {
413138889Sjdp      byte = (value & 0x7f);
413238889Sjdp      value >>= 7;
413338889Sjdp      size += 1;
413438889Sjdp    }
413538889Sjdp  while (value != 0);
413638889Sjdp
413738889Sjdp  return size;
413838889Sjdp}
413938889Sjdp
414060484Sobrienint
4141130561Sobriensizeof_leb128 (valueT value, int sign)
414238889Sjdp{
414338889Sjdp  if (sign)
414438889Sjdp    return sizeof_sleb128 ((offsetT) value);
414538889Sjdp  else
414638889Sjdp    return sizeof_uleb128 (value);
414738889Sjdp}
414838889Sjdp
414938889Sjdp/* Output a LEB128 value.  */
415038889Sjdp
415138889Sjdpstatic inline int
4152130561Sobrienoutput_sleb128 (char *p, offsetT value)
415338889Sjdp{
415438889Sjdp  register char *orig = p;
415538889Sjdp  register int more;
415638889Sjdp
415738889Sjdp  do
415838889Sjdp    {
415938889Sjdp      unsigned byte = (value & 0x7f);
416038889Sjdp
416138889Sjdp      /* Sadly, we cannot rely on typical arithmetic right shift behaviour.
416238889Sjdp	 Fortunately, we can structure things so that the extra work reduces
416338889Sjdp	 to a noop on systems that do things "properly".  */
416438889Sjdp      value = (value >> 7) | ~(-(offsetT)1 >> 7);
416538889Sjdp
416638889Sjdp      more = !((((value == 0) && ((byte & 0x40) == 0))
416738889Sjdp		|| ((value == -1) && ((byte & 0x40) != 0))));
416838889Sjdp      if (more)
416938889Sjdp	byte |= 0x80;
417038889Sjdp
417138889Sjdp      *p++ = byte;
417238889Sjdp    }
417338889Sjdp  while (more);
417438889Sjdp
417538889Sjdp  return p - orig;
417638889Sjdp}
417738889Sjdp
417838889Sjdpstatic inline int
4179130561Sobrienoutput_uleb128 (char *p, valueT value)
418038889Sjdp{
418138889Sjdp  char *orig = p;
418238889Sjdp
418338889Sjdp  do
418438889Sjdp    {
418538889Sjdp      unsigned byte = (value & 0x7f);
418638889Sjdp      value >>= 7;
418738889Sjdp      if (value != 0)
418838889Sjdp	/* More bytes to follow.  */
418938889Sjdp	byte |= 0x80;
419038889Sjdp
419138889Sjdp      *p++ = byte;
419238889Sjdp    }
419338889Sjdp  while (value != 0);
419438889Sjdp
419538889Sjdp  return p - orig;
419638889Sjdp}
419738889Sjdp
419860484Sobrienint
4199130561Sobrienoutput_leb128 (char *p, valueT value, int sign)
420038889Sjdp{
420138889Sjdp  if (sign)
420238889Sjdp    return output_sleb128 (p, (offsetT) value);
420338889Sjdp  else
420438889Sjdp    return output_uleb128 (p, value);
420538889Sjdp}
420638889Sjdp
420738889Sjdp/* Do the same for bignums.  We combine sizeof with output here in that
420838889Sjdp   we don't output for NULL values of P.  It isn't really as critical as
420938889Sjdp   for "normal" values that this be streamlined.  */
421038889Sjdp
421160484Sobrienstatic inline int
4212130561Sobrienoutput_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
421338889Sjdp{
421438889Sjdp  char *orig = p;
421538889Sjdp  valueT val = 0;
421638889Sjdp  int loaded = 0;
421738889Sjdp  unsigned byte;
421838889Sjdp
421938889Sjdp  /* Strip leading sign extensions off the bignum.  */
422077298Sobrien  while (size > 0 && bignum[size - 1] == (LITTLENUM_TYPE) -1)
422138889Sjdp    size--;
422238889Sjdp
422338889Sjdp  do
422438889Sjdp    {
422538889Sjdp      if (loaded < 7 && size > 0)
422638889Sjdp	{
422738889Sjdp	  val |= (*bignum << loaded);
422838889Sjdp	  loaded += 8 * CHARS_PER_LITTLENUM;
422938889Sjdp	  size--;
423038889Sjdp	  bignum++;
423138889Sjdp	}
423238889Sjdp
423338889Sjdp      byte = val & 0x7f;
423438889Sjdp      loaded -= 7;
423538889Sjdp      val >>= 7;
423638889Sjdp
423738889Sjdp      if (size == 0)
423838889Sjdp	{
423938889Sjdp	  if ((val == 0 && (byte & 0x40) == 0)
424077298Sobrien	      || (~(val | ~(((valueT) 1 << loaded) - 1)) == 0
424138889Sjdp		  && (byte & 0x40) != 0))
424238889Sjdp	    byte |= 0x80;
424338889Sjdp	}
424438889Sjdp
424538889Sjdp      if (orig)
424638889Sjdp	*p = byte;
424738889Sjdp      p++;
424838889Sjdp    }
424938889Sjdp  while (byte & 0x80);
425038889Sjdp
425138889Sjdp  return p - orig;
425238889Sjdp}
425338889Sjdp
425460484Sobrienstatic inline int
4255130561Sobrienoutput_big_uleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
425638889Sjdp{
425738889Sjdp  char *orig = p;
425838889Sjdp  valueT val = 0;
425938889Sjdp  int loaded = 0;
426038889Sjdp  unsigned byte;
426138889Sjdp
426238889Sjdp  /* Strip leading zeros off the bignum.  */
426338889Sjdp  /* XXX: Is this needed?  */
426477298Sobrien  while (size > 0 && bignum[size - 1] == 0)
426538889Sjdp    size--;
426638889Sjdp
426738889Sjdp  do
426838889Sjdp    {
426938889Sjdp      if (loaded < 7 && size > 0)
427038889Sjdp	{
427138889Sjdp	  val |= (*bignum << loaded);
427238889Sjdp	  loaded += 8 * CHARS_PER_LITTLENUM;
427338889Sjdp	  size--;
427438889Sjdp	  bignum++;
427538889Sjdp	}
427638889Sjdp
427738889Sjdp      byte = val & 0x7f;
427838889Sjdp      loaded -= 7;
427938889Sjdp      val >>= 7;
428038889Sjdp
428138889Sjdp      if (size > 0 || val)
428238889Sjdp	byte |= 0x80;
428338889Sjdp
428438889Sjdp      if (orig)
428538889Sjdp	*p = byte;
428638889Sjdp      p++;
428738889Sjdp    }
428838889Sjdp  while (byte & 0x80);
428938889Sjdp
429038889Sjdp  return p - orig;
429138889Sjdp}
429238889Sjdp
429360484Sobrienstatic int
4294130561Sobrienoutput_big_leb128 (char *p, LITTLENUM_TYPE *bignum, int size, int sign)
429538889Sjdp{
429638889Sjdp  if (sign)
429738889Sjdp    return output_big_sleb128 (p, bignum, size);
429838889Sjdp  else
429938889Sjdp    return output_big_uleb128 (p, bignum, size);
430038889Sjdp}
430138889Sjdp
430238889Sjdp/* Generate the appropriate fragments for a given expression to emit a
430338889Sjdp   leb128 value.  */
430438889Sjdp
430538889Sjdpvoid
4306130561Sobrienemit_leb128_expr (expressionS *exp, int sign)
430738889Sjdp{
430838889Sjdp  operatorT op = exp->X_op;
430978828Sobrien  int nbytes;
431038889Sjdp
431138889Sjdp  if (op == O_absent || op == O_illegal)
431238889Sjdp    {
431360484Sobrien      as_warn (_("zero assumed for missing expression"));
431438889Sjdp      exp->X_add_number = 0;
431538889Sjdp      op = O_constant;
431638889Sjdp    }
431738889Sjdp  else if (op == O_big && exp->X_add_number <= 0)
431838889Sjdp    {
431989857Sobrien      as_bad (_("floating point number invalid"));
432038889Sjdp      exp->X_add_number = 0;
432138889Sjdp      op = O_constant;
432238889Sjdp    }
432338889Sjdp  else if (op == O_register)
432438889Sjdp    {
432560484Sobrien      as_warn (_("register value used as expression"));
432638889Sjdp      op = O_constant;
432738889Sjdp    }
432838889Sjdp
432978828Sobrien  /* Let check_eh_frame know that data is being emitted.  nbytes == -1 is
433078828Sobrien     a signal that this is leb128 data.  It shouldn't optimize this away.  */
433178828Sobrien  nbytes = -1;
433278828Sobrien  if (check_eh_frame (exp, &nbytes))
433378828Sobrien    abort ();
433478828Sobrien
433578828Sobrien  /* Let the backend know that subsequent data may be byte aligned.  */
433678828Sobrien#ifdef md_cons_align
433778828Sobrien  md_cons_align (1);
433878828Sobrien#endif
433978828Sobrien
434038889Sjdp  if (op == O_constant)
434138889Sjdp    {
434238889Sjdp      /* If we've got a constant, emit the thing directly right now.  */
434338889Sjdp
434438889Sjdp      valueT value = exp->X_add_number;
434538889Sjdp      int size;
434638889Sjdp      char *p;
434738889Sjdp
434838889Sjdp      size = sizeof_leb128 (value, sign);
434938889Sjdp      p = frag_more (size);
435038889Sjdp      output_leb128 (p, value, sign);
435138889Sjdp    }
435238889Sjdp  else if (op == O_big)
435338889Sjdp    {
435438889Sjdp      /* O_big is a different sort of constant.  */
435538889Sjdp
435638889Sjdp      int size;
435738889Sjdp      char *p;
435838889Sjdp
435938889Sjdp      size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign);
436038889Sjdp      p = frag_more (size);
436138889Sjdp      output_big_leb128 (p, generic_bignum, exp->X_add_number, sign);
436238889Sjdp    }
436338889Sjdp  else
436438889Sjdp    {
436577298Sobrien      /* Otherwise, we have to create a variable sized fragment and
436638889Sjdp	 resolve things later.  */
436738889Sjdp
436877298Sobrien      frag_var (rs_leb128, sizeof_uleb128 (~(valueT) 0), 0, sign,
436938889Sjdp		make_expr_symbol (exp), 0, (char *) NULL);
437038889Sjdp    }
437138889Sjdp}
437238889Sjdp
437338889Sjdp/* Parse the .sleb128 and .uleb128 pseudos.  */
437438889Sjdp
437538889Sjdpvoid
4376130561Sobriens_leb128 (int sign)
437738889Sjdp{
437838889Sjdp  expressionS exp;
437938889Sjdp
4380130561Sobrien#ifdef md_flush_pending_output
4381130561Sobrien  md_flush_pending_output ();
4382130561Sobrien#endif
4383130561Sobrien
4384130561Sobrien#ifdef md_flush_pending_output
4385130561Sobrien  md_flush_pending_output ();
4386130561Sobrien#endif
4387130561Sobrien
438877298Sobrien  do
438977298Sobrien    {
439077298Sobrien      expression (&exp);
439177298Sobrien      emit_leb128_expr (&exp, sign);
439277298Sobrien    }
439377298Sobrien  while (*input_line_pointer++ == ',');
439438889Sjdp
439538889Sjdp  input_line_pointer--;
439638889Sjdp  demand_empty_rest_of_line ();
439738889Sjdp}
439838889Sjdp
439977298Sobrien/* We read 0 or more ',' separated, double-quoted strings.
440077298Sobrien   Caller should have checked need_pass_2 is FALSE because we don't
440177298Sobrien   check it.  */
440233965Sjdp
440377298Sobrienvoid
4404130561Sobrienstringer (/* Worker to do .ascii etc statements.  */
4405130561Sobrien	  /* Checks end-of-line.  */
4406130561Sobrien	  register int append_zero	/* 0: don't append '\0', else 1.  */)
440733965Sjdp{
440833965Sjdp  register unsigned int c;
440938889Sjdp  char *start;
441033965Sjdp
441133965Sjdp#ifdef md_flush_pending_output
441233965Sjdp  md_flush_pending_output ();
441333965Sjdp#endif
441433965Sjdp
441577298Sobrien  /* The following awkward logic is to parse ZERO or more strings,
441677298Sobrien     comma separated. Recall a string expression includes spaces
441777298Sobrien     before the opening '\"' and spaces after the closing '\"'.
441877298Sobrien     We fake a leading ',' if there is (supposed to be)
441977298Sobrien     a 1st, expression. We keep demanding expressions for each ','.  */
442033965Sjdp  if (is_it_end_of_statement ())
442133965Sjdp    {
442277298Sobrien      c = 0;			/* Skip loop.  */
442377298Sobrien      ++input_line_pointer;	/* Compensate for end of loop.  */
442433965Sjdp    }
442533965Sjdp  else
442633965Sjdp    {
442777298Sobrien      c = ',';			/* Do loop.  */
442833965Sjdp    }
4429104834Sobrien  /* If we have been switched into the abs_section then we
4430104834Sobrien     will not have an obstack onto which we can hang strings.  */
4431104834Sobrien  if (now_seg == absolute_section)
4432104834Sobrien    {
4433104834Sobrien      as_bad (_("strings must be placed into a section"));
4434104834Sobrien      c = 0;
4435104834Sobrien      ignore_rest_of_line ();
4436104834Sobrien    }
4437130561Sobrien
443833965Sjdp  while (c == ',' || c == '<' || c == '"')
443933965Sjdp    {
444033965Sjdp      SKIP_WHITESPACE ();
444133965Sjdp      switch (*input_line_pointer)
444233965Sjdp	{
444333965Sjdp	case '\"':
444477298Sobrien	  ++input_line_pointer;	/*->1st char of string.  */
444538889Sjdp	  start = input_line_pointer;
444633965Sjdp	  while (is_a_char (c = next_char_of_string ()))
444733965Sjdp	    {
444833965Sjdp	      FRAG_APPEND_1_CHAR (c);
444933965Sjdp	    }
445033965Sjdp	  if (append_zero)
445133965Sjdp	    {
445233965Sjdp	      FRAG_APPEND_1_CHAR (0);
445333965Sjdp	    }
445433965Sjdp	  know (input_line_pointer[-1] == '\"');
445538889Sjdp
445638889Sjdp#ifndef NO_LISTING
445738889Sjdp#ifdef OBJ_ELF
445838889Sjdp	  /* In ELF, when gcc is emitting DWARF 1 debugging output, it
4459130561Sobrien	     will emit .string with a filename in the .debug section
4460130561Sobrien	     after a sequence of constants.  See the comment in
4461130561Sobrien	     emit_expr for the sequence.  emit_expr will set
4462130561Sobrien	     dwarf_file_string to non-zero if this string might be a
4463130561Sobrien	     source file name.  */
446438889Sjdp	  if (strcmp (segment_name (now_seg), ".debug") != 0)
446538889Sjdp	    dwarf_file_string = 0;
446638889Sjdp	  else if (dwarf_file_string)
446738889Sjdp	    {
446838889Sjdp	      c = input_line_pointer[-1];
446938889Sjdp	      input_line_pointer[-1] = '\0';
447038889Sjdp	      listing_source_file (start);
447138889Sjdp	      input_line_pointer[-1] = c;
447238889Sjdp	    }
447338889Sjdp#endif
447438889Sjdp#endif
447538889Sjdp
447633965Sjdp	  break;
447733965Sjdp	case '<':
447833965Sjdp	  input_line_pointer++;
447933965Sjdp	  c = get_single_number ();
448033965Sjdp	  FRAG_APPEND_1_CHAR (c);
448133965Sjdp	  if (*input_line_pointer != '>')
448233965Sjdp	    {
448389857Sobrien	      as_bad (_("expected <nn>"));
448433965Sjdp	    }
448533965Sjdp	  input_line_pointer++;
448633965Sjdp	  break;
448733965Sjdp	case ',':
448833965Sjdp	  input_line_pointer++;
448933965Sjdp	  break;
449033965Sjdp	}
449133965Sjdp      SKIP_WHITESPACE ();
449233965Sjdp      c = *input_line_pointer;
449333965Sjdp    }
449433965Sjdp
449533965Sjdp  demand_empty_rest_of_line ();
449633965Sjdp}				/* stringer() */
449733965Sjdp
449833965Sjdp/* FIXME-SOMEDAY: I had trouble here on characters with the
449933965Sjdp    high bits set.  We'll probably also have trouble with
450033965Sjdp    multibyte chars, wide chars, etc.  Also be careful about
450177298Sobrien    returning values bigger than 1 byte.  xoxorich.  */
450233965Sjdp
450377298Sobrienunsigned int
4504130561Sobriennext_char_of_string (void)
450533965Sjdp{
450633965Sjdp  register unsigned int c;
450733965Sjdp
450833965Sjdp  c = *input_line_pointer++ & CHAR_MASK;
450933965Sjdp  switch (c)
451033965Sjdp    {
451133965Sjdp    case '\"':
451233965Sjdp      c = NOT_A_CHAR;
451333965Sjdp      break;
451433965Sjdp
451533965Sjdp    case '\n':
451689857Sobrien      as_warn (_("unterminated string; newline inserted"));
451733965Sjdp      bump_line_counters ();
451833965Sjdp      break;
451933965Sjdp
452033965Sjdp#ifndef NO_STRING_ESCAPES
452133965Sjdp    case '\\':
452233965Sjdp      switch (c = *input_line_pointer++)
452333965Sjdp	{
452433965Sjdp	case 'b':
452533965Sjdp	  c = '\b';
452633965Sjdp	  break;
452733965Sjdp
452833965Sjdp	case 'f':
452933965Sjdp	  c = '\f';
453033965Sjdp	  break;
453133965Sjdp
453233965Sjdp	case 'n':
453333965Sjdp	  c = '\n';
453433965Sjdp	  break;
453533965Sjdp
453633965Sjdp	case 'r':
453733965Sjdp	  c = '\r';
453833965Sjdp	  break;
453933965Sjdp
454033965Sjdp	case 't':
454133965Sjdp	  c = '\t';
454233965Sjdp	  break;
454333965Sjdp
454433965Sjdp	case 'v':
454533965Sjdp	  c = '\013';
454633965Sjdp	  break;
454733965Sjdp
454833965Sjdp	case '\\':
454933965Sjdp	case '"':
455077298Sobrien	  break;		/* As itself.  */
455133965Sjdp
455233965Sjdp	case '0':
455333965Sjdp	case '1':
455433965Sjdp	case '2':
455533965Sjdp	case '3':
455633965Sjdp	case '4':
455733965Sjdp	case '5':
455833965Sjdp	case '6':
455933965Sjdp	case '7':
456033965Sjdp	case '8':
456133965Sjdp	case '9':
456233965Sjdp	  {
456333965Sjdp	    long number;
456433965Sjdp	    int i;
456533965Sjdp
456677298Sobrien	    for (i = 0, number = 0;
456789857Sobrien		 ISDIGIT (c) && i < 3;
456877298Sobrien		 c = *input_line_pointer++, i++)
456933965Sjdp	      {
457033965Sjdp		number = number * 8 + c - '0';
457133965Sjdp	      }
457277298Sobrien
457333965Sjdp	    c = number & 0xff;
457433965Sjdp	  }
457533965Sjdp	  --input_line_pointer;
457633965Sjdp	  break;
457733965Sjdp
457833965Sjdp	case 'x':
457933965Sjdp	case 'X':
458033965Sjdp	  {
458133965Sjdp	    long number;
458233965Sjdp
458333965Sjdp	    number = 0;
458433965Sjdp	    c = *input_line_pointer++;
458589857Sobrien	    while (ISXDIGIT (c))
458633965Sjdp	      {
458789857Sobrien		if (ISDIGIT (c))
458833965Sjdp		  number = number * 16 + c - '0';
458989857Sobrien		else if (ISUPPER (c))
459033965Sjdp		  number = number * 16 + c - 'A' + 10;
459133965Sjdp		else
459233965Sjdp		  number = number * 16 + c - 'a' + 10;
459333965Sjdp		c = *input_line_pointer++;
459433965Sjdp	      }
459533965Sjdp	    c = number & 0xff;
459633965Sjdp	    --input_line_pointer;
459733965Sjdp	  }
459833965Sjdp	  break;
459933965Sjdp
460033965Sjdp	case '\n':
460177298Sobrien	  /* To be compatible with BSD 4.2 as: give the luser a linefeed!!  */
460289857Sobrien	  as_warn (_("unterminated string; newline inserted"));
460333965Sjdp	  c = '\n';
460433965Sjdp	  bump_line_counters ();
460533965Sjdp	  break;
460633965Sjdp
460733965Sjdp	default:
460833965Sjdp
460933965Sjdp#ifdef ONLY_STANDARD_ESCAPES
461089857Sobrien	  as_bad (_("bad escaped character in string"));
461133965Sjdp	  c = '?';
461233965Sjdp#endif /* ONLY_STANDARD_ESCAPES */
461333965Sjdp
461433965Sjdp	  break;
461577298Sobrien	}
461633965Sjdp      break;
461733965Sjdp#endif /* ! defined (NO_STRING_ESCAPES) */
461833965Sjdp
461933965Sjdp    default:
462033965Sjdp      break;
462177298Sobrien    }
462233965Sjdp  return (c);
462377298Sobrien}
462433965Sjdp
462533965Sjdpstatic segT
4626130561Sobrienget_segmented_expression (register expressionS *expP)
462733965Sjdp{
462833965Sjdp  register segT retval;
462933965Sjdp
463033965Sjdp  retval = expression (expP);
463133965Sjdp  if (expP->X_op == O_illegal
463233965Sjdp      || expP->X_op == O_absent
463333965Sjdp      || expP->X_op == O_big)
463433965Sjdp    {
463589857Sobrien      as_bad (_("expected address expression"));
463633965Sjdp      expP->X_op = O_constant;
463733965Sjdp      expP->X_add_number = 0;
463833965Sjdp      retval = absolute_section;
463933965Sjdp    }
464033965Sjdp  return retval;
464133965Sjdp}
464233965Sjdp
464377298Sobrienstatic segT
4644130561Sobrienget_known_segmented_expression (register expressionS *expP)
464533965Sjdp{
464633965Sjdp  register segT retval;
464733965Sjdp
464833965Sjdp  if ((retval = get_segmented_expression (expP)) == undefined_section)
464933965Sjdp    {
465033965Sjdp      /* There is no easy way to extract the undefined symbol from the
465133965Sjdp	 expression.  */
465233965Sjdp      if (expP->X_add_symbol != NULL
465333965Sjdp	  && S_GET_SEGMENT (expP->X_add_symbol) != expr_section)
465460484Sobrien	as_warn (_("symbol \"%s\" undefined; zero assumed"),
465533965Sjdp		 S_GET_NAME (expP->X_add_symbol));
465633965Sjdp      else
465760484Sobrien	as_warn (_("some symbol undefined; zero assumed"));
465833965Sjdp      retval = absolute_section;
465933965Sjdp      expP->X_op = O_constant;
466033965Sjdp      expP->X_add_number = 0;
466133965Sjdp    }
466233965Sjdp  know (retval == absolute_section || SEG_NORMAL (retval));
466333965Sjdp  return (retval);
466477298Sobrien}
466533965Sjdp
466633965SjdpoffsetT
4667130561Sobrienget_absolute_expr (expressionS *exp)
466833965Sjdp{
4669130561Sobrien  expression (exp);
4670130561Sobrien  if (exp->X_op != O_constant)
467133965Sjdp    {
4672130561Sobrien      if (exp->X_op != O_absent)
467389857Sobrien	as_bad (_("bad or irreducible absolute expression"));
4674130561Sobrien      exp->X_add_number = 0;
467533965Sjdp    }
4676130561Sobrien  return exp->X_add_number;
467733965Sjdp}
467833965Sjdp
4679130561SobrienoffsetT
4680130561Sobrienget_absolute_expression (void)
4681130561Sobrien{
4682130561Sobrien  expressionS exp;
4683130561Sobrien
4684130561Sobrien  return get_absolute_expr (&exp);
4685130561Sobrien}
4686130561Sobrien
468777298Sobrienchar				/* Return terminator.  */
4688130561Sobrienget_absolute_expression_and_terminator (long *val_pointer /* Return value of expression.  */)
468933965Sjdp{
469033965Sjdp  /* FIXME: val_pointer should probably be offsetT *.  */
469133965Sjdp  *val_pointer = (long) get_absolute_expression ();
469233965Sjdp  return (*input_line_pointer++);
469333965Sjdp}
469433965Sjdp
469577298Sobrien/* Like demand_copy_string, but return NULL if the string contains any '\0's.
469677298Sobrien   Give a warning if that happens.  */
469777298Sobrien
469833965Sjdpchar *
4699130561Sobriendemand_copy_C_string (int *len_pointer)
470033965Sjdp{
470133965Sjdp  register char *s;
470233965Sjdp
470333965Sjdp  if ((s = demand_copy_string (len_pointer)) != 0)
470433965Sjdp    {
470533965Sjdp      register int len;
470633965Sjdp
470733965Sjdp      for (len = *len_pointer; len > 0; len--)
470833965Sjdp	{
470933965Sjdp	  if (*s == 0)
471033965Sjdp	    {
471133965Sjdp	      s = 0;
471233965Sjdp	      len = 1;
471333965Sjdp	      *len_pointer = 0;
471489857Sobrien	      as_bad (_("this string may not contain \'\\0\'"));
471533965Sjdp	    }
471633965Sjdp	}
471733965Sjdp    }
471877298Sobrien
471933965Sjdp  return s;
472033965Sjdp}
472133965Sjdp
472277298Sobrien/* Demand string, but return a safe (=private) copy of the string.
472377298Sobrien   Return NULL if we can't read a string here.  */
472477298Sobrien
472533965Sjdpchar *
4726130561Sobriendemand_copy_string (int *lenP)
472733965Sjdp{
472833965Sjdp  register unsigned int c;
472933965Sjdp  register int len;
473033965Sjdp  char *retval;
473133965Sjdp
473233965Sjdp  len = 0;
473333965Sjdp  SKIP_WHITESPACE ();
473433965Sjdp  if (*input_line_pointer == '\"')
473533965Sjdp    {
473677298Sobrien      input_line_pointer++;	/* Skip opening quote.  */
473733965Sjdp
473833965Sjdp      while (is_a_char (c = next_char_of_string ()))
473933965Sjdp	{
474033965Sjdp	  obstack_1grow (&notes, c);
474133965Sjdp	  len++;
474233965Sjdp	}
474333965Sjdp      /* JF this next line is so demand_copy_C_string will return a
474477298Sobrien	 null terminated string.  */
474533965Sjdp      obstack_1grow (&notes, '\0');
474633965Sjdp      retval = obstack_finish (&notes);
474733965Sjdp    }
474833965Sjdp  else
474933965Sjdp    {
4750130561Sobrien      as_bad (_("missing string"));
475133965Sjdp      retval = NULL;
475233965Sjdp      ignore_rest_of_line ();
475333965Sjdp    }
475433965Sjdp  *lenP = len;
475533965Sjdp  return (retval);
475677298Sobrien}
475733965Sjdp
475877298Sobrien/* In:	Input_line_pointer->next character.
475977298Sobrien
476077298Sobrien   Do:	Skip input_line_pointer over all whitespace.
476177298Sobrien
476277298Sobrien   Out:	1 if input_line_pointer->end-of-line.  */
476377298Sobrien
476477298Sobrienint
4765130561Sobrienis_it_end_of_statement (void)
476633965Sjdp{
476733965Sjdp  SKIP_WHITESPACE ();
476833965Sjdp  return (is_end_of_line[(unsigned char) *input_line_pointer]);
476977298Sobrien}
477033965Sjdp
477177298Sobrienvoid
4772130561Sobrienequals (char *sym_name, int reassign)
477333965Sjdp{
477477298Sobrien  register symbolS *symbolP;	/* Symbol we are working with.  */
477538889Sjdp  char *stop = NULL;
477633965Sjdp  char stopc;
477733965Sjdp
477833965Sjdp  input_line_pointer++;
477933965Sjdp  if (*input_line_pointer == '=')
478033965Sjdp    input_line_pointer++;
478133965Sjdp
478233965Sjdp  while (*input_line_pointer == ' ' || *input_line_pointer == '\t')
478333965Sjdp    input_line_pointer++;
478433965Sjdp
478533965Sjdp  if (flag_mri)
478633965Sjdp    stop = mri_comment_field (&stopc);
478733965Sjdp
478833965Sjdp  if (sym_name[0] == '.' && sym_name[1] == '\0')
478933965Sjdp    {
479077298Sobrien      /* Turn '. = mumble' into a .org mumble.  */
479133965Sjdp      register segT segment;
479233965Sjdp      expressionS exp;
479333965Sjdp
479433965Sjdp      segment = get_known_segmented_expression (&exp);
479533965Sjdp      if (!need_pass_2)
479633965Sjdp	do_org (segment, &exp, 0);
479733965Sjdp    }
479833965Sjdp  else
479933965Sjdp    {
480078828Sobrien#ifdef OBJ_COFF
480178828Sobrien      int local;
480278828Sobrien
480378828Sobrien      symbolP = symbol_find (sym_name);
480478828Sobrien      local = symbolP == NULL;
480578828Sobrien      if (local)
480678828Sobrien#endif /* OBJ_COFF */
480733965Sjdp      symbolP = symbol_find_or_make (sym_name);
480833965Sjdp      /* Permit register names to be redefined.  */
480977298Sobrien      if (!reassign
481033965Sjdp	  && S_IS_DEFINED (symbolP)
481133965Sjdp	  && S_GET_SEGMENT (symbolP) != reg_section)
481289857Sobrien	as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
481378828Sobrien
481478828Sobrien#ifdef OBJ_COFF
481578828Sobrien      /* "set" symbols are local unless otherwise specified.  */
481678828Sobrien      if (local)
481778828Sobrien	SF_SET_LOCAL (symbolP);
481878828Sobrien#endif /* OBJ_COFF */
481978828Sobrien
482033965Sjdp      pseudo_set (symbolP);
482133965Sjdp    }
482233965Sjdp
482333965Sjdp  if (flag_mri)
482477298Sobrien    {
482577298Sobrien      /* Check garbage after the expression.  */
4826130561Sobrien      demand_empty_rest_of_line ();
482777298Sobrien      mri_comment_end (stop, stopc);
482877298Sobrien    }
482977298Sobrien}
483033965Sjdp
483189857Sobrien/* .incbin -- include a file verbatim at the current location.  */
483289857Sobrien
483389857Sobrienvoid
4834130561Sobriens_incbin (int x ATTRIBUTE_UNUSED)
483589857Sobrien{
483689857Sobrien  FILE * binfile;
483789857Sobrien  char * path;
483889857Sobrien  char * filename;
483989857Sobrien  char * binfrag;
484089857Sobrien  long   skip = 0;
484189857Sobrien  long   count = 0;
484289857Sobrien  long   bytes;
484389857Sobrien  int    len;
484489857Sobrien
484589857Sobrien#ifdef md_flush_pending_output
484689857Sobrien  md_flush_pending_output ();
484789857Sobrien#endif
484889857Sobrien
484989857Sobrien  SKIP_WHITESPACE ();
485089857Sobrien  filename = demand_copy_string (& len);
485189857Sobrien  if (filename == NULL)
485289857Sobrien    return;
485389857Sobrien
485489857Sobrien  SKIP_WHITESPACE ();
485589857Sobrien
485689857Sobrien  /* Look for optional skip and count.  */
485789857Sobrien  if (* input_line_pointer == ',')
485889857Sobrien    {
485989857Sobrien      ++ input_line_pointer;
486089857Sobrien      skip = get_absolute_expression ();
486189857Sobrien
486289857Sobrien      SKIP_WHITESPACE ();
486389857Sobrien
486489857Sobrien      if (* input_line_pointer == ',')
486589857Sobrien	{
486689857Sobrien	  ++ input_line_pointer;
486789857Sobrien
486889857Sobrien	  count = get_absolute_expression ();
486989857Sobrien	  if (count == 0)
487089857Sobrien	    as_warn (_(".incbin count zero, ignoring `%s'"), filename);
487189857Sobrien
487289857Sobrien	  SKIP_WHITESPACE ();
487389857Sobrien	}
487489857Sobrien    }
487589857Sobrien
487689857Sobrien  demand_empty_rest_of_line ();
487789857Sobrien
487889857Sobrien  /* Try opening absolute path first, then try include dirs.  */
487989857Sobrien  binfile = fopen (filename, FOPEN_RB);
488089857Sobrien  if (binfile == NULL)
488189857Sobrien    {
488289857Sobrien      int i;
488389857Sobrien
488489857Sobrien      path = xmalloc ((unsigned long) len + include_dir_maxlen + 5);
488589857Sobrien
488689857Sobrien      for (i = 0; i < include_dir_count; i++)
488789857Sobrien	{
488889857Sobrien	  sprintf (path, "%s/%s", include_dirs[i], filename);
488989857Sobrien
489089857Sobrien	  binfile = fopen (path, FOPEN_RB);
489189857Sobrien	  if (binfile != NULL)
489289857Sobrien	    break;
489389857Sobrien	}
489489857Sobrien
489589857Sobrien      if (binfile == NULL)
489689857Sobrien	as_bad (_("file not found: %s"), filename);
489789857Sobrien    }
489889857Sobrien  else
489989857Sobrien    path = xstrdup (filename);
490089857Sobrien
490189857Sobrien  if (binfile)
490289857Sobrien    {
490389857Sobrien      long   file_len;
490489857Sobrien
490589857Sobrien      register_dependency (path);
490689857Sobrien
490789857Sobrien      /* Compute the length of the file.  */
490889857Sobrien      if (fseek (binfile, 0, SEEK_END) != 0)
490989857Sobrien	{
491089857Sobrien	  as_bad (_("seek to end of .incbin file failed `%s'"), path);
491189857Sobrien	  goto done;
491289857Sobrien	}
491389857Sobrien      file_len = ftell (binfile);
491489857Sobrien
491589857Sobrien      /* If a count was not specified use the size of the file.  */
491689857Sobrien      if (count == 0)
491789857Sobrien	count = file_len;
491889857Sobrien
491989857Sobrien      if (skip + count > file_len)
492089857Sobrien	{
492189857Sobrien	  as_bad (_("skip (%ld) + count (%ld) larger than file size (%ld)"),
492289857Sobrien		  skip, count, file_len);
492389857Sobrien	  goto done;
492489857Sobrien	}
492589857Sobrien
492689857Sobrien      if (fseek (binfile, skip, SEEK_SET) != 0)
492789857Sobrien	{
492889857Sobrien	  as_bad (_("could not skip to %ld in file `%s'"), skip, path);
492989857Sobrien	  goto done;
493089857Sobrien	}
493189857Sobrien
493289857Sobrien      /* Allocate frag space and store file contents in it.  */
493389857Sobrien      binfrag = frag_more (count);
493489857Sobrien
493589857Sobrien      bytes = fread (binfrag, 1, count, binfile);
493689857Sobrien      if (bytes < count)
493789857Sobrien	as_warn (_("truncated file `%s', %ld of %ld bytes read"),
493889857Sobrien		 path, bytes, count);
493989857Sobrien    }
494089857Sobriendone:
494189857Sobrien  if (binfile != NULL)
494289857Sobrien    fclose (binfile);
494389857Sobrien  if (path)
494489857Sobrien    free (path);
494589857Sobrien}
494689857Sobrien
494777298Sobrien/* .include -- include a file at this point.  */
494833965Sjdp
494977298Sobrienvoid
4950130561Sobriens_include (int arg ATTRIBUTE_UNUSED)
495133965Sjdp{
495233965Sjdp  char *filename;
495333965Sjdp  int i;
495433965Sjdp  FILE *try;
495533965Sjdp  char *path;
495633965Sjdp
495777298Sobrien  if (!flag_m68k_mri)
495838889Sjdp    {
495938889Sjdp      filename = demand_copy_string (&i);
496038889Sjdp      if (filename == NULL)
496138889Sjdp	{
496238889Sjdp	  /* demand_copy_string has already printed an error and
4963130561Sobrien	     called ignore_rest_of_line.  */
496438889Sjdp	  return;
496538889Sjdp	}
496638889Sjdp    }
496733965Sjdp  else
496833965Sjdp    {
496933965Sjdp      SKIP_WHITESPACE ();
497033965Sjdp      i = 0;
497177298Sobrien      while (!is_end_of_line[(unsigned char) *input_line_pointer]
497233965Sjdp	     && *input_line_pointer != ' '
497333965Sjdp	     && *input_line_pointer != '\t')
497433965Sjdp	{
497533965Sjdp	  obstack_1grow (&notes, *input_line_pointer);
497633965Sjdp	  ++input_line_pointer;
497733965Sjdp	  ++i;
497833965Sjdp	}
497977298Sobrien
498033965Sjdp      obstack_1grow (&notes, '\0');
498133965Sjdp      filename = obstack_finish (&notes);
498277298Sobrien      while (!is_end_of_line[(unsigned char) *input_line_pointer])
498333965Sjdp	++input_line_pointer;
498433965Sjdp    }
498577298Sobrien
498633965Sjdp  demand_empty_rest_of_line ();
498733965Sjdp  path = xmalloc ((unsigned long) i + include_dir_maxlen + 5 /* slop */ );
498877298Sobrien
498933965Sjdp  for (i = 0; i < include_dir_count; i++)
499033965Sjdp    {
499133965Sjdp      strcpy (path, include_dirs[i]);
499233965Sjdp      strcat (path, "/");
499333965Sjdp      strcat (path, filename);
499489857Sobrien      if (0 != (try = fopen (path, FOPEN_RT)))
499533965Sjdp	{
499633965Sjdp	  fclose (try);
499733965Sjdp	  goto gotit;
499833965Sjdp	}
499933965Sjdp    }
500077298Sobrien
500133965Sjdp  free (path);
500233965Sjdp  path = filename;
500333965Sjdpgotit:
500477298Sobrien  /* malloc Storage leak when file is found on path.  FIXME-SOMEDAY.  */
500538889Sjdp  register_dependency (path);
500660484Sobrien  input_scrub_insert_file (path);
500777298Sobrien}
500833965Sjdp
500977298Sobrienvoid
5010130561Sobrienadd_include_dir (char *path)
501133965Sjdp{
501233965Sjdp  int i;
501333965Sjdp
501433965Sjdp  if (include_dir_count == 0)
501533965Sjdp    {
501633965Sjdp      include_dirs = (char **) xmalloc (2 * sizeof (*include_dirs));
501777298Sobrien      include_dirs[0] = ".";	/* Current dir.  */
501833965Sjdp      include_dir_count = 2;
501933965Sjdp    }
502033965Sjdp  else
502133965Sjdp    {
502233965Sjdp      include_dir_count++;
502377298Sobrien      include_dirs =
502477298Sobrien	(char **) realloc (include_dirs,
502577298Sobrien			   include_dir_count * sizeof (*include_dirs));
502633965Sjdp    }
502733965Sjdp
502877298Sobrien  include_dirs[include_dir_count - 1] = path;	/* New one.  */
502933965Sjdp
503033965Sjdp  i = strlen (path);
503133965Sjdp  if (i > include_dir_maxlen)
503233965Sjdp    include_dir_maxlen = i;
503377298Sobrien}
503460484Sobrien
503560484Sobrien/* Output debugging information to denote the source file.  */
503633965Sjdp
503760484Sobrienstatic void
5038130561Sobriengenerate_file_debug (void)
503960484Sobrien{
504060484Sobrien  if (debug_type == DEBUG_STABS)
504160484Sobrien    stabs_generate_asm_file ();
504260484Sobrien}
504360484Sobrien
504460484Sobrien/* Output line number debugging information for the current source line.  */
504560484Sobrien
504660484Sobrienvoid
5047130561Sobriengenerate_lineno_debug (void)
504860484Sobrien{
504960484Sobrien  switch (debug_type)
505060484Sobrien    {
505160484Sobrien    case DEBUG_UNSPECIFIED:
505260484Sobrien    case DEBUG_NONE:
505377298Sobrien    case DEBUG_DWARF:
505460484Sobrien      break;
505560484Sobrien    case DEBUG_STABS:
505660484Sobrien      stabs_generate_asm_lineno ();
505760484Sobrien      break;
505860484Sobrien    case DEBUG_ECOFF:
505960484Sobrien      ecoff_generate_asm_lineno ();
506060484Sobrien      break;
506160484Sobrien    case DEBUG_DWARF2:
506277298Sobrien      /* ??? We could here indicate to dwarf2dbg.c that something
506377298Sobrien	 has changed.  However, since there is additional backend
506477298Sobrien	 support that is required (calling dwarf2_emit_insn), we
506577298Sobrien	 let dwarf2dbg.c call as_where on its own.  */
506660484Sobrien      break;
506760484Sobrien    }
506860484Sobrien}
506960484Sobrien
507060484Sobrien/* Output debugging information to mark a function entry point or end point.
507160484Sobrien   END_P is zero for .func, and non-zero for .endfunc.  */
507260484Sobrien
507360484Sobrienvoid
5074130561Sobriens_func (int end_p)
507560484Sobrien{
507660484Sobrien  do_s_func (end_p, NULL);
507760484Sobrien}
507860484Sobrien
507960484Sobrien/* Subroutine of s_func so targets can choose a different default prefix.
508060484Sobrien   If DEFAULT_PREFIX is NULL, use the target's "leading char".  */
508160484Sobrien
508260484Sobrienvoid
5083130561Sobriendo_s_func (int end_p, const char *default_prefix)
508460484Sobrien{
508560484Sobrien  /* Record the current function so that we can issue an error message for
508660484Sobrien     misplaced .func,.endfunc, and also so that .endfunc needs no
508760484Sobrien     arguments.  */
508860484Sobrien  static char *current_name;
508960484Sobrien  static char *current_label;
509060484Sobrien
509160484Sobrien  if (end_p)
509260484Sobrien    {
509360484Sobrien      if (current_name == NULL)
509460484Sobrien	{
509560484Sobrien	  as_bad (_("missing .func"));
509660484Sobrien	  ignore_rest_of_line ();
509760484Sobrien	  return;
509860484Sobrien	}
509960484Sobrien
510060484Sobrien      if (debug_type == DEBUG_STABS)
510160484Sobrien	stabs_generate_asm_endfunc (current_name, current_label);
510260484Sobrien
510360484Sobrien      current_name = current_label = NULL;
510460484Sobrien    }
510560484Sobrien  else /* ! end_p */
510660484Sobrien    {
510777298Sobrien      char *name, *label;
510877298Sobrien      char delim1, delim2;
510960484Sobrien
511060484Sobrien      if (current_name != NULL)
511160484Sobrien	{
511260484Sobrien	  as_bad (_(".endfunc missing for previous .func"));
511360484Sobrien	  ignore_rest_of_line ();
511460484Sobrien	  return;
511560484Sobrien	}
511660484Sobrien
511760484Sobrien      name = input_line_pointer;
511860484Sobrien      delim1 = get_symbol_end ();
511960484Sobrien      name = xstrdup (name);
512060484Sobrien      *input_line_pointer = delim1;
512160484Sobrien      SKIP_WHITESPACE ();
512260484Sobrien      if (*input_line_pointer != ',')
512360484Sobrien	{
512460484Sobrien	  if (default_prefix)
512560484Sobrien	    asprintf (&label, "%s%s", default_prefix, name);
512660484Sobrien	  else
512760484Sobrien	    {
512860484Sobrien	      char leading_char = 0;
512960484Sobrien#ifdef BFD_ASSEMBLER
513060484Sobrien	      leading_char = bfd_get_symbol_leading_char (stdoutput);
513160484Sobrien#endif
513260484Sobrien	      /* Missing entry point, use function's name with the leading
513360484Sobrien		 char prepended.  */
513460484Sobrien	      if (leading_char)
513560484Sobrien		asprintf (&label, "%c%s", leading_char, name);
513660484Sobrien	      else
513760484Sobrien		label = name;
513860484Sobrien	    }
513960484Sobrien	}
514060484Sobrien      else
514160484Sobrien	{
514260484Sobrien	  ++input_line_pointer;
514360484Sobrien	  SKIP_WHITESPACE ();
514460484Sobrien	  label = input_line_pointer;
514560484Sobrien	  delim2 = get_symbol_end ();
514660484Sobrien	  label = xstrdup (label);
514760484Sobrien	  *input_line_pointer = delim2;
514860484Sobrien	}
514960484Sobrien
515060484Sobrien      if (debug_type == DEBUG_STABS)
515160484Sobrien	stabs_generate_asm_func (name, label);
515260484Sobrien
515360484Sobrien      current_name = name;
515460484Sobrien      current_label = label;
515560484Sobrien    }
515660484Sobrien
515760484Sobrien  demand_empty_rest_of_line ();
515860484Sobrien}
515960484Sobrien
516077298Sobrienvoid
5161130561Sobriens_ignore (int arg ATTRIBUTE_UNUSED)
516233965Sjdp{
516333965Sjdp  while (!is_end_of_line[(unsigned char) *input_line_pointer])
516433965Sjdp    {
516533965Sjdp      ++input_line_pointer;
516633965Sjdp    }
516733965Sjdp  ++input_line_pointer;
516833965Sjdp}
516933965Sjdp
517033965Sjdpvoid
5171130561Sobrienread_print_statistics (FILE *file)
517233965Sjdp{
517333965Sjdp  hash_print_statistics (file, "pseudo-op table", po_hash);
517433965Sjdp}
517533965Sjdp
517677298Sobrien/* Inserts the given line into the input stream.
517777298Sobrien
517860484Sobrien   This call avoids macro/conditionals nesting checking, since the contents of
517960484Sobrien   the line are assumed to replace the contents of a line already scanned.
518060484Sobrien
5181130561Sobrien   An appropriate use of this function would be substitution of input lines when
518260484Sobrien   called by md_start_line_hook().  The given line is assumed to already be
518360484Sobrien   properly scrubbed.  */
518460484Sobrien
518560484Sobrienvoid
5186130561Sobrieninput_scrub_insert_line (const char *line)
518760484Sobrien{
518860484Sobrien  sb newline;
518960484Sobrien  sb_new (&newline);
519060484Sobrien  sb_add_string (&newline, line);
519160484Sobrien  input_scrub_include_sb (&newline, input_line_pointer, 0);
519260484Sobrien  sb_kill (&newline);
519360484Sobrien  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
519460484Sobrien}
519560484Sobrien
519660484Sobrien/* Insert a file into the input stream; the path must resolve to an actual
519777298Sobrien   file; no include path searching or dependency registering is performed.  */
519860484Sobrien
519960484Sobrienvoid
5200130561Sobrieninput_scrub_insert_file (char *path)
520160484Sobrien{
520260484Sobrien  input_scrub_include_file (path, input_line_pointer);
520360484Sobrien  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
520460484Sobrien}
5205