read.c revision 89857
133965Sjdp/* read.c - read a source file -
278828Sobrien   Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
389857Sobrien   1998, 1999, 2000, 2001 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
3533965Sjdp/* Routines that read assembler source text to build spagetti 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"
4633965Sjdp
4733965Sjdp#ifndef TC_START_LABEL
4833965Sjdp#define TC_START_LABEL(x,y) (x==':')
4933965Sjdp#endif
5033965Sjdp
5160484Sobrien/* Set by the object-format or the target.  */
5260484Sobrien#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
5377298Sobrien#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR)        	\
5477298Sobrien  do								\
5577298Sobrien    {                                                   	\
5677298Sobrien      if ((SIZE) >= 8)                                      	\
5777298Sobrien	(P2VAR) = 3;                                        	\
5877298Sobrien      else if ((SIZE) >= 4)                                 	\
5977298Sobrien	(P2VAR) = 2;                                        	\
6077298Sobrien      else if ((SIZE) >= 2)                                 	\
6177298Sobrien	(P2VAR) = 1;                                        	\
6277298Sobrien      else                                                  	\
6377298Sobrien	(P2VAR) = 0;                                        	\
6477298Sobrien    }								\
6577298Sobrien  while (0)
6660484Sobrien#endif
6760484Sobrien
6877298Sobrienchar *input_line_pointer;	/*->next char of source file to parse.  */
6933965Sjdp
7033965Sjdp#if BITS_PER_CHAR != 8
7133965Sjdp/*  The following table is indexed by[(char)] and will break if
7233965Sjdp    a char does not have exactly 256 states (hopefully 0:255!)!  */
7333965Sjdpdie horribly;
7433965Sjdp#endif
7533965Sjdp
7633965Sjdp#ifndef LEX_AT
7733965Sjdp/* The m88k unfortunately uses @ as a label beginner.  */
7833965Sjdp#define LEX_AT 0
7933965Sjdp#endif
8033965Sjdp
8133965Sjdp#ifndef LEX_BR
8233965Sjdp/* The RS/6000 assembler uses {,},[,] as parts of symbol names.  */
8333965Sjdp#define LEX_BR 0
8433965Sjdp#endif
8533965Sjdp
8633965Sjdp#ifndef LEX_PCT
8733965Sjdp/* The Delta 68k assembler permits % inside label names.  */
8833965Sjdp#define LEX_PCT 0
8933965Sjdp#endif
9033965Sjdp
9133965Sjdp#ifndef LEX_QM
9233965Sjdp/* The PowerPC Windows NT assemblers permits ? inside label names.  */
9333965Sjdp#define LEX_QM 0
9433965Sjdp#endif
9533965Sjdp
9660484Sobrien#ifndef LEX_HASH
9777298Sobrien/* The IA-64 assembler uses # as a suffix designating a symbol.  We include
9877298Sobrien   it in the symbol and strip it out in tc_canonicalize_symbol_name.  */
9960484Sobrien#define LEX_HASH 0
10060484Sobrien#endif
10160484Sobrien
10233965Sjdp#ifndef LEX_DOLLAR
10333965Sjdp/* The a29k assembler does not permits labels to start with $.  */
10433965Sjdp#define LEX_DOLLAR 3
10533965Sjdp#endif
10633965Sjdp
10733965Sjdp#ifndef LEX_TILDE
10833965Sjdp/* The Delta 68k assembler permits ~ at start of label names.  */
10933965Sjdp#define LEX_TILDE 0
11033965Sjdp#endif
11133965Sjdp
11277298Sobrien/* Used by is_... macros. our ctype[].  */
11377298Sobrienchar lex_type[256] = {
11433965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* @ABCDEFGHIJKLMNO */
11533965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* PQRSTUVWXYZ[\]^_ */
11660484Sobrien  0, 0, 0, LEX_HASH, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
11733965Sjdp  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM,	/* 0123456789:;<=>? */
11833965Sjdp  LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,	/* @ABCDEFGHIJKLMNO */
11933965Sjdp  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
12033965Sjdp  0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,	/* `abcdefghijklmno */
12177298Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~.  */
12260484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12360484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12460484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
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
13033965Sjdp};
13133965Sjdp
13277298Sobrien/* In: a character.
13377298Sobrien   Out: 1 if this character ends a line.  */
13477298Sobrienchar is_end_of_line[256] = {
13533965Sjdp#ifdef CR_EOL
13677298Sobrien  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,	/* @abcdefghijklmno */
13733965Sjdp#else
13877298Sobrien  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,	/* @abcdefghijklmno */
13933965Sjdp#endif
14077298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14177298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* _!"#$%&'()*+,-./ */
14277298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0123456789:;<=>? */
14377298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14477298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14577298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14677298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14777298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14877298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
14977298Sobrien  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* */
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	/* */
15533965Sjdp};
15633965Sjdp
15777298Sobrien#ifdef  IGNORE_OPCODE_CASE
15877298Sobrienchar original_case_string[128];
15977298Sobrien#endif
16033965Sjdp
16177298Sobrien/* Functions private to this file.  */
16233965Sjdp
16377298Sobrienstatic char *buffer;	/* 1st char of each buffer of lines is here.  */
16477298Sobrienstatic char *buffer_limit;	/*->1 + last char in buffer.  */
16577298Sobrien
16677298Sobrien/* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1
16777298Sobrien   in the tc-<CPU>.h file.  See the "Porting GAS" section of the
16877298Sobrien   internals manual.  */
16933965Sjdpint target_big_endian = TARGET_BYTES_BIG_ENDIAN;
17033965Sjdp
17177298Sobrienstatic char *old_buffer;	/* JF a hack.  */
17233965Sjdpstatic char *old_input;
17333965Sjdpstatic char *old_limit;
17433965Sjdp
17577298Sobrien/* Variables for handling include file directory table.  */
17633965Sjdp
17777298Sobrien/* Table of pointers to directories to search for .include's.  */
17877298Sobrienchar **include_dirs;
17933965Sjdp
18077298Sobrien/* How many are in the table.  */
18177298Sobrienint include_dir_count;
18277298Sobrien
18377298Sobrien/* Length of longest in table.  */
18477298Sobrienint include_dir_maxlen = 1;
18577298Sobrien
18633965Sjdp#ifndef WORKING_DOT_WORD
18733965Sjdpstruct broken_word *broken_words;
18833965Sjdpint new_broken_words;
18933965Sjdp#endif
19033965Sjdp
19133965Sjdp/* The current offset into the absolute section.  We don't try to
19233965Sjdp   build frags in the absolute section, since no data can be stored
19333965Sjdp   there.  We just keep track of the current offset.  */
19433965SjdpaddressT abs_section_offset;
19533965Sjdp
19633965Sjdp/* If this line had an MRI style label, it is stored in this variable.
19733965Sjdp   This is used by some of the MRI pseudo-ops.  */
19833965SjdpsymbolS *line_label;
19933965Sjdp
20033965Sjdp/* This global variable is used to support MRI common sections.  We
20133965Sjdp   translate such sections into a common symbol.  This variable is
20233965Sjdp   non-NULL when we are in an MRI common section.  */
20333965SjdpsymbolS *mri_common_symbol;
20433965Sjdp
20533965Sjdp/* In MRI mode, after a dc.b pseudo-op with an odd number of bytes, we
20633965Sjdp   need to align to an even byte boundary unless the next pseudo-op is
20733965Sjdp   dc.b, ds.b, or dcb.b.  This variable is set to 1 if an alignment
20833965Sjdp   may be needed.  */
20933965Sjdpstatic int mri_pending_align;
21033965Sjdp
21138889Sjdp#ifndef NO_LISTING
21238889Sjdp#ifdef OBJ_ELF
21338889Sjdp/* This variable is set to be non-zero if the next string we see might
21438889Sjdp   be the name of the source file in DWARF debugging information.  See
21538889Sjdp   the comment in emit_expr for the format we look for.  */
21638889Sjdpstatic int dwarf_file_string;
21738889Sjdp#endif
21838889Sjdp#endif
21938889Sjdp
22033965Sjdpstatic void cons_worker PARAMS ((int, int));
22160484Sobrienstatic int scrub_from_string PARAMS ((char *, int));
22233965Sjdpstatic void do_align PARAMS ((int, char *, int, int));
22333965Sjdpstatic void s_align PARAMS ((int, int));
22460484Sobrienstatic void s_lcomm_internal PARAMS ((int, int));
22533965Sjdpstatic int hex_float PARAMS ((int, char *));
22660484Sobrienstatic inline int sizeof_sleb128 PARAMS ((offsetT));
22760484Sobrienstatic inline int sizeof_uleb128 PARAMS ((valueT));
22860484Sobrienstatic inline int output_sleb128 PARAMS ((char *, offsetT));
22960484Sobrienstatic inline int output_uleb128 PARAMS ((char *, valueT));
23060484Sobrienstatic inline int output_big_sleb128 PARAMS ((char *, LITTLENUM_TYPE *, int));
23160484Sobrienstatic inline int output_big_uleb128 PARAMS ((char *, LITTLENUM_TYPE *, int));
23260484Sobrienstatic int output_big_leb128 PARAMS ((char *, LITTLENUM_TYPE *, int, int));
23333965Sjdpstatic void do_org PARAMS ((segT, expressionS *, int));
23433965Sjdpchar *demand_copy_string PARAMS ((int *lenP));
23533965Sjdpstatic segT get_segmented_expression PARAMS ((expressionS *expP));
23633965Sjdpstatic segT get_known_segmented_expression PARAMS ((expressionS * expP));
23733965Sjdpstatic void pobegin PARAMS ((void));
23833965Sjdpstatic int get_line_sb PARAMS ((sb *));
23960484Sobrienstatic void generate_file_debug PARAMS ((void));
24033965Sjdp
24133965Sjdpvoid
24233965Sjdpread_begin ()
24333965Sjdp{
24433965Sjdp  const char *p;
24533965Sjdp
24633965Sjdp  pobegin ();
24733965Sjdp  obj_read_begin_hook ();
24833965Sjdp
24933965Sjdp  /* Something close -- but not too close -- to a multiple of 1024.
25033965Sjdp     The debugging malloc I'm using has 24 bytes of overhead.  */
25133965Sjdp  obstack_begin (&notes, chunksize);
25233965Sjdp  obstack_begin (&cond_obstack, chunksize);
25333965Sjdp
25477298Sobrien  /* Use machine dependent syntax.  */
25533965Sjdp  for (p = line_separator_chars; *p; p++)
25633965Sjdp    is_end_of_line[(unsigned char) *p] = 1;
25777298Sobrien  /* Use more.  FIXME-SOMEDAY.  */
25833965Sjdp
25933965Sjdp  if (flag_mri)
26033965Sjdp    lex_type['?'] = 3;
26133965Sjdp}
26233965Sjdp
26377298Sobrien/* Set up pseudo-op tables.  */
26433965Sjdp
26533965Sjdpstatic struct hash_control *po_hash;
26633965Sjdp
26777298Sobrienstatic const pseudo_typeS potable[] = {
26833965Sjdp  {"abort", s_abort, 0},
26933965Sjdp  {"align", s_align_ptwo, 0},
27033965Sjdp  {"ascii", stringer, 0},
27133965Sjdp  {"asciz", stringer, 1},
27233965Sjdp  {"balign", s_align_bytes, 0},
27333965Sjdp  {"balignw", s_align_bytes, -2},
27433965Sjdp  {"balignl", s_align_bytes, -4},
27577298Sobrien/* block  */
27633965Sjdp  {"byte", cons, 1},
27733965Sjdp  {"comm", s_comm, 0},
27833965Sjdp  {"common", s_mri_common, 0},
27933965Sjdp  {"common.s", s_mri_common, 1},
28033965Sjdp  {"data", s_data, 0},
28133965Sjdp  {"dc", cons, 2},
28233965Sjdp  {"dc.b", cons, 1},
28333965Sjdp  {"dc.d", float_cons, 'd'},
28433965Sjdp  {"dc.l", cons, 4},
28533965Sjdp  {"dc.s", float_cons, 'f'},
28633965Sjdp  {"dc.w", cons, 2},
28733965Sjdp  {"dc.x", float_cons, 'x'},
28833965Sjdp  {"dcb", s_space, 2},
28933965Sjdp  {"dcb.b", s_space, 1},
29033965Sjdp  {"dcb.d", s_float_space, 'd'},
29133965Sjdp  {"dcb.l", s_space, 4},
29233965Sjdp  {"dcb.s", s_float_space, 'f'},
29333965Sjdp  {"dcb.w", s_space, 2},
29433965Sjdp  {"dcb.x", s_float_space, 'x'},
29533965Sjdp  {"ds", s_space, 2},
29633965Sjdp  {"ds.b", s_space, 1},
29733965Sjdp  {"ds.d", s_space, 8},
29833965Sjdp  {"ds.l", s_space, 4},
29933965Sjdp  {"ds.p", s_space, 12},
30033965Sjdp  {"ds.s", s_space, 4},
30133965Sjdp  {"ds.w", s_space, 2},
30233965Sjdp  {"ds.x", s_space, 12},
30333965Sjdp  {"debug", s_ignore, 0},
30433965Sjdp#ifdef S_SET_DESC
30533965Sjdp  {"desc", s_desc, 0},
30633965Sjdp#endif
30777298Sobrien/* dim  */
30833965Sjdp  {"double", float_cons, 'd'},
30977298Sobrien/* dsect  */
31077298Sobrien  {"eject", listing_eject, 0},	/* Formfeed listing.  */
31133965Sjdp  {"else", s_else, 0},
31233965Sjdp  {"elsec", s_else, 0},
31360484Sobrien  {"elseif", s_elseif, (int) O_ne},
31433965Sjdp  {"end", s_end, 0},
31533965Sjdp  {"endc", s_endif, 0},
31660484Sobrien  {"endfunc", s_func, 1},
31733965Sjdp  {"endif", s_endif, 0},
31889857Sobrien  {"endr", s_bad_endr, 0},
31977298Sobrien/* endef  */
32033965Sjdp  {"equ", s_set, 0},
32133965Sjdp  {"equiv", s_set, 1},
32233965Sjdp  {"err", s_err, 0},
32333965Sjdp  {"exitm", s_mexit, 0},
32477298Sobrien/* extend  */
32577298Sobrien  {"extern", s_ignore, 0},	/* We treat all undef as ext.  */
32633965Sjdp  {"appfile", s_app_file, 1},
32733965Sjdp  {"appline", s_app_line, 0},
32833965Sjdp  {"fail", s_fail, 0},
32933965Sjdp  {"file", s_app_file, 0},
33033965Sjdp  {"fill", s_fill, 0},
33133965Sjdp  {"float", float_cons, 'f'},
33233965Sjdp  {"format", s_ignore, 0},
33360484Sobrien  {"func", s_func, 0},
33433965Sjdp  {"global", s_globl, 0},
33533965Sjdp  {"globl", s_globl, 0},
33633965Sjdp  {"hword", cons, 2},
33733965Sjdp  {"if", s_if, (int) O_ne},
33833965Sjdp  {"ifc", s_ifc, 0},
33933965Sjdp  {"ifdef", s_ifdef, 0},
34033965Sjdp  {"ifeq", s_if, (int) O_eq},
34133965Sjdp  {"ifeqs", s_ifeqs, 0},
34233965Sjdp  {"ifge", s_if, (int) O_ge},
34333965Sjdp  {"ifgt", s_if, (int) O_gt},
34433965Sjdp  {"ifle", s_if, (int) O_le},
34533965Sjdp  {"iflt", s_if, (int) O_lt},
34633965Sjdp  {"ifnc", s_ifc, 1},
34733965Sjdp  {"ifndef", s_ifdef, 1},
34833965Sjdp  {"ifne", s_if, (int) O_ne},
34933965Sjdp  {"ifnes", s_ifeqs, 1},
35033965Sjdp  {"ifnotdef", s_ifdef, 1},
35189857Sobrien  {"incbin", s_incbin, 0},
35233965Sjdp  {"include", s_include, 0},
35333965Sjdp  {"int", cons, 4},
35433965Sjdp  {"irp", s_irp, 0},
35533965Sjdp  {"irep", s_irp, 0},
35633965Sjdp  {"irpc", s_irp, 1},
35733965Sjdp  {"irepc", s_irp, 1},
35833965Sjdp  {"lcomm", s_lcomm, 0},
35977298Sobrien  {"lflags", listing_flags, 0},	/* Listing flags.  */
36033965Sjdp  {"linkonce", s_linkonce, 0},
36177298Sobrien  {"list", listing_list, 1},	/* Turn listing on.  */
36233965Sjdp  {"llen", listing_psize, 1},
36333965Sjdp  {"long", cons, 4},
36433965Sjdp  {"lsym", s_lsym, 0},
36533965Sjdp  {"macro", s_macro, 0},
36633965Sjdp  {"mexit", s_mexit, 0},
36733965Sjdp  {"mri", s_mri, 0},
36833965Sjdp  {".mri", s_mri, 0},	/* Special case so .mri works in MRI mode.  */
36933965Sjdp  {"name", s_ignore, 0},
37033965Sjdp  {"noformat", s_ignore, 0},
37177298Sobrien  {"nolist", listing_list, 0},	/* Turn listing off.  */
37233965Sjdp  {"nopage", listing_nopage, 0},
37333965Sjdp  {"octa", cons, 16},
37433965Sjdp  {"offset", s_struct, 0},
37533965Sjdp  {"org", s_org, 0},
37633965Sjdp  {"p2align", s_align_ptwo, 0},
37733965Sjdp  {"p2alignw", s_align_ptwo, -2},
37833965Sjdp  {"p2alignl", s_align_ptwo, -4},
37933965Sjdp  {"page", listing_eject, 0},
38033965Sjdp  {"plen", listing_psize, 0},
38133965Sjdp  {"print", s_print, 0},
38277298Sobrien  {"psize", listing_psize, 0},	/* Set paper size.  */
38333965Sjdp  {"purgem", s_purgem, 0},
38433965Sjdp  {"quad", cons, 8},
38533965Sjdp  {"rep", s_rept, 0},
38633965Sjdp  {"rept", s_rept, 0},
38733965Sjdp  {"rva", s_rva, 4},
38877298Sobrien  {"sbttl", listing_title, 1},	/* Subtitle of listing.  */
38977298Sobrien/* scl  */
39077298Sobrien/* sect  */
39133965Sjdp  {"set", s_set, 0},
39233965Sjdp  {"short", cons, 2},
39333965Sjdp  {"single", float_cons, 'f'},
39477298Sobrien/* size  */
39533965Sjdp  {"space", s_space, 0},
39633965Sjdp  {"skip", s_space, 0},
39738889Sjdp  {"sleb128", s_leb128, 1},
39833965Sjdp  {"spc", s_ignore, 0},
39933965Sjdp  {"stabd", s_stab, 'd'},
40033965Sjdp  {"stabn", s_stab, 'n'},
40133965Sjdp  {"stabs", s_stab, 's'},
40233965Sjdp  {"string", stringer, 1},
40333965Sjdp  {"struct", s_struct, 0},
40477298Sobrien/* tag  */
40533965Sjdp  {"text", s_text, 0},
40633965Sjdp
40733965Sjdp  /* This is for gcc to use.  It's only just been added (2/94), so gcc
40833965Sjdp     won't be able to use it for a while -- probably a year or more.
40933965Sjdp     But once this has been released, check with gcc maintainers
41033965Sjdp     before deleting it or even changing the spelling.  */
41133965Sjdp  {"this_GCC_requires_the_GNU_assembler", s_ignore, 0},
41233965Sjdp  /* If we're folding case -- done for some targets, not necessarily
41333965Sjdp     all -- the above string in an input file will be converted to
41433965Sjdp     this one.  Match it either way...  */
41533965Sjdp  {"this_gcc_requires_the_gnu_assembler", s_ignore, 0},
41633965Sjdp
41777298Sobrien  {"title", listing_title, 0},	/* Listing title.  */
41833965Sjdp  {"ttl", listing_title, 0},
41977298Sobrien/* type  */
42038889Sjdp  {"uleb128", s_leb128, 0},
42177298Sobrien/* use  */
42277298Sobrien/* val  */
42333965Sjdp  {"xcom", s_comm, 0},
42433965Sjdp  {"xdef", s_globl, 0},
42533965Sjdp  {"xref", s_ignore, 0},
42633965Sjdp  {"xstabs", s_xstab, 's'},
42733965Sjdp  {"word", cons, 2},
42833965Sjdp  {"zero", s_space, 0},
42977298Sobrien  {NULL, NULL, 0}			/* End sentinel.  */
43033965Sjdp};
43133965Sjdp
43233965Sjdpstatic int pop_override_ok = 0;
43333965Sjdpstatic const char *pop_table_name;
43433965Sjdp
43533965Sjdpvoid
43633965Sjdppop_insert (table)
43733965Sjdp     const pseudo_typeS *table;
43833965Sjdp{
43933965Sjdp  const char *errtxt;
44033965Sjdp  const pseudo_typeS *pop;
44133965Sjdp  for (pop = table; pop->poc_name; pop++)
44233965Sjdp    {
44333965Sjdp      errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
44433965Sjdp      if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists")))
44560484Sobrien	as_fatal (_("error constructing %s pseudo-op table: %s"), pop_table_name,
44633965Sjdp		  errtxt);
44733965Sjdp    }
44833965Sjdp}
44933965Sjdp
45033965Sjdp#ifndef md_pop_insert
45133965Sjdp#define md_pop_insert()		pop_insert(md_pseudo_table)
45233965Sjdp#endif
45333965Sjdp
45433965Sjdp#ifndef obj_pop_insert
45533965Sjdp#define obj_pop_insert()	pop_insert(obj_pseudo_table)
45633965Sjdp#endif
45733965Sjdp
45877298Sobrienstatic void
45933965Sjdppobegin ()
46033965Sjdp{
46133965Sjdp  po_hash = hash_new ();
46233965Sjdp
46377298Sobrien  /* Do the target-specific pseudo ops.  */
46433965Sjdp  pop_table_name = "md";
46533965Sjdp  md_pop_insert ();
46633965Sjdp
46777298Sobrien  /* Now object specific.  Skip any that were in the target table.  */
46833965Sjdp  pop_table_name = "obj";
46933965Sjdp  pop_override_ok = 1;
47033965Sjdp  obj_pop_insert ();
47133965Sjdp
47277298Sobrien  /* Now portable ones.  Skip any that we've seen already.  */
47333965Sjdp  pop_table_name = "standard";
47433965Sjdp  pop_insert (potable);
47533965Sjdp}
47633965Sjdp
47733965Sjdp#define HANDLE_CONDITIONAL_ASSEMBLY()					\
47833965Sjdp  if (ignore_input ())							\
47933965Sjdp    {									\
48077298Sobrien      while (!is_end_of_line[(unsigned char) *input_line_pointer++])	\
48133965Sjdp	if (input_line_pointer == buffer_limit)				\
48233965Sjdp	  break;							\
48333965Sjdp      continue;								\
48433965Sjdp    }
48533965Sjdp
48633965Sjdp/* This function is used when scrubbing the characters between #APP
48733965Sjdp   and #NO_APP.  */
48833965Sjdp
48933965Sjdpstatic char *scrub_string;
49033965Sjdpstatic char *scrub_string_end;
49133965Sjdp
49233965Sjdpstatic int
49360484Sobrienscrub_from_string (buf, buflen)
49460484Sobrien     char *buf;
49560484Sobrien     int buflen;
49633965Sjdp{
49760484Sobrien  int copy;
49833965Sjdp
49960484Sobrien  copy = scrub_string_end - scrub_string;
50060484Sobrien  if (copy > buflen)
50160484Sobrien    copy = buflen;
50260484Sobrien  memcpy (buf, scrub_string, copy);
50360484Sobrien  scrub_string += copy;
50460484Sobrien  return copy;
50533965Sjdp}
50633965Sjdp
50777298Sobrien/* We read the file, putting things into a web that represents what we
50877298Sobrien   have been reading.  */
50977298Sobrienvoid
51033965Sjdpread_a_source_file (name)
51133965Sjdp     char *name;
51233965Sjdp{
51333965Sjdp  register char c;
51477298Sobrien  register char *s;		/* String of symbol, '\0' appended.  */
51533965Sjdp  register int temp;
51633965Sjdp  pseudo_typeS *pop;
51733965Sjdp
51877298Sobrien#ifdef WARN_COMMENTS
51977298Sobrien  found_comment = 0;
52077298Sobrien#endif
52177298Sobrien
52233965Sjdp  buffer = input_scrub_new_file (name);
52333965Sjdp
52433965Sjdp  listing_file (name);
52538889Sjdp  listing_newline (NULL);
52638889Sjdp  register_dependency (name);
52733965Sjdp
52860484Sobrien  /* Generate debugging information before we've read anything in to denote
52960484Sobrien     this file as the "main" source file and not a subordinate one
53060484Sobrien     (e.g. N_SO vs N_SOL in stabs).  */
53160484Sobrien  generate_file_debug ();
53260484Sobrien
53333965Sjdp  while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0)
53477298Sobrien    {				/* We have another line to parse.  */
53577298Sobrien      know (buffer_limit[-1] == '\n');	/* Must have a sentinel.  */
53633965Sjdp    contin:			/* JF this goto is my fault I admit it.
53733965Sjdp				   Someone brave please re-write the whole
53833965Sjdp				   input section here?  Pleeze???  */
53933965Sjdp      while (input_line_pointer < buffer_limit)
54033965Sjdp	{
54177298Sobrien	  /* We have more of this buffer to parse.  */
54233965Sjdp
54377298Sobrien	  /* We now have input_line_pointer->1st char of next line.
54477298Sobrien	     If input_line_pointer [-1] == '\n' then we just
54577298Sobrien	     scanned another line: so bump line counters.  */
54633965Sjdp	  if (is_end_of_line[(unsigned char) input_line_pointer[-1]])
54733965Sjdp	    {
54833965Sjdp#ifdef md_start_line_hook
54933965Sjdp	      md_start_line_hook ();
55033965Sjdp#endif
55133965Sjdp	      if (input_line_pointer[-1] == '\n')
55233965Sjdp		bump_line_counters ();
55333965Sjdp
55433965Sjdp	      line_label = NULL;
55533965Sjdp
55660484Sobrien	      if (LABELS_WITHOUT_COLONS || flag_m68k_mri)
55733965Sjdp		{
55833965Sjdp		  /* Text at the start of a line must be a label, we
55933965Sjdp		     run down and stick a colon in.  */
56033965Sjdp		  if (is_name_beginner (*input_line_pointer))
56133965Sjdp		    {
56233965Sjdp		      char *line_start = input_line_pointer;
56333965Sjdp		      char c;
56433965Sjdp		      int mri_line_macro;
56533965Sjdp
56633965Sjdp		      LISTING_NEWLINE ();
56733965Sjdp		      HANDLE_CONDITIONAL_ASSEMBLY ();
56833965Sjdp
56933965Sjdp		      c = get_symbol_end ();
57033965Sjdp
57133965Sjdp		      /* In MRI mode, the EQU and MACRO pseudoops must
57233965Sjdp			 be handled specially.  */
57333965Sjdp		      mri_line_macro = 0;
57433965Sjdp		      if (flag_m68k_mri)
57533965Sjdp			{
57633965Sjdp			  char *rest = input_line_pointer + 1;
57733965Sjdp
57833965Sjdp			  if (*rest == ':')
57933965Sjdp			    ++rest;
58033965Sjdp			  if (*rest == ' ' || *rest == '\t')
58133965Sjdp			    ++rest;
58233965Sjdp			  if ((strncasecmp (rest, "EQU", 3) == 0
58333965Sjdp			       || strncasecmp (rest, "SET", 3) == 0)
58433965Sjdp			      && (rest[3] == ' ' || rest[3] == '\t'))
58533965Sjdp			    {
58633965Sjdp			      input_line_pointer = rest + 3;
58733965Sjdp			      equals (line_start,
58833965Sjdp				      strncasecmp (rest, "SET", 3) == 0);
58933965Sjdp			      continue;
59033965Sjdp			    }
59133965Sjdp			  if (strncasecmp (rest, "MACRO", 5) == 0
59233965Sjdp			      && (rest[5] == ' '
59333965Sjdp				  || rest[5] == '\t'
59433965Sjdp				  || is_end_of_line[(unsigned char) rest[5]]))
59533965Sjdp			    mri_line_macro = 1;
59633965Sjdp			}
59733965Sjdp
59833965Sjdp		      /* In MRI mode, we need to handle the MACRO
59933965Sjdp                         pseudo-op specially: we don't want to put the
60033965Sjdp                         symbol in the symbol table.  */
60177298Sobrien		      if (!mri_line_macro
60260484Sobrien#ifdef TC_START_LABEL_WITHOUT_COLON
60377298Sobrien			  && TC_START_LABEL_WITHOUT_COLON(c,
60477298Sobrien							  input_line_pointer)
60560484Sobrien#endif
60677298Sobrien			  )
60733965Sjdp			line_label = colon (line_start);
60833965Sjdp		      else
60933965Sjdp			line_label = symbol_create (line_start,
61033965Sjdp						    absolute_section,
61133965Sjdp						    (valueT) 0,
61233965Sjdp						    &zero_address_frag);
61333965Sjdp
61433965Sjdp		      *input_line_pointer = c;
61533965Sjdp		      if (c == ':')
61633965Sjdp			input_line_pointer++;
61733965Sjdp		    }
61833965Sjdp		}
61933965Sjdp	    }
62033965Sjdp
62177298Sobrien	  /* We are at the begining of a line, or similar place.
62277298Sobrien	     We expect a well-formed assembler statement.
62377298Sobrien	     A "symbol-name:" is a statement.
62477298Sobrien
62577298Sobrien	     Depending on what compiler is used, the order of these tests
62677298Sobrien	     may vary to catch most common case 1st.
62777298Sobrien	     Each test is independent of all other tests at the (top) level.
62877298Sobrien	     PLEASE make a compiler that doesn't use this assembler.
62977298Sobrien	     It is crufty to waste a compiler's time encoding things for this
63077298Sobrien	     assembler, which then wastes more time decoding it.
63177298Sobrien	     (And communicating via (linear) files is silly!
63277298Sobrien	     If you must pass stuff, please pass a tree!)  */
63333965Sjdp	  if ((c = *input_line_pointer++) == '\t'
63433965Sjdp	      || c == ' '
63533965Sjdp	      || c == '\f'
63633965Sjdp	      || c == 0)
63777298Sobrien	    c = *input_line_pointer++;
63838889Sjdp
63977298Sobrien	  know (c != ' ');	/* No further leading whitespace.  */
64077298Sobrien
64138889Sjdp#ifndef NO_LISTING
64238889Sjdp	  /* If listing is on, and we are expanding a macro, then give
64338889Sjdp	     the listing code the contents of the expanded line.  */
64438889Sjdp	  if (listing)
64538889Sjdp	    {
64638889Sjdp	      if ((listing & LISTING_MACEXP) && macro_nest > 0)
64738889Sjdp		{
64838889Sjdp		  char *copy;
64938889Sjdp		  int len;
65038889Sjdp
65138889Sjdp		  /* Find the end of the current expanded macro line.  */
65277298Sobrien		  for (s = input_line_pointer - 1; *s; ++s)
65338889Sjdp		    if (is_end_of_line[(unsigned char) *s])
65438889Sjdp		      break;
65538889Sjdp
65638889Sjdp		  /* Copy it for safe keeping.  Also give an indication of
65738889Sjdp		     how much macro nesting is involved at this point.  */
65877298Sobrien		  len = s - (input_line_pointer - 1);
65938889Sjdp		  copy = (char *) xmalloc (len + macro_nest + 2);
66038889Sjdp		  memset (copy, '>', macro_nest);
66138889Sjdp		  copy[macro_nest] = ' ';
66277298Sobrien		  memcpy (copy + macro_nest + 1, input_line_pointer - 1, len);
66377298Sobrien		  copy[macro_nest + 1 + len] = '\0';
66438889Sjdp
66538889Sjdp		  /* Install the line with the listing facility.  */
66638889Sjdp		  listing_newline (copy);
66738889Sjdp		}
66838889Sjdp	      else
66938889Sjdp		listing_newline (NULL);
67038889Sjdp	    }
67138889Sjdp#endif
67277298Sobrien	  /* C is the 1st significant character.
67377298Sobrien	     Input_line_pointer points after that character.  */
67433965Sjdp	  if (is_name_beginner (c))
67533965Sjdp	    {
67677298Sobrien	      /* Want user-defined label or pseudo/opcode.  */
67733965Sjdp	      HANDLE_CONDITIONAL_ASSEMBLY ();
67833965Sjdp
67933965Sjdp	      s = --input_line_pointer;
68077298Sobrien	      c = get_symbol_end ();	/* name's delimiter.  */
68177298Sobrien
68277298Sobrien	      /* C is character after symbol.
68377298Sobrien	         That character's place in the input line is now '\0'.
68477298Sobrien	         S points to the beginning of the symbol.
68577298Sobrien	           [In case of pseudo-op, s->'.'.]
68677298Sobrien	         Input_line_pointer->'\0' where c was.  */
68777298Sobrien	      if (TC_START_LABEL (c, input_line_pointer))
68833965Sjdp		{
68933965Sjdp		  if (flag_m68k_mri)
69033965Sjdp		    {
69133965Sjdp		      char *rest = input_line_pointer + 1;
69233965Sjdp
69333965Sjdp		      /* In MRI mode, \tsym: set 0 is permitted.  */
69433965Sjdp		      if (*rest == ':')
69533965Sjdp			++rest;
69677298Sobrien
69733965Sjdp		      if (*rest == ' ' || *rest == '\t')
69833965Sjdp			++rest;
69977298Sobrien
70033965Sjdp		      if ((strncasecmp (rest, "EQU", 3) == 0
70133965Sjdp			   || strncasecmp (rest, "SET", 3) == 0)
70233965Sjdp			  && (rest[3] == ' ' || rest[3] == '\t'))
70333965Sjdp			{
70433965Sjdp			  input_line_pointer = rest + 3;
70533965Sjdp			  equals (s, 1);
70633965Sjdp			  continue;
70733965Sjdp			}
70833965Sjdp		    }
70933965Sjdp
71077298Sobrien		  line_label = colon (s);	/* User-defined label.  */
71177298Sobrien		  /* Put ':' back for error messages' sake.  */
71277298Sobrien		  *input_line_pointer++ = ':';
71377298Sobrien		  /* Input_line_pointer->after ':'.  */
71433965Sjdp		  SKIP_WHITESPACE ();
71533965Sjdp		}
71633965Sjdp	      else if (c == '='
71733965Sjdp		       || ((c == ' ' || c == '\t')
71833965Sjdp			   && input_line_pointer[1] == '='
71933965Sjdp#ifdef TC_EQUAL_IN_INSN
72077298Sobrien			   && !TC_EQUAL_IN_INSN (c, input_line_pointer)
72133965Sjdp#endif
72233965Sjdp			   ))
72333965Sjdp		{
72433965Sjdp		  equals (s, 1);
72533965Sjdp		  demand_empty_rest_of_line ();
72633965Sjdp		}
72733965Sjdp	      else
72877298Sobrien		{
72977298Sobrien		  /* Expect pseudo-op or machine instruction.  */
73033965Sjdp		  pop = NULL;
73133965Sjdp
73233965Sjdp#ifdef IGNORE_OPCODE_CASE
73333965Sjdp		  {
73433965Sjdp		    char *s2 = s;
73577298Sobrien
73677298Sobrien		    strncpy (original_case_string, s2, sizeof (original_case_string));
73777298Sobrien		    original_case_string[sizeof (original_case_string) - 1] = 0;
73877298Sobrien
73933965Sjdp		    while (*s2)
74033965Sjdp		      {
74189857Sobrien			*s2 = TOLOWER (*s2);
74233965Sjdp			s2++;
74333965Sjdp		      }
74433965Sjdp		  }
74533965Sjdp#endif
74660484Sobrien		  if (NO_PSEUDO_DOT || flag_m68k_mri)
74733965Sjdp		    {
74833965Sjdp		      /* The MRI assembler and the m88k use pseudo-ops
74933965Sjdp                         without a period.  */
75033965Sjdp		      pop = (pseudo_typeS *) hash_find (po_hash, s);
75133965Sjdp		      if (pop != NULL && pop->poc_handler == NULL)
75233965Sjdp			pop = NULL;
75333965Sjdp		    }
75433965Sjdp
75533965Sjdp		  if (pop != NULL
75677298Sobrien		      || (!flag_m68k_mri && *s == '.'))
75733965Sjdp		    {
75877298Sobrien		      /* PSEUDO - OP.
75933965Sjdp
76077298Sobrien		         WARNING: c has next char, which may be end-of-line.
76177298Sobrien		         We lookup the pseudo-op table with s+1 because we
76277298Sobrien		         already know that the pseudo-op begins with a '.'.  */
76377298Sobrien
76433965Sjdp		      if (pop == NULL)
76533965Sjdp			pop = (pseudo_typeS *) hash_find (po_hash, s + 1);
76633965Sjdp
76733965Sjdp		      /* In MRI mode, we may need to insert an
76833965Sjdp                         automatic alignment directive.  What a hack
76933965Sjdp                         this is.  */
77033965Sjdp		      if (mri_pending_align
77133965Sjdp			  && (pop == NULL
77277298Sobrien			      || !((pop->poc_handler == cons
77377298Sobrien				    && pop->poc_val == 1)
77477298Sobrien				   || (pop->poc_handler == s_space
77577298Sobrien				       && pop->poc_val == 1)
77633965Sjdp#ifdef tc_conditional_pseudoop
77777298Sobrien				   || tc_conditional_pseudoop (pop)
77833965Sjdp#endif
77977298Sobrien				   || pop->poc_handler == s_if
78077298Sobrien				   || pop->poc_handler == s_ifdef
78177298Sobrien				   || pop->poc_handler == s_ifc
78277298Sobrien				   || pop->poc_handler == s_ifeqs
78377298Sobrien				   || pop->poc_handler == s_else
78477298Sobrien				   || pop->poc_handler == s_endif
78577298Sobrien				   || pop->poc_handler == s_globl
78677298Sobrien				   || pop->poc_handler == s_ignore)))
78733965Sjdp			{
78833965Sjdp			  do_align (1, (char *) NULL, 0, 0);
78933965Sjdp			  mri_pending_align = 0;
79077298Sobrien
79133965Sjdp			  if (line_label != NULL)
79233965Sjdp			    {
79360484Sobrien			      symbol_set_frag (line_label, frag_now);
79433965Sjdp			      S_SET_VALUE (line_label, frag_now_fix ());
79533965Sjdp			    }
79633965Sjdp			}
79733965Sjdp
79877298Sobrien		      /* Print the error msg now, while we still can.  */
79933965Sjdp		      if (pop == NULL)
80033965Sjdp			{
80189857Sobrien			  as_bad (_("unknown pseudo-op: `%s'"), s);
80233965Sjdp			  *input_line_pointer = c;
80333965Sjdp			  s_ignore (0);
80433965Sjdp			  continue;
80533965Sjdp			}
80633965Sjdp
80777298Sobrien		      /* Put it back for error messages etc.  */
80833965Sjdp		      *input_line_pointer = c;
80933965Sjdp		      /* The following skip of whitespace is compulsory.
81033965Sjdp			 A well shaped space is sometimes all that separates
81177298Sobrien			 keyword from operands.  */
81233965Sjdp		      if (c == ' ' || c == '\t')
81333965Sjdp			input_line_pointer++;
81477298Sobrien
81577298Sobrien		      /* Input_line is restored.
81677298Sobrien		         Input_line_pointer->1st non-blank char
81777298Sobrien		         after pseudo-operation.  */
81833965Sjdp		      (*pop->poc_handler) (pop->poc_val);
81933965Sjdp
82033965Sjdp		      /* If that was .end, just get out now.  */
82133965Sjdp		      if (pop->poc_handler == s_end)
82233965Sjdp			goto quit;
82333965Sjdp		    }
82433965Sjdp		  else
82533965Sjdp		    {
82633965Sjdp		      int inquote = 0;
82760484Sobrien#ifdef QUOTES_IN_INSN
82860484Sobrien		      int inescape = 0;
82960484Sobrien#endif
83033965Sjdp
83177298Sobrien		      /* WARNING: c has char, which may be end-of-line.  */
83277298Sobrien		      /* Also: input_line_pointer->`\0` where c was.  */
83333965Sjdp		      *input_line_pointer = c;
83433965Sjdp		      while (!is_end_of_line[(unsigned char) *input_line_pointer]
83533965Sjdp			     || inquote
83633965Sjdp#ifdef TC_EOL_IN_INSN
83733965Sjdp			     || TC_EOL_IN_INSN (input_line_pointer)
83833965Sjdp#endif
83933965Sjdp			     )
84033965Sjdp			{
84133965Sjdp			  if (flag_m68k_mri && *input_line_pointer == '\'')
84277298Sobrien			    inquote = !inquote;
84360484Sobrien#ifdef QUOTES_IN_INSN
84460484Sobrien			  if (inescape)
84560484Sobrien			    inescape = 0;
84660484Sobrien			  else if (*input_line_pointer == '"')
84777298Sobrien			    inquote = !inquote;
84860484Sobrien			  else if (*input_line_pointer == '\\')
84960484Sobrien			    inescape = 1;
85060484Sobrien#endif
85133965Sjdp			  input_line_pointer++;
85233965Sjdp			}
85333965Sjdp
85433965Sjdp		      c = *input_line_pointer;
85533965Sjdp		      *input_line_pointer = '\0';
85633965Sjdp
85760484Sobrien		      generate_lineno_debug ();
85838889Sjdp
85933965Sjdp		      if (macro_defined)
86033965Sjdp			{
86133965Sjdp			  sb out;
86233965Sjdp			  const char *err;
86377298Sobrien			  macro_entry *macro;
86433965Sjdp
86560484Sobrien			  if (check_macro (s, &out, '\0', &err, &macro))
86633965Sjdp			    {
86733965Sjdp			      if (err != NULL)
86860484Sobrien				as_bad ("%s", err);
86933965Sjdp			      *input_line_pointer++ = c;
87033965Sjdp			      input_scrub_include_sb (&out,
87160484Sobrien						      input_line_pointer, 1);
87233965Sjdp			      sb_kill (&out);
87333965Sjdp			      buffer_limit =
87433965Sjdp				input_scrub_next_buffer (&input_line_pointer);
87560484Sobrien#ifdef md_macro_info
87677298Sobrien			      md_macro_info (macro);
87760484Sobrien#endif
87833965Sjdp			      continue;
87933965Sjdp			    }
88033965Sjdp			}
88133965Sjdp
88233965Sjdp		      if (mri_pending_align)
88333965Sjdp			{
88433965Sjdp			  do_align (1, (char *) NULL, 0, 0);
88533965Sjdp			  mri_pending_align = 0;
88633965Sjdp			  if (line_label != NULL)
88733965Sjdp			    {
88860484Sobrien			      symbol_set_frag (line_label, frag_now);
88933965Sjdp			      S_SET_VALUE (line_label, frag_now_fix ());
89033965Sjdp			    }
89133965Sjdp			}
89233965Sjdp
89377298Sobrien		      md_assemble (s);	/* Assemble 1 instruction.  */
89433965Sjdp
89533965Sjdp		      *input_line_pointer++ = c;
89633965Sjdp
89733965Sjdp		      /* We resume loop AFTER the end-of-line from
89877298Sobrien			 this instruction.  */
89977298Sobrien		    }
90077298Sobrien		}
90133965Sjdp	      continue;
90277298Sobrien	    }
90333965Sjdp
90433965Sjdp	  /* Empty statement?  */
90533965Sjdp	  if (is_end_of_line[(unsigned char) c])
90633965Sjdp	    continue;
90733965Sjdp
90889857Sobrien	  if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (c))
90933965Sjdp	    {
91077298Sobrien	      /* local label  ("4:")  */
91133965Sjdp	      char *backup = input_line_pointer;
91233965Sjdp
91333965Sjdp	      HANDLE_CONDITIONAL_ASSEMBLY ();
91433965Sjdp
91533965Sjdp	      temp = c - '0';
91633965Sjdp
91777298Sobrien	      /* Read the whole number.  */
91889857Sobrien	      while (ISDIGIT (*input_line_pointer))
91933965Sjdp		{
92033965Sjdp		  temp = (temp * 10) + *input_line_pointer - '0';
92133965Sjdp		  ++input_line_pointer;
92277298Sobrien		}
92333965Sjdp
92433965Sjdp	      if (LOCAL_LABELS_DOLLAR
92533965Sjdp		  && *input_line_pointer == '$'
92633965Sjdp		  && *(input_line_pointer + 1) == ':')
92733965Sjdp		{
92833965Sjdp		  input_line_pointer += 2;
92933965Sjdp
93033965Sjdp		  if (dollar_label_defined (temp))
93133965Sjdp		    {
93260484Sobrien		      as_fatal (_("label \"%d$\" redefined"), temp);
93333965Sjdp		    }
93433965Sjdp
93533965Sjdp		  define_dollar_label (temp);
93633965Sjdp		  colon (dollar_label_name (temp, 0));
93733965Sjdp		  continue;
93833965Sjdp		}
93933965Sjdp
94033965Sjdp	      if (LOCAL_LABELS_FB
94133965Sjdp		  && *input_line_pointer++ == ':')
94233965Sjdp		{
94333965Sjdp		  fb_label_instance_inc (temp);
94433965Sjdp		  colon (fb_label_name (temp, 0));
94533965Sjdp		  continue;
94633965Sjdp		}
94733965Sjdp
94833965Sjdp	      input_line_pointer = backup;
94933965Sjdp	    }			/* local label  ("4:") */
95033965Sjdp
95133965Sjdp	  if (c && strchr (line_comment_chars, c))
95277298Sobrien	    {			/* Its a comment.  Better say APP or NO_APP.  */
95333965Sjdp	      char *ends;
95433965Sjdp	      char *new_buf;
95533965Sjdp	      char *new_tmp;
95633965Sjdp	      unsigned int new_length;
95733965Sjdp	      char *tmp_buf = 0;
95833965Sjdp
95933965Sjdp	      bump_line_counters ();
96033965Sjdp	      s = input_line_pointer;
96133965Sjdp	      if (strncmp (s, "APP\n", 4))
96233965Sjdp		continue;	/* We ignore it */
96333965Sjdp	      s += 4;
96433965Sjdp
96533965Sjdp	      ends = strstr (s, "#NO_APP\n");
96633965Sjdp
96733965Sjdp	      if (!ends)
96833965Sjdp		{
96933965Sjdp		  unsigned int tmp_len;
97033965Sjdp		  unsigned int num;
97133965Sjdp
97233965Sjdp		  /* The end of the #APP wasn't in this buffer.  We
97333965Sjdp		     keep reading in buffers until we find the #NO_APP
97433965Sjdp		     that goes with this #APP  There is one.  The specs
97577298Sobrien		     guarentee it...  */
97633965Sjdp		  tmp_len = buffer_limit - s;
97733965Sjdp		  tmp_buf = xmalloc (tmp_len + 1);
97833965Sjdp		  memcpy (tmp_buf, s, tmp_len);
97933965Sjdp		  do
98033965Sjdp		    {
98133965Sjdp		      new_tmp = input_scrub_next_buffer (&buffer);
98233965Sjdp		      if (!new_tmp)
98333965Sjdp			break;
98433965Sjdp		      else
98533965Sjdp			buffer_limit = new_tmp;
98633965Sjdp		      input_line_pointer = buffer;
98733965Sjdp		      ends = strstr (buffer, "#NO_APP\n");
98833965Sjdp		      if (ends)
98933965Sjdp			num = ends - buffer;
99033965Sjdp		      else
99133965Sjdp			num = buffer_limit - buffer;
99233965Sjdp
99333965Sjdp		      tmp_buf = xrealloc (tmp_buf, tmp_len + num);
99433965Sjdp		      memcpy (tmp_buf + tmp_len, buffer, num);
99533965Sjdp		      tmp_len += num;
99633965Sjdp		    }
99733965Sjdp		  while (!ends);
99833965Sjdp
99933965Sjdp		  input_line_pointer = ends ? ends + 8 : NULL;
100033965Sjdp
100133965Sjdp		  s = tmp_buf;
100233965Sjdp		  ends = s + tmp_len;
100333965Sjdp
100433965Sjdp		}
100533965Sjdp	      else
100633965Sjdp		{
100733965Sjdp		  input_line_pointer = ends + 8;
100833965Sjdp		}
100933965Sjdp
101033965Sjdp	      scrub_string = s;
101133965Sjdp	      scrub_string_end = ends;
101233965Sjdp
101333965Sjdp	      new_length = ends - s;
101433965Sjdp	      new_buf = (char *) xmalloc (new_length);
101533965Sjdp	      new_tmp = new_buf;
101633965Sjdp	      for (;;)
101733965Sjdp		{
101833965Sjdp		  int space;
101933965Sjdp		  int size;
102033965Sjdp
102133965Sjdp		  space = (new_buf + new_length) - new_tmp;
102233965Sjdp		  size = do_scrub_chars (scrub_from_string, new_tmp, space);
102333965Sjdp
102433965Sjdp		  if (size < space)
102533965Sjdp		    {
102633965Sjdp		      new_tmp += size;
102733965Sjdp		      break;
102833965Sjdp		    }
102933965Sjdp
103033965Sjdp		  new_buf = xrealloc (new_buf, new_length + 100);
103133965Sjdp		  new_tmp = new_buf + new_length;
103233965Sjdp		  new_length += 100;
103333965Sjdp		}
103433965Sjdp
103533965Sjdp	      if (tmp_buf)
103633965Sjdp		free (tmp_buf);
103733965Sjdp	      old_buffer = buffer;
103833965Sjdp	      old_input = input_line_pointer;
103933965Sjdp	      old_limit = buffer_limit;
104033965Sjdp	      buffer = new_buf;
104133965Sjdp	      input_line_pointer = new_buf;
104233965Sjdp	      buffer_limit = new_tmp;
104377298Sobrien
104433965Sjdp	      continue;
104533965Sjdp	    }
104633965Sjdp
104733965Sjdp	  HANDLE_CONDITIONAL_ASSEMBLY ();
104833965Sjdp
104933965Sjdp#ifdef tc_unrecognized_line
105033965Sjdp	  if (tc_unrecognized_line (c))
105133965Sjdp	    continue;
105233965Sjdp#endif
105389857Sobrien	  input_line_pointer--;
105489857Sobrien	  /* Report unknown char as ignored.  */
105533965Sjdp	  ignore_rest_of_line ();
105677298Sobrien	}
105733965Sjdp
105833965Sjdp#ifdef md_after_pass_hook
105933965Sjdp      md_after_pass_hook ();
106033965Sjdp#endif
106133965Sjdp
106233965Sjdp      if (old_buffer)
106333965Sjdp	{
106433965Sjdp	  free (buffer);
106533965Sjdp	  bump_line_counters ();
106633965Sjdp	  if (old_input != 0)
106733965Sjdp	    {
106833965Sjdp	      buffer = old_buffer;
106933965Sjdp	      input_line_pointer = old_input;
107033965Sjdp	      buffer_limit = old_limit;
107133965Sjdp	      old_buffer = 0;
107233965Sjdp	      goto contin;
107333965Sjdp	    }
107433965Sjdp	}
107577298Sobrien    }
107633965Sjdp
107733965Sjdp quit:
107833965Sjdp
107933965Sjdp#ifdef md_cleanup
108077298Sobrien  md_cleanup ();
108133965Sjdp#endif
108277298Sobrien  /* Close the input file.  */
108377298Sobrien  input_scrub_close ();
108477298Sobrien#ifdef WARN_COMMENTS
108577298Sobrien  {
108677298Sobrien    if (warn_comment && found_comment)
108777298Sobrien      as_warn_where (found_comment_file, found_comment,
108877298Sobrien		     "first comment found here");
108977298Sobrien  }
109077298Sobrien#endif
109133965Sjdp}
109233965Sjdp
109333965Sjdp/* For most MRI pseudo-ops, the line actually ends at the first
109433965Sjdp   nonquoted space.  This function looks for that point, stuffs a null
109533965Sjdp   in, and sets *STOPCP to the character that used to be there, and
109633965Sjdp   returns the location.
109733965Sjdp
109833965Sjdp   Until I hear otherwise, I am going to assume that this is only true
109933965Sjdp   for the m68k MRI assembler.  */
110033965Sjdp
110133965Sjdpchar *
110233965Sjdpmri_comment_field (stopcp)
110333965Sjdp     char *stopcp;
110433965Sjdp{
110577298Sobrien  char *s;
110633965Sjdp#ifdef TC_M68K
110733965Sjdp  int inquote = 0;
110833965Sjdp
110933965Sjdp  know (flag_m68k_mri);
111033965Sjdp
111133965Sjdp  for (s = input_line_pointer;
111277298Sobrien       ((!is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t')
111333965Sjdp	|| inquote);
111433965Sjdp       s++)
111533965Sjdp    {
111633965Sjdp      if (*s == '\'')
111777298Sobrien	inquote = !inquote;
111833965Sjdp    }
111933965Sjdp#else
112077298Sobrien  for (s = input_line_pointer;
112177298Sobrien       !is_end_of_line[(unsigned char) *s];
112277298Sobrien       s++)
112333965Sjdp    ;
112477298Sobrien#endif
112533965Sjdp  *stopcp = *s;
112633965Sjdp  *s = '\0';
112777298Sobrien
112833965Sjdp  return s;
112933965Sjdp}
113033965Sjdp
113133965Sjdp/* Skip to the end of an MRI comment field.  */
113233965Sjdp
113333965Sjdpvoid
113433965Sjdpmri_comment_end (stop, stopc)
113533965Sjdp     char *stop;
113633965Sjdp     int stopc;
113733965Sjdp{
113833965Sjdp  know (flag_mri);
113933965Sjdp
114033965Sjdp  input_line_pointer = stop;
114133965Sjdp  *stop = stopc;
114277298Sobrien  while (!is_end_of_line[(unsigned char) *input_line_pointer])
114333965Sjdp    ++input_line_pointer;
114433965Sjdp}
114533965Sjdp
114677298Sobrienvoid
114733965Sjdps_abort (ignore)
114860484Sobrien     int ignore ATTRIBUTE_UNUSED;
114933965Sjdp{
115060484Sobrien  as_fatal (_(".abort detected.  Abandoning ship."));
115133965Sjdp}
115233965Sjdp
115333965Sjdp/* Guts of .align directive.  N is the power of two to which to align.
115433965Sjdp   FILL may be NULL, or it may point to the bytes of the fill pattern.
115533965Sjdp   LEN is the length of whatever FILL points to, if anything.  MAX is
115633965Sjdp   the maximum number of characters to skip when doing the alignment,
115733965Sjdp   or 0 if there is no maximum.  */
115833965Sjdp
115977298Sobrienstatic void
116033965Sjdpdo_align (n, fill, len, max)
116133965Sjdp     int n;
116233965Sjdp     char *fill;
116333965Sjdp     int len;
116433965Sjdp     int max;
116533965Sjdp{
116689857Sobrien  if (now_seg == absolute_section)
116789857Sobrien    {
116889857Sobrien      if (fill != NULL)
116989857Sobrien	while (len-- > 0)
117089857Sobrien	  if (*fill++ != '\0')
117189857Sobrien	    {
117289857Sobrien	      as_warn (_("ignoring fill value in absolute section"));
117389857Sobrien	      break;
117489857Sobrien	    }
117589857Sobrien      fill = NULL;
117689857Sobrien      len = 0;
117789857Sobrien    }
117889857Sobrien
117933965Sjdp#ifdef md_do_align
118033965Sjdp  md_do_align (n, fill, len, max, just_record_alignment);
118133965Sjdp#endif
118233965Sjdp
118377298Sobrien  /* Only make a frag if we HAVE to...  */
118433965Sjdp  if (n != 0 && !need_pass_2)
118533965Sjdp    {
118677298Sobrien      if (fill == NULL)
118777298Sobrien	{
118877298Sobrien	  if (subseg_text_p (now_seg))
118977298Sobrien	    frag_align_code (n, max);
119077298Sobrien	  else
119177298Sobrien	    frag_align (n, 0, max);
119277298Sobrien	}
119377298Sobrien      else if (len <= 1)
119433965Sjdp	frag_align (n, *fill, max);
119533965Sjdp      else
119633965Sjdp	frag_align_pattern (n, fill, len, max);
119733965Sjdp    }
119833965Sjdp
119933965Sjdp#ifdef md_do_align
120033965Sjdp just_record_alignment:
120133965Sjdp#endif
120233965Sjdp
120360484Sobrien  record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
120433965Sjdp}
120533965Sjdp
120633965Sjdp/* Handle the .align pseudo-op.  A positive ARG is a default alignment
120733965Sjdp   (in bytes).  A negative ARG is the negative of the length of the
120833965Sjdp   fill pattern.  BYTES_P is non-zero if the alignment value should be
120933965Sjdp   interpreted as the byte boundary, rather than the power of 2.  */
121033965Sjdp
121133965Sjdpstatic void
121233965Sjdps_align (arg, bytes_p)
121333965Sjdp     int arg;
121433965Sjdp     int bytes_p;
121533965Sjdp{
121633965Sjdp  register unsigned int align;
121733965Sjdp  char *stop = NULL;
121833965Sjdp  char stopc;
121933965Sjdp  offsetT fill = 0;
122033965Sjdp  int max;
122133965Sjdp  int fill_p;
122233965Sjdp
122333965Sjdp  if (flag_mri)
122433965Sjdp    stop = mri_comment_field (&stopc);
122533965Sjdp
122633965Sjdp  if (is_end_of_line[(unsigned char) *input_line_pointer])
122733965Sjdp    {
122833965Sjdp      if (arg < 0)
122933965Sjdp	align = 0;
123033965Sjdp      else
123177298Sobrien	align = arg;	/* Default value from pseudo-op table.  */
123233965Sjdp    }
123333965Sjdp  else
123433965Sjdp    {
123533965Sjdp      align = get_absolute_expression ();
123633965Sjdp      SKIP_WHITESPACE ();
123733965Sjdp    }
123833965Sjdp
123933965Sjdp  if (bytes_p)
124033965Sjdp    {
124133965Sjdp      /* Convert to a power of 2.  */
124233965Sjdp      if (align != 0)
124333965Sjdp	{
124433965Sjdp	  unsigned int i;
124533965Sjdp
124633965Sjdp	  for (i = 0; (align & 1) == 0; align >>= 1, ++i)
124733965Sjdp	    ;
124833965Sjdp	  if (align != 1)
124989857Sobrien	    as_bad (_("alignment not a power of 2"));
125077298Sobrien
125133965Sjdp	  align = i;
125233965Sjdp	}
125333965Sjdp    }
125433965Sjdp
125533965Sjdp  if (align > 15)
125633965Sjdp    {
125733965Sjdp      align = 15;
125889857Sobrien      as_warn (_("alignment too large: %u assumed"), align);
125933965Sjdp    }
126033965Sjdp
126133965Sjdp  if (*input_line_pointer != ',')
126233965Sjdp    {
126333965Sjdp      fill_p = 0;
126433965Sjdp      max = 0;
126533965Sjdp    }
126633965Sjdp  else
126733965Sjdp    {
126833965Sjdp      ++input_line_pointer;
126933965Sjdp      if (*input_line_pointer == ',')
127033965Sjdp	fill_p = 0;
127133965Sjdp      else
127233965Sjdp	{
127333965Sjdp	  fill = get_absolute_expression ();
127433965Sjdp	  SKIP_WHITESPACE ();
127533965Sjdp	  fill_p = 1;
127633965Sjdp	}
127733965Sjdp
127833965Sjdp      if (*input_line_pointer != ',')
127933965Sjdp	max = 0;
128033965Sjdp      else
128133965Sjdp	{
128233965Sjdp	  ++input_line_pointer;
128333965Sjdp	  max = get_absolute_expression ();
128433965Sjdp	}
128533965Sjdp    }
128633965Sjdp
128777298Sobrien  if (!fill_p)
128833965Sjdp    {
128933965Sjdp      if (arg < 0)
129060484Sobrien	as_warn (_("expected fill pattern missing"));
129133965Sjdp      do_align (align, (char *) NULL, 0, max);
129233965Sjdp    }
129333965Sjdp  else
129433965Sjdp    {
129533965Sjdp      int fill_len;
129633965Sjdp
129733965Sjdp      if (arg >= 0)
129833965Sjdp	fill_len = 1;
129933965Sjdp      else
130077298Sobrien	fill_len = -arg;
130133965Sjdp      if (fill_len <= 1)
130233965Sjdp	{
130333965Sjdp	  char fill_char;
130433965Sjdp
130533965Sjdp	  fill_char = fill;
130633965Sjdp	  do_align (align, &fill_char, fill_len, max);
130733965Sjdp	}
130833965Sjdp      else
130933965Sjdp	{
131033965Sjdp	  char ab[16];
131133965Sjdp
131238889Sjdp	  if ((size_t) fill_len > sizeof ab)
131333965Sjdp	    abort ();
131433965Sjdp	  md_number_to_chars (ab, fill, fill_len);
131533965Sjdp	  do_align (align, ab, fill_len, max);
131633965Sjdp	}
131733965Sjdp    }
131833965Sjdp
131960484Sobrien  demand_empty_rest_of_line ();
132060484Sobrien
132133965Sjdp  if (flag_mri)
132233965Sjdp    mri_comment_end (stop, stopc);
132333965Sjdp}
132433965Sjdp
132533965Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means
132633965Sjdp   align to a 4 byte boundary.  */
132733965Sjdp
132877298Sobrienvoid
132933965Sjdps_align_bytes (arg)
133033965Sjdp     int arg;
133133965Sjdp{
133233965Sjdp  s_align (arg, 1);
133333965Sjdp}
133433965Sjdp
133538889Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means align
133633965Sjdp   to a 2**4 boundary.  */
133733965Sjdp
133877298Sobrienvoid
133933965Sjdps_align_ptwo (arg)
134033965Sjdp     int arg;
134133965Sjdp{
134233965Sjdp  s_align (arg, 0);
134333965Sjdp}
134433965Sjdp
134577298Sobrienvoid
134633965Sjdps_comm (ignore)
134760484Sobrien     int ignore ATTRIBUTE_UNUSED;
134833965Sjdp{
134933965Sjdp  register char *name;
135033965Sjdp  register char c;
135133965Sjdp  register char *p;
135233965Sjdp  offsetT temp;
135333965Sjdp  register symbolS *symbolP;
135433965Sjdp  char *stop = NULL;
135533965Sjdp  char stopc;
135633965Sjdp
135733965Sjdp  if (flag_mri)
135833965Sjdp    stop = mri_comment_field (&stopc);
135933965Sjdp
136033965Sjdp  name = input_line_pointer;
136133965Sjdp  c = get_symbol_end ();
136277298Sobrien  /* Just after name is now '\0'.  */
136333965Sjdp  p = input_line_pointer;
136433965Sjdp  *p = c;
136589857Sobrien
136689857Sobrien  if (name == p)
136789857Sobrien    {
136889857Sobrien      as_bad (_("expected symbol name"));
136989857Sobrien      discard_rest_of_line ();
137089857Sobrien      return;
137189857Sobrien    }
137289857Sobrien
137333965Sjdp  SKIP_WHITESPACE ();
137477298Sobrien
137533965Sjdp  if (*input_line_pointer != ',')
137633965Sjdp    {
137789857Sobrien      *p = 0;
137889857Sobrien      as_bad (_("expected comma after \"%s\""), name);
137989857Sobrien      *p = c;
138060484Sobrien      ignore_rest_of_line ();
138133965Sjdp      if (flag_mri)
138233965Sjdp	mri_comment_end (stop, stopc);
138333965Sjdp      return;
138433965Sjdp    }
138577298Sobrien
138633965Sjdp  input_line_pointer++;		/* skip ',' */
138777298Sobrien
138833965Sjdp  if ((temp = get_absolute_expression ()) < 0)
138933965Sjdp    {
139089857Sobrien      as_warn (_(".COMMon length (%ld) < 0 ignored"), (long) temp);
139160484Sobrien      ignore_rest_of_line ();
139233965Sjdp      if (flag_mri)
139333965Sjdp	mri_comment_end (stop, stopc);
139433965Sjdp      return;
139533965Sjdp    }
139677298Sobrien
139733965Sjdp  *p = 0;
139833965Sjdp  symbolP = symbol_find_or_make (name);
139933965Sjdp  *p = c;
140077298Sobrien
140177298Sobrien  if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP))
140233965Sjdp    {
140389857Sobrien      as_bad (_("symbol `%s' is already defined"),
140433965Sjdp	      S_GET_NAME (symbolP));
140560484Sobrien      ignore_rest_of_line ();
140633965Sjdp      if (flag_mri)
140733965Sjdp	mri_comment_end (stop, stopc);
140833965Sjdp      return;
140933965Sjdp    }
141077298Sobrien
141133965Sjdp  if (S_GET_VALUE (symbolP))
141233965Sjdp    {
141333965Sjdp      if (S_GET_VALUE (symbolP) != (valueT) temp)
141489857Sobrien	as_bad (_("length of .comm \"%s\" is already %ld; not changing to %ld"),
141533965Sjdp		S_GET_NAME (symbolP),
141633965Sjdp		(long) S_GET_VALUE (symbolP),
141733965Sjdp		(long) temp);
141833965Sjdp    }
141933965Sjdp  else
142033965Sjdp    {
142133965Sjdp      S_SET_VALUE (symbolP, (valueT) temp);
142233965Sjdp      S_SET_EXTERNAL (symbolP);
142333965Sjdp    }
142433965Sjdp#ifdef OBJ_VMS
142533965Sjdp  {
142633965Sjdp    extern int flag_one;
142777298Sobrien    if (!temp || !flag_one)
142833965Sjdp      S_GET_OTHER(symbolP) = const_flag;
142933965Sjdp  }
143033965Sjdp#endif /* not OBJ_VMS */
143133965Sjdp  know (symbolP->sy_frag == &zero_address_frag);
143233965Sjdp
143360484Sobrien  demand_empty_rest_of_line ();
143460484Sobrien
143533965Sjdp  if (flag_mri)
143633965Sjdp    mri_comment_end (stop, stopc);
143733965Sjdp}				/* s_comm() */
143833965Sjdp
143933965Sjdp/* The MRI COMMON pseudo-op.  We handle this by creating a common
144033965Sjdp   symbol with the appropriate name.  We make s_space do the right
144133965Sjdp   thing by increasing the size.  */
144233965Sjdp
144333965Sjdpvoid
144433965Sjdps_mri_common (small)
144560484Sobrien     int small ATTRIBUTE_UNUSED;
144633965Sjdp{
144733965Sjdp  char *name;
144833965Sjdp  char c;
144933965Sjdp  char *alc = NULL;
145033965Sjdp  symbolS *sym;
145133965Sjdp  offsetT align;
145233965Sjdp  char *stop = NULL;
145333965Sjdp  char stopc;
145433965Sjdp
145577298Sobrien  if (!flag_mri)
145633965Sjdp    {
145733965Sjdp      s_comm (0);
145833965Sjdp      return;
145933965Sjdp    }
146033965Sjdp
146133965Sjdp  stop = mri_comment_field (&stopc);
146233965Sjdp
146333965Sjdp  SKIP_WHITESPACE ();
146433965Sjdp
146533965Sjdp  name = input_line_pointer;
146689857Sobrien  if (!ISDIGIT (*name))
146733965Sjdp    c = get_symbol_end ();
146833965Sjdp  else
146933965Sjdp    {
147033965Sjdp      do
147133965Sjdp	{
147233965Sjdp	  ++input_line_pointer;
147333965Sjdp	}
147489857Sobrien      while (ISDIGIT (*input_line_pointer));
147577298Sobrien
147633965Sjdp      c = *input_line_pointer;
147733965Sjdp      *input_line_pointer = '\0';
147833965Sjdp
147933965Sjdp      if (line_label != NULL)
148033965Sjdp	{
148133965Sjdp	  alc = (char *) xmalloc (strlen (S_GET_NAME (line_label))
148233965Sjdp				  + (input_line_pointer - name)
148333965Sjdp				  + 1);
148433965Sjdp	  sprintf (alc, "%s%s", name, S_GET_NAME (line_label));
148533965Sjdp	  name = alc;
148633965Sjdp	}
148733965Sjdp    }
148833965Sjdp
148933965Sjdp  sym = symbol_find_or_make (name);
149033965Sjdp  *input_line_pointer = c;
149133965Sjdp  if (alc != NULL)
149233965Sjdp    free (alc);
149333965Sjdp
149433965Sjdp  if (*input_line_pointer != ',')
149533965Sjdp    align = 0;
149633965Sjdp  else
149733965Sjdp    {
149833965Sjdp      ++input_line_pointer;
149933965Sjdp      align = get_absolute_expression ();
150033965Sjdp    }
150133965Sjdp
150277298Sobrien  if (S_IS_DEFINED (sym) && !S_IS_COMMON (sym))
150333965Sjdp    {
150489857Sobrien      as_bad (_("symbol `%s' is already defined"), S_GET_NAME (sym));
150560484Sobrien      ignore_rest_of_line ();
150633965Sjdp      mri_comment_end (stop, stopc);
150733965Sjdp      return;
150833965Sjdp    }
150933965Sjdp
151033965Sjdp  S_SET_EXTERNAL (sym);
151133965Sjdp  mri_common_symbol = sym;
151233965Sjdp
151333965Sjdp#ifdef S_SET_ALIGN
151433965Sjdp  if (align != 0)
151533965Sjdp    S_SET_ALIGN (sym, align);
151633965Sjdp#endif
151733965Sjdp
151833965Sjdp  if (line_label != NULL)
151933965Sjdp    {
152060484Sobrien      expressionS exp;
152160484Sobrien      exp.X_op = O_symbol;
152260484Sobrien      exp.X_add_symbol = sym;
152360484Sobrien      exp.X_add_number = 0;
152460484Sobrien      symbol_set_value_expression (line_label, &exp);
152560484Sobrien      symbol_set_frag (line_label, &zero_address_frag);
152633965Sjdp      S_SET_SEGMENT (line_label, expr_section);
152733965Sjdp    }
152833965Sjdp
152933965Sjdp  /* FIXME: We just ignore the small argument, which distinguishes
153033965Sjdp     COMMON and COMMON.S.  I don't know what we can do about it.  */
153133965Sjdp
153233965Sjdp  /* Ignore the type and hptype.  */
153333965Sjdp  if (*input_line_pointer == ',')
153433965Sjdp    input_line_pointer += 2;
153533965Sjdp  if (*input_line_pointer == ',')
153633965Sjdp    input_line_pointer += 2;
153733965Sjdp
153860484Sobrien  demand_empty_rest_of_line ();
153960484Sobrien
154033965Sjdp  mri_comment_end (stop, stopc);
154133965Sjdp}
154233965Sjdp
154333965Sjdpvoid
154433965Sjdps_data (ignore)
154560484Sobrien     int ignore ATTRIBUTE_UNUSED;
154633965Sjdp{
154733965Sjdp  segT section;
154833965Sjdp  register int temp;
154933965Sjdp
155033965Sjdp  temp = get_absolute_expression ();
155133965Sjdp  if (flag_readonly_data_in_text)
155233965Sjdp    {
155333965Sjdp      section = text_section;
155433965Sjdp      temp += 1000;
155533965Sjdp    }
155633965Sjdp  else
155733965Sjdp    section = data_section;
155833965Sjdp
155933965Sjdp  subseg_set (section, (subsegT) temp);
156033965Sjdp
156133965Sjdp#ifdef OBJ_VMS
156233965Sjdp  const_flag = 0;
156333965Sjdp#endif
156433965Sjdp  demand_empty_rest_of_line ();
156533965Sjdp}
156633965Sjdp
156733965Sjdp/* Handle the .appfile pseudo-op.  This is automatically generated by
156833965Sjdp   do_scrub_chars when a preprocessor # line comment is seen with a
156933965Sjdp   file name.  This default definition may be overridden by the object
157033965Sjdp   or CPU specific pseudo-ops.  This function is also the default
157133965Sjdp   definition for .file; the APPFILE argument is 1 for .appfile, 0 for
157233965Sjdp   .file.  */
157333965Sjdp
157477298Sobrienvoid
157533965Sjdps_app_file (appfile)
157633965Sjdp     int appfile;
157733965Sjdp{
157833965Sjdp  register char *s;
157933965Sjdp  int length;
158033965Sjdp
158177298Sobrien  /* Some assemblers tolerate immediately following '"'.  */
158233965Sjdp  if ((s = demand_copy_string (&length)) != 0)
158333965Sjdp    {
158433965Sjdp      /* If this is a fake .appfile, a fake newline was inserted into
158533965Sjdp	 the buffer.  Passing -2 to new_logical_line tells it to
158633965Sjdp	 account for it.  */
158738889Sjdp      int may_omit
158877298Sobrien	= (!new_logical_line (s, appfile ? -2 : -1) && appfile);
158933965Sjdp
159033965Sjdp      /* In MRI mode, the preprocessor may have inserted an extraneous
159133965Sjdp         backquote.  */
159233965Sjdp      if (flag_m68k_mri
159333965Sjdp	  && *input_line_pointer == '\''
159433965Sjdp	  && is_end_of_line[(unsigned char) input_line_pointer[1]])
159533965Sjdp	++input_line_pointer;
159633965Sjdp
159733965Sjdp      demand_empty_rest_of_line ();
159877298Sobrien      if (!may_omit)
159938889Sjdp	{
160033965Sjdp#ifdef LISTING
160138889Sjdp	  if (listing)
160238889Sjdp	    listing_source_file (s);
160333965Sjdp#endif
160438889Sjdp	  register_dependency (s);
160533965Sjdp#ifdef obj_app_file
160638889Sjdp	  obj_app_file (s);
160733965Sjdp#endif
160838889Sjdp	}
160938889Sjdp    }
161033965Sjdp}
161133965Sjdp
161233965Sjdp/* Handle the .appline pseudo-op.  This is automatically generated by
161333965Sjdp   do_scrub_chars when a preprocessor # line comment is seen.  This
161433965Sjdp   default definition may be overridden by the object or CPU specific
161533965Sjdp   pseudo-ops.  */
161633965Sjdp
161733965Sjdpvoid
161833965Sjdps_app_line (ignore)
161960484Sobrien     int ignore ATTRIBUTE_UNUSED;
162033965Sjdp{
162133965Sjdp  int l;
162233965Sjdp
162333965Sjdp  /* The given number is that of the next line.  */
162433965Sjdp  l = get_absolute_expression () - 1;
162533965Sjdp  if (l < 0)
162633965Sjdp    /* Some of the back ends can't deal with non-positive line numbers.
162733965Sjdp       Besides, it's silly.  */
162889857Sobrien    as_warn (_("line numbers must be positive; line number %d rejected"),
162977298Sobrien	     l + 1);
163033965Sjdp  else
163133965Sjdp    {
163233965Sjdp      new_logical_line ((char *) NULL, l);
163333965Sjdp#ifdef LISTING
163433965Sjdp      if (listing)
163533965Sjdp	listing_source_line (l);
163633965Sjdp#endif
163733965Sjdp    }
163833965Sjdp  demand_empty_rest_of_line ();
163933965Sjdp}
164033965Sjdp
164133965Sjdp/* Handle the .end pseudo-op.  Actually, the real work is done in
164233965Sjdp   read_a_source_file.  */
164333965Sjdp
164433965Sjdpvoid
164533965Sjdps_end (ignore)
164660484Sobrien     int ignore ATTRIBUTE_UNUSED;
164733965Sjdp{
164833965Sjdp  if (flag_mri)
164933965Sjdp    {
165033965Sjdp      /* The MRI assembler permits the start symbol to follow .end,
165133965Sjdp         but we don't support that.  */
165233965Sjdp      SKIP_WHITESPACE ();
165377298Sobrien      if (!is_end_of_line[(unsigned char) *input_line_pointer]
165433965Sjdp	  && *input_line_pointer != '*'
165533965Sjdp	  && *input_line_pointer != '!')
165660484Sobrien	as_warn (_("start address not supported"));
165733965Sjdp    }
165833965Sjdp}
165933965Sjdp
166033965Sjdp/* Handle the .err pseudo-op.  */
166133965Sjdp
166233965Sjdpvoid
166333965Sjdps_err (ignore)
166460484Sobrien     int ignore ATTRIBUTE_UNUSED;
166533965Sjdp{
166660484Sobrien  as_bad (_(".err encountered"));
166733965Sjdp  demand_empty_rest_of_line ();
166833965Sjdp}
166933965Sjdp
167033965Sjdp/* Handle the MRI fail pseudo-op.  */
167133965Sjdp
167233965Sjdpvoid
167333965Sjdps_fail (ignore)
167460484Sobrien     int ignore ATTRIBUTE_UNUSED;
167533965Sjdp{
167633965Sjdp  offsetT temp;
167733965Sjdp  char *stop = NULL;
167833965Sjdp  char stopc;
167933965Sjdp
168033965Sjdp  if (flag_mri)
168133965Sjdp    stop = mri_comment_field (&stopc);
168233965Sjdp
168333965Sjdp  temp = get_absolute_expression ();
168433965Sjdp  if (temp >= 500)
168560484Sobrien    as_warn (_(".fail %ld encountered"), (long) temp);
168633965Sjdp  else
168760484Sobrien    as_bad (_(".fail %ld encountered"), (long) temp);
168833965Sjdp
168960484Sobrien  demand_empty_rest_of_line ();
169060484Sobrien
169133965Sjdp  if (flag_mri)
169233965Sjdp    mri_comment_end (stop, stopc);
169333965Sjdp}
169433965Sjdp
169577298Sobrienvoid
169633965Sjdps_fill (ignore)
169760484Sobrien     int ignore ATTRIBUTE_UNUSED;
169833965Sjdp{
169938889Sjdp  expressionS rep_exp;
170038889Sjdp  long size = 1;
170138889Sjdp  register long fill = 0;
170233965Sjdp  char *p;
170333965Sjdp
170433965Sjdp#ifdef md_flush_pending_output
170533965Sjdp  md_flush_pending_output ();
170633965Sjdp#endif
170733965Sjdp
170838889Sjdp  get_known_segmented_expression (&rep_exp);
170933965Sjdp  if (*input_line_pointer == ',')
171033965Sjdp    {
171133965Sjdp      input_line_pointer++;
171238889Sjdp      size = get_absolute_expression ();
171333965Sjdp      if (*input_line_pointer == ',')
171433965Sjdp	{
171533965Sjdp	  input_line_pointer++;
171638889Sjdp	  fill = get_absolute_expression ();
171733965Sjdp	}
171833965Sjdp    }
171938889Sjdp
172033965Sjdp  /* This is to be compatible with BSD 4.2 AS, not for any rational reason.  */
172133965Sjdp#define BSD_FILL_SIZE_CROCK_8 (8)
172238889Sjdp  if (size > BSD_FILL_SIZE_CROCK_8)
172333965Sjdp    {
172489857Sobrien      as_warn (_(".fill size clamped to %d"), BSD_FILL_SIZE_CROCK_8);
172538889Sjdp      size = BSD_FILL_SIZE_CROCK_8;
172633965Sjdp    }
172738889Sjdp  if (size < 0)
172833965Sjdp    {
172989857Sobrien      as_warn (_("size negative; .fill ignored"));
173038889Sjdp      size = 0;
173133965Sjdp    }
173238889Sjdp  else if (rep_exp.X_op == O_constant && rep_exp.X_add_number <= 0)
173333965Sjdp    {
173438889Sjdp      if (rep_exp.X_add_number < 0)
173589857Sobrien	as_warn (_("repeat < 0; .fill ignored"));
173638889Sjdp      size = 0;
173733965Sjdp    }
173833965Sjdp
173938889Sjdp  if (size && !need_pass_2)
174033965Sjdp    {
174138889Sjdp      if (rep_exp.X_op == O_constant)
174238889Sjdp	{
174338889Sjdp	  p = frag_var (rs_fill, (int) size, (int) size,
174438889Sjdp			(relax_substateT) 0, (symbolS *) 0,
174538889Sjdp			(offsetT) rep_exp.X_add_number,
174638889Sjdp			(char *) 0);
174738889Sjdp	}
174838889Sjdp      else
174938889Sjdp	{
175038889Sjdp	  /* We don't have a constant repeat count, so we can't use
175138889Sjdp	     rs_fill.  We can get the same results out of rs_space,
175238889Sjdp	     but its argument is in bytes, so we must multiply the
175338889Sjdp	     repeat count by size.  */
175438889Sjdp
175538889Sjdp	  symbolS *rep_sym;
175638889Sjdp	  rep_sym = make_expr_symbol (&rep_exp);
175738889Sjdp	  if (size != 1)
175838889Sjdp	    {
175938889Sjdp	      expressionS size_exp;
176038889Sjdp	      size_exp.X_op = O_constant;
176138889Sjdp	      size_exp.X_add_number = size;
176238889Sjdp
176338889Sjdp	      rep_exp.X_op = O_multiply;
176438889Sjdp	      rep_exp.X_add_symbol = rep_sym;
176538889Sjdp	      rep_exp.X_op_symbol = make_expr_symbol (&size_exp);
176638889Sjdp	      rep_exp.X_add_number = 0;
176738889Sjdp	      rep_sym = make_expr_symbol (&rep_exp);
176838889Sjdp	    }
176938889Sjdp
177038889Sjdp	  p = frag_var (rs_space, (int) size, (int) size,
177138889Sjdp			(relax_substateT) 0, rep_sym, (offsetT) 0, (char *) 0);
177238889Sjdp	}
177377298Sobrien
177438889Sjdp      memset (p, 0, (unsigned int) size);
177577298Sobrien
177633965Sjdp      /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX
177789857Sobrien         flavoured AS.  The following bizarre behaviour is to be
177877298Sobrien         compatible with above.  I guess they tried to take up to 8
177977298Sobrien         bytes from a 4-byte expression and they forgot to sign
178089857Sobrien         extend.  */
178133965Sjdp#define BSD_FILL_SIZE_CROCK_4 (4)
178238889Sjdp      md_number_to_chars (p, (valueT) fill,
178338889Sjdp			  (size > BSD_FILL_SIZE_CROCK_4
178433965Sjdp			   ? BSD_FILL_SIZE_CROCK_4
178538889Sjdp			   : (int) size));
178633965Sjdp      /* Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes)
178777298Sobrien         but emits no error message because it seems a legal thing to do.
178877298Sobrien         It is a degenerate case of .fill but could be emitted by a
178977298Sobrien	 compiler.  */
179033965Sjdp    }
179133965Sjdp  demand_empty_rest_of_line ();
179233965Sjdp}
179333965Sjdp
179477298Sobrienvoid
179533965Sjdps_globl (ignore)
179660484Sobrien     int ignore ATTRIBUTE_UNUSED;
179733965Sjdp{
179833965Sjdp  char *name;
179933965Sjdp  int c;
180033965Sjdp  symbolS *symbolP;
180133965Sjdp  char *stop = NULL;
180233965Sjdp  char stopc;
180333965Sjdp
180433965Sjdp  if (flag_mri)
180533965Sjdp    stop = mri_comment_field (&stopc);
180633965Sjdp
180733965Sjdp  do
180833965Sjdp    {
180933965Sjdp      name = input_line_pointer;
181033965Sjdp      c = get_symbol_end ();
181133965Sjdp      symbolP = symbol_find_or_make (name);
181260484Sobrien      S_SET_EXTERNAL (symbolP);
181360484Sobrien
181433965Sjdp      *input_line_pointer = c;
181533965Sjdp      SKIP_WHITESPACE ();
181660484Sobrien      c = *input_line_pointer;
181733965Sjdp      if (c == ',')
181833965Sjdp	{
181933965Sjdp	  input_line_pointer++;
182033965Sjdp	  SKIP_WHITESPACE ();
182189857Sobrien	  if (is_end_of_line[(unsigned char) *input_line_pointer])
182233965Sjdp	    c = '\n';
182333965Sjdp	}
182433965Sjdp    }
182533965Sjdp  while (c == ',');
182633965Sjdp
182760484Sobrien  demand_empty_rest_of_line ();
182860484Sobrien
182933965Sjdp  if (flag_mri)
183033965Sjdp    mri_comment_end (stop, stopc);
183133965Sjdp}
183233965Sjdp
183333965Sjdp/* Handle the MRI IRP and IRPC pseudo-ops.  */
183433965Sjdp
183533965Sjdpvoid
183633965Sjdps_irp (irpc)
183733965Sjdp     int irpc;
183833965Sjdp{
183933965Sjdp  char *file;
184033965Sjdp  unsigned int line;
184133965Sjdp  sb s;
184233965Sjdp  const char *err;
184333965Sjdp  sb out;
184433965Sjdp
184533965Sjdp  as_where (&file, &line);
184633965Sjdp
184733965Sjdp  sb_new (&s);
184877298Sobrien  while (!is_end_of_line[(unsigned char) *input_line_pointer])
184933965Sjdp    sb_add_char (&s, *input_line_pointer++);
185033965Sjdp
185133965Sjdp  sb_new (&out);
185233965Sjdp
185333965Sjdp  err = expand_irp (irpc, 0, &s, &out, get_line_sb, '\0');
185433965Sjdp  if (err != NULL)
185533965Sjdp    as_bad_where (file, line, "%s", err);
185633965Sjdp
185733965Sjdp  sb_kill (&s);
185833965Sjdp
185960484Sobrien  input_scrub_include_sb (&out, input_line_pointer, 1);
186033965Sjdp  sb_kill (&out);
186133965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
186233965Sjdp}
186333965Sjdp
186433965Sjdp/* Handle the .linkonce pseudo-op.  This tells the assembler to mark
186533965Sjdp   the section to only be linked once.  However, this is not supported
186633965Sjdp   by most object file formats.  This takes an optional argument,
186733965Sjdp   which is what to do about duplicates.  */
186833965Sjdp
186933965Sjdpvoid
187033965Sjdps_linkonce (ignore)
187160484Sobrien     int ignore ATTRIBUTE_UNUSED;
187233965Sjdp{
187333965Sjdp  enum linkonce_type type;
187433965Sjdp
187533965Sjdp  SKIP_WHITESPACE ();
187633965Sjdp
187733965Sjdp  type = LINKONCE_DISCARD;
187833965Sjdp
187977298Sobrien  if (!is_end_of_line[(unsigned char) *input_line_pointer])
188033965Sjdp    {
188133965Sjdp      char *s;
188233965Sjdp      char c;
188333965Sjdp
188433965Sjdp      s = input_line_pointer;
188533965Sjdp      c = get_symbol_end ();
188633965Sjdp      if (strcasecmp (s, "discard") == 0)
188733965Sjdp	type = LINKONCE_DISCARD;
188833965Sjdp      else if (strcasecmp (s, "one_only") == 0)
188933965Sjdp	type = LINKONCE_ONE_ONLY;
189033965Sjdp      else if (strcasecmp (s, "same_size") == 0)
189133965Sjdp	type = LINKONCE_SAME_SIZE;
189233965Sjdp      else if (strcasecmp (s, "same_contents") == 0)
189333965Sjdp	type = LINKONCE_SAME_CONTENTS;
189433965Sjdp      else
189560484Sobrien	as_warn (_("unrecognized .linkonce type `%s'"), s);
189633965Sjdp
189733965Sjdp      *input_line_pointer = c;
189833965Sjdp    }
189933965Sjdp
190033965Sjdp#ifdef obj_handle_link_once
190133965Sjdp  obj_handle_link_once (type);
190233965Sjdp#else /* ! defined (obj_handle_link_once) */
190333965Sjdp#ifdef BFD_ASSEMBLER
190433965Sjdp  {
190533965Sjdp    flagword flags;
190633965Sjdp
190733965Sjdp    if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0)
190860484Sobrien      as_warn (_(".linkonce is not supported for this object file format"));
190933965Sjdp
191033965Sjdp    flags = bfd_get_section_flags (stdoutput, now_seg);
191133965Sjdp    flags |= SEC_LINK_ONCE;
191233965Sjdp    switch (type)
191333965Sjdp      {
191433965Sjdp      default:
191533965Sjdp	abort ();
191633965Sjdp      case LINKONCE_DISCARD:
191733965Sjdp	flags |= SEC_LINK_DUPLICATES_DISCARD;
191833965Sjdp	break;
191933965Sjdp      case LINKONCE_ONE_ONLY:
192033965Sjdp	flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
192133965Sjdp	break;
192233965Sjdp      case LINKONCE_SAME_SIZE:
192333965Sjdp	flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
192433965Sjdp	break;
192533965Sjdp      case LINKONCE_SAME_CONTENTS:
192633965Sjdp	flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
192733965Sjdp	break;
192833965Sjdp      }
192977298Sobrien    if (!bfd_set_section_flags (stdoutput, now_seg, flags))
193060484Sobrien      as_bad (_("bfd_set_section_flags: %s"),
193133965Sjdp	      bfd_errmsg (bfd_get_error ()));
193233965Sjdp  }
193333965Sjdp#else /* ! defined (BFD_ASSEMBLER) */
193460484Sobrien  as_warn (_(".linkonce is not supported for this object file format"));
193533965Sjdp#endif /* ! defined (BFD_ASSEMBLER) */
193633965Sjdp#endif /* ! defined (obj_handle_link_once) */
193733965Sjdp
193833965Sjdp  demand_empty_rest_of_line ();
193933965Sjdp}
194033965Sjdp
194177298Sobrienstatic void
194238889Sjdps_lcomm_internal (needs_align, bytes_p)
194333965Sjdp     /* 1 if this was a ".bss" directive, which may require a 3rd argument
194477298Sobrien	(alignment); 0 if it was an ".lcomm" (2 args only).  */
194533965Sjdp     int needs_align;
194638889Sjdp     /* 1 if the alignment value should be interpreted as the byte boundary,
194777298Sobrien	rather than the power of 2.  */
194838889Sjdp     int bytes_p;
194933965Sjdp{
195033965Sjdp  register char *name;
195133965Sjdp  register char c;
195233965Sjdp  register char *p;
195333965Sjdp  register int temp;
195433965Sjdp  register symbolS *symbolP;
195533965Sjdp  segT current_seg = now_seg;
195633965Sjdp  subsegT current_subseg = now_subseg;
195733965Sjdp  const int max_alignment = 15;
195833965Sjdp  int align = 0;
195933965Sjdp  segT bss_seg = bss_section;
196033965Sjdp
196133965Sjdp  name = input_line_pointer;
196233965Sjdp  c = get_symbol_end ();
196333965Sjdp  p = input_line_pointer;
196433965Sjdp  *p = c;
196589857Sobrien
196689857Sobrien  if (name == p)
196789857Sobrien    {
196889857Sobrien      as_bad (_("expected symbol name"));
196989857Sobrien      discard_rest_of_line ();
197089857Sobrien      return;
197189857Sobrien    }
197289857Sobrien
197333965Sjdp  SKIP_WHITESPACE ();
197433965Sjdp
197533965Sjdp  /* Accept an optional comma after the name.  The comma used to be
197633965Sjdp     required, but Irix 5 cc does not generate it.  */
197733965Sjdp  if (*input_line_pointer == ',')
197833965Sjdp    {
197933965Sjdp      ++input_line_pointer;
198033965Sjdp      SKIP_WHITESPACE ();
198133965Sjdp    }
198233965Sjdp
198389857Sobrien  if (is_end_of_line[(unsigned char) *input_line_pointer])
198433965Sjdp    {
198589857Sobrien      as_bad (_("missing size expression"));
198633965Sjdp      return;
198733965Sjdp    }
198833965Sjdp
198933965Sjdp  if ((temp = get_absolute_expression ()) < 0)
199033965Sjdp    {
199189857Sobrien      as_warn (_("BSS length (%d) < 0 ignored"), temp);
199233965Sjdp      ignore_rest_of_line ();
199333965Sjdp      return;
199433965Sjdp    }
199533965Sjdp
199633965Sjdp#if defined (TC_MIPS) || defined (TC_ALPHA)
199733965Sjdp  if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
199833965Sjdp      || OUTPUT_FLAVOR == bfd_target_elf_flavour)
199933965Sjdp    {
200033965Sjdp      /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss.  */
200189857Sobrien      if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
200233965Sjdp	{
200333965Sjdp	  bss_seg = subseg_new (".sbss", 1);
200433965Sjdp	  seg_info (bss_seg)->bss = 1;
200533965Sjdp#ifdef BFD_ASSEMBLER
200677298Sobrien	  if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
200760484Sobrien	    as_warn (_("error setting flags for \".sbss\": %s"),
200833965Sjdp		     bfd_errmsg (bfd_get_error ()));
200933965Sjdp#endif
201033965Sjdp	}
201133965Sjdp    }
201233965Sjdp#endif
201360484Sobrien
201477298Sobrien  if (!needs_align)
201577298Sobrien    {
201677298Sobrien      TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
201733965Sjdp
201877298Sobrien      /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
201977298Sobrien      if (align)
202077298Sobrien	record_alignment (bss_seg, align);
202177298Sobrien    }
202233965Sjdp
202333965Sjdp  if (needs_align)
202433965Sjdp    {
202533965Sjdp      align = 0;
202633965Sjdp      SKIP_WHITESPACE ();
202777298Sobrien
202833965Sjdp      if (*input_line_pointer != ',')
202933965Sjdp	{
203089857Sobrien	  as_bad (_("expected comma after size"));
203133965Sjdp	  ignore_rest_of_line ();
203233965Sjdp	  return;
203333965Sjdp	}
203477298Sobrien
203533965Sjdp      input_line_pointer++;
203633965Sjdp      SKIP_WHITESPACE ();
203777298Sobrien
203889857Sobrien      if (is_end_of_line[(unsigned char) *input_line_pointer])
203933965Sjdp	{
204089857Sobrien	  as_bad (_("missing alignment"));
204133965Sjdp	  return;
204233965Sjdp	}
204377298Sobrien
204433965Sjdp      align = get_absolute_expression ();
204577298Sobrien
204638889Sjdp      if (bytes_p)
204738889Sjdp	{
204838889Sjdp	  /* Convert to a power of 2.  */
204938889Sjdp	  if (align != 0)
205038889Sjdp	    {
205138889Sjdp	      unsigned int i;
205238889Sjdp
205338889Sjdp	      for (i = 0; (align & 1) == 0; align >>= 1, ++i)
205438889Sjdp		;
205538889Sjdp	      if (align != 1)
205689857Sobrien		as_bad (_("alignment not a power of 2"));
205738889Sjdp	      align = i;
205838889Sjdp	    }
205938889Sjdp	}
206077298Sobrien
206133965Sjdp      if (align > max_alignment)
206233965Sjdp	{
206333965Sjdp	  align = max_alignment;
206489857Sobrien	  as_warn (_("alignment too large; %d assumed"), align);
206533965Sjdp	}
206633965Sjdp      else if (align < 0)
206733965Sjdp	{
206833965Sjdp	  align = 0;
206989857Sobrien	  as_warn (_("alignment negative; 0 assumed"));
207033965Sjdp	}
207177298Sobrien
207233965Sjdp      record_alignment (bss_seg, align);
207377298Sobrien    }
207433965Sjdp  else
207533965Sjdp    {
207633965Sjdp      /* Assume some objects may require alignment on some systems.  */
207733965Sjdp#if defined (TC_ALPHA) && ! defined (VMS)
207833965Sjdp      if (temp > 1)
207933965Sjdp	{
208033965Sjdp	  align = ffs (temp) - 1;
208133965Sjdp	  if (temp % (1 << align))
208233965Sjdp	    abort ();
208333965Sjdp	}
208433965Sjdp#endif
208533965Sjdp    }
208633965Sjdp
208733965Sjdp  *p = 0;
208833965Sjdp  symbolP = symbol_find_or_make (name);
208933965Sjdp  *p = c;
209033965Sjdp
209133965Sjdp  if (
209260484Sobrien#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
209360484Sobrien     || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
209460484Sobrien#ifdef BFD_ASSEMBLER
209560484Sobrien      (OUTPUT_FLAVOR != bfd_target_aout_flavour
209660484Sobrien       || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
209760484Sobrien#else
209860484Sobrien      (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
209960484Sobrien#endif
210060484Sobrien#endif
210160484Sobrien      (S_GET_SEGMENT (symbolP) == bss_seg
210260484Sobrien       || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
210333965Sjdp    {
210433965Sjdp      char *pfrag;
210533965Sjdp
210633965Sjdp      subseg_set (bss_seg, 1);
210733965Sjdp
210833965Sjdp      if (align)
210933965Sjdp	frag_align (align, 0, 0);
211077298Sobrien
211177298Sobrien      /* Detach from old frag.  */
211233965Sjdp      if (S_GET_SEGMENT (symbolP) == bss_seg)
211360484Sobrien	symbol_get_frag (symbolP)->fr_symbol = NULL;
211433965Sjdp
211560484Sobrien      symbol_set_frag (symbolP, frag_now);
211677298Sobrien      pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
211733965Sjdp			(offsetT) temp, (char *) 0);
211833965Sjdp      *pfrag = 0;
211933965Sjdp
212033965Sjdp      S_SET_SEGMENT (symbolP, bss_seg);
212133965Sjdp
212233965Sjdp#ifdef OBJ_COFF
212333965Sjdp      /* The symbol may already have been created with a preceding
212433965Sjdp         ".globl" directive -- be careful not to step on storage class
212577298Sobrien         in that case.  Otherwise, set it to static.  */
212633965Sjdp      if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
212733965Sjdp	{
212833965Sjdp	  S_SET_STORAGE_CLASS (symbolP, C_STAT);
212933965Sjdp	}
213033965Sjdp#endif /* OBJ_COFF */
213133965Sjdp
213233965Sjdp#ifdef S_SET_SIZE
213333965Sjdp      S_SET_SIZE (symbolP, temp);
213433965Sjdp#endif
213533965Sjdp    }
213633965Sjdp  else
213789857Sobrien    as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
213833965Sjdp
213933965Sjdp  subseg_set (current_seg, current_subseg);
214033965Sjdp
214133965Sjdp  demand_empty_rest_of_line ();
214277298Sobrien}
214333965Sjdp
214438889Sjdpvoid
214538889Sjdps_lcomm (needs_align)
214638889Sjdp     int needs_align;
214738889Sjdp{
214838889Sjdp  s_lcomm_internal (needs_align, 0);
214938889Sjdp}
215038889Sjdp
215177298Sobrienvoid
215277298Sobriens_lcomm_bytes (needs_align)
215338889Sjdp     int needs_align;
215438889Sjdp{
215538889Sjdp  s_lcomm_internal (needs_align, 1);
215638889Sjdp}
215738889Sjdp
215877298Sobrienvoid
215933965Sjdps_lsym (ignore)
216060484Sobrien     int ignore ATTRIBUTE_UNUSED;
216133965Sjdp{
216233965Sjdp  register char *name;
216333965Sjdp  register char c;
216433965Sjdp  register char *p;
216533965Sjdp  expressionS exp;
216633965Sjdp  register symbolS *symbolP;
216733965Sjdp
216877298Sobrien  /* We permit ANY defined expression: BSD4.2 demands constants.  */
216933965Sjdp  name = input_line_pointer;
217033965Sjdp  c = get_symbol_end ();
217133965Sjdp  p = input_line_pointer;
217233965Sjdp  *p = c;
217389857Sobrien
217489857Sobrien  if (name == p)
217589857Sobrien    {
217689857Sobrien      as_bad (_("expected symbol name"));
217789857Sobrien      discard_rest_of_line ();
217889857Sobrien      return;
217989857Sobrien    }
218089857Sobrien
218133965Sjdp  SKIP_WHITESPACE ();
218277298Sobrien
218333965Sjdp  if (*input_line_pointer != ',')
218433965Sjdp    {
218533965Sjdp      *p = 0;
218689857Sobrien      as_bad (_("expected comma after \"%s\""), name);
218733965Sjdp      *p = c;
218833965Sjdp      ignore_rest_of_line ();
218933965Sjdp      return;
219033965Sjdp    }
219177298Sobrien
219233965Sjdp  input_line_pointer++;
219333965Sjdp  expression (&exp);
219477298Sobrien
219533965Sjdp  if (exp.X_op != O_constant
219633965Sjdp      && exp.X_op != O_register)
219733965Sjdp    {
219860484Sobrien      as_bad (_("bad expression"));
219933965Sjdp      ignore_rest_of_line ();
220033965Sjdp      return;
220133965Sjdp    }
220277298Sobrien
220333965Sjdp  *p = 0;
220433965Sjdp  symbolP = symbol_find_or_make (name);
220533965Sjdp
220633965Sjdp  /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0 &&
220733965Sjdp     symbolP->sy_desc == 0) out of this test because coff doesn't have
220833965Sjdp     those fields, and I can't see when they'd ever be tripped.  I
220933965Sjdp     don't think I understand why they were here so I may have
221033965Sjdp     introduced a bug. As recently as 1.37 didn't have this test
221177298Sobrien     anyway.  xoxorich.  */
221233965Sjdp
221333965Sjdp  if (S_GET_SEGMENT (symbolP) == undefined_section
221433965Sjdp      && S_GET_VALUE (symbolP) == 0)
221533965Sjdp    {
221633965Sjdp      /* The name might be an undefined .global symbol; be sure to
221777298Sobrien	 keep the "external" bit.  */
221833965Sjdp      S_SET_SEGMENT (symbolP,
221933965Sjdp		     (exp.X_op == O_constant
222033965Sjdp		      ? absolute_section
222133965Sjdp		      : reg_section));
222233965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
222333965Sjdp    }
222433965Sjdp  else
222533965Sjdp    {
222689857Sobrien      as_bad (_("symbol `%s' is already defined"), name);
222733965Sjdp    }
222877298Sobrien
222933965Sjdp  *p = c;
223033965Sjdp  demand_empty_rest_of_line ();
223177298Sobrien}
223233965Sjdp
223333965Sjdp/* Read a line into an sb.  */
223433965Sjdp
223533965Sjdpstatic int
223633965Sjdpget_line_sb (line)
223733965Sjdp     sb *line;
223833965Sjdp{
223933965Sjdp  char quote1, quote2, inquote;
224033965Sjdp
224133965Sjdp  if (input_line_pointer[-1] == '\n')
224233965Sjdp    bump_line_counters ();
224333965Sjdp
224433965Sjdp  if (input_line_pointer >= buffer_limit)
224533965Sjdp    {
224633965Sjdp      buffer_limit = input_scrub_next_buffer (&input_line_pointer);
224733965Sjdp      if (buffer_limit == 0)
224833965Sjdp	return 0;
224933965Sjdp    }
225033965Sjdp
225133965Sjdp  /* If app.c sets any other characters to LEX_IS_STRINGQUOTE, this
225233965Sjdp     code needs to be changed.  */
225377298Sobrien  if (!flag_m68k_mri)
225433965Sjdp    quote1 = '"';
225533965Sjdp  else
225633965Sjdp    quote1 = '\0';
225733965Sjdp
225833965Sjdp  quote2 = '\0';
225933965Sjdp  if (flag_m68k_mri)
226033965Sjdp    quote2 = '\'';
226133965Sjdp#ifdef LEX_IS_STRINGQUOTE
226233965Sjdp  quote2 = '\'';
226333965Sjdp#endif
226433965Sjdp
226533965Sjdp  inquote = '\0';
226677298Sobrien
226777298Sobrien  while (!is_end_of_line[(unsigned char) *input_line_pointer]
226833965Sjdp	 || (inquote != '\0' && *input_line_pointer != '\n'))
226933965Sjdp    {
227033965Sjdp      if (inquote == *input_line_pointer)
227133965Sjdp	inquote = '\0';
227233965Sjdp      else if (inquote == '\0')
227333965Sjdp	{
227433965Sjdp	  if (*input_line_pointer == quote1)
227533965Sjdp	    inquote = quote1;
227633965Sjdp	  else if (*input_line_pointer == quote2)
227733965Sjdp	    inquote = quote2;
227833965Sjdp	}
227977298Sobrien
228033965Sjdp      sb_add_char (line, *input_line_pointer++);
228133965Sjdp    }
228277298Sobrien
228338889Sjdp  while (input_line_pointer < buffer_limit
228438889Sjdp	 && is_end_of_line[(unsigned char) *input_line_pointer])
228533965Sjdp    {
228633965Sjdp      if (input_line_pointer[-1] == '\n')
228733965Sjdp	bump_line_counters ();
228833965Sjdp      ++input_line_pointer;
228933965Sjdp    }
229077298Sobrien
229133965Sjdp  return 1;
229233965Sjdp}
229333965Sjdp
229433965Sjdp/* Define a macro.  This is an interface to macro.c, which is shared
229533965Sjdp   between gas and gasp.  */
229633965Sjdp
229733965Sjdpvoid
229833965Sjdps_macro (ignore)
229960484Sobrien     int ignore ATTRIBUTE_UNUSED;
230033965Sjdp{
230133965Sjdp  char *file;
230233965Sjdp  unsigned int line;
230333965Sjdp  sb s;
230433965Sjdp  sb label;
230533965Sjdp  const char *err;
230633965Sjdp  const char *name;
230733965Sjdp
230833965Sjdp  as_where (&file, &line);
230933965Sjdp
231033965Sjdp  sb_new (&s);
231177298Sobrien  while (!is_end_of_line[(unsigned char) *input_line_pointer])
231233965Sjdp    sb_add_char (&s, *input_line_pointer++);
231333965Sjdp
231433965Sjdp  sb_new (&label);
231533965Sjdp  if (line_label != NULL)
231633965Sjdp    sb_add_string (&label, S_GET_NAME (line_label));
231733965Sjdp
231833965Sjdp  err = define_macro (0, &s, &label, get_line_sb, &name);
231933965Sjdp  if (err != NULL)
232033965Sjdp    as_bad_where (file, line, "%s", err);
232133965Sjdp  else
232233965Sjdp    {
232333965Sjdp      if (line_label != NULL)
232433965Sjdp	{
232533965Sjdp	  S_SET_SEGMENT (line_label, undefined_section);
232633965Sjdp	  S_SET_VALUE (line_label, 0);
232760484Sobrien	  symbol_set_frag (line_label, &zero_address_frag);
232833965Sjdp	}
232933965Sjdp
233060484Sobrien      if (((NO_PSEUDO_DOT || flag_m68k_mri)
233133965Sjdp	   && hash_find (po_hash, name) != NULL)
233277298Sobrien	  || (!flag_m68k_mri
233333965Sjdp	      && *name == '.'
233433965Sjdp	      && hash_find (po_hash, name + 1) != NULL))
233560484Sobrien	as_warn (_("attempt to redefine pseudo-op `%s' ignored"),
233633965Sjdp		 name);
233733965Sjdp    }
233833965Sjdp
233933965Sjdp  sb_kill (&s);
234033965Sjdp}
234133965Sjdp
234233965Sjdp/* Handle the .mexit pseudo-op, which immediately exits a macro
234333965Sjdp   expansion.  */
234433965Sjdp
234533965Sjdpvoid
234633965Sjdps_mexit (ignore)
234760484Sobrien     int ignore ATTRIBUTE_UNUSED;
234833965Sjdp{
234933965Sjdp  cond_exit_macro (macro_nest);
235033965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
235133965Sjdp}
235233965Sjdp
235333965Sjdp/* Switch in and out of MRI mode.  */
235433965Sjdp
235533965Sjdpvoid
235633965Sjdps_mri (ignore)
235760484Sobrien     int ignore ATTRIBUTE_UNUSED;
235833965Sjdp{
235933965Sjdp  int on, old_flag;
236033965Sjdp
236133965Sjdp  on = get_absolute_expression ();
236233965Sjdp  old_flag = flag_mri;
236333965Sjdp  if (on != 0)
236433965Sjdp    {
236533965Sjdp      flag_mri = 1;
236633965Sjdp#ifdef TC_M68K
236733965Sjdp      flag_m68k_mri = 1;
236833965Sjdp#endif
236960484Sobrien      macro_mri_mode (1);
237033965Sjdp    }
237133965Sjdp  else
237233965Sjdp    {
237333965Sjdp      flag_mri = 0;
237460484Sobrien#ifdef TC_M68K
237533965Sjdp      flag_m68k_mri = 0;
237660484Sobrien#endif
237760484Sobrien      macro_mri_mode (0);
237833965Sjdp    }
237933965Sjdp
238060484Sobrien  /* Operator precedence changes in m68k MRI mode, so we need to
238160484Sobrien     update the operator rankings.  */
238260484Sobrien  expr_set_precedence ();
238360484Sobrien
238433965Sjdp#ifdef MRI_MODE_CHANGE
238533965Sjdp  if (on != old_flag)
238633965Sjdp    MRI_MODE_CHANGE (on);
238733965Sjdp#endif
238833965Sjdp
238933965Sjdp  demand_empty_rest_of_line ();
239033965Sjdp}
239133965Sjdp
239233965Sjdp/* Handle changing the location counter.  */
239333965Sjdp
239433965Sjdpstatic void
239533965Sjdpdo_org (segment, exp, fill)
239633965Sjdp     segT segment;
239733965Sjdp     expressionS *exp;
239833965Sjdp     int fill;
239933965Sjdp{
240033965Sjdp  if (segment != now_seg && segment != absolute_section)
240189857Sobrien    as_bad (_("invalid segment \"%s\""), segment_name (segment));
240233965Sjdp
240333965Sjdp  if (now_seg == absolute_section)
240433965Sjdp    {
240533965Sjdp      if (fill != 0)
240660484Sobrien	as_warn (_("ignoring fill value in absolute section"));
240733965Sjdp      if (exp->X_op != O_constant)
240833965Sjdp	{
240960484Sobrien	  as_bad (_("only constant offsets supported in absolute section"));
241033965Sjdp	  exp->X_add_number = 0;
241133965Sjdp	}
241233965Sjdp      abs_section_offset = exp->X_add_number;
241333965Sjdp    }
241433965Sjdp  else
241533965Sjdp    {
241633965Sjdp      char *p;
241778828Sobrien      symbolS *sym = exp->X_add_symbol;
241878828Sobrien      offsetT off = exp->X_add_number * OCTETS_PER_BYTE;
241933965Sjdp
242078828Sobrien      if (exp->X_op != O_constant && exp->X_op != O_symbol)
242178828Sobrien	{
242278828Sobrien	  /* Handle complex expressions.  */
242378828Sobrien	  sym = make_expr_symbol (exp);
242478828Sobrien	  off = 0;
242578828Sobrien	}
242678828Sobrien
242778828Sobrien      p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0);
242833965Sjdp      *p = fill;
242933965Sjdp    }
243033965Sjdp}
243133965Sjdp
243277298Sobrienvoid
243333965Sjdps_org (ignore)
243460484Sobrien     int ignore ATTRIBUTE_UNUSED;
243533965Sjdp{
243633965Sjdp  register segT segment;
243733965Sjdp  expressionS exp;
243833965Sjdp  register long temp_fill;
243933965Sjdp
244060484Sobrien#ifdef md_flush_pending_output
244160484Sobrien  md_flush_pending_output ();
244260484Sobrien#endif
244360484Sobrien
244433965Sjdp  /* The m68k MRI assembler has a different meaning for .org.  It
244533965Sjdp     means to create an absolute section at a given address.  We can't
244633965Sjdp     support that--use a linker script instead.  */
244733965Sjdp  if (flag_m68k_mri)
244833965Sjdp    {
244960484Sobrien      as_bad (_("MRI style ORG pseudo-op not supported"));
245033965Sjdp      ignore_rest_of_line ();
245133965Sjdp      return;
245233965Sjdp    }
245333965Sjdp
245433965Sjdp  /* Don't believe the documentation of BSD 4.2 AS.  There is no such
245533965Sjdp     thing as a sub-segment-relative origin.  Any absolute origin is
245633965Sjdp     given a warning, then assumed to be segment-relative.  Any
245733965Sjdp     segmented origin expression ("foo+42") had better be in the right
245833965Sjdp     segment or the .org is ignored.
245933965Sjdp
246033965Sjdp     BSD 4.2 AS warns if you try to .org backwards. We cannot because
246133965Sjdp     we never know sub-segment sizes when we are reading code.  BSD
246233965Sjdp     will crash trying to emit negative numbers of filler bytes in
246333965Sjdp     certain .orgs. We don't crash, but see as-write for that code.
246433965Sjdp
246533965Sjdp     Don't make frag if need_pass_2==1.  */
246633965Sjdp  segment = get_known_segmented_expression (&exp);
246733965Sjdp  if (*input_line_pointer == ',')
246833965Sjdp    {
246933965Sjdp      input_line_pointer++;
247033965Sjdp      temp_fill = get_absolute_expression ();
247133965Sjdp    }
247233965Sjdp  else
247333965Sjdp    temp_fill = 0;
247433965Sjdp
247533965Sjdp  if (!need_pass_2)
247633965Sjdp    do_org (segment, &exp, temp_fill);
247733965Sjdp
247833965Sjdp  demand_empty_rest_of_line ();
247977298Sobrien}
248033965Sjdp
248133965Sjdp/* Handle parsing for the MRI SECT/SECTION pseudo-op.  This should be
248233965Sjdp   called by the obj-format routine which handles section changing
248333965Sjdp   when in MRI mode.  It will create a new section, and return it.  It
248433965Sjdp   will set *TYPE to the section type: one of 'C' (code), 'D' (data),
248533965Sjdp   'M' (mixed), or 'R' (romable).  If BFD_ASSEMBLER is defined, the
248633965Sjdp   flags will be set in the section.  */
248733965Sjdp
248833965Sjdpvoid
248933965Sjdps_mri_sect (type)
249060484Sobrien     char *type ATTRIBUTE_UNUSED;
249133965Sjdp{
249233965Sjdp#ifdef TC_M68K
249333965Sjdp
249433965Sjdp  char *name;
249533965Sjdp  char c;
249633965Sjdp  segT seg;
249733965Sjdp
249833965Sjdp  SKIP_WHITESPACE ();
249977298Sobrien
250033965Sjdp  name = input_line_pointer;
250189857Sobrien  if (!ISDIGIT (*name))
250233965Sjdp    c = get_symbol_end ();
250333965Sjdp  else
250433965Sjdp    {
250533965Sjdp      do
250633965Sjdp	{
250733965Sjdp	  ++input_line_pointer;
250833965Sjdp	}
250989857Sobrien      while (ISDIGIT (*input_line_pointer));
251077298Sobrien
251133965Sjdp      c = *input_line_pointer;
251233965Sjdp      *input_line_pointer = '\0';
251333965Sjdp    }
251433965Sjdp
251533965Sjdp  name = xstrdup (name);
251633965Sjdp
251733965Sjdp  *input_line_pointer = c;
251833965Sjdp
251933965Sjdp  seg = subseg_new (name, 0);
252033965Sjdp
252133965Sjdp  if (*input_line_pointer == ',')
252233965Sjdp    {
252333965Sjdp      int align;
252433965Sjdp
252533965Sjdp      ++input_line_pointer;
252633965Sjdp      align = get_absolute_expression ();
252733965Sjdp      record_alignment (seg, align);
252833965Sjdp    }
252933965Sjdp
253033965Sjdp  *type = 'C';
253133965Sjdp  if (*input_line_pointer == ',')
253233965Sjdp    {
253333965Sjdp      c = *++input_line_pointer;
253489857Sobrien      c = TOUPPER (c);
253533965Sjdp      if (c == 'C' || c == 'D' || c == 'M' || c == 'R')
253633965Sjdp	*type = c;
253733965Sjdp      else
253860484Sobrien	as_bad (_("unrecognized section type"));
253933965Sjdp      ++input_line_pointer;
254033965Sjdp
254133965Sjdp#ifdef BFD_ASSEMBLER
254233965Sjdp      {
254333965Sjdp	flagword flags;
254433965Sjdp
254533965Sjdp	flags = SEC_NO_FLAGS;
254633965Sjdp	if (*type == 'C')
254733965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE;
254833965Sjdp	else if (*type == 'D' || *type == 'M')
254933965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_DATA;
255033965Sjdp	else if (*type == 'R')
255133965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM;
255233965Sjdp	if (flags != SEC_NO_FLAGS)
255333965Sjdp	  {
255477298Sobrien	    if (!bfd_set_section_flags (stdoutput, seg, flags))
255560484Sobrien	      as_warn (_("error setting flags for \"%s\": %s"),
255633965Sjdp		       bfd_section_name (stdoutput, seg),
255733965Sjdp		       bfd_errmsg (bfd_get_error ()));
255833965Sjdp	  }
255933965Sjdp      }
256033965Sjdp#endif
256133965Sjdp    }
256233965Sjdp
256333965Sjdp  /* Ignore the HP type.  */
256433965Sjdp  if (*input_line_pointer == ',')
256533965Sjdp    input_line_pointer += 2;
256633965Sjdp
256733965Sjdp  demand_empty_rest_of_line ();
256833965Sjdp
256933965Sjdp#else /* ! TC_M68K */
257033965Sjdp#ifdef TC_I960
257133965Sjdp
257233965Sjdp  char *name;
257333965Sjdp  char c;
257433965Sjdp  segT seg;
257533965Sjdp
257633965Sjdp  SKIP_WHITESPACE ();
257733965Sjdp
257833965Sjdp  name = input_line_pointer;
257933965Sjdp  c = get_symbol_end ();
258033965Sjdp
258133965Sjdp  name = xstrdup (name);
258233965Sjdp
258333965Sjdp  *input_line_pointer = c;
258433965Sjdp
258533965Sjdp  seg = subseg_new (name, 0);
258633965Sjdp
258733965Sjdp  if (*input_line_pointer != ',')
258833965Sjdp    *type = 'C';
258933965Sjdp  else
259033965Sjdp    {
259133965Sjdp      char *sectype;
259233965Sjdp
259333965Sjdp      ++input_line_pointer;
259433965Sjdp      SKIP_WHITESPACE ();
259533965Sjdp      sectype = input_line_pointer;
259633965Sjdp      c = get_symbol_end ();
259733965Sjdp      if (*sectype == '\0')
259833965Sjdp	*type = 'C';
259933965Sjdp      else if (strcasecmp (sectype, "text") == 0)
260033965Sjdp	*type = 'C';
260133965Sjdp      else if (strcasecmp (sectype, "data") == 0)
260233965Sjdp	*type = 'D';
260333965Sjdp      else if (strcasecmp (sectype, "romdata") == 0)
260433965Sjdp	*type = 'R';
260533965Sjdp      else
260660484Sobrien	as_warn (_("unrecognized section type `%s'"), sectype);
260733965Sjdp      *input_line_pointer = c;
260833965Sjdp    }
260933965Sjdp
261033965Sjdp  if (*input_line_pointer == ',')
261133965Sjdp    {
261233965Sjdp      char *seccmd;
261333965Sjdp
261433965Sjdp      ++input_line_pointer;
261533965Sjdp      SKIP_WHITESPACE ();
261633965Sjdp      seccmd = input_line_pointer;
261733965Sjdp      c = get_symbol_end ();
261833965Sjdp      if (strcasecmp (seccmd, "absolute") == 0)
261933965Sjdp	{
262060484Sobrien	  as_bad (_("absolute sections are not supported"));
262133965Sjdp	  *input_line_pointer = c;
262233965Sjdp	  ignore_rest_of_line ();
262333965Sjdp	  return;
262433965Sjdp	}
262533965Sjdp      else if (strcasecmp (seccmd, "align") == 0)
262633965Sjdp	{
262733965Sjdp	  int align;
262833965Sjdp
262933965Sjdp	  *input_line_pointer = c;
263033965Sjdp	  align = get_absolute_expression ();
263133965Sjdp	  record_alignment (seg, align);
263233965Sjdp	}
263333965Sjdp      else
263433965Sjdp	{
263560484Sobrien	  as_warn (_("unrecognized section command `%s'"), seccmd);
263633965Sjdp	  *input_line_pointer = c;
263733965Sjdp	}
263833965Sjdp    }
263933965Sjdp
264077298Sobrien  demand_empty_rest_of_line ();
264133965Sjdp
264233965Sjdp#else /* ! TC_I960 */
264333965Sjdp  /* The MRI assembler seems to use different forms of .sect for
264433965Sjdp     different targets.  */
264560484Sobrien  as_bad ("MRI mode not supported for this target");
264660484Sobrien  ignore_rest_of_line ();
264733965Sjdp#endif /* ! TC_I960 */
264833965Sjdp#endif /* ! TC_M68K */
264933965Sjdp}
265033965Sjdp
265133965Sjdp/* Handle the .print pseudo-op.  */
265233965Sjdp
265333965Sjdpvoid
265433965Sjdps_print (ignore)
265560484Sobrien     int ignore ATTRIBUTE_UNUSED;
265633965Sjdp{
265733965Sjdp  char *s;
265833965Sjdp  int len;
265933965Sjdp
266033965Sjdp  s = demand_copy_C_string (&len);
266133965Sjdp  printf ("%s\n", s);
266233965Sjdp  demand_empty_rest_of_line ();
266333965Sjdp}
266433965Sjdp
266533965Sjdp/* Handle the .purgem pseudo-op.  */
266633965Sjdp
266733965Sjdpvoid
266833965Sjdps_purgem (ignore)
266960484Sobrien     int ignore ATTRIBUTE_UNUSED;
267033965Sjdp{
267133965Sjdp  if (is_it_end_of_statement ())
267233965Sjdp    {
267333965Sjdp      demand_empty_rest_of_line ();
267433965Sjdp      return;
267533965Sjdp    }
267633965Sjdp
267733965Sjdp  do
267833965Sjdp    {
267933965Sjdp      char *name;
268033965Sjdp      char c;
268133965Sjdp
268233965Sjdp      SKIP_WHITESPACE ();
268333965Sjdp      name = input_line_pointer;
268433965Sjdp      c = get_symbol_end ();
268533965Sjdp      delete_macro (name);
268633965Sjdp      *input_line_pointer = c;
268733965Sjdp      SKIP_WHITESPACE ();
268833965Sjdp    }
268933965Sjdp  while (*input_line_pointer++ == ',');
269033965Sjdp
269133965Sjdp  --input_line_pointer;
269233965Sjdp  demand_empty_rest_of_line ();
269333965Sjdp}
269433965Sjdp
269533965Sjdp/* Handle the .rept pseudo-op.  */
269633965Sjdp
269733965Sjdpvoid
269889857Sobriens_bad_endr (ignore)
269989857Sobrien     int ignore ATTRIBUTE_UNUSED;
270089857Sobrien{
270189857Sobrien  as_warn (_(".endr encountered without preceeding .rept, .irc, or .irp"));
270289857Sobrien  demand_empty_rest_of_line ();
270389857Sobrien}
270489857Sobrien
270589857Sobrien/* Handle the .rept pseudo-op.  */
270689857Sobrien
270789857Sobrienvoid
270833965Sjdps_rept (ignore)
270960484Sobrien     int ignore ATTRIBUTE_UNUSED;
271033965Sjdp{
271133965Sjdp  int count;
271260484Sobrien
271360484Sobrien  count = get_absolute_expression ();
271460484Sobrien
271577298Sobrien  do_repeat (count, "REPT", "ENDR");
271660484Sobrien}
271760484Sobrien
271860484Sobrien/* This function provides a generic repeat block implementation.   It allows
271977298Sobrien   different directives to be used as the start/end keys.  */
272060484Sobrien
272160484Sobrienvoid
272260484Sobriendo_repeat (count, start, end)
272377298Sobrien     int count;
272477298Sobrien     const char *start;
272577298Sobrien     const char *end;
272660484Sobrien{
272733965Sjdp  sb one;
272833965Sjdp  sb many;
272933965Sjdp
273033965Sjdp  sb_new (&one);
273177298Sobrien  if (!buffer_and_nest (start, end, &one, get_line_sb))
273233965Sjdp    {
273360484Sobrien      as_bad (_("%s without %s"), start, end);
273433965Sjdp      return;
273533965Sjdp    }
273633965Sjdp
273733965Sjdp  sb_new (&many);
273833965Sjdp  while (count-- > 0)
273933965Sjdp    sb_add_sb (&many, &one);
274033965Sjdp
274133965Sjdp  sb_kill (&one);
274233965Sjdp
274360484Sobrien  input_scrub_include_sb (&many, input_line_pointer, 1);
274433965Sjdp  sb_kill (&many);
274533965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
274633965Sjdp}
274733965Sjdp
274860484Sobrien/* Skip to end of current repeat loop; EXTRA indicates how many additional
274960484Sobrien   input buffers to skip.  Assumes that conditionals preceding the loop end
275077298Sobrien   are properly nested.
275160484Sobrien
275260484Sobrien   This function makes it easier to implement a premature "break" out of the
275360484Sobrien   loop.  The EXTRA arg accounts for other buffers we might have inserted,
275477298Sobrien   such as line substitutions.  */
275560484Sobrien
275660484Sobrienvoid
275760484Sobrienend_repeat (extra)
275877298Sobrien     int extra;
275960484Sobrien{
276060484Sobrien  cond_exit_macro (macro_nest);
276160484Sobrien  while (extra-- >= 0)
276260484Sobrien    buffer_limit = input_scrub_next_buffer (&input_line_pointer);
276360484Sobrien}
276460484Sobrien
276533965Sjdp/* Handle the .equ, .equiv and .set directives.  If EQUIV is 1, then
276633965Sjdp   this is .equiv, and it is an error if the symbol is already
276733965Sjdp   defined.  */
276833965Sjdp
276977298Sobrienvoid
277033965Sjdps_set (equiv)
277133965Sjdp     int equiv;
277233965Sjdp{
277333965Sjdp  register char *name;
277433965Sjdp  register char delim;
277533965Sjdp  register char *end_name;
277633965Sjdp  register symbolS *symbolP;
277733965Sjdp
277877298Sobrien  /* Especial apologies for the random logic:
277977298Sobrien     this just grew, and could be parsed much more simply!
278077298Sobrien     Dean in haste.  */
278133965Sjdp  name = input_line_pointer;
278233965Sjdp  delim = get_symbol_end ();
278333965Sjdp  end_name = input_line_pointer;
278433965Sjdp  *end_name = delim;
278589857Sobrien
278689857Sobrien  if (name == end_name)
278789857Sobrien    {
278889857Sobrien      as_bad (_("expected symbol name"));
278989857Sobrien      discard_rest_of_line ();
279089857Sobrien      return;
279189857Sobrien    }
279289857Sobrien
279333965Sjdp  SKIP_WHITESPACE ();
279433965Sjdp
279533965Sjdp  if (*input_line_pointer != ',')
279633965Sjdp    {
279733965Sjdp      *end_name = 0;
279889857Sobrien      as_bad (_("expected comma after \"%s\""), name);
279933965Sjdp      *end_name = delim;
280033965Sjdp      ignore_rest_of_line ();
280133965Sjdp      return;
280233965Sjdp    }
280333965Sjdp
280433965Sjdp  input_line_pointer++;
280533965Sjdp  *end_name = 0;
280633965Sjdp
280733965Sjdp  if (name[0] == '.' && name[1] == '\0')
280833965Sjdp    {
280977298Sobrien      /* Turn '. = mumble' into a .org mumble.  */
281033965Sjdp      register segT segment;
281133965Sjdp      expressionS exp;
281233965Sjdp
281333965Sjdp      segment = get_known_segmented_expression (&exp);
281433965Sjdp
281533965Sjdp      if (!need_pass_2)
281633965Sjdp	do_org (segment, &exp, 0);
281733965Sjdp
281833965Sjdp      *end_name = delim;
281933965Sjdp      return;
282033965Sjdp    }
282133965Sjdp
282233965Sjdp  if ((symbolP = symbol_find (name)) == NULL
282333965Sjdp      && (symbolP = md_undefined_symbol (name)) == NULL)
282433965Sjdp    {
282538889Sjdp#ifndef NO_LISTING
282638889Sjdp      /* When doing symbol listings, play games with dummy fragments living
282738889Sjdp	 outside the normal fragment chain to record the file and line info
282838889Sjdp         for this symbol.  */
282938889Sjdp      if (listing & LISTING_SYMBOLS)
283038889Sjdp	{
283138889Sjdp	  extern struct list_info_struct *listing_tail;
283277298Sobrien	  fragS *dummy_frag = (fragS *) xmalloc (sizeof (fragS));
283377298Sobrien	  memset (dummy_frag, 0, sizeof (fragS));
283438889Sjdp	  dummy_frag->fr_type = rs_fill;
283538889Sjdp	  dummy_frag->line = listing_tail;
283638889Sjdp	  symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
283738889Sjdp	  dummy_frag->fr_symbol = symbolP;
283838889Sjdp	}
283938889Sjdp      else
284038889Sjdp#endif
284177298Sobrien	symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
284277298Sobrien
284333965Sjdp#ifdef OBJ_COFF
284477298Sobrien      /* "set" symbols are local unless otherwise specified.  */
284533965Sjdp      SF_SET_LOCAL (symbolP);
284633965Sjdp#endif /* OBJ_COFF */
284777298Sobrien    }
284833965Sjdp
284933965Sjdp  symbol_table_insert (symbolP);
285033965Sjdp
285133965Sjdp  *end_name = delim;
285233965Sjdp
285333965Sjdp  if (equiv
285433965Sjdp      && S_IS_DEFINED (symbolP)
285533965Sjdp      && S_GET_SEGMENT (symbolP) != reg_section)
285689857Sobrien    as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
285733965Sjdp
285833965Sjdp  pseudo_set (symbolP);
285933965Sjdp  demand_empty_rest_of_line ();
286077298Sobrien}
286133965Sjdp
286277298Sobrienvoid
286333965Sjdps_space (mult)
286433965Sjdp     int mult;
286533965Sjdp{
286633965Sjdp  expressionS exp;
286733965Sjdp  expressionS val;
286833965Sjdp  char *p = 0;
286933965Sjdp  char *stop = NULL;
287033965Sjdp  char stopc;
287133965Sjdp  int bytes;
287233965Sjdp
287333965Sjdp#ifdef md_flush_pending_output
287433965Sjdp  md_flush_pending_output ();
287533965Sjdp#endif
287633965Sjdp
287733965Sjdp  if (flag_mri)
287833965Sjdp    stop = mri_comment_field (&stopc);
287933965Sjdp
288033965Sjdp  /* In m68k MRI mode, we need to align to a word boundary, unless
288133965Sjdp     this is ds.b.  */
288233965Sjdp  if (flag_m68k_mri && mult > 1)
288333965Sjdp    {
288433965Sjdp      if (now_seg == absolute_section)
288533965Sjdp	{
288633965Sjdp	  abs_section_offset += abs_section_offset & 1;
288733965Sjdp	  if (line_label != NULL)
288833965Sjdp	    S_SET_VALUE (line_label, abs_section_offset);
288933965Sjdp	}
289033965Sjdp      else if (mri_common_symbol != NULL)
289133965Sjdp	{
289233965Sjdp	  valueT val;
289333965Sjdp
289433965Sjdp	  val = S_GET_VALUE (mri_common_symbol);
289533965Sjdp	  if ((val & 1) != 0)
289633965Sjdp	    {
289733965Sjdp	      S_SET_VALUE (mri_common_symbol, val + 1);
289833965Sjdp	      if (line_label != NULL)
289933965Sjdp		{
290060484Sobrien		  expressionS *symexp;
290160484Sobrien
290260484Sobrien		  symexp = symbol_get_value_expression (line_label);
290360484Sobrien		  know (symexp->X_op == O_symbol);
290460484Sobrien		  know (symexp->X_add_symbol == mri_common_symbol);
290560484Sobrien		  symexp->X_add_number += 1;
290633965Sjdp		}
290733965Sjdp	    }
290833965Sjdp	}
290933965Sjdp      else
291033965Sjdp	{
291133965Sjdp	  do_align (1, (char *) NULL, 0, 0);
291233965Sjdp	  if (line_label != NULL)
291333965Sjdp	    {
291460484Sobrien	      symbol_set_frag (line_label, frag_now);
291533965Sjdp	      S_SET_VALUE (line_label, frag_now_fix ());
291633965Sjdp	    }
291733965Sjdp	}
291833965Sjdp    }
291933965Sjdp
292033965Sjdp  bytes = mult;
292133965Sjdp
292233965Sjdp  expression (&exp);
292333965Sjdp
292433965Sjdp  SKIP_WHITESPACE ();
292533965Sjdp  if (*input_line_pointer == ',')
292633965Sjdp    {
292733965Sjdp      ++input_line_pointer;
292833965Sjdp      expression (&val);
292933965Sjdp    }
293033965Sjdp  else
293133965Sjdp    {
293233965Sjdp      val.X_op = O_constant;
293333965Sjdp      val.X_add_number = 0;
293433965Sjdp    }
293533965Sjdp
293633965Sjdp  if (val.X_op != O_constant
293733965Sjdp      || val.X_add_number < - 0x80
293833965Sjdp      || val.X_add_number > 0xff
293933965Sjdp      || (mult != 0 && mult != 1 && val.X_add_number != 0))
294033965Sjdp    {
294133965Sjdp      if (exp.X_op != O_constant)
294289857Sobrien	as_bad (_("unsupported variable size or fill value"));
294333965Sjdp      else
294433965Sjdp	{
294533965Sjdp	  offsetT i;
294633965Sjdp
294733965Sjdp	  if (mult == 0)
294833965Sjdp	    mult = 1;
294933965Sjdp	  bytes = mult * exp.X_add_number;
295033965Sjdp	  for (i = 0; i < exp.X_add_number; i++)
295133965Sjdp	    emit_expr (&val, mult);
295233965Sjdp	}
295333965Sjdp    }
295433965Sjdp  else
295533965Sjdp    {
295633965Sjdp      if (exp.X_op == O_constant)
295733965Sjdp	{
295833965Sjdp	  long repeat;
295933965Sjdp
296033965Sjdp	  repeat = exp.X_add_number;
296133965Sjdp	  if (mult)
296233965Sjdp	    repeat *= mult;
296333965Sjdp	  bytes = repeat;
296433965Sjdp	  if (repeat <= 0)
296533965Sjdp	    {
296677298Sobrien	      if (!flag_mri)
296760484Sobrien		as_warn (_(".space repeat count is zero, ignored"));
296860484Sobrien	      else if (repeat < 0)
296960484Sobrien		as_warn (_(".space repeat count is negative, ignored"));
297033965Sjdp	      goto getout;
297133965Sjdp	    }
297233965Sjdp
297333965Sjdp	  /* If we are in the absolute section, just bump the offset.  */
297433965Sjdp	  if (now_seg == absolute_section)
297533965Sjdp	    {
297633965Sjdp	      abs_section_offset += repeat;
297733965Sjdp	      goto getout;
297833965Sjdp	    }
297933965Sjdp
298033965Sjdp	  /* If we are secretly in an MRI common section, then
298133965Sjdp	     creating space just increases the size of the common
298233965Sjdp	     symbol.  */
298333965Sjdp	  if (mri_common_symbol != NULL)
298433965Sjdp	    {
298533965Sjdp	      S_SET_VALUE (mri_common_symbol,
298633965Sjdp			   S_GET_VALUE (mri_common_symbol) + repeat);
298733965Sjdp	      goto getout;
298833965Sjdp	    }
298933965Sjdp
299033965Sjdp	  if (!need_pass_2)
299133965Sjdp	    p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
299233965Sjdp			  (offsetT) repeat, (char *) 0);
299333965Sjdp	}
299433965Sjdp      else
299533965Sjdp	{
299633965Sjdp	  if (now_seg == absolute_section)
299733965Sjdp	    {
299860484Sobrien	      as_bad (_("space allocation too complex in absolute section"));
299933965Sjdp	      subseg_set (text_section, 0);
300033965Sjdp	    }
300177298Sobrien
300233965Sjdp	  if (mri_common_symbol != NULL)
300333965Sjdp	    {
300460484Sobrien	      as_bad (_("space allocation too complex in common section"));
300533965Sjdp	      mri_common_symbol = NULL;
300633965Sjdp	    }
300777298Sobrien
300833965Sjdp	  if (!need_pass_2)
300933965Sjdp	    p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
301033965Sjdp			  make_expr_symbol (&exp), (offsetT) 0, (char *) 0);
301133965Sjdp	}
301233965Sjdp
301333965Sjdp      if (p)
301433965Sjdp	*p = val.X_add_number;
301533965Sjdp    }
301633965Sjdp
301733965Sjdp getout:
301833965Sjdp
301933965Sjdp  /* In MRI mode, after an odd number of bytes, we must align to an
302033965Sjdp     even word boundary, unless the next instruction is a dc.b, ds.b
302133965Sjdp     or dcb.b.  */
302233965Sjdp  if (flag_mri && (bytes & 1) != 0)
302333965Sjdp    mri_pending_align = 1;
302433965Sjdp
302560484Sobrien  demand_empty_rest_of_line ();
302660484Sobrien
302733965Sjdp  if (flag_mri)
302833965Sjdp    mri_comment_end (stop, stopc);
302933965Sjdp}
303033965Sjdp
303133965Sjdp/* This is like s_space, but the value is a floating point number with
303233965Sjdp   the given precision.  This is for the MRI dcb.s pseudo-op and
303333965Sjdp   friends.  */
303433965Sjdp
303533965Sjdpvoid
303633965Sjdps_float_space (float_type)
303733965Sjdp     int float_type;
303833965Sjdp{
303933965Sjdp  offsetT count;
304033965Sjdp  int flen;
304133965Sjdp  char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
304233965Sjdp  char *stop = NULL;
304333965Sjdp  char stopc;
304433965Sjdp
304533965Sjdp  if (flag_mri)
304633965Sjdp    stop = mri_comment_field (&stopc);
304733965Sjdp
304833965Sjdp  count = get_absolute_expression ();
304933965Sjdp
305033965Sjdp  SKIP_WHITESPACE ();
305133965Sjdp  if (*input_line_pointer != ',')
305233965Sjdp    {
305360484Sobrien      as_bad (_("missing value"));
305460484Sobrien      ignore_rest_of_line ();
305533965Sjdp      if (flag_mri)
305633965Sjdp	mri_comment_end (stop, stopc);
305733965Sjdp      return;
305833965Sjdp    }
305933965Sjdp
306033965Sjdp  ++input_line_pointer;
306133965Sjdp
306233965Sjdp  SKIP_WHITESPACE ();
306333965Sjdp
306433965Sjdp  /* Skip any 0{letter} that may be present.  Don't even check if the
306533965Sjdp   * letter is legal.  */
306638889Sjdp  if (input_line_pointer[0] == '0'
306789857Sobrien      && ISALPHA (input_line_pointer[1]))
306833965Sjdp    input_line_pointer += 2;
306933965Sjdp
307033965Sjdp  /* Accept :xxxx, where the x's are hex digits, for a floating point
307133965Sjdp     with the exact digits specified.  */
307233965Sjdp  if (input_line_pointer[0] == ':')
307333965Sjdp    {
307433965Sjdp      flen = hex_float (float_type, temp);
307533965Sjdp      if (flen < 0)
307633965Sjdp	{
307760484Sobrien	  ignore_rest_of_line ();
307833965Sjdp	  if (flag_mri)
307933965Sjdp	    mri_comment_end (stop, stopc);
308033965Sjdp	  return;
308133965Sjdp	}
308233965Sjdp    }
308333965Sjdp  else
308433965Sjdp    {
308533965Sjdp      char *err;
308633965Sjdp
308733965Sjdp      err = md_atof (float_type, temp, &flen);
308833965Sjdp      know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
308933965Sjdp      know (flen > 0);
309033965Sjdp      if (err)
309133965Sjdp	{
309289857Sobrien	  as_bad (_("bad floating literal: %s"), err);
309360484Sobrien	  ignore_rest_of_line ();
309433965Sjdp	  if (flag_mri)
309533965Sjdp	    mri_comment_end (stop, stopc);
309633965Sjdp	  return;
309733965Sjdp	}
309833965Sjdp    }
309933965Sjdp
310033965Sjdp  while (--count >= 0)
310133965Sjdp    {
310233965Sjdp      char *p;
310333965Sjdp
310433965Sjdp      p = frag_more (flen);
310533965Sjdp      memcpy (p, temp, (unsigned int) flen);
310633965Sjdp    }
310733965Sjdp
310860484Sobrien  demand_empty_rest_of_line ();
310960484Sobrien
311033965Sjdp  if (flag_mri)
311133965Sjdp    mri_comment_end (stop, stopc);
311233965Sjdp}
311333965Sjdp
311433965Sjdp/* Handle the .struct pseudo-op, as found in MIPS assemblers.  */
311533965Sjdp
311633965Sjdpvoid
311733965Sjdps_struct (ignore)
311860484Sobrien     int ignore ATTRIBUTE_UNUSED;
311933965Sjdp{
312033965Sjdp  char *stop = NULL;
312133965Sjdp  char stopc;
312233965Sjdp
312333965Sjdp  if (flag_mri)
312433965Sjdp    stop = mri_comment_field (&stopc);
312533965Sjdp  abs_section_offset = get_absolute_expression ();
312633965Sjdp  subseg_set (absolute_section, 0);
312760484Sobrien  demand_empty_rest_of_line ();
312833965Sjdp  if (flag_mri)
312933965Sjdp    mri_comment_end (stop, stopc);
313033965Sjdp}
313133965Sjdp
313233965Sjdpvoid
313333965Sjdps_text (ignore)
313460484Sobrien     int ignore ATTRIBUTE_UNUSED;
313533965Sjdp{
313633965Sjdp  register int temp;
313733965Sjdp
313833965Sjdp  temp = get_absolute_expression ();
313933965Sjdp  subseg_set (text_section, (subsegT) temp);
314033965Sjdp  demand_empty_rest_of_line ();
314133965Sjdp#ifdef OBJ_VMS
314233965Sjdp  const_flag &= ~IN_DEFAULT_SECTION;
314333965Sjdp#endif
314477298Sobrien}
314533965Sjdp
314677298Sobrienvoid
314733965Sjdpdemand_empty_rest_of_line ()
314833965Sjdp{
314933965Sjdp  SKIP_WHITESPACE ();
315033965Sjdp  if (is_end_of_line[(unsigned char) *input_line_pointer])
315177298Sobrien    input_line_pointer++;
315233965Sjdp  else
315377298Sobrien    ignore_rest_of_line ();
315433965Sjdp
315577298Sobrien  /* Return having already swallowed end-of-line.  */
315677298Sobrien}
315777298Sobrien
315833965Sjdpvoid
315977298Sobrienignore_rest_of_line ()
316033965Sjdp{
316177298Sobrien  /* For suspect lines: gives warning.  */
316233965Sjdp  if (!is_end_of_line[(unsigned char) *input_line_pointer])
316333965Sjdp    {
316489857Sobrien      if (ISPRINT (*input_line_pointer))
316589857Sobrien	as_warn (_("rest of line ignored; first ignored character is `%c'"),
316689857Sobrien		 *input_line_pointer);
316733965Sjdp      else
316889857Sobrien	as_warn (_("rest of line ignored; first ignored character valued 0x%x"),
316989857Sobrien		 *input_line_pointer);
317077298Sobrien
317133965Sjdp      while (input_line_pointer < buffer_limit
317233965Sjdp	     && !is_end_of_line[(unsigned char) *input_line_pointer])
317377298Sobrien	input_line_pointer++;
317433965Sjdp    }
317577298Sobrien
317677298Sobrien  input_line_pointer++;
317777298Sobrien
317877298Sobrien  /* Return pointing just after end-of-line.  */
317933965Sjdp  know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
318033965Sjdp}
318133965Sjdp
318260484Sobrienvoid
318360484Sobriendiscard_rest_of_line ()
318460484Sobrien{
318560484Sobrien  while (input_line_pointer < buffer_limit
318677298Sobrien	 && !is_end_of_line[(unsigned char) *input_line_pointer])
318777298Sobrien    input_line_pointer++;
318877298Sobrien
318977298Sobrien  input_line_pointer++;
319077298Sobrien
319177298Sobrien  /* Return pointing just after end-of-line.  */
319260484Sobrien  know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
319360484Sobrien}
319460484Sobrien
319577298Sobrien/* In:	Pointer to a symbol.
319677298Sobrien  	Input_line_pointer->expression.
319777298Sobrien
319877298Sobrien   Out:	Input_line_pointer->just after any whitespace after expression.
319977298Sobrien  	Tried to set symbol to value of expression.
320077298Sobrien  	Will change symbols type, value, and frag;  */
320177298Sobrien
320233965Sjdpvoid
320333965Sjdppseudo_set (symbolP)
320433965Sjdp     symbolS *symbolP;
320533965Sjdp{
320633965Sjdp  expressionS exp;
320733965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
320833965Sjdp  int ext;
320933965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
321033965Sjdp
321177298Sobrien  know (symbolP);		/* NULL pointer is logic error.  */
321233965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
321333965Sjdp  ext = S_IS_EXTERNAL (symbolP);
321433965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
321533965Sjdp
321633965Sjdp  (void) expression (&exp);
321733965Sjdp
321833965Sjdp  if (exp.X_op == O_illegal)
321989857Sobrien    as_bad (_("illegal expression"));
322033965Sjdp  else if (exp.X_op == O_absent)
322189857Sobrien    as_bad (_("missing expression"));
322233965Sjdp  else if (exp.X_op == O_big)
322360484Sobrien    {
322460484Sobrien      if (exp.X_add_number > 0)
322589857Sobrien	as_bad (_("bignum invalid"));
322660484Sobrien      else
322789857Sobrien	as_bad (_("floating point number invalid"));
322860484Sobrien    }
322933965Sjdp  else if (exp.X_op == O_subtract
323033965Sjdp	   && (S_GET_SEGMENT (exp.X_add_symbol)
323133965Sjdp	       == S_GET_SEGMENT (exp.X_op_symbol))
323233965Sjdp	   && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol))
323360484Sobrien	   && (symbol_get_frag (exp.X_add_symbol)
323460484Sobrien	       == symbol_get_frag (exp.X_op_symbol)))
323533965Sjdp    {
323633965Sjdp      exp.X_op = O_constant;
323733965Sjdp      exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol)
323833965Sjdp			  - S_GET_VALUE (exp.X_op_symbol));
323933965Sjdp    }
324033965Sjdp
324133965Sjdp  switch (exp.X_op)
324233965Sjdp    {
324333965Sjdp    case O_illegal:
324433965Sjdp    case O_absent:
324533965Sjdp    case O_big:
324633965Sjdp      exp.X_add_number = 0;
324733965Sjdp      /* Fall through.  */
324833965Sjdp    case O_constant:
324933965Sjdp      S_SET_SEGMENT (symbolP, absolute_section);
325033965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
325133965Sjdp      if (ext)
325233965Sjdp	S_SET_EXTERNAL (symbolP);
325333965Sjdp      else
325433965Sjdp	S_CLEAR_EXTERNAL (symbolP);
325533965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
325633965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
325738889Sjdp      if (exp.X_op != O_constant)
325877298Sobrien	symbol_set_frag (symbolP, &zero_address_frag);
325933965Sjdp      break;
326033965Sjdp
326133965Sjdp    case O_register:
326233965Sjdp      S_SET_SEGMENT (symbolP, reg_section);
326333965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
326460484Sobrien      symbol_set_frag (symbolP, &zero_address_frag);
326533965Sjdp      break;
326633965Sjdp
326733965Sjdp    case O_symbol:
326833965Sjdp      if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section
326933965Sjdp	  || exp.X_add_number != 0)
327060484Sobrien	symbol_set_value_expression (symbolP, &exp);
327160484Sobrien      else if (symbol_section_p (symbolP))
327289857Sobrien	as_bad ("attempt to set value of section symbol");
327333965Sjdp      else
327433965Sjdp	{
327533965Sjdp	  symbolS *s = exp.X_add_symbol;
327633965Sjdp
327733965Sjdp	  S_SET_SEGMENT (symbolP, S_GET_SEGMENT (s));
327833965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
327933965Sjdp	  if (ext)
328033965Sjdp	    S_SET_EXTERNAL (symbolP);
328133965Sjdp	  else
328233965Sjdp	    S_CLEAR_EXTERNAL (symbolP);
328333965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
328433965Sjdp	  S_SET_VALUE (symbolP,
328533965Sjdp		       exp.X_add_number + S_GET_VALUE (s));
328660484Sobrien	  symbol_set_frag (symbolP, symbol_get_frag (s));
328733965Sjdp	  copy_symbol_attributes (symbolP, s);
328833965Sjdp	}
328933965Sjdp      break;
329033965Sjdp
329133965Sjdp    default:
329233965Sjdp      /* The value is some complex expression.
329333965Sjdp	 FIXME: Should we set the segment to anything?  */
329460484Sobrien      symbol_set_value_expression (symbolP, &exp);
329533965Sjdp      break;
329633965Sjdp    }
329733965Sjdp}
329833965Sjdp
329977298Sobrien/*  			cons()
330033965Sjdp
330177298Sobrien   CONStruct more frag of .bytes, or .words etc.
330277298Sobrien   Should need_pass_2 be 1 then emit no frag(s).
330377298Sobrien   This understands EXPRESSIONS.
330477298Sobrien
330577298Sobrien   Bug (?)
330677298Sobrien
330777298Sobrien   This has a split personality. We use expression() to read the
330877298Sobrien   value. We can detect if the value won't fit in a byte or word.
330977298Sobrien   But we can't detect if expression() discarded significant digits
331077298Sobrien   in the case of a long. Not worth the crocks required to fix it.  */
331177298Sobrien
331233965Sjdp/* Select a parser for cons expressions.  */
331333965Sjdp
331433965Sjdp/* Some targets need to parse the expression in various fancy ways.
331533965Sjdp   You can define TC_PARSE_CONS_EXPRESSION to do whatever you like
331633965Sjdp   (for example, the HPPA does this).  Otherwise, you can define
331733965Sjdp   BITFIELD_CONS_EXPRESSIONS to permit bitfields to be specified, or
331833965Sjdp   REPEAT_CONS_EXPRESSIONS to permit repeat counts.  If none of these
331933965Sjdp   are defined, which is the normal case, then only simple expressions
332033965Sjdp   are permitted.  */
332133965Sjdp
332260484Sobrien#ifdef TC_M68K
332333965Sjdpstatic void
332433965Sjdpparse_mri_cons PARAMS ((expressionS *exp, unsigned int nbytes));
332560484Sobrien#endif
332633965Sjdp
332733965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION
332833965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS
332933965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES)
333077298Sobrienstatic void
333133965Sjdpparse_bitfield_cons PARAMS ((expressionS *exp, unsigned int nbytes));
333233965Sjdp#endif
333333965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
333433965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES)
333533965Sjdpstatic void
333633965Sjdpparse_repeat_cons PARAMS ((expressionS *exp, unsigned int nbytes));
333733965Sjdp#endif
333833965Sjdp
333933965Sjdp/* If we haven't gotten one yet, just call expression.  */
334033965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION
334133965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP)
334233965Sjdp#endif
334333965Sjdp#endif
334433965Sjdp
334577298Sobrien/* Worker to do .byte etc statements.
334677298Sobrien   Clobbers input_line_pointer and checks end-of-line.  */
334777298Sobrien
334877298Sobrienstatic void
334933965Sjdpcons_worker (nbytes, rva)
335077298Sobrien     register int nbytes;	/* 1=.byte, 2=.word, 4=.long.  */
335133965Sjdp     int rva;
335233965Sjdp{
335333965Sjdp  int c;
335433965Sjdp  expressionS exp;
335533965Sjdp  char *stop = NULL;
335633965Sjdp  char stopc;
335733965Sjdp
335833965Sjdp#ifdef md_flush_pending_output
335933965Sjdp  md_flush_pending_output ();
336033965Sjdp#endif
336133965Sjdp
336233965Sjdp  if (flag_mri)
336333965Sjdp    stop = mri_comment_field (&stopc);
336433965Sjdp
336533965Sjdp  if (is_it_end_of_statement ())
336633965Sjdp    {
336760484Sobrien      demand_empty_rest_of_line ();
336833965Sjdp      if (flag_mri)
336933965Sjdp	mri_comment_end (stop, stopc);
337033965Sjdp      return;
337133965Sjdp    }
337233965Sjdp
337333965Sjdp#ifdef md_cons_align
337433965Sjdp  md_cons_align (nbytes);
337533965Sjdp#endif
337633965Sjdp
337733965Sjdp  c = 0;
337833965Sjdp  do
337933965Sjdp    {
338060484Sobrien#ifdef TC_M68K
338133965Sjdp      if (flag_m68k_mri)
338233965Sjdp	parse_mri_cons (&exp, (unsigned int) nbytes);
338333965Sjdp      else
338460484Sobrien#endif
338533965Sjdp	TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
338633965Sjdp
338733965Sjdp      if (rva)
338833965Sjdp	{
338933965Sjdp	  if (exp.X_op == O_symbol)
339033965Sjdp	    exp.X_op = O_symbol_rva;
339133965Sjdp	  else
339260484Sobrien	    as_fatal (_("rva without symbol"));
339333965Sjdp	}
339433965Sjdp      emit_expr (&exp, (unsigned int) nbytes);
339533965Sjdp      ++c;
339633965Sjdp    }
339733965Sjdp  while (*input_line_pointer++ == ',');
339833965Sjdp
339933965Sjdp  /* In MRI mode, after an odd number of bytes, we must align to an
340033965Sjdp     even word boundary, unless the next instruction is a dc.b, ds.b
340133965Sjdp     or dcb.b.  */
340233965Sjdp  if (flag_mri && nbytes == 1 && (c & 1) != 0)
340333965Sjdp    mri_pending_align = 1;
340433965Sjdp
340577298Sobrien  input_line_pointer--;		/* Put terminator back into stream.  */
340633965Sjdp
340760484Sobrien  demand_empty_rest_of_line ();
340860484Sobrien
340933965Sjdp  if (flag_mri)
341033965Sjdp    mri_comment_end (stop, stopc);
341133965Sjdp}
341233965Sjdp
341333965Sjdpvoid
341433965Sjdpcons (size)
341533965Sjdp     int size;
341633965Sjdp{
341733965Sjdp  cons_worker (size, 0);
341833965Sjdp}
341933965Sjdp
342077298Sobrienvoid
342133965Sjdps_rva (size)
342233965Sjdp     int size;
342333965Sjdp{
342433965Sjdp  cons_worker (size, 1);
342533965Sjdp}
342633965Sjdp
342733965Sjdp/* Put the contents of expression EXP into the object file using
342833965Sjdp   NBYTES bytes.  If need_pass_2 is 1, this does nothing.  */
342933965Sjdp
343033965Sjdpvoid
343133965Sjdpemit_expr (exp, nbytes)
343233965Sjdp     expressionS *exp;
343333965Sjdp     unsigned int nbytes;
343433965Sjdp{
343533965Sjdp  operatorT op;
343633965Sjdp  register char *p;
343733965Sjdp  valueT extra_digit = 0;
343833965Sjdp
343933965Sjdp  /* Don't do anything if we are going to make another pass.  */
344033965Sjdp  if (need_pass_2)
344133965Sjdp    return;
344233965Sjdp
344338889Sjdp#ifndef NO_LISTING
344438889Sjdp#ifdef OBJ_ELF
344538889Sjdp  /* When gcc emits DWARF 1 debugging pseudo-ops, a line number will
344638889Sjdp     appear as a four byte positive constant in the .line section,
344738889Sjdp     followed by a 2 byte 0xffff.  Look for that case here.  */
344838889Sjdp  {
344938889Sjdp    static int dwarf_line = -1;
345038889Sjdp
345138889Sjdp    if (strcmp (segment_name (now_seg), ".line") != 0)
345238889Sjdp      dwarf_line = -1;
345338889Sjdp    else if (dwarf_line >= 0
345438889Sjdp	     && nbytes == 2
345538889Sjdp	     && exp->X_op == O_constant
345638889Sjdp	     && (exp->X_add_number == -1 || exp->X_add_number == 0xffff))
345738889Sjdp      listing_source_line ((unsigned int) dwarf_line);
345838889Sjdp    else if (nbytes == 4
345938889Sjdp	     && exp->X_op == O_constant
346038889Sjdp	     && exp->X_add_number >= 0)
346138889Sjdp      dwarf_line = exp->X_add_number;
346238889Sjdp    else
346338889Sjdp      dwarf_line = -1;
346438889Sjdp  }
346538889Sjdp
346638889Sjdp  /* When gcc emits DWARF 1 debugging pseudo-ops, a file name will
346738889Sjdp     appear as a 2 byte TAG_compile_unit (0x11) followed by a 2 byte
346838889Sjdp     AT_sibling (0x12) followed by a four byte address of the sibling
346938889Sjdp     followed by a 2 byte AT_name (0x38) followed by the name of the
347038889Sjdp     file.  We look for that case here.  */
347138889Sjdp  {
347238889Sjdp    static int dwarf_file = 0;
347338889Sjdp
347438889Sjdp    if (strcmp (segment_name (now_seg), ".debug") != 0)
347538889Sjdp      dwarf_file = 0;
347638889Sjdp    else if (dwarf_file == 0
347738889Sjdp	     && nbytes == 2
347838889Sjdp	     && exp->X_op == O_constant
347938889Sjdp	     && exp->X_add_number == 0x11)
348038889Sjdp      dwarf_file = 1;
348138889Sjdp    else if (dwarf_file == 1
348238889Sjdp	     && nbytes == 2
348338889Sjdp	     && exp->X_op == O_constant
348438889Sjdp	     && exp->X_add_number == 0x12)
348538889Sjdp      dwarf_file = 2;
348638889Sjdp    else if (dwarf_file == 2
348738889Sjdp	     && nbytes == 4)
348838889Sjdp      dwarf_file = 3;
348938889Sjdp    else if (dwarf_file == 3
349038889Sjdp	     && nbytes == 2
349138889Sjdp	     && exp->X_op == O_constant
349238889Sjdp	     && exp->X_add_number == 0x38)
349338889Sjdp      dwarf_file = 4;
349438889Sjdp    else
349538889Sjdp      dwarf_file = 0;
349638889Sjdp
349738889Sjdp    /* The variable dwarf_file_string tells stringer that the string
349838889Sjdp       may be the name of the source file.  */
349938889Sjdp    if (dwarf_file == 4)
350038889Sjdp      dwarf_file_string = 1;
350138889Sjdp    else
350238889Sjdp      dwarf_file_string = 0;
350338889Sjdp  }
350438889Sjdp#endif
350538889Sjdp#endif
350638889Sjdp
350738889Sjdp  if (check_eh_frame (exp, &nbytes))
350838889Sjdp    return;
350938889Sjdp
351033965Sjdp  op = exp->X_op;
351133965Sjdp
351233965Sjdp  /* Allow `.word 0' in the absolute section.  */
351333965Sjdp  if (now_seg == absolute_section)
351433965Sjdp    {
351533965Sjdp      if (op != O_constant || exp->X_add_number != 0)
351660484Sobrien	as_bad (_("attempt to store value in absolute section"));
351733965Sjdp      abs_section_offset += nbytes;
351833965Sjdp      return;
351933965Sjdp    }
352033965Sjdp
352133965Sjdp  /* Handle a negative bignum.  */
352233965Sjdp  if (op == O_uminus
352333965Sjdp      && exp->X_add_number == 0
352460484Sobrien      && symbol_get_value_expression (exp->X_add_symbol)->X_op == O_big
352560484Sobrien      && symbol_get_value_expression (exp->X_add_symbol)->X_add_number > 0)
352633965Sjdp    {
352733965Sjdp      int i;
352833965Sjdp      unsigned long carry;
352933965Sjdp
353060484Sobrien      exp = symbol_get_value_expression (exp->X_add_symbol);
353133965Sjdp
353233965Sjdp      /* Negate the bignum: one's complement each digit and add 1.  */
353333965Sjdp      carry = 1;
353433965Sjdp      for (i = 0; i < exp->X_add_number; i++)
353533965Sjdp	{
353633965Sjdp	  unsigned long next;
353733965Sjdp
353877298Sobrien	  next = (((~(generic_bignum[i] & LITTLENUM_MASK))
353933965Sjdp		   & LITTLENUM_MASK)
354033965Sjdp		  + carry);
354133965Sjdp	  generic_bignum[i] = next & LITTLENUM_MASK;
354233965Sjdp	  carry = next >> LITTLENUM_NUMBER_OF_BITS;
354333965Sjdp	}
354433965Sjdp
354533965Sjdp      /* We can ignore any carry out, because it will be handled by
354633965Sjdp	 extra_digit if it is needed.  */
354733965Sjdp
354833965Sjdp      extra_digit = (valueT) -1;
354933965Sjdp      op = O_big;
355033965Sjdp    }
355133965Sjdp
355233965Sjdp  if (op == O_absent || op == O_illegal)
355333965Sjdp    {
355460484Sobrien      as_warn (_("zero assumed for missing expression"));
355533965Sjdp      exp->X_add_number = 0;
355633965Sjdp      op = O_constant;
355733965Sjdp    }
355833965Sjdp  else if (op == O_big && exp->X_add_number <= 0)
355933965Sjdp    {
356089857Sobrien      as_bad (_("floating point number invalid"));
356133965Sjdp      exp->X_add_number = 0;
356233965Sjdp      op = O_constant;
356333965Sjdp    }
356433965Sjdp  else if (op == O_register)
356533965Sjdp    {
356660484Sobrien      as_warn (_("register value used as expression"));
356733965Sjdp      op = O_constant;
356833965Sjdp    }
356933965Sjdp
357033965Sjdp  p = frag_more ((int) nbytes);
357133965Sjdp
357233965Sjdp#ifndef WORKING_DOT_WORD
357333965Sjdp  /* If we have the difference of two symbols in a word, save it on
357433965Sjdp     the broken_words list.  See the code in write.c.  */
357533965Sjdp  if (op == O_subtract && nbytes == 2)
357633965Sjdp    {
357733965Sjdp      struct broken_word *x;
357833965Sjdp
357933965Sjdp      x = (struct broken_word *) xmalloc (sizeof (struct broken_word));
358033965Sjdp      x->next_broken_word = broken_words;
358133965Sjdp      broken_words = x;
358260484Sobrien      x->seg = now_seg;
358360484Sobrien      x->subseg = now_subseg;
358433965Sjdp      x->frag = frag_now;
358533965Sjdp      x->word_goes_here = p;
358633965Sjdp      x->dispfrag = 0;
358733965Sjdp      x->add = exp->X_add_symbol;
358833965Sjdp      x->sub = exp->X_op_symbol;
358933965Sjdp      x->addnum = exp->X_add_number;
359033965Sjdp      x->added = 0;
359133965Sjdp      new_broken_words++;
359233965Sjdp      return;
359333965Sjdp    }
359433965Sjdp#endif
359533965Sjdp
359633965Sjdp  /* If we have an integer, but the number of bytes is too large to
359733965Sjdp     pass to md_number_to_chars, handle it as a bignum.  */
359833965Sjdp  if (op == O_constant && nbytes > sizeof (valueT))
359933965Sjdp    {
360033965Sjdp      valueT val;
360133965Sjdp      int gencnt;
360233965Sjdp
360377298Sobrien      if (!exp->X_unsigned && exp->X_add_number < 0)
360433965Sjdp	extra_digit = (valueT) -1;
360533965Sjdp      val = (valueT) exp->X_add_number;
360633965Sjdp      gencnt = 0;
360733965Sjdp      do
360833965Sjdp	{
360933965Sjdp	  generic_bignum[gencnt] = val & LITTLENUM_MASK;
361033965Sjdp	  val >>= LITTLENUM_NUMBER_OF_BITS;
361133965Sjdp	  ++gencnt;
361233965Sjdp	}
361333965Sjdp      while (val != 0);
361433965Sjdp      op = exp->X_op = O_big;
361533965Sjdp      exp->X_add_number = gencnt;
361633965Sjdp    }
361733965Sjdp
361833965Sjdp  if (op == O_constant)
361933965Sjdp    {
362033965Sjdp      register valueT get;
362133965Sjdp      register valueT use;
362233965Sjdp      register valueT mask;
362333965Sjdp      valueT hibit;
362433965Sjdp      register valueT unmask;
362533965Sjdp
362633965Sjdp      /* JF << of >= number of bits in the object is undefined.  In
362777298Sobrien	 particular SPARC (Sun 4) has problems.  */
362833965Sjdp      if (nbytes >= sizeof (valueT))
362933965Sjdp	{
363033965Sjdp	  mask = 0;
363133965Sjdp	  if (nbytes > sizeof (valueT))
363233965Sjdp	    hibit = 0;
363333965Sjdp	  else
363433965Sjdp	    hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
363533965Sjdp	}
363633965Sjdp      else
363733965Sjdp	{
363877298Sobrien	  /* Don't store these bits.  */
363933965Sjdp	  mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes);
364033965Sjdp	  hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
364133965Sjdp	}
364233965Sjdp
364377298Sobrien      unmask = ~mask;		/* Do store these bits.  */
364433965Sjdp
364533965Sjdp#ifdef NEVER
364633965Sjdp      "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
364777298Sobrien      mask = ~(unmask >> 1);	/* Includes sign bit now.  */
364833965Sjdp#endif
364933965Sjdp
365033965Sjdp      get = exp->X_add_number;
365133965Sjdp      use = get & unmask;
365233965Sjdp      if ((get & mask) != 0
365333965Sjdp	  && ((get & mask) != mask
365433965Sjdp	      || (get & hibit) == 0))
365577298Sobrien	{		/* Leading bits contain both 0s & 1s.  */
365689857Sobrien	  as_warn (_("value 0x%lx truncated to 0x%lx"),
365733965Sjdp		   (unsigned long) get, (unsigned long) use);
365833965Sjdp	}
365977298Sobrien      /* Put bytes in right order.  */
366033965Sjdp      md_number_to_chars (p, use, (int) nbytes);
366133965Sjdp    }
366233965Sjdp  else if (op == O_big)
366333965Sjdp    {
366438889Sjdp      unsigned int size;
366533965Sjdp      LITTLENUM_TYPE *nums;
366633965Sjdp
366733965Sjdp      know (nbytes % CHARS_PER_LITTLENUM == 0);
366833965Sjdp
366933965Sjdp      size = exp->X_add_number * CHARS_PER_LITTLENUM;
367033965Sjdp      if (nbytes < size)
367133965Sjdp	{
367289857Sobrien	  as_warn (_("bignum truncated to %d bytes"), nbytes);
367333965Sjdp	  size = nbytes;
367433965Sjdp	}
367533965Sjdp
367633965Sjdp      if (target_big_endian)
367733965Sjdp	{
367833965Sjdp	  while (nbytes > size)
367933965Sjdp	    {
368033965Sjdp	      md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
368133965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
368233965Sjdp	      p += CHARS_PER_LITTLENUM;
368333965Sjdp	    }
368433965Sjdp
368533965Sjdp	  nums = generic_bignum + size / CHARS_PER_LITTLENUM;
368689857Sobrien	  while (size >= CHARS_PER_LITTLENUM)
368733965Sjdp	    {
368833965Sjdp	      --nums;
368933965Sjdp	      md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
369033965Sjdp	      size -= CHARS_PER_LITTLENUM;
369133965Sjdp	      p += CHARS_PER_LITTLENUM;
369233965Sjdp	    }
369333965Sjdp	}
369433965Sjdp      else
369533965Sjdp	{
369633965Sjdp	  nums = generic_bignum;
369789857Sobrien	  while (size >= CHARS_PER_LITTLENUM)
369833965Sjdp	    {
369933965Sjdp	      md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
370033965Sjdp	      ++nums;
370133965Sjdp	      size -= CHARS_PER_LITTLENUM;
370233965Sjdp	      p += CHARS_PER_LITTLENUM;
370333965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
370433965Sjdp	    }
370533965Sjdp
370689857Sobrien	  while (nbytes >= CHARS_PER_LITTLENUM)
370733965Sjdp	    {
370833965Sjdp	      md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
370933965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
371033965Sjdp	      p += CHARS_PER_LITTLENUM;
371133965Sjdp	    }
371233965Sjdp	}
371333965Sjdp    }
371433965Sjdp  else
371533965Sjdp    {
371633965Sjdp      memset (p, 0, nbytes);
371733965Sjdp
371833965Sjdp      /* Now we need to generate a fixS to record the symbol value.
371933965Sjdp	 This is easy for BFD.  For other targets it can be more
372033965Sjdp	 complex.  For very complex cases (currently, the HPPA and
372133965Sjdp	 NS32K), you can define TC_CONS_FIX_NEW to do whatever you
372233965Sjdp	 want.  For simpler cases, you can define TC_CONS_RELOC to be
372333965Sjdp	 the name of the reloc code that should be stored in the fixS.
372433965Sjdp	 If neither is defined, the code uses NO_RELOC if it is
372533965Sjdp	 defined, and otherwise uses 0.  */
372633965Sjdp
372733965Sjdp#ifdef BFD_ASSEMBLER
372833965Sjdp#ifdef TC_CONS_FIX_NEW
372933965Sjdp      TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
373033965Sjdp#else
373133965Sjdp      {
373233965Sjdp	bfd_reloc_code_real_type r;
373333965Sjdp
373433965Sjdp	switch (nbytes)
373533965Sjdp	  {
373633965Sjdp	  case 1:
373733965Sjdp	    r = BFD_RELOC_8;
373833965Sjdp	    break;
373933965Sjdp	  case 2:
374033965Sjdp	    r = BFD_RELOC_16;
374133965Sjdp	    break;
374233965Sjdp	  case 4:
374333965Sjdp	    r = BFD_RELOC_32;
374433965Sjdp	    break;
374533965Sjdp	  case 8:
374633965Sjdp	    r = BFD_RELOC_64;
374733965Sjdp	    break;
374833965Sjdp	  default:
374960484Sobrien	    as_bad (_("unsupported BFD relocation size %u"), nbytes);
375033965Sjdp	    r = BFD_RELOC_32;
375133965Sjdp	    break;
375233965Sjdp	  }
375333965Sjdp	fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp,
375433965Sjdp		     0, r);
375533965Sjdp      }
375633965Sjdp#endif
375733965Sjdp#else
375833965Sjdp#ifdef TC_CONS_FIX_NEW
375933965Sjdp      TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
376033965Sjdp#else
376133965Sjdp      /* Figure out which reloc number to use.  Use TC_CONS_RELOC if
376233965Sjdp	 it is defined, otherwise use NO_RELOC if it is defined,
376333965Sjdp	 otherwise use 0.  */
376433965Sjdp#ifndef TC_CONS_RELOC
376533965Sjdp#ifdef NO_RELOC
376633965Sjdp#define TC_CONS_RELOC NO_RELOC
376733965Sjdp#else
376833965Sjdp#define TC_CONS_RELOC 0
376933965Sjdp#endif
377033965Sjdp#endif
377133965Sjdp      fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0,
377233965Sjdp		   TC_CONS_RELOC);
377333965Sjdp#endif /* TC_CONS_FIX_NEW */
377433965Sjdp#endif /* BFD_ASSEMBLER */
377533965Sjdp    }
377633965Sjdp}
377733965Sjdp
377833965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS
377933965Sjdp
378033965Sjdp/* i960 assemblers, (eg, asm960), allow bitfields after ".byte" as
378133965Sjdp   w:x,y:z, where w and y are bitwidths and x and y are values.  They
378233965Sjdp   then pack them all together. We do a little better in that we allow
378333965Sjdp   them in words, longs, etc. and we'll pack them in target byte order
378433965Sjdp   for you.
378533965Sjdp
378633965Sjdp   The rules are: pack least significat bit first, if a field doesn't
378733965Sjdp   entirely fit, put it in the next unit.  Overflowing the bitfield is
378833965Sjdp   explicitly *not* even a warning.  The bitwidth should be considered
378933965Sjdp   a "mask".
379033965Sjdp
379133965Sjdp   To use this function the tc-XXX.h file should define
379233965Sjdp   BITFIELD_CONS_EXPRESSIONS.  */
379333965Sjdp
379477298Sobrienstatic void
379533965Sjdpparse_bitfield_cons (exp, nbytes)
379633965Sjdp     expressionS *exp;
379733965Sjdp     unsigned int nbytes;
379833965Sjdp{
379933965Sjdp  unsigned int bits_available = BITS_PER_CHAR * nbytes;
380033965Sjdp  char *hold = input_line_pointer;
380133965Sjdp
380233965Sjdp  (void) expression (exp);
380333965Sjdp
380433965Sjdp  if (*input_line_pointer == ':')
380577298Sobrien    {
380677298Sobrien      /* Bitfields.  */
380733965Sjdp      long value = 0;
380833965Sjdp
380933965Sjdp      for (;;)
381033965Sjdp	{
381133965Sjdp	  unsigned long width;
381233965Sjdp
381333965Sjdp	  if (*input_line_pointer != ':')
381433965Sjdp	    {
381533965Sjdp	      input_line_pointer = hold;
381633965Sjdp	      break;
381777298Sobrien	    }			/* Next piece is not a bitfield.  */
381833965Sjdp
381933965Sjdp	  /* In the general case, we can't allow
382033965Sjdp	     full expressions with symbol
382133965Sjdp	     differences and such.  The relocation
382233965Sjdp	     entries for symbols not defined in this
382333965Sjdp	     assembly would require arbitrary field
382433965Sjdp	     widths, positions, and masks which most
382533965Sjdp	     of our current object formats don't
382633965Sjdp	     support.
382733965Sjdp
382833965Sjdp	     In the specific case where a symbol
382933965Sjdp	     *is* defined in this assembly, we
383033965Sjdp	     *could* build fixups and track it, but
383133965Sjdp	     this could lead to confusion for the
383233965Sjdp	     backends.  I'm lazy. I'll take any
383333965Sjdp	     SEG_ABSOLUTE. I think that means that
383433965Sjdp	     you can use a previous .set or
383577298Sobrien	     .equ type symbol.  xoxorich.  */
383633965Sjdp
383733965Sjdp	  if (exp->X_op == O_absent)
383833965Sjdp	    {
383960484Sobrien	      as_warn (_("using a bit field width of zero"));
384033965Sjdp	      exp->X_add_number = 0;
384133965Sjdp	      exp->X_op = O_constant;
384277298Sobrien	    }			/* Implied zero width bitfield.  */
384333965Sjdp
384433965Sjdp	  if (exp->X_op != O_constant)
384533965Sjdp	    {
384633965Sjdp	      *input_line_pointer = '\0';
384760484Sobrien	      as_bad (_("field width \"%s\" too complex for a bitfield"), hold);
384833965Sjdp	      *input_line_pointer = ':';
384933965Sjdp	      demand_empty_rest_of_line ();
385033965Sjdp	      return;
385177298Sobrien	    }			/* Too complex.  */
385233965Sjdp
385333965Sjdp	  if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes))
385433965Sjdp	    {
385560484Sobrien	      as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"),
385633965Sjdp		       width, nbytes, (BITS_PER_CHAR * nbytes));
385733965Sjdp	      width = BITS_PER_CHAR * nbytes;
385877298Sobrien	    }			/* Too big.  */
385933965Sjdp
386033965Sjdp	  if (width > bits_available)
386133965Sjdp	    {
386233965Sjdp	      /* FIXME-SOMEDAY: backing up and reparsing is wasteful.  */
386333965Sjdp	      input_line_pointer = hold;
386433965Sjdp	      exp->X_add_number = value;
386533965Sjdp	      break;
386677298Sobrien	    }			/* Won't fit.  */
386733965Sjdp
386877298Sobrien	  /* Skip ':'.  */
386977298Sobrien	  hold = ++input_line_pointer;
387033965Sjdp
387133965Sjdp	  (void) expression (exp);
387233965Sjdp	  if (exp->X_op != O_constant)
387333965Sjdp	    {
387433965Sjdp	      char cache = *input_line_pointer;
387533965Sjdp
387633965Sjdp	      *input_line_pointer = '\0';
387760484Sobrien	      as_bad (_("field value \"%s\" too complex for a bitfield"), hold);
387833965Sjdp	      *input_line_pointer = cache;
387933965Sjdp	      demand_empty_rest_of_line ();
388033965Sjdp	      return;
388177298Sobrien	    }			/* Too complex.  */
388233965Sjdp
388333965Sjdp	  value |= ((~(-1 << width) & exp->X_add_number)
388433965Sjdp		    << ((BITS_PER_CHAR * nbytes) - bits_available));
388533965Sjdp
388633965Sjdp	  if ((bits_available -= width) == 0
388733965Sjdp	      || is_it_end_of_statement ()
388833965Sjdp	      || *input_line_pointer != ',')
388933965Sjdp	    {
389033965Sjdp	      break;
389177298Sobrien	    }			/* All the bitfields we're gonna get.  */
389233965Sjdp
389333965Sjdp	  hold = ++input_line_pointer;
389433965Sjdp	  (void) expression (exp);
389577298Sobrien	}
389633965Sjdp
389733965Sjdp      exp->X_add_number = value;
389833965Sjdp      exp->X_op = O_constant;
389933965Sjdp      exp->X_unsigned = 1;
390077298Sobrien    }
390177298Sobrien}
390233965Sjdp
390333965Sjdp#endif /* BITFIELD_CONS_EXPRESSIONS */
390433965Sjdp
390533965Sjdp/* Handle an MRI style string expression.  */
390633965Sjdp
390760484Sobrien#ifdef TC_M68K
390833965Sjdpstatic void
390933965Sjdpparse_mri_cons (exp, nbytes)
391033965Sjdp     expressionS *exp;
391133965Sjdp     unsigned int nbytes;
391233965Sjdp{
391333965Sjdp  if (*input_line_pointer != '\''
391433965Sjdp      && (input_line_pointer[1] != '\''
391533965Sjdp	  || (*input_line_pointer != 'A'
391633965Sjdp	      && *input_line_pointer != 'E')))
391733965Sjdp    TC_PARSE_CONS_EXPRESSION (exp, nbytes);
391833965Sjdp  else
391933965Sjdp    {
392038889Sjdp      unsigned int scan;
392133965Sjdp      unsigned int result = 0;
392233965Sjdp
392333965Sjdp      /* An MRI style string.  Cut into as many bytes as will fit into
392433965Sjdp	 a nbyte chunk, left justify if necessary, and separate with
392533965Sjdp	 commas so we can try again later.  */
392633965Sjdp      if (*input_line_pointer == 'A')
392733965Sjdp	++input_line_pointer;
392833965Sjdp      else if (*input_line_pointer == 'E')
392933965Sjdp	{
393060484Sobrien	  as_bad (_("EBCDIC constants are not supported"));
393133965Sjdp	  ++input_line_pointer;
393233965Sjdp	}
393333965Sjdp
393433965Sjdp      input_line_pointer++;
393533965Sjdp      for (scan = 0; scan < nbytes; scan++)
393633965Sjdp	{
393733965Sjdp	  if (*input_line_pointer == '\'')
393833965Sjdp	    {
393933965Sjdp	      if (input_line_pointer[1] == '\'')
394033965Sjdp		{
394133965Sjdp		  input_line_pointer++;
394233965Sjdp		}
394333965Sjdp	      else
394433965Sjdp		break;
394533965Sjdp	    }
394633965Sjdp	  result = (result << 8) | (*input_line_pointer++);
394733965Sjdp	}
394833965Sjdp
394977298Sobrien      /* Left justify.  */
395033965Sjdp      while (scan < nbytes)
395133965Sjdp	{
395233965Sjdp	  result <<= 8;
395333965Sjdp	  scan++;
395433965Sjdp	}
395577298Sobrien
395677298Sobrien      /* Create correct expression.  */
395733965Sjdp      exp->X_op = O_constant;
395833965Sjdp      exp->X_add_number = result;
395977298Sobrien
396077298Sobrien      /* Fake it so that we can read the next char too.  */
396133965Sjdp      if (input_line_pointer[0] != '\'' ||
396233965Sjdp	  (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\''))
396333965Sjdp	{
396433965Sjdp	  input_line_pointer -= 2;
396533965Sjdp	  input_line_pointer[0] = ',';
396633965Sjdp	  input_line_pointer[1] = '\'';
396733965Sjdp	}
396833965Sjdp      else
396933965Sjdp	input_line_pointer++;
397033965Sjdp    }
397133965Sjdp}
397260484Sobrien#endif /* TC_M68K */
397333965Sjdp
397433965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
397533965Sjdp
397633965Sjdp/* Parse a repeat expression for cons.  This is used by the MIPS
397733965Sjdp   assembler.  The format is NUMBER:COUNT; NUMBER appears in the
397833965Sjdp   object file COUNT times.
397933965Sjdp
398033965Sjdp   To use this for a target, define REPEAT_CONS_EXPRESSIONS.  */
398133965Sjdp
398233965Sjdpstatic void
398333965Sjdpparse_repeat_cons (exp, nbytes)
398433965Sjdp     expressionS *exp;
398533965Sjdp     unsigned int nbytes;
398633965Sjdp{
398733965Sjdp  expressionS count;
398833965Sjdp  register int i;
398933965Sjdp
399033965Sjdp  expression (exp);
399133965Sjdp
399233965Sjdp  if (*input_line_pointer != ':')
399333965Sjdp    {
399433965Sjdp      /* No repeat count.  */
399533965Sjdp      return;
399633965Sjdp    }
399733965Sjdp
399833965Sjdp  ++input_line_pointer;
399933965Sjdp  expression (&count);
400033965Sjdp  if (count.X_op != O_constant
400133965Sjdp      || count.X_add_number <= 0)
400233965Sjdp    {
400389857Sobrien      as_warn (_("unresolvable or nonpositive repeat count; using 1"));
400433965Sjdp      return;
400533965Sjdp    }
400633965Sjdp
400733965Sjdp  /* The cons function is going to output this expression once.  So we
400833965Sjdp     output it count - 1 times.  */
400933965Sjdp  for (i = count.X_add_number - 1; i > 0; i--)
401033965Sjdp    emit_expr (exp, nbytes);
401133965Sjdp}
401233965Sjdp
401333965Sjdp#endif /* REPEAT_CONS_EXPRESSIONS */
401433965Sjdp
401533965Sjdp/* Parse a floating point number represented as a hex constant.  This
401633965Sjdp   permits users to specify the exact bits they want in the floating
401733965Sjdp   point number.  */
401833965Sjdp
401933965Sjdpstatic int
402033965Sjdphex_float (float_type, bytes)
402133965Sjdp     int float_type;
402233965Sjdp     char *bytes;
402333965Sjdp{
402433965Sjdp  int length;
402533965Sjdp  int i;
402633965Sjdp
402733965Sjdp  switch (float_type)
402833965Sjdp    {
402933965Sjdp    case 'f':
403033965Sjdp    case 'F':
403133965Sjdp    case 's':
403233965Sjdp    case 'S':
403333965Sjdp      length = 4;
403433965Sjdp      break;
403533965Sjdp
403633965Sjdp    case 'd':
403733965Sjdp    case 'D':
403833965Sjdp    case 'r':
403933965Sjdp    case 'R':
404033965Sjdp      length = 8;
404133965Sjdp      break;
404233965Sjdp
404333965Sjdp    case 'x':
404433965Sjdp    case 'X':
404533965Sjdp      length = 12;
404633965Sjdp      break;
404733965Sjdp
404833965Sjdp    case 'p':
404933965Sjdp    case 'P':
405033965Sjdp      length = 12;
405133965Sjdp      break;
405233965Sjdp
405333965Sjdp    default:
405489857Sobrien      as_bad (_("unknown floating type type '%c'"), float_type);
405533965Sjdp      return -1;
405633965Sjdp    }
405733965Sjdp
405833965Sjdp  /* It would be nice if we could go through expression to parse the
405933965Sjdp     hex constant, but if we get a bignum it's a pain to sort it into
406033965Sjdp     the buffer correctly.  */
406133965Sjdp  i = 0;
406233965Sjdp  while (hex_p (*input_line_pointer) || *input_line_pointer == '_')
406333965Sjdp    {
406433965Sjdp      int d;
406533965Sjdp
406633965Sjdp      /* The MRI assembler accepts arbitrary underscores strewn about
406777298Sobrien	 through the hex constant, so we ignore them as well.  */
406833965Sjdp      if (*input_line_pointer == '_')
406933965Sjdp	{
407033965Sjdp	  ++input_line_pointer;
407133965Sjdp	  continue;
407233965Sjdp	}
407333965Sjdp
407433965Sjdp      if (i >= length)
407533965Sjdp	{
407689857Sobrien	  as_warn (_("floating point constant too large"));
407733965Sjdp	  return -1;
407833965Sjdp	}
407933965Sjdp      d = hex_value (*input_line_pointer) << 4;
408033965Sjdp      ++input_line_pointer;
408133965Sjdp      while (*input_line_pointer == '_')
408233965Sjdp	++input_line_pointer;
408333965Sjdp      if (hex_p (*input_line_pointer))
408433965Sjdp	{
408533965Sjdp	  d += hex_value (*input_line_pointer);
408633965Sjdp	  ++input_line_pointer;
408733965Sjdp	}
408833965Sjdp      if (target_big_endian)
408933965Sjdp	bytes[i] = d;
409033965Sjdp      else
409133965Sjdp	bytes[length - i - 1] = d;
409233965Sjdp      ++i;
409333965Sjdp    }
409433965Sjdp
409533965Sjdp  if (i < length)
409633965Sjdp    {
409733965Sjdp      if (target_big_endian)
409833965Sjdp	memset (bytes + i, 0, length - i);
409933965Sjdp      else
410033965Sjdp	memset (bytes, 0, length - i);
410133965Sjdp    }
410233965Sjdp
410333965Sjdp  return length;
410433965Sjdp}
410533965Sjdp
410677298Sobrien/*  			float_cons()
410733965Sjdp
410877298Sobrien   CONStruct some more frag chars of .floats .ffloats etc.
410977298Sobrien   Makes 0 or more new frags.
411077298Sobrien   If need_pass_2 == 1, no frags are emitted.
411177298Sobrien   This understands only floating literals, not expressions. Sorry.
411277298Sobrien
411377298Sobrien   A floating constant is defined by atof_generic(), except it is preceded
411477298Sobrien   by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its
411577298Sobrien   reading, I decided to be incompatible. This always tries to give you
411677298Sobrien   rounded bits to the precision of the pseudo-op. Former AS did premature
411777298Sobrien   truncatation, restored noisy bits instead of trailing 0s AND gave you
411877298Sobrien   a choice of 2 flavours of noise according to which of 2 floating-point
411977298Sobrien   scanners you directed AS to use.
412077298Sobrien
412177298Sobrien   In:	input_line_pointer->whitespace before, or '0' of flonum.  */
412277298Sobrien
412333965Sjdpvoid
412433965Sjdpfloat_cons (float_type)
412577298Sobrien     /* Clobbers input_line-pointer, checks end-of-line.  */
412677298Sobrien     register int float_type;	/* 'f':.ffloat ... 'F':.float ...  */
412733965Sjdp{
412833965Sjdp  register char *p;
412977298Sobrien  int length;			/* Number of chars in an object.  */
413077298Sobrien  register char *err;		/* Error from scanning floating literal.  */
413133965Sjdp  char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
413233965Sjdp
413333965Sjdp  if (is_it_end_of_statement ())
413433965Sjdp    {
413533965Sjdp      demand_empty_rest_of_line ();
413633965Sjdp      return;
413733965Sjdp    }
413833965Sjdp
413933965Sjdp#ifdef md_flush_pending_output
414033965Sjdp  md_flush_pending_output ();
414133965Sjdp#endif
414233965Sjdp
414333965Sjdp  do
414433965Sjdp    {
414577298Sobrien      /* input_line_pointer->1st char of a flonum (we hope!).  */
414633965Sjdp      SKIP_WHITESPACE ();
414733965Sjdp
414833965Sjdp      /* Skip any 0{letter} that may be present. Don't even check if the
414977298Sobrien         letter is legal. Someone may invent a "z" format and this routine
415077298Sobrien         has no use for such information. Lusers beware: you get
415177298Sobrien         diagnostics if your input is ill-conditioned.  */
415238889Sjdp      if (input_line_pointer[0] == '0'
415389857Sobrien	  && ISALPHA (input_line_pointer[1]))
415433965Sjdp	input_line_pointer += 2;
415533965Sjdp
415633965Sjdp      /* Accept :xxxx, where the x's are hex digits, for a floating
415733965Sjdp         point with the exact digits specified.  */
415833965Sjdp      if (input_line_pointer[0] == ':')
415933965Sjdp	{
416033965Sjdp	  ++input_line_pointer;
416133965Sjdp	  length = hex_float (float_type, temp);
416233965Sjdp	  if (length < 0)
416333965Sjdp	    {
416433965Sjdp	      ignore_rest_of_line ();
416533965Sjdp	      return;
416633965Sjdp	    }
416733965Sjdp	}
416833965Sjdp      else
416933965Sjdp	{
417033965Sjdp	  err = md_atof (float_type, temp, &length);
417133965Sjdp	  know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
417233965Sjdp	  know (length > 0);
417333965Sjdp	  if (err)
417433965Sjdp	    {
417589857Sobrien	      as_bad (_("bad floating literal: %s"), err);
417633965Sjdp	      ignore_rest_of_line ();
417733965Sjdp	      return;
417833965Sjdp	    }
417933965Sjdp	}
418033965Sjdp
418133965Sjdp      if (!need_pass_2)
418233965Sjdp	{
418333965Sjdp	  int count;
418433965Sjdp
418533965Sjdp	  count = 1;
418633965Sjdp
418733965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
418833965Sjdp	  if (*input_line_pointer == ':')
418933965Sjdp	    {
419033965Sjdp	      expressionS count_exp;
419133965Sjdp
419233965Sjdp	      ++input_line_pointer;
419333965Sjdp	      expression (&count_exp);
419477298Sobrien
419533965Sjdp	      if (count_exp.X_op != O_constant
419633965Sjdp		  || count_exp.X_add_number <= 0)
419777298Sobrien		as_warn (_("unresolvable or nonpositive repeat count; using 1"));
419833965Sjdp	      else
419933965Sjdp		count = count_exp.X_add_number;
420033965Sjdp	    }
420133965Sjdp#endif
420233965Sjdp
420333965Sjdp	  while (--count >= 0)
420433965Sjdp	    {
420533965Sjdp	      p = frag_more (length);
420633965Sjdp	      memcpy (p, temp, (unsigned int) length);
420733965Sjdp	    }
420833965Sjdp	}
420933965Sjdp      SKIP_WHITESPACE ();
421033965Sjdp    }
421133965Sjdp  while (*input_line_pointer++ == ',');
421233965Sjdp
421377298Sobrien  /* Put terminator back into stream.  */
421477298Sobrien  --input_line_pointer;
421533965Sjdp  demand_empty_rest_of_line ();
421677298Sobrien}
421733965Sjdp
421877298Sobrien/* Return the size of a LEB128 value.  */
421938889Sjdp
422038889Sjdpstatic inline int
422138889Sjdpsizeof_sleb128 (value)
422238889Sjdp     offsetT value;
422338889Sjdp{
422438889Sjdp  register int size = 0;
422538889Sjdp  register unsigned byte;
422638889Sjdp
422738889Sjdp  do
422838889Sjdp    {
422938889Sjdp      byte = (value & 0x7f);
423038889Sjdp      /* Sadly, we cannot rely on typical arithmetic right shift behaviour.
423138889Sjdp	 Fortunately, we can structure things so that the extra work reduces
423238889Sjdp	 to a noop on systems that do things "properly".  */
423338889Sjdp      value = (value >> 7) | ~(-(offsetT)1 >> 7);
423438889Sjdp      size += 1;
423538889Sjdp    }
423638889Sjdp  while (!(((value == 0) && ((byte & 0x40) == 0))
423738889Sjdp	   || ((value == -1) && ((byte & 0x40) != 0))));
423838889Sjdp
423938889Sjdp  return size;
424038889Sjdp}
424138889Sjdp
424238889Sjdpstatic inline int
424338889Sjdpsizeof_uleb128 (value)
424438889Sjdp     valueT value;
424538889Sjdp{
424638889Sjdp  register int size = 0;
424738889Sjdp  register unsigned byte;
424838889Sjdp
424938889Sjdp  do
425038889Sjdp    {
425138889Sjdp      byte = (value & 0x7f);
425238889Sjdp      value >>= 7;
425338889Sjdp      size += 1;
425438889Sjdp    }
425538889Sjdp  while (value != 0);
425638889Sjdp
425738889Sjdp  return size;
425838889Sjdp}
425938889Sjdp
426060484Sobrienint
426138889Sjdpsizeof_leb128 (value, sign)
426238889Sjdp     valueT value;
426338889Sjdp     int sign;
426438889Sjdp{
426538889Sjdp  if (sign)
426638889Sjdp    return sizeof_sleb128 ((offsetT) value);
426738889Sjdp  else
426838889Sjdp    return sizeof_uleb128 (value);
426938889Sjdp}
427038889Sjdp
427138889Sjdp/* Output a LEB128 value.  */
427238889Sjdp
427338889Sjdpstatic inline int
427438889Sjdpoutput_sleb128 (p, value)
427538889Sjdp     char *p;
427638889Sjdp     offsetT value;
427738889Sjdp{
427838889Sjdp  register char *orig = p;
427938889Sjdp  register int more;
428038889Sjdp
428138889Sjdp  do
428238889Sjdp    {
428338889Sjdp      unsigned byte = (value & 0x7f);
428438889Sjdp
428538889Sjdp      /* Sadly, we cannot rely on typical arithmetic right shift behaviour.
428638889Sjdp	 Fortunately, we can structure things so that the extra work reduces
428738889Sjdp	 to a noop on systems that do things "properly".  */
428838889Sjdp      value = (value >> 7) | ~(-(offsetT)1 >> 7);
428938889Sjdp
429038889Sjdp      more = !((((value == 0) && ((byte & 0x40) == 0))
429138889Sjdp		|| ((value == -1) && ((byte & 0x40) != 0))));
429238889Sjdp      if (more)
429338889Sjdp	byte |= 0x80;
429438889Sjdp
429538889Sjdp      *p++ = byte;
429638889Sjdp    }
429738889Sjdp  while (more);
429838889Sjdp
429938889Sjdp  return p - orig;
430038889Sjdp}
430138889Sjdp
430238889Sjdpstatic inline int
430338889Sjdpoutput_uleb128 (p, value)
430438889Sjdp     char *p;
430538889Sjdp     valueT value;
430638889Sjdp{
430738889Sjdp  char *orig = p;
430838889Sjdp
430938889Sjdp  do
431038889Sjdp    {
431138889Sjdp      unsigned byte = (value & 0x7f);
431238889Sjdp      value >>= 7;
431338889Sjdp      if (value != 0)
431438889Sjdp	/* More bytes to follow.  */
431538889Sjdp	byte |= 0x80;
431638889Sjdp
431738889Sjdp      *p++ = byte;
431838889Sjdp    }
431938889Sjdp  while (value != 0);
432038889Sjdp
432138889Sjdp  return p - orig;
432238889Sjdp}
432338889Sjdp
432460484Sobrienint
432538889Sjdpoutput_leb128 (p, value, sign)
432638889Sjdp     char *p;
432738889Sjdp     valueT value;
432838889Sjdp     int sign;
432938889Sjdp{
433038889Sjdp  if (sign)
433138889Sjdp    return output_sleb128 (p, (offsetT) value);
433238889Sjdp  else
433338889Sjdp    return output_uleb128 (p, value);
433438889Sjdp}
433538889Sjdp
433638889Sjdp/* Do the same for bignums.  We combine sizeof with output here in that
433738889Sjdp   we don't output for NULL values of P.  It isn't really as critical as
433838889Sjdp   for "normal" values that this be streamlined.  */
433938889Sjdp
434060484Sobrienstatic inline int
434138889Sjdpoutput_big_sleb128 (p, bignum, size)
434238889Sjdp     char *p;
434338889Sjdp     LITTLENUM_TYPE *bignum;
434438889Sjdp     int size;
434538889Sjdp{
434638889Sjdp  char *orig = p;
434738889Sjdp  valueT val = 0;
434838889Sjdp  int loaded = 0;
434938889Sjdp  unsigned byte;
435038889Sjdp
435138889Sjdp  /* Strip leading sign extensions off the bignum.  */
435277298Sobrien  while (size > 0 && bignum[size - 1] == (LITTLENUM_TYPE) -1)
435338889Sjdp    size--;
435438889Sjdp
435538889Sjdp  do
435638889Sjdp    {
435738889Sjdp      if (loaded < 7 && size > 0)
435838889Sjdp	{
435938889Sjdp	  val |= (*bignum << loaded);
436038889Sjdp	  loaded += 8 * CHARS_PER_LITTLENUM;
436138889Sjdp	  size--;
436238889Sjdp	  bignum++;
436338889Sjdp	}
436438889Sjdp
436538889Sjdp      byte = val & 0x7f;
436638889Sjdp      loaded -= 7;
436738889Sjdp      val >>= 7;
436838889Sjdp
436938889Sjdp      if (size == 0)
437038889Sjdp	{
437138889Sjdp	  if ((val == 0 && (byte & 0x40) == 0)
437277298Sobrien	      || (~(val | ~(((valueT) 1 << loaded) - 1)) == 0
437338889Sjdp		  && (byte & 0x40) != 0))
437438889Sjdp	    byte |= 0x80;
437538889Sjdp	}
437638889Sjdp
437738889Sjdp      if (orig)
437838889Sjdp	*p = byte;
437938889Sjdp      p++;
438038889Sjdp    }
438138889Sjdp  while (byte & 0x80);
438238889Sjdp
438338889Sjdp  return p - orig;
438438889Sjdp}
438538889Sjdp
438660484Sobrienstatic inline int
438738889Sjdpoutput_big_uleb128 (p, bignum, size)
438838889Sjdp     char *p;
438938889Sjdp     LITTLENUM_TYPE *bignum;
439038889Sjdp     int size;
439138889Sjdp{
439238889Sjdp  char *orig = p;
439338889Sjdp  valueT val = 0;
439438889Sjdp  int loaded = 0;
439538889Sjdp  unsigned byte;
439638889Sjdp
439738889Sjdp  /* Strip leading zeros off the bignum.  */
439838889Sjdp  /* XXX: Is this needed?  */
439977298Sobrien  while (size > 0 && bignum[size - 1] == 0)
440038889Sjdp    size--;
440138889Sjdp
440238889Sjdp  do
440338889Sjdp    {
440438889Sjdp      if (loaded < 7 && size > 0)
440538889Sjdp	{
440638889Sjdp	  val |= (*bignum << loaded);
440738889Sjdp	  loaded += 8 * CHARS_PER_LITTLENUM;
440838889Sjdp	  size--;
440938889Sjdp	  bignum++;
441038889Sjdp	}
441138889Sjdp
441238889Sjdp      byte = val & 0x7f;
441338889Sjdp      loaded -= 7;
441438889Sjdp      val >>= 7;
441538889Sjdp
441638889Sjdp      if (size > 0 || val)
441738889Sjdp	byte |= 0x80;
441838889Sjdp
441938889Sjdp      if (orig)
442038889Sjdp	*p = byte;
442138889Sjdp      p++;
442238889Sjdp    }
442338889Sjdp  while (byte & 0x80);
442438889Sjdp
442538889Sjdp  return p - orig;
442638889Sjdp}
442738889Sjdp
442860484Sobrienstatic int
442938889Sjdpoutput_big_leb128 (p, bignum, size, sign)
443038889Sjdp     char *p;
443138889Sjdp     LITTLENUM_TYPE *bignum;
443238889Sjdp     int size, sign;
443338889Sjdp{
443438889Sjdp  if (sign)
443538889Sjdp    return output_big_sleb128 (p, bignum, size);
443638889Sjdp  else
443738889Sjdp    return output_big_uleb128 (p, bignum, size);
443838889Sjdp}
443938889Sjdp
444038889Sjdp/* Generate the appropriate fragments for a given expression to emit a
444138889Sjdp   leb128 value.  */
444238889Sjdp
444338889Sjdpvoid
444477298Sobrienemit_leb128_expr (exp, sign)
444538889Sjdp     expressionS *exp;
444638889Sjdp     int sign;
444738889Sjdp{
444838889Sjdp  operatorT op = exp->X_op;
444978828Sobrien  int nbytes;
445038889Sjdp
445138889Sjdp  if (op == O_absent || op == O_illegal)
445238889Sjdp    {
445360484Sobrien      as_warn (_("zero assumed for missing expression"));
445438889Sjdp      exp->X_add_number = 0;
445538889Sjdp      op = O_constant;
445638889Sjdp    }
445738889Sjdp  else if (op == O_big && exp->X_add_number <= 0)
445838889Sjdp    {
445989857Sobrien      as_bad (_("floating point number invalid"));
446038889Sjdp      exp->X_add_number = 0;
446138889Sjdp      op = O_constant;
446238889Sjdp    }
446338889Sjdp  else if (op == O_register)
446438889Sjdp    {
446560484Sobrien      as_warn (_("register value used as expression"));
446638889Sjdp      op = O_constant;
446738889Sjdp    }
446838889Sjdp
446978828Sobrien  /* Let check_eh_frame know that data is being emitted.  nbytes == -1 is
447078828Sobrien     a signal that this is leb128 data.  It shouldn't optimize this away.  */
447178828Sobrien  nbytes = -1;
447278828Sobrien  if (check_eh_frame (exp, &nbytes))
447378828Sobrien    abort ();
447478828Sobrien
447578828Sobrien  /* Let the backend know that subsequent data may be byte aligned.  */
447678828Sobrien#ifdef md_cons_align
447778828Sobrien  md_cons_align (1);
447878828Sobrien#endif
447978828Sobrien
448038889Sjdp  if (op == O_constant)
448138889Sjdp    {
448238889Sjdp      /* If we've got a constant, emit the thing directly right now.  */
448338889Sjdp
448438889Sjdp      valueT value = exp->X_add_number;
448538889Sjdp      int size;
448638889Sjdp      char *p;
448738889Sjdp
448838889Sjdp      size = sizeof_leb128 (value, sign);
448938889Sjdp      p = frag_more (size);
449038889Sjdp      output_leb128 (p, value, sign);
449138889Sjdp    }
449238889Sjdp  else if (op == O_big)
449338889Sjdp    {
449438889Sjdp      /* O_big is a different sort of constant.  */
449538889Sjdp
449638889Sjdp      int size;
449738889Sjdp      char *p;
449838889Sjdp
449938889Sjdp      size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign);
450038889Sjdp      p = frag_more (size);
450138889Sjdp      output_big_leb128 (p, generic_bignum, exp->X_add_number, sign);
450238889Sjdp    }
450338889Sjdp  else
450438889Sjdp    {
450577298Sobrien      /* Otherwise, we have to create a variable sized fragment and
450638889Sjdp	 resolve things later.  */
450738889Sjdp
450877298Sobrien      frag_var (rs_leb128, sizeof_uleb128 (~(valueT) 0), 0, sign,
450938889Sjdp		make_expr_symbol (exp), 0, (char *) NULL);
451038889Sjdp    }
451138889Sjdp}
451238889Sjdp
451338889Sjdp/* Parse the .sleb128 and .uleb128 pseudos.  */
451438889Sjdp
451538889Sjdpvoid
451638889Sjdps_leb128 (sign)
451738889Sjdp     int sign;
451838889Sjdp{
451938889Sjdp  expressionS exp;
452038889Sjdp
452177298Sobrien  do
452277298Sobrien    {
452377298Sobrien      expression (&exp);
452477298Sobrien      emit_leb128_expr (&exp, sign);
452577298Sobrien    }
452677298Sobrien  while (*input_line_pointer++ == ',');
452738889Sjdp
452838889Sjdp  input_line_pointer--;
452938889Sjdp  demand_empty_rest_of_line ();
453038889Sjdp}
453138889Sjdp
453277298Sobrien/* We read 0 or more ',' separated, double-quoted strings.
453377298Sobrien   Caller should have checked need_pass_2 is FALSE because we don't
453477298Sobrien   check it.  */
453533965Sjdp
453677298Sobrienvoid
453777298Sobrienstringer (append_zero)		/* Worker to do .ascii etc statements.  */
453877298Sobrien     /* Checks end-of-line.  */
453977298Sobrien     register int append_zero;	/* 0: don't append '\0', else 1.  */
454033965Sjdp{
454133965Sjdp  register unsigned int c;
454238889Sjdp  char *start;
454333965Sjdp
454433965Sjdp#ifdef md_flush_pending_output
454533965Sjdp  md_flush_pending_output ();
454633965Sjdp#endif
454733965Sjdp
454877298Sobrien  /* The following awkward logic is to parse ZERO or more strings,
454977298Sobrien     comma separated. Recall a string expression includes spaces
455077298Sobrien     before the opening '\"' and spaces after the closing '\"'.
455177298Sobrien     We fake a leading ',' if there is (supposed to be)
455277298Sobrien     a 1st, expression. We keep demanding expressions for each ','.  */
455333965Sjdp  if (is_it_end_of_statement ())
455433965Sjdp    {
455577298Sobrien      c = 0;			/* Skip loop.  */
455677298Sobrien      ++input_line_pointer;	/* Compensate for end of loop.  */
455733965Sjdp    }
455833965Sjdp  else
455933965Sjdp    {
456077298Sobrien      c = ',';			/* Do loop.  */
456133965Sjdp    }
456233965Sjdp  while (c == ',' || c == '<' || c == '"')
456333965Sjdp    {
456433965Sjdp      SKIP_WHITESPACE ();
456533965Sjdp      switch (*input_line_pointer)
456633965Sjdp	{
456733965Sjdp	case '\"':
456877298Sobrien	  ++input_line_pointer;	/*->1st char of string.  */
456938889Sjdp	  start = input_line_pointer;
457033965Sjdp	  while (is_a_char (c = next_char_of_string ()))
457133965Sjdp	    {
457233965Sjdp	      FRAG_APPEND_1_CHAR (c);
457333965Sjdp	    }
457433965Sjdp	  if (append_zero)
457533965Sjdp	    {
457633965Sjdp	      FRAG_APPEND_1_CHAR (0);
457733965Sjdp	    }
457833965Sjdp	  know (input_line_pointer[-1] == '\"');
457938889Sjdp
458038889Sjdp#ifndef NO_LISTING
458138889Sjdp#ifdef OBJ_ELF
458238889Sjdp	  /* In ELF, when gcc is emitting DWARF 1 debugging output, it
458338889Sjdp             will emit .string with a filename in the .debug section
458438889Sjdp             after a sequence of constants.  See the comment in
458538889Sjdp             emit_expr for the sequence.  emit_expr will set
458638889Sjdp             dwarf_file_string to non-zero if this string might be a
458738889Sjdp             source file name.  */
458838889Sjdp	  if (strcmp (segment_name (now_seg), ".debug") != 0)
458938889Sjdp	    dwarf_file_string = 0;
459038889Sjdp	  else if (dwarf_file_string)
459138889Sjdp	    {
459238889Sjdp	      c = input_line_pointer[-1];
459338889Sjdp	      input_line_pointer[-1] = '\0';
459438889Sjdp	      listing_source_file (start);
459538889Sjdp	      input_line_pointer[-1] = c;
459638889Sjdp	    }
459738889Sjdp#endif
459838889Sjdp#endif
459938889Sjdp
460033965Sjdp	  break;
460133965Sjdp	case '<':
460233965Sjdp	  input_line_pointer++;
460333965Sjdp	  c = get_single_number ();
460433965Sjdp	  FRAG_APPEND_1_CHAR (c);
460533965Sjdp	  if (*input_line_pointer != '>')
460633965Sjdp	    {
460789857Sobrien	      as_bad (_("expected <nn>"));
460833965Sjdp	    }
460933965Sjdp	  input_line_pointer++;
461033965Sjdp	  break;
461133965Sjdp	case ',':
461233965Sjdp	  input_line_pointer++;
461333965Sjdp	  break;
461433965Sjdp	}
461533965Sjdp      SKIP_WHITESPACE ();
461633965Sjdp      c = *input_line_pointer;
461733965Sjdp    }
461833965Sjdp
461933965Sjdp  demand_empty_rest_of_line ();
462033965Sjdp}				/* stringer() */
462133965Sjdp
462233965Sjdp/* FIXME-SOMEDAY: I had trouble here on characters with the
462333965Sjdp    high bits set.  We'll probably also have trouble with
462433965Sjdp    multibyte chars, wide chars, etc.  Also be careful about
462577298Sobrien    returning values bigger than 1 byte.  xoxorich.  */
462633965Sjdp
462777298Sobrienunsigned int
462833965Sjdpnext_char_of_string ()
462933965Sjdp{
463033965Sjdp  register unsigned int c;
463133965Sjdp
463233965Sjdp  c = *input_line_pointer++ & CHAR_MASK;
463333965Sjdp  switch (c)
463433965Sjdp    {
463533965Sjdp    case '\"':
463633965Sjdp      c = NOT_A_CHAR;
463733965Sjdp      break;
463833965Sjdp
463933965Sjdp    case '\n':
464089857Sobrien      as_warn (_("unterminated string; newline inserted"));
464133965Sjdp      bump_line_counters ();
464233965Sjdp      break;
464333965Sjdp
464433965Sjdp#ifndef NO_STRING_ESCAPES
464533965Sjdp    case '\\':
464633965Sjdp      switch (c = *input_line_pointer++)
464733965Sjdp	{
464833965Sjdp	case 'b':
464933965Sjdp	  c = '\b';
465033965Sjdp	  break;
465133965Sjdp
465233965Sjdp	case 'f':
465333965Sjdp	  c = '\f';
465433965Sjdp	  break;
465533965Sjdp
465633965Sjdp	case 'n':
465733965Sjdp	  c = '\n';
465833965Sjdp	  break;
465933965Sjdp
466033965Sjdp	case 'r':
466133965Sjdp	  c = '\r';
466233965Sjdp	  break;
466333965Sjdp
466433965Sjdp	case 't':
466533965Sjdp	  c = '\t';
466633965Sjdp	  break;
466733965Sjdp
466833965Sjdp	case 'v':
466933965Sjdp	  c = '\013';
467033965Sjdp	  break;
467133965Sjdp
467233965Sjdp	case '\\':
467333965Sjdp	case '"':
467477298Sobrien	  break;		/* As itself.  */
467533965Sjdp
467633965Sjdp	case '0':
467733965Sjdp	case '1':
467833965Sjdp	case '2':
467933965Sjdp	case '3':
468033965Sjdp	case '4':
468133965Sjdp	case '5':
468233965Sjdp	case '6':
468333965Sjdp	case '7':
468433965Sjdp	case '8':
468533965Sjdp	case '9':
468633965Sjdp	  {
468733965Sjdp	    long number;
468833965Sjdp	    int i;
468933965Sjdp
469077298Sobrien	    for (i = 0, number = 0;
469189857Sobrien		 ISDIGIT (c) && i < 3;
469277298Sobrien		 c = *input_line_pointer++, i++)
469333965Sjdp	      {
469433965Sjdp		number = number * 8 + c - '0';
469533965Sjdp	      }
469677298Sobrien
469733965Sjdp	    c = number & 0xff;
469833965Sjdp	  }
469933965Sjdp	  --input_line_pointer;
470033965Sjdp	  break;
470133965Sjdp
470233965Sjdp	case 'x':
470333965Sjdp	case 'X':
470433965Sjdp	  {
470533965Sjdp	    long number;
470633965Sjdp
470733965Sjdp	    number = 0;
470833965Sjdp	    c = *input_line_pointer++;
470989857Sobrien	    while (ISXDIGIT (c))
471033965Sjdp	      {
471189857Sobrien		if (ISDIGIT (c))
471233965Sjdp		  number = number * 16 + c - '0';
471389857Sobrien		else if (ISUPPER (c))
471433965Sjdp		  number = number * 16 + c - 'A' + 10;
471533965Sjdp		else
471633965Sjdp		  number = number * 16 + c - 'a' + 10;
471733965Sjdp		c = *input_line_pointer++;
471833965Sjdp	      }
471933965Sjdp	    c = number & 0xff;
472033965Sjdp	    --input_line_pointer;
472133965Sjdp	  }
472233965Sjdp	  break;
472333965Sjdp
472433965Sjdp	case '\n':
472577298Sobrien	  /* To be compatible with BSD 4.2 as: give the luser a linefeed!!  */
472689857Sobrien	  as_warn (_("unterminated string; newline inserted"));
472733965Sjdp	  c = '\n';
472833965Sjdp	  bump_line_counters ();
472933965Sjdp	  break;
473033965Sjdp
473133965Sjdp	default:
473233965Sjdp
473333965Sjdp#ifdef ONLY_STANDARD_ESCAPES
473489857Sobrien	  as_bad (_("bad escaped character in string"));
473533965Sjdp	  c = '?';
473633965Sjdp#endif /* ONLY_STANDARD_ESCAPES */
473733965Sjdp
473833965Sjdp	  break;
473977298Sobrien	}
474033965Sjdp      break;
474133965Sjdp#endif /* ! defined (NO_STRING_ESCAPES) */
474233965Sjdp
474333965Sjdp    default:
474433965Sjdp      break;
474577298Sobrien    }
474633965Sjdp  return (c);
474777298Sobrien}
474833965Sjdp
474933965Sjdpstatic segT
475033965Sjdpget_segmented_expression (expP)
475133965Sjdp     register expressionS *expP;
475233965Sjdp{
475333965Sjdp  register segT retval;
475433965Sjdp
475533965Sjdp  retval = expression (expP);
475633965Sjdp  if (expP->X_op == O_illegal
475733965Sjdp      || expP->X_op == O_absent
475833965Sjdp      || expP->X_op == O_big)
475933965Sjdp    {
476089857Sobrien      as_bad (_("expected address expression"));
476133965Sjdp      expP->X_op = O_constant;
476233965Sjdp      expP->X_add_number = 0;
476333965Sjdp      retval = absolute_section;
476433965Sjdp    }
476533965Sjdp  return retval;
476633965Sjdp}
476733965Sjdp
476877298Sobrienstatic segT
476933965Sjdpget_known_segmented_expression (expP)
477033965Sjdp     register expressionS *expP;
477133965Sjdp{
477233965Sjdp  register segT retval;
477333965Sjdp
477433965Sjdp  if ((retval = get_segmented_expression (expP)) == undefined_section)
477533965Sjdp    {
477633965Sjdp      /* There is no easy way to extract the undefined symbol from the
477733965Sjdp	 expression.  */
477833965Sjdp      if (expP->X_add_symbol != NULL
477933965Sjdp	  && S_GET_SEGMENT (expP->X_add_symbol) != expr_section)
478060484Sobrien	as_warn (_("symbol \"%s\" undefined; zero assumed"),
478133965Sjdp		 S_GET_NAME (expP->X_add_symbol));
478233965Sjdp      else
478360484Sobrien	as_warn (_("some symbol undefined; zero assumed"));
478433965Sjdp      retval = absolute_section;
478533965Sjdp      expP->X_op = O_constant;
478633965Sjdp      expP->X_add_number = 0;
478733965Sjdp    }
478833965Sjdp  know (retval == absolute_section || SEG_NORMAL (retval));
478933965Sjdp  return (retval);
479077298Sobrien}
479133965Sjdp
479233965SjdpoffsetT
479333965Sjdpget_absolute_expression ()
479433965Sjdp{
479533965Sjdp  expressionS exp;
479633965Sjdp
479733965Sjdp  expression (&exp);
479833965Sjdp  if (exp.X_op != O_constant)
479933965Sjdp    {
480033965Sjdp      if (exp.X_op != O_absent)
480189857Sobrien	as_bad (_("bad or irreducible absolute expression"));
480233965Sjdp      exp.X_add_number = 0;
480333965Sjdp    }
480433965Sjdp  return exp.X_add_number;
480533965Sjdp}
480633965Sjdp
480777298Sobrienchar				/* Return terminator.  */
480833965Sjdpget_absolute_expression_and_terminator (val_pointer)
480977298Sobrien     long *val_pointer;		/* Return value of expression.  */
481033965Sjdp{
481133965Sjdp  /* FIXME: val_pointer should probably be offsetT *.  */
481233965Sjdp  *val_pointer = (long) get_absolute_expression ();
481333965Sjdp  return (*input_line_pointer++);
481433965Sjdp}
481533965Sjdp
481677298Sobrien/* Like demand_copy_string, but return NULL if the string contains any '\0's.
481777298Sobrien   Give a warning if that happens.  */
481877298Sobrien
481933965Sjdpchar *
482033965Sjdpdemand_copy_C_string (len_pointer)
482133965Sjdp     int *len_pointer;
482233965Sjdp{
482333965Sjdp  register char *s;
482433965Sjdp
482533965Sjdp  if ((s = demand_copy_string (len_pointer)) != 0)
482633965Sjdp    {
482733965Sjdp      register int len;
482833965Sjdp
482933965Sjdp      for (len = *len_pointer; len > 0; len--)
483033965Sjdp	{
483133965Sjdp	  if (*s == 0)
483233965Sjdp	    {
483333965Sjdp	      s = 0;
483433965Sjdp	      len = 1;
483533965Sjdp	      *len_pointer = 0;
483689857Sobrien	      as_bad (_("this string may not contain \'\\0\'"));
483733965Sjdp	    }
483833965Sjdp	}
483933965Sjdp    }
484077298Sobrien
484133965Sjdp  return s;
484233965Sjdp}
484333965Sjdp
484477298Sobrien/* Demand string, but return a safe (=private) copy of the string.
484577298Sobrien   Return NULL if we can't read a string here.  */
484677298Sobrien
484733965Sjdpchar *
484833965Sjdpdemand_copy_string (lenP)
484933965Sjdp     int *lenP;
485033965Sjdp{
485133965Sjdp  register unsigned int c;
485233965Sjdp  register int len;
485333965Sjdp  char *retval;
485433965Sjdp
485533965Sjdp  len = 0;
485633965Sjdp  SKIP_WHITESPACE ();
485733965Sjdp  if (*input_line_pointer == '\"')
485833965Sjdp    {
485977298Sobrien      input_line_pointer++;	/* Skip opening quote.  */
486033965Sjdp
486133965Sjdp      while (is_a_char (c = next_char_of_string ()))
486233965Sjdp	{
486333965Sjdp	  obstack_1grow (&notes, c);
486433965Sjdp	  len++;
486533965Sjdp	}
486633965Sjdp      /* JF this next line is so demand_copy_C_string will return a
486777298Sobrien	 null terminated string.  */
486833965Sjdp      obstack_1grow (&notes, '\0');
486933965Sjdp      retval = obstack_finish (&notes);
487033965Sjdp    }
487133965Sjdp  else
487233965Sjdp    {
487389857Sobrien      as_warn (_("missing string"));
487433965Sjdp      retval = NULL;
487533965Sjdp      ignore_rest_of_line ();
487633965Sjdp    }
487733965Sjdp  *lenP = len;
487833965Sjdp  return (retval);
487977298Sobrien}
488033965Sjdp
488177298Sobrien/* In:	Input_line_pointer->next character.
488277298Sobrien
488377298Sobrien   Do:	Skip input_line_pointer over all whitespace.
488477298Sobrien
488577298Sobrien   Out:	1 if input_line_pointer->end-of-line.  */
488677298Sobrien
488777298Sobrienint
488833965Sjdpis_it_end_of_statement ()
488933965Sjdp{
489033965Sjdp  SKIP_WHITESPACE ();
489133965Sjdp  return (is_end_of_line[(unsigned char) *input_line_pointer]);
489277298Sobrien}
489333965Sjdp
489477298Sobrienvoid
489533965Sjdpequals (sym_name, reassign)
489633965Sjdp     char *sym_name;
489733965Sjdp     int reassign;
489833965Sjdp{
489977298Sobrien  register symbolS *symbolP;	/* Symbol we are working with.  */
490038889Sjdp  char *stop = NULL;
490133965Sjdp  char stopc;
490233965Sjdp
490333965Sjdp  input_line_pointer++;
490433965Sjdp  if (*input_line_pointer == '=')
490533965Sjdp    input_line_pointer++;
490633965Sjdp
490733965Sjdp  while (*input_line_pointer == ' ' || *input_line_pointer == '\t')
490833965Sjdp    input_line_pointer++;
490933965Sjdp
491033965Sjdp  if (flag_mri)
491133965Sjdp    stop = mri_comment_field (&stopc);
491233965Sjdp
491333965Sjdp  if (sym_name[0] == '.' && sym_name[1] == '\0')
491433965Sjdp    {
491577298Sobrien      /* Turn '. = mumble' into a .org mumble.  */
491633965Sjdp      register segT segment;
491733965Sjdp      expressionS exp;
491833965Sjdp
491933965Sjdp      segment = get_known_segmented_expression (&exp);
492033965Sjdp      if (!need_pass_2)
492133965Sjdp	do_org (segment, &exp, 0);
492233965Sjdp    }
492333965Sjdp  else
492433965Sjdp    {
492578828Sobrien#ifdef OBJ_COFF
492678828Sobrien      int local;
492778828Sobrien
492878828Sobrien      symbolP = symbol_find (sym_name);
492978828Sobrien      local = symbolP == NULL;
493078828Sobrien      if (local)
493178828Sobrien#endif /* OBJ_COFF */
493233965Sjdp      symbolP = symbol_find_or_make (sym_name);
493333965Sjdp      /* Permit register names to be redefined.  */
493477298Sobrien      if (!reassign
493533965Sjdp	  && S_IS_DEFINED (symbolP)
493633965Sjdp	  && S_GET_SEGMENT (symbolP) != reg_section)
493789857Sobrien	as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
493878828Sobrien
493978828Sobrien#ifdef OBJ_COFF
494078828Sobrien      /* "set" symbols are local unless otherwise specified.  */
494178828Sobrien      if (local)
494278828Sobrien	SF_SET_LOCAL (symbolP);
494378828Sobrien#endif /* OBJ_COFF */
494478828Sobrien
494533965Sjdp      pseudo_set (symbolP);
494633965Sjdp    }
494733965Sjdp
494833965Sjdp  if (flag_mri)
494977298Sobrien    {
495077298Sobrien      /* Check garbage after the expression.  */
495177298Sobrien      ignore_rest_of_line ();
495277298Sobrien      mri_comment_end (stop, stopc);
495377298Sobrien    }
495477298Sobrien}
495533965Sjdp
495689857Sobrien/* .incbin -- include a file verbatim at the current location.  */
495789857Sobrien
495889857Sobrienvoid
495989857Sobriens_incbin (x)
496089857Sobrien     int x ATTRIBUTE_UNUSED;
496189857Sobrien{
496289857Sobrien  FILE * binfile;
496389857Sobrien  char * path;
496489857Sobrien  char * filename;
496589857Sobrien  char * binfrag;
496689857Sobrien  long   skip = 0;
496789857Sobrien  long   count = 0;
496889857Sobrien  long   bytes;
496989857Sobrien  int    len;
497089857Sobrien
497189857Sobrien#ifdef md_flush_pending_output
497289857Sobrien  md_flush_pending_output ();
497389857Sobrien#endif
497489857Sobrien
497589857Sobrien  SKIP_WHITESPACE ();
497689857Sobrien  filename = demand_copy_string (& len);
497789857Sobrien  if (filename == NULL)
497889857Sobrien    return;
497989857Sobrien
498089857Sobrien  SKIP_WHITESPACE ();
498189857Sobrien
498289857Sobrien  /* Look for optional skip and count.  */
498389857Sobrien  if (* input_line_pointer == ',')
498489857Sobrien    {
498589857Sobrien      ++ input_line_pointer;
498689857Sobrien      skip = get_absolute_expression ();
498789857Sobrien
498889857Sobrien      SKIP_WHITESPACE ();
498989857Sobrien
499089857Sobrien      if (* input_line_pointer == ',')
499189857Sobrien	{
499289857Sobrien	  ++ input_line_pointer;
499389857Sobrien
499489857Sobrien	  count = get_absolute_expression ();
499589857Sobrien	  if (count == 0)
499689857Sobrien	    as_warn (_(".incbin count zero, ignoring `%s'"), filename);
499789857Sobrien
499889857Sobrien	  SKIP_WHITESPACE ();
499989857Sobrien	}
500089857Sobrien    }
500189857Sobrien
500289857Sobrien  demand_empty_rest_of_line ();
500389857Sobrien
500489857Sobrien  /* Try opening absolute path first, then try include dirs.  */
500589857Sobrien  binfile = fopen (filename, FOPEN_RB);
500689857Sobrien  if (binfile == NULL)
500789857Sobrien    {
500889857Sobrien      int i;
500989857Sobrien
501089857Sobrien      path = xmalloc ((unsigned long) len + include_dir_maxlen + 5);
501189857Sobrien
501289857Sobrien      for (i = 0; i < include_dir_count; i++)
501389857Sobrien	{
501489857Sobrien	  sprintf (path, "%s/%s", include_dirs[i], filename);
501589857Sobrien
501689857Sobrien	  binfile = fopen (path, FOPEN_RB);
501789857Sobrien	  if (binfile != NULL)
501889857Sobrien	    break;
501989857Sobrien	}
502089857Sobrien
502189857Sobrien      if (binfile == NULL)
502289857Sobrien	as_bad (_("file not found: %s"), filename);
502389857Sobrien    }
502489857Sobrien  else
502589857Sobrien    path = xstrdup (filename);
502689857Sobrien
502789857Sobrien  if (binfile)
502889857Sobrien    {
502989857Sobrien      long   file_len;
503089857Sobrien
503189857Sobrien      register_dependency (path);
503289857Sobrien
503389857Sobrien      /* Compute the length of the file.  */
503489857Sobrien      if (fseek (binfile, 0, SEEK_END) != 0)
503589857Sobrien	{
503689857Sobrien	  as_bad (_("seek to end of .incbin file failed `%s'"), path);
503789857Sobrien	  goto done;
503889857Sobrien	}
503989857Sobrien      file_len = ftell (binfile);
504089857Sobrien
504189857Sobrien      /* If a count was not specified use the size of the file.  */
504289857Sobrien      if (count == 0)
504389857Sobrien	count = file_len;
504489857Sobrien
504589857Sobrien      if (skip + count > file_len)
504689857Sobrien	{
504789857Sobrien	  as_bad (_("skip (%ld) + count (%ld) larger than file size (%ld)"),
504889857Sobrien		  skip, count, file_len);
504989857Sobrien	  goto done;
505089857Sobrien	}
505189857Sobrien
505289857Sobrien      if (fseek (binfile, skip, SEEK_SET) != 0)
505389857Sobrien	{
505489857Sobrien	  as_bad (_("could not skip to %ld in file `%s'"), skip, path);
505589857Sobrien	  goto done;
505689857Sobrien	}
505789857Sobrien
505889857Sobrien      /* Allocate frag space and store file contents in it.  */
505989857Sobrien      binfrag = frag_more (count);
506089857Sobrien
506189857Sobrien      bytes = fread (binfrag, 1, count, binfile);
506289857Sobrien      if (bytes < count)
506389857Sobrien	as_warn (_("truncated file `%s', %ld of %ld bytes read"),
506489857Sobrien		 path, bytes, count);
506589857Sobrien    }
506689857Sobriendone:
506789857Sobrien  if (binfile != NULL)
506889857Sobrien    fclose (binfile);
506989857Sobrien  if (path)
507089857Sobrien    free (path);
507189857Sobrien}
507289857Sobrien
507377298Sobrien/* .include -- include a file at this point.  */
507433965Sjdp
507577298Sobrienvoid
507633965Sjdps_include (arg)
507760484Sobrien     int arg ATTRIBUTE_UNUSED;
507833965Sjdp{
507933965Sjdp  char *filename;
508033965Sjdp  int i;
508133965Sjdp  FILE *try;
508233965Sjdp  char *path;
508333965Sjdp
508477298Sobrien  if (!flag_m68k_mri)
508538889Sjdp    {
508638889Sjdp      filename = demand_copy_string (&i);
508738889Sjdp      if (filename == NULL)
508838889Sjdp	{
508938889Sjdp	  /* demand_copy_string has already printed an error and
509038889Sjdp             called ignore_rest_of_line.  */
509138889Sjdp	  return;
509238889Sjdp	}
509338889Sjdp    }
509433965Sjdp  else
509533965Sjdp    {
509633965Sjdp      SKIP_WHITESPACE ();
509733965Sjdp      i = 0;
509877298Sobrien      while (!is_end_of_line[(unsigned char) *input_line_pointer]
509933965Sjdp	     && *input_line_pointer != ' '
510033965Sjdp	     && *input_line_pointer != '\t')
510133965Sjdp	{
510233965Sjdp	  obstack_1grow (&notes, *input_line_pointer);
510333965Sjdp	  ++input_line_pointer;
510433965Sjdp	  ++i;
510533965Sjdp	}
510677298Sobrien
510733965Sjdp      obstack_1grow (&notes, '\0');
510833965Sjdp      filename = obstack_finish (&notes);
510977298Sobrien      while (!is_end_of_line[(unsigned char) *input_line_pointer])
511033965Sjdp	++input_line_pointer;
511133965Sjdp    }
511277298Sobrien
511333965Sjdp  demand_empty_rest_of_line ();
511433965Sjdp  path = xmalloc ((unsigned long) i + include_dir_maxlen + 5 /* slop */ );
511577298Sobrien
511633965Sjdp  for (i = 0; i < include_dir_count; i++)
511733965Sjdp    {
511833965Sjdp      strcpy (path, include_dirs[i]);
511933965Sjdp      strcat (path, "/");
512033965Sjdp      strcat (path, filename);
512189857Sobrien      if (0 != (try = fopen (path, FOPEN_RT)))
512233965Sjdp	{
512333965Sjdp	  fclose (try);
512433965Sjdp	  goto gotit;
512533965Sjdp	}
512633965Sjdp    }
512777298Sobrien
512833965Sjdp  free (path);
512933965Sjdp  path = filename;
513033965Sjdpgotit:
513177298Sobrien  /* malloc Storage leak when file is found on path.  FIXME-SOMEDAY.  */
513238889Sjdp  register_dependency (path);
513360484Sobrien  input_scrub_insert_file (path);
513477298Sobrien}
513533965Sjdp
513677298Sobrienvoid
513733965Sjdpadd_include_dir (path)
513833965Sjdp     char *path;
513933965Sjdp{
514033965Sjdp  int i;
514133965Sjdp
514233965Sjdp  if (include_dir_count == 0)
514333965Sjdp    {
514433965Sjdp      include_dirs = (char **) xmalloc (2 * sizeof (*include_dirs));
514577298Sobrien      include_dirs[0] = ".";	/* Current dir.  */
514633965Sjdp      include_dir_count = 2;
514733965Sjdp    }
514833965Sjdp  else
514933965Sjdp    {
515033965Sjdp      include_dir_count++;
515177298Sobrien      include_dirs =
515277298Sobrien	(char **) realloc (include_dirs,
515377298Sobrien			   include_dir_count * sizeof (*include_dirs));
515433965Sjdp    }
515533965Sjdp
515677298Sobrien  include_dirs[include_dir_count - 1] = path;	/* New one.  */
515733965Sjdp
515833965Sjdp  i = strlen (path);
515933965Sjdp  if (i > include_dir_maxlen)
516033965Sjdp    include_dir_maxlen = i;
516177298Sobrien}
516260484Sobrien
516360484Sobrien/* Output debugging information to denote the source file.  */
516433965Sjdp
516560484Sobrienstatic void
516660484Sobriengenerate_file_debug ()
516760484Sobrien{
516860484Sobrien  if (debug_type == DEBUG_STABS)
516960484Sobrien    stabs_generate_asm_file ();
517060484Sobrien}
517160484Sobrien
517260484Sobrien/* Output line number debugging information for the current source line.  */
517360484Sobrien
517460484Sobrienvoid
517560484Sobriengenerate_lineno_debug ()
517660484Sobrien{
517760484Sobrien  switch (debug_type)
517860484Sobrien    {
517960484Sobrien    case DEBUG_UNSPECIFIED:
518060484Sobrien    case DEBUG_NONE:
518177298Sobrien    case DEBUG_DWARF:
518260484Sobrien      break;
518360484Sobrien    case DEBUG_STABS:
518460484Sobrien      stabs_generate_asm_lineno ();
518560484Sobrien      break;
518660484Sobrien    case DEBUG_ECOFF:
518760484Sobrien      ecoff_generate_asm_lineno ();
518860484Sobrien      break;
518960484Sobrien    case DEBUG_DWARF2:
519077298Sobrien      /* ??? We could here indicate to dwarf2dbg.c that something
519177298Sobrien	 has changed.  However, since there is additional backend
519277298Sobrien	 support that is required (calling dwarf2_emit_insn), we
519377298Sobrien	 let dwarf2dbg.c call as_where on its own.  */
519460484Sobrien      break;
519560484Sobrien    }
519660484Sobrien}
519760484Sobrien
519860484Sobrien/* Output debugging information to mark a function entry point or end point.
519960484Sobrien   END_P is zero for .func, and non-zero for .endfunc.  */
520060484Sobrien
520160484Sobrienvoid
520260484Sobriens_func (end_p)
520360484Sobrien     int end_p;
520460484Sobrien{
520560484Sobrien  do_s_func (end_p, NULL);
520660484Sobrien}
520760484Sobrien
520860484Sobrien/* Subroutine of s_func so targets can choose a different default prefix.
520960484Sobrien   If DEFAULT_PREFIX is NULL, use the target's "leading char".  */
521060484Sobrien
521160484Sobrienvoid
521260484Sobriendo_s_func (end_p, default_prefix)
521360484Sobrien     int end_p;
521460484Sobrien     const char *default_prefix;
521560484Sobrien{
521660484Sobrien  /* Record the current function so that we can issue an error message for
521760484Sobrien     misplaced .func,.endfunc, and also so that .endfunc needs no
521860484Sobrien     arguments.  */
521960484Sobrien  static char *current_name;
522060484Sobrien  static char *current_label;
522160484Sobrien
522260484Sobrien  if (end_p)
522360484Sobrien    {
522460484Sobrien      if (current_name == NULL)
522560484Sobrien	{
522660484Sobrien	  as_bad (_("missing .func"));
522760484Sobrien	  ignore_rest_of_line ();
522860484Sobrien	  return;
522960484Sobrien	}
523060484Sobrien
523160484Sobrien      if (debug_type == DEBUG_STABS)
523260484Sobrien	stabs_generate_asm_endfunc (current_name, current_label);
523360484Sobrien
523460484Sobrien      current_name = current_label = NULL;
523560484Sobrien    }
523660484Sobrien  else /* ! end_p */
523760484Sobrien    {
523877298Sobrien      char *name, *label;
523977298Sobrien      char delim1, delim2;
524060484Sobrien
524160484Sobrien      if (current_name != NULL)
524260484Sobrien	{
524360484Sobrien	  as_bad (_(".endfunc missing for previous .func"));
524460484Sobrien	  ignore_rest_of_line ();
524560484Sobrien	  return;
524660484Sobrien	}
524760484Sobrien
524860484Sobrien      name = input_line_pointer;
524960484Sobrien      delim1 = get_symbol_end ();
525060484Sobrien      name = xstrdup (name);
525160484Sobrien      *input_line_pointer = delim1;
525260484Sobrien      SKIP_WHITESPACE ();
525360484Sobrien      if (*input_line_pointer != ',')
525460484Sobrien	{
525560484Sobrien	  if (default_prefix)
525660484Sobrien	    asprintf (&label, "%s%s", default_prefix, name);
525760484Sobrien	  else
525860484Sobrien	    {
525960484Sobrien	      char leading_char = 0;
526060484Sobrien#ifdef BFD_ASSEMBLER
526160484Sobrien	      leading_char = bfd_get_symbol_leading_char (stdoutput);
526260484Sobrien#endif
526360484Sobrien	      /* Missing entry point, use function's name with the leading
526460484Sobrien		 char prepended.  */
526560484Sobrien	      if (leading_char)
526660484Sobrien		asprintf (&label, "%c%s", leading_char, name);
526760484Sobrien	      else
526860484Sobrien		label = name;
526960484Sobrien	    }
527060484Sobrien	}
527160484Sobrien      else
527260484Sobrien	{
527360484Sobrien	  ++input_line_pointer;
527460484Sobrien	  SKIP_WHITESPACE ();
527560484Sobrien	  label = input_line_pointer;
527660484Sobrien	  delim2 = get_symbol_end ();
527760484Sobrien	  label = xstrdup (label);
527860484Sobrien	  *input_line_pointer = delim2;
527960484Sobrien	}
528060484Sobrien
528160484Sobrien      if (debug_type == DEBUG_STABS)
528260484Sobrien	stabs_generate_asm_func (name, label);
528360484Sobrien
528460484Sobrien      current_name = name;
528560484Sobrien      current_label = label;
528660484Sobrien    }
528760484Sobrien
528860484Sobrien  demand_empty_rest_of_line ();
528960484Sobrien}
529060484Sobrien
529177298Sobrienvoid
529233965Sjdps_ignore (arg)
529360484Sobrien     int arg ATTRIBUTE_UNUSED;
529433965Sjdp{
529533965Sjdp  while (!is_end_of_line[(unsigned char) *input_line_pointer])
529633965Sjdp    {
529733965Sjdp      ++input_line_pointer;
529833965Sjdp    }
529933965Sjdp  ++input_line_pointer;
530033965Sjdp}
530133965Sjdp
530233965Sjdpvoid
530333965Sjdpread_print_statistics (file)
530433965Sjdp     FILE *file;
530533965Sjdp{
530633965Sjdp  hash_print_statistics (file, "pseudo-op table", po_hash);
530733965Sjdp}
530833965Sjdp
530977298Sobrien/* Inserts the given line into the input stream.
531077298Sobrien
531160484Sobrien   This call avoids macro/conditionals nesting checking, since the contents of
531260484Sobrien   the line are assumed to replace the contents of a line already scanned.
531360484Sobrien
531460484Sobrien   An appropriate use of this function would be substition of input lines when
531560484Sobrien   called by md_start_line_hook().  The given line is assumed to already be
531660484Sobrien   properly scrubbed.  */
531760484Sobrien
531860484Sobrienvoid
531960484Sobrieninput_scrub_insert_line (line)
532077298Sobrien     const char *line;
532160484Sobrien{
532260484Sobrien  sb newline;
532360484Sobrien  sb_new (&newline);
532460484Sobrien  sb_add_string (&newline, line);
532560484Sobrien  input_scrub_include_sb (&newline, input_line_pointer, 0);
532660484Sobrien  sb_kill (&newline);
532760484Sobrien  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
532860484Sobrien}
532960484Sobrien
533060484Sobrien/* Insert a file into the input stream; the path must resolve to an actual
533177298Sobrien   file; no include path searching or dependency registering is performed.  */
533260484Sobrien
533360484Sobrienvoid
533460484Sobrieninput_scrub_insert_file (path)
533577298Sobrien     char *path;
533660484Sobrien{
533760484Sobrien  input_scrub_include_file (path, input_line_pointer);
533860484Sobrien  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
533960484Sobrien}
5340