read.c revision 60484
133965Sjdp/* read.c - read a source file -
260484Sobrien   Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
360484Sobrien   2000 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
2033965Sjdp02111-1307, USA. */
2133965Sjdp
2233965Sjdp#if 0
2333965Sjdp#define MASK_CHAR (0xFF)	/* If your chars aren't 8 bits, you will
2433965Sjdp				   change this a bit.  But then, GNU isn't
2533965Sjdp				   spozed to run on your machine anyway.
2633965Sjdp				   (RMS is so shortsighted sometimes.)
2733965Sjdp				   */
2833965Sjdp#else
2933965Sjdp#define MASK_CHAR ((int)(unsigned char)-1)
3033965Sjdp#endif
3133965Sjdp
3233965Sjdp
3333965Sjdp/* This is the largest known floating point format (for now). It will
3433965Sjdp   grow when we do 4361 style flonums. */
3533965Sjdp
3633965Sjdp#define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)
3733965Sjdp
3833965Sjdp/* Routines that read assembler source text to build spagetti in memory.
3933965Sjdp   Another group of these functions is in the expr.c module.  */
4033965Sjdp
4133965Sjdp/* for isdigit() */
4233965Sjdp#include <ctype.h>
4333965Sjdp
4433965Sjdp#include "as.h"
4533965Sjdp#include "subsegs.h"
4633965Sjdp#include "sb.h"
4733965Sjdp#include "macro.h"
4833965Sjdp#include "obstack.h"
4933965Sjdp#include "listing.h"
5033965Sjdp#include "ecoff.h"
5133965Sjdp
5233965Sjdp#ifndef TC_START_LABEL
5333965Sjdp#define TC_START_LABEL(x,y) (x==':')
5433965Sjdp#endif
5533965Sjdp
5660484Sobrien/* Set by the object-format or the target.  */
5760484Sobrien#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
5860484Sobrien#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR)        \
5960484Sobrien do {                                                   \
6060484Sobrien  if ((SIZE) >= 8)                                      \
6160484Sobrien    (P2VAR) = 3;                                        \
6260484Sobrien  else if ((SIZE) >= 4)                                 \
6360484Sobrien    (P2VAR) = 2;                                        \
6460484Sobrien  else if ((SIZE) >= 2)                                 \
6560484Sobrien    (P2VAR) = 1;                                        \
6660484Sobrien  else                                                  \
6760484Sobrien    (P2VAR) = 0;                                        \
6860484Sobrien } while (0)
6960484Sobrien#endif
7060484Sobrien
7133965Sjdp/* The NOP_OPCODE is for the alignment fill value.
7233965Sjdp * fill it a nop instruction so that the disassembler does not choke
7333965Sjdp * on it
7433965Sjdp */
7533965Sjdp#ifndef NOP_OPCODE
7633965Sjdp#define NOP_OPCODE 0x00
7733965Sjdp#endif
7833965Sjdp
7933965Sjdpchar *input_line_pointer;	/*->next char of source file to parse. */
8033965Sjdp
8133965Sjdp#if BITS_PER_CHAR != 8
8233965Sjdp/*  The following table is indexed by[(char)] and will break if
8333965Sjdp    a char does not have exactly 256 states (hopefully 0:255!)!  */
8433965Sjdpdie horribly;
8533965Sjdp#endif
8633965Sjdp
8733965Sjdp#ifndef LEX_AT
8833965Sjdp/* The m88k unfortunately uses @ as a label beginner.  */
8933965Sjdp#define LEX_AT 0
9033965Sjdp#endif
9133965Sjdp
9233965Sjdp#ifndef LEX_BR
9333965Sjdp/* The RS/6000 assembler uses {,},[,] as parts of symbol names.  */
9433965Sjdp#define LEX_BR 0
9533965Sjdp#endif
9633965Sjdp
9733965Sjdp#ifndef LEX_PCT
9833965Sjdp/* The Delta 68k assembler permits % inside label names.  */
9933965Sjdp#define LEX_PCT 0
10033965Sjdp#endif
10133965Sjdp
10233965Sjdp#ifndef LEX_QM
10333965Sjdp/* The PowerPC Windows NT assemblers permits ? inside label names.  */
10433965Sjdp#define LEX_QM 0
10533965Sjdp#endif
10633965Sjdp
10760484Sobrien#ifndef LEX_HASH
10860484Sobrien#define LEX_HASH 0
10960484Sobrien#endif
11060484Sobrien
11133965Sjdp#ifndef LEX_DOLLAR
11233965Sjdp/* The a29k assembler does not permits labels to start with $.  */
11333965Sjdp#define LEX_DOLLAR 3
11433965Sjdp#endif
11533965Sjdp
11633965Sjdp#ifndef LEX_TILDE
11733965Sjdp/* The Delta 68k assembler permits ~ at start of label names.  */
11833965Sjdp#define LEX_TILDE 0
11933965Sjdp#endif
12033965Sjdp
12133965Sjdp/* used by is_... macros. our ctype[] */
12233965Sjdpchar lex_type[256] =
12333965Sjdp{
12433965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* @ABCDEFGHIJKLMNO */
12533965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* PQRSTUVWXYZ[\]^_ */
12660484Sobrien  0, 0, 0, LEX_HASH, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
12733965Sjdp  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM,	/* 0123456789:;<=>? */
12833965Sjdp  LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,	/* @ABCDEFGHIJKLMNO */
12933965Sjdp  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
13033965Sjdp  0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,	/* `abcdefghijklmno */
13133965Sjdp  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~. */
13260484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
13360484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
13460484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
13560484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
13660484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
13760484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
13860484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
13960484Sobrien  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
14033965Sjdp};
14133965Sjdp
14233965Sjdp
14333965Sjdp/*
14433965Sjdp * In: a character.
14533965Sjdp * Out: 1 if this character ends a line.
14633965Sjdp */
14760484Sobrien#define Z_ (0)
14833965Sjdpchar is_end_of_line[256] =
14933965Sjdp{
15033965Sjdp#ifdef CR_EOL
15160484Sobrien  99, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, 99, Z_, Z_, 99, Z_, Z_,	/* @abcdefghijklmno */
15233965Sjdp#else
15360484Sobrien  99, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, 99, Z_, Z_, Z_, Z_, Z_,	/* @abcdefghijklmno */
15433965Sjdp#endif
15560484Sobrien  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,	/* */
15633965Sjdp#ifdef TC_HPPA
15760484Sobrien  Z_,99, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,	/* _!"#$%&'()*+,-./ */
15860484Sobrien  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,	/* 0123456789:;<=>? */
15933965Sjdp#else
16060484Sobrien  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,	/* */
16160484Sobrien  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, 99, Z_, Z_, Z_, Z_,	/* 0123456789:;<=>? */
16233965Sjdp#endif
16360484Sobrien  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,	/* */
16460484Sobrien  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,	/* */
16560484Sobrien  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,	/* */
16660484Sobrien  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,	/* */
16760484Sobrien  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,	/* */
16860484Sobrien  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,	/* */
16960484Sobrien  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,	/* */
17060484Sobrien  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,	/* */
17160484Sobrien  Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_,	/* */
17233965Sjdp};
17360484Sobrien#undef Z_
17433965Sjdp
17533965Sjdp/* Functions private to this file. */
17633965Sjdp
17733965Sjdpstatic char *buffer;	/* 1st char of each buffer of lines is here. */
17833965Sjdpstatic char *buffer_limit;	/*->1 + last char in buffer. */
17933965Sjdp
18033965Sjdp/* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1 in the
18133965Sjdp   tc-<CPU>.h file.  See the "Porting GAS" section of the internals manual. */
18233965Sjdpint target_big_endian = TARGET_BYTES_BIG_ENDIAN;
18333965Sjdp
18433965Sjdpstatic char *old_buffer;	/* JF a hack */
18533965Sjdpstatic char *old_input;
18633965Sjdpstatic char *old_limit;
18733965Sjdp
18838889Sjdp/* Variables for handling include file directory table. */
18933965Sjdp
19038889Sjdpchar **include_dirs;	/* Table of pointers to directories to
19133965Sjdp			   search for .include's */
19238889Sjdpint include_dir_count;	/* How many are in the table */
19338889Sjdpint include_dir_maxlen = 1;/* Length of longest in table */
19433965Sjdp
19533965Sjdp#ifndef WORKING_DOT_WORD
19633965Sjdpstruct broken_word *broken_words;
19733965Sjdpint new_broken_words;
19833965Sjdp#endif
19933965Sjdp
20033965Sjdp/* The current offset into the absolute section.  We don't try to
20133965Sjdp   build frags in the absolute section, since no data can be stored
20233965Sjdp   there.  We just keep track of the current offset.  */
20333965SjdpaddressT abs_section_offset;
20433965Sjdp
20533965Sjdp/* If this line had an MRI style label, it is stored in this variable.
20633965Sjdp   This is used by some of the MRI pseudo-ops.  */
20733965SjdpsymbolS *line_label;
20833965Sjdp
20933965Sjdp/* This global variable is used to support MRI common sections.  We
21033965Sjdp   translate such sections into a common symbol.  This variable is
21133965Sjdp   non-NULL when we are in an MRI common section.  */
21233965SjdpsymbolS *mri_common_symbol;
21333965Sjdp
21433965Sjdp/* In MRI mode, after a dc.b pseudo-op with an odd number of bytes, we
21533965Sjdp   need to align to an even byte boundary unless the next pseudo-op is
21633965Sjdp   dc.b, ds.b, or dcb.b.  This variable is set to 1 if an alignment
21733965Sjdp   may be needed.  */
21833965Sjdpstatic int mri_pending_align;
21933965Sjdp
22038889Sjdp#ifndef NO_LISTING
22138889Sjdp#ifdef OBJ_ELF
22238889Sjdp/* This variable is set to be non-zero if the next string we see might
22338889Sjdp   be the name of the source file in DWARF debugging information.  See
22438889Sjdp   the comment in emit_expr for the format we look for.  */
22538889Sjdpstatic int dwarf_file_string;
22638889Sjdp#endif
22738889Sjdp#endif
22838889Sjdp
22933965Sjdpstatic void cons_worker PARAMS ((int, int));
23060484Sobrienstatic int scrub_from_string PARAMS ((char *, int));
23133965Sjdpstatic void do_align PARAMS ((int, char *, int, int));
23233965Sjdpstatic void s_align PARAMS ((int, int));
23360484Sobrienstatic void s_lcomm_internal PARAMS ((int, int));
23433965Sjdpstatic int hex_float PARAMS ((int, char *));
23560484Sobrienstatic inline int sizeof_sleb128 PARAMS ((offsetT));
23660484Sobrienstatic inline int sizeof_uleb128 PARAMS ((valueT));
23760484Sobrienstatic inline int output_sleb128 PARAMS ((char *, offsetT));
23860484Sobrienstatic inline int output_uleb128 PARAMS ((char *, valueT));
23960484Sobrienstatic inline int output_big_sleb128 PARAMS ((char *, LITTLENUM_TYPE *, int));
24060484Sobrienstatic inline int output_big_uleb128 PARAMS ((char *, LITTLENUM_TYPE *, int));
24160484Sobrienstatic int output_big_leb128 PARAMS ((char *, LITTLENUM_TYPE *, int, int));
24233965Sjdpstatic void do_org PARAMS ((segT, expressionS *, int));
24333965Sjdpchar *demand_copy_string PARAMS ((int *lenP));
24433965Sjdpstatic segT get_segmented_expression PARAMS ((expressionS *expP));
24533965Sjdpstatic segT get_known_segmented_expression PARAMS ((expressionS * expP));
24633965Sjdpstatic void pobegin PARAMS ((void));
24733965Sjdpstatic int get_line_sb PARAMS ((sb *));
24860484Sobrienstatic void generate_file_debug PARAMS ((void));
24933965Sjdp
25033965Sjdp
25133965Sjdpvoid
25233965Sjdpread_begin ()
25333965Sjdp{
25433965Sjdp  const char *p;
25533965Sjdp
25633965Sjdp  pobegin ();
25733965Sjdp  obj_read_begin_hook ();
25833965Sjdp
25933965Sjdp  /* Something close -- but not too close -- to a multiple of 1024.
26033965Sjdp     The debugging malloc I'm using has 24 bytes of overhead.  */
26133965Sjdp  obstack_begin (&notes, chunksize);
26233965Sjdp  obstack_begin (&cond_obstack, chunksize);
26333965Sjdp
26433965Sjdp  /* Use machine dependent syntax */
26533965Sjdp  for (p = line_separator_chars; *p; p++)
26633965Sjdp    is_end_of_line[(unsigned char) *p] = 1;
26733965Sjdp  /* Use more.  FIXME-SOMEDAY. */
26833965Sjdp
26933965Sjdp  if (flag_mri)
27033965Sjdp    lex_type['?'] = 3;
27133965Sjdp}
27233965Sjdp
27333965Sjdp/* set up pseudo-op tables */
27433965Sjdp
27533965Sjdpstatic struct hash_control *po_hash;
27633965Sjdp
27733965Sjdpstatic const pseudo_typeS potable[] =
27833965Sjdp{
27933965Sjdp  {"abort", s_abort, 0},
28033965Sjdp  {"align", s_align_ptwo, 0},
28133965Sjdp  {"ascii", stringer, 0},
28233965Sjdp  {"asciz", stringer, 1},
28333965Sjdp  {"balign", s_align_bytes, 0},
28433965Sjdp  {"balignw", s_align_bytes, -2},
28533965Sjdp  {"balignl", s_align_bytes, -4},
28633965Sjdp/* block */
28733965Sjdp  {"byte", cons, 1},
28833965Sjdp  {"comm", s_comm, 0},
28933965Sjdp  {"common", s_mri_common, 0},
29033965Sjdp  {"common.s", s_mri_common, 1},
29133965Sjdp  {"data", s_data, 0},
29233965Sjdp  {"dc", cons, 2},
29333965Sjdp  {"dc.b", cons, 1},
29433965Sjdp  {"dc.d", float_cons, 'd'},
29533965Sjdp  {"dc.l", cons, 4},
29633965Sjdp  {"dc.s", float_cons, 'f'},
29733965Sjdp  {"dc.w", cons, 2},
29833965Sjdp  {"dc.x", float_cons, 'x'},
29933965Sjdp  {"dcb", s_space, 2},
30033965Sjdp  {"dcb.b", s_space, 1},
30133965Sjdp  {"dcb.d", s_float_space, 'd'},
30233965Sjdp  {"dcb.l", s_space, 4},
30333965Sjdp  {"dcb.s", s_float_space, 'f'},
30433965Sjdp  {"dcb.w", s_space, 2},
30533965Sjdp  {"dcb.x", s_float_space, 'x'},
30633965Sjdp  {"ds", s_space, 2},
30733965Sjdp  {"ds.b", s_space, 1},
30833965Sjdp  {"ds.d", s_space, 8},
30933965Sjdp  {"ds.l", s_space, 4},
31033965Sjdp  {"ds.p", s_space, 12},
31133965Sjdp  {"ds.s", s_space, 4},
31233965Sjdp  {"ds.w", s_space, 2},
31333965Sjdp  {"ds.x", s_space, 12},
31433965Sjdp  {"debug", s_ignore, 0},
31533965Sjdp#ifdef S_SET_DESC
31633965Sjdp  {"desc", s_desc, 0},
31733965Sjdp#endif
31833965Sjdp/* dim */
31933965Sjdp  {"double", float_cons, 'd'},
32033965Sjdp/* dsect */
32133965Sjdp  {"eject", listing_eject, 0},	/* Formfeed listing */
32233965Sjdp  {"else", s_else, 0},
32333965Sjdp  {"elsec", s_else, 0},
32460484Sobrien  {"elseif", s_elseif, (int) O_ne},
32533965Sjdp  {"end", s_end, 0},
32633965Sjdp  {"endc", s_endif, 0},
32760484Sobrien  {"endfunc", s_func, 1},
32833965Sjdp  {"endif", s_endif, 0},
32933965Sjdp/* endef */
33033965Sjdp  {"equ", s_set, 0},
33133965Sjdp  {"equiv", s_set, 1},
33233965Sjdp  {"err", s_err, 0},
33333965Sjdp  {"exitm", s_mexit, 0},
33433965Sjdp/* extend */
33533965Sjdp  {"extern", s_ignore, 0},	/* We treat all undef as ext */
33633965Sjdp  {"appfile", s_app_file, 1},
33733965Sjdp  {"appline", s_app_line, 0},
33833965Sjdp  {"fail", s_fail, 0},
33933965Sjdp  {"file", s_app_file, 0},
34033965Sjdp  {"fill", s_fill, 0},
34133965Sjdp  {"float", float_cons, 'f'},
34233965Sjdp  {"format", s_ignore, 0},
34360484Sobrien  {"func", s_func, 0},
34433965Sjdp  {"global", s_globl, 0},
34533965Sjdp  {"globl", s_globl, 0},
34633965Sjdp  {"hword", cons, 2},
34733965Sjdp  {"if", s_if, (int) O_ne},
34833965Sjdp  {"ifc", s_ifc, 0},
34933965Sjdp  {"ifdef", s_ifdef, 0},
35033965Sjdp  {"ifeq", s_if, (int) O_eq},
35133965Sjdp  {"ifeqs", s_ifeqs, 0},
35233965Sjdp  {"ifge", s_if, (int) O_ge},
35333965Sjdp  {"ifgt", s_if, (int) O_gt},
35433965Sjdp  {"ifle", s_if, (int) O_le},
35533965Sjdp  {"iflt", s_if, (int) O_lt},
35633965Sjdp  {"ifnc", s_ifc, 1},
35733965Sjdp  {"ifndef", s_ifdef, 1},
35833965Sjdp  {"ifne", s_if, (int) O_ne},
35933965Sjdp  {"ifnes", s_ifeqs, 1},
36033965Sjdp  {"ifnotdef", s_ifdef, 1},
36133965Sjdp  {"include", s_include, 0},
36233965Sjdp  {"int", cons, 4},
36333965Sjdp  {"irp", s_irp, 0},
36433965Sjdp  {"irep", s_irp, 0},
36533965Sjdp  {"irpc", s_irp, 1},
36633965Sjdp  {"irepc", s_irp, 1},
36733965Sjdp  {"lcomm", s_lcomm, 0},
36833965Sjdp  {"lflags", listing_flags, 0},	/* Listing flags */
36933965Sjdp  {"linkonce", s_linkonce, 0},
37033965Sjdp  {"list", listing_list, 1},	/* Turn listing on */
37133965Sjdp  {"llen", listing_psize, 1},
37233965Sjdp  {"long", cons, 4},
37333965Sjdp  {"lsym", s_lsym, 0},
37433965Sjdp  {"macro", s_macro, 0},
37533965Sjdp  {"mexit", s_mexit, 0},
37633965Sjdp  {"mri", s_mri, 0},
37733965Sjdp  {".mri", s_mri, 0},	/* Special case so .mri works in MRI mode.  */
37833965Sjdp  {"name", s_ignore, 0},
37933965Sjdp  {"noformat", s_ignore, 0},
38033965Sjdp  {"nolist", listing_list, 0},	/* Turn listing off */
38133965Sjdp  {"nopage", listing_nopage, 0},
38233965Sjdp  {"octa", cons, 16},
38333965Sjdp  {"offset", s_struct, 0},
38433965Sjdp  {"org", s_org, 0},
38533965Sjdp  {"p2align", s_align_ptwo, 0},
38633965Sjdp  {"p2alignw", s_align_ptwo, -2},
38733965Sjdp  {"p2alignl", s_align_ptwo, -4},
38833965Sjdp  {"page", listing_eject, 0},
38933965Sjdp  {"plen", listing_psize, 0},
39033965Sjdp  {"print", s_print, 0},
39133965Sjdp  {"psize", listing_psize, 0},	/* set paper size */
39233965Sjdp  {"purgem", s_purgem, 0},
39333965Sjdp  {"quad", cons, 8},
39433965Sjdp  {"rep", s_rept, 0},
39533965Sjdp  {"rept", s_rept, 0},
39633965Sjdp  {"rva", s_rva, 4},
39733965Sjdp  {"sbttl", listing_title, 1},	/* Subtitle of listing */
39833965Sjdp/* scl */
39933965Sjdp/* sect */
40033965Sjdp  {"set", s_set, 0},
40133965Sjdp  {"short", cons, 2},
40233965Sjdp  {"single", float_cons, 'f'},
40333965Sjdp/* size */
40433965Sjdp  {"space", s_space, 0},
40533965Sjdp  {"skip", s_space, 0},
40638889Sjdp  {"sleb128", s_leb128, 1},
40733965Sjdp  {"spc", s_ignore, 0},
40833965Sjdp  {"stabd", s_stab, 'd'},
40933965Sjdp  {"stabn", s_stab, 'n'},
41033965Sjdp  {"stabs", s_stab, 's'},
41133965Sjdp  {"string", stringer, 1},
41233965Sjdp  {"struct", s_struct, 0},
41333965Sjdp/* tag */
41433965Sjdp  {"text", s_text, 0},
41533965Sjdp
41633965Sjdp  /* This is for gcc to use.  It's only just been added (2/94), so gcc
41733965Sjdp     won't be able to use it for a while -- probably a year or more.
41833965Sjdp     But once this has been released, check with gcc maintainers
41933965Sjdp     before deleting it or even changing the spelling.  */
42033965Sjdp  {"this_GCC_requires_the_GNU_assembler", s_ignore, 0},
42133965Sjdp  /* If we're folding case -- done for some targets, not necessarily
42233965Sjdp     all -- the above string in an input file will be converted to
42333965Sjdp     this one.  Match it either way...  */
42433965Sjdp  {"this_gcc_requires_the_gnu_assembler", s_ignore, 0},
42533965Sjdp
42633965Sjdp  {"title", listing_title, 0},	/* Listing title */
42733965Sjdp  {"ttl", listing_title, 0},
42833965Sjdp/* type */
42938889Sjdp  {"uleb128", s_leb128, 0},
43033965Sjdp/* use */
43133965Sjdp/* val */
43233965Sjdp  {"xcom", s_comm, 0},
43333965Sjdp  {"xdef", s_globl, 0},
43433965Sjdp  {"xref", s_ignore, 0},
43533965Sjdp  {"xstabs", s_xstab, 's'},
43633965Sjdp  {"word", cons, 2},
43733965Sjdp  {"zero", s_space, 0},
43860484Sobrien  {NULL, NULL, 0}			/* end sentinel */
43933965Sjdp};
44033965Sjdp
44133965Sjdpstatic int pop_override_ok = 0;
44233965Sjdpstatic const char *pop_table_name;
44333965Sjdp
44433965Sjdpvoid
44533965Sjdppop_insert (table)
44633965Sjdp     const pseudo_typeS *table;
44733965Sjdp{
44833965Sjdp  const char *errtxt;
44933965Sjdp  const pseudo_typeS *pop;
45033965Sjdp  for (pop = table; pop->poc_name; pop++)
45133965Sjdp    {
45233965Sjdp      errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
45333965Sjdp      if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists")))
45460484Sobrien	as_fatal (_("error constructing %s pseudo-op table: %s"), pop_table_name,
45533965Sjdp		  errtxt);
45633965Sjdp    }
45733965Sjdp}
45833965Sjdp
45933965Sjdp#ifndef md_pop_insert
46033965Sjdp#define md_pop_insert()		pop_insert(md_pseudo_table)
46133965Sjdp#endif
46233965Sjdp
46333965Sjdp#ifndef obj_pop_insert
46433965Sjdp#define obj_pop_insert()	pop_insert(obj_pseudo_table)
46533965Sjdp#endif
46633965Sjdp
46733965Sjdpstatic void
46833965Sjdppobegin ()
46933965Sjdp{
47033965Sjdp  po_hash = hash_new ();
47133965Sjdp
47233965Sjdp  /* Do the target-specific pseudo ops. */
47333965Sjdp  pop_table_name = "md";
47433965Sjdp  md_pop_insert ();
47533965Sjdp
47633965Sjdp  /* Now object specific.  Skip any that were in the target table. */
47733965Sjdp  pop_table_name = "obj";
47833965Sjdp  pop_override_ok = 1;
47933965Sjdp  obj_pop_insert ();
48033965Sjdp
48133965Sjdp  /* Now portable ones.  Skip any that we've seen already. */
48233965Sjdp  pop_table_name = "standard";
48333965Sjdp  pop_insert (potable);
48433965Sjdp}
48533965Sjdp
48633965Sjdp#define HANDLE_CONDITIONAL_ASSEMBLY()					\
48733965Sjdp  if (ignore_input ())							\
48833965Sjdp    {									\
48933965Sjdp      while (! is_end_of_line[(unsigned char) *input_line_pointer++])	\
49033965Sjdp	if (input_line_pointer == buffer_limit)				\
49133965Sjdp	  break;							\
49233965Sjdp      continue;								\
49333965Sjdp    }
49433965Sjdp
49533965Sjdp
49633965Sjdp/* This function is used when scrubbing the characters between #APP
49733965Sjdp   and #NO_APP.  */
49833965Sjdp
49933965Sjdpstatic char *scrub_string;
50033965Sjdpstatic char *scrub_string_end;
50133965Sjdp
50233965Sjdpstatic int
50360484Sobrienscrub_from_string (buf, buflen)
50460484Sobrien     char *buf;
50560484Sobrien     int buflen;
50633965Sjdp{
50760484Sobrien  int copy;
50833965Sjdp
50960484Sobrien  copy = scrub_string_end - scrub_string;
51060484Sobrien  if (copy > buflen)
51160484Sobrien    copy = buflen;
51260484Sobrien  memcpy (buf, scrub_string, copy);
51360484Sobrien  scrub_string += copy;
51460484Sobrien  return copy;
51533965Sjdp}
51633965Sjdp
51733965Sjdp/*	read_a_source_file()
51833965Sjdp *
51933965Sjdp * We read the file, putting things into a web that
52033965Sjdp * represents what we have been reading.
52133965Sjdp */
52233965Sjdpvoid
52333965Sjdpread_a_source_file (name)
52433965Sjdp     char *name;
52533965Sjdp{
52633965Sjdp  register char c;
52733965Sjdp  register char *s;		/* string of symbol, '\0' appended */
52833965Sjdp  register int temp;
52933965Sjdp  pseudo_typeS *pop;
53033965Sjdp
53133965Sjdp  buffer = input_scrub_new_file (name);
53233965Sjdp
53333965Sjdp  listing_file (name);
53438889Sjdp  listing_newline (NULL);
53538889Sjdp  register_dependency (name);
53633965Sjdp
53760484Sobrien  /* Generate debugging information before we've read anything in to denote
53860484Sobrien     this file as the "main" source file and not a subordinate one
53960484Sobrien     (e.g. N_SO vs N_SOL in stabs).  */
54060484Sobrien  generate_file_debug ();
54160484Sobrien
54233965Sjdp  while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0)
54333965Sjdp    {				/* We have another line to parse. */
54433965Sjdp      know (buffer_limit[-1] == '\n');	/* Must have a sentinel. */
54533965Sjdp    contin:			/* JF this goto is my fault I admit it.
54633965Sjdp				   Someone brave please re-write the whole
54733965Sjdp				   input section here?  Pleeze???  */
54833965Sjdp      while (input_line_pointer < buffer_limit)
54933965Sjdp	{
55033965Sjdp	  /* We have more of this buffer to parse. */
55133965Sjdp
55233965Sjdp	  /*
55333965Sjdp	   * We now have input_line_pointer->1st char of next line.
55433965Sjdp	   * If input_line_pointer [-1] == '\n' then we just
55533965Sjdp	   * scanned another line: so bump line counters.
55633965Sjdp	   */
55733965Sjdp	  if (is_end_of_line[(unsigned char) input_line_pointer[-1]])
55833965Sjdp	    {
55933965Sjdp#ifdef md_start_line_hook
56033965Sjdp	      md_start_line_hook ();
56133965Sjdp#endif
56233965Sjdp
56333965Sjdp	      if (input_line_pointer[-1] == '\n')
56433965Sjdp		bump_line_counters ();
56533965Sjdp
56633965Sjdp	      line_label = NULL;
56733965Sjdp
56860484Sobrien	      if (LABELS_WITHOUT_COLONS || flag_m68k_mri)
56933965Sjdp		{
57033965Sjdp		  /* Text at the start of a line must be a label, we
57133965Sjdp		     run down and stick a colon in.  */
57233965Sjdp		  if (is_name_beginner (*input_line_pointer))
57333965Sjdp		    {
57433965Sjdp		      char *line_start = input_line_pointer;
57533965Sjdp		      char c;
57633965Sjdp		      int mri_line_macro;
57733965Sjdp
57833965Sjdp		      LISTING_NEWLINE ();
57933965Sjdp		      HANDLE_CONDITIONAL_ASSEMBLY ();
58033965Sjdp
58133965Sjdp		      c = get_symbol_end ();
58233965Sjdp
58333965Sjdp		      /* In MRI mode, the EQU and MACRO pseudoops must
58433965Sjdp			 be handled specially.  */
58533965Sjdp		      mri_line_macro = 0;
58633965Sjdp		      if (flag_m68k_mri)
58733965Sjdp			{
58833965Sjdp			  char *rest = input_line_pointer + 1;
58933965Sjdp
59033965Sjdp			  if (*rest == ':')
59133965Sjdp			    ++rest;
59233965Sjdp			  if (*rest == ' ' || *rest == '\t')
59333965Sjdp			    ++rest;
59433965Sjdp			  if ((strncasecmp (rest, "EQU", 3) == 0
59533965Sjdp			       || strncasecmp (rest, "SET", 3) == 0)
59633965Sjdp			      && (rest[3] == ' ' || rest[3] == '\t'))
59733965Sjdp			    {
59833965Sjdp			      input_line_pointer = rest + 3;
59933965Sjdp			      equals (line_start,
60033965Sjdp				      strncasecmp (rest, "SET", 3) == 0);
60133965Sjdp			      continue;
60233965Sjdp			    }
60333965Sjdp			  if (strncasecmp (rest, "MACRO", 5) == 0
60433965Sjdp			      && (rest[5] == ' '
60533965Sjdp				  || rest[5] == '\t'
60633965Sjdp				  || is_end_of_line[(unsigned char) rest[5]]))
60733965Sjdp			    mri_line_macro = 1;
60833965Sjdp			}
60933965Sjdp
61033965Sjdp		      /* In MRI mode, we need to handle the MACRO
61133965Sjdp                         pseudo-op specially: we don't want to put the
61233965Sjdp                         symbol in the symbol table.  */
61360484Sobrien		      if (! mri_line_macro
61460484Sobrien#ifdef TC_START_LABEL_WITHOUT_COLON
61560484Sobrien                          && TC_START_LABEL_WITHOUT_COLON(c,
61660484Sobrien                                                          input_line_pointer)
61760484Sobrien#endif
61860484Sobrien                          )
61933965Sjdp			line_label = colon (line_start);
62033965Sjdp		      else
62133965Sjdp			line_label = symbol_create (line_start,
62233965Sjdp						    absolute_section,
62333965Sjdp						    (valueT) 0,
62433965Sjdp						    &zero_address_frag);
62533965Sjdp
62633965Sjdp		      *input_line_pointer = c;
62733965Sjdp		      if (c == ':')
62833965Sjdp			input_line_pointer++;
62933965Sjdp		    }
63033965Sjdp		}
63133965Sjdp	    }
63233965Sjdp
63333965Sjdp	  /*
63433965Sjdp	   * We are at the begining of a line, or similar place.
63533965Sjdp	   * We expect a well-formed assembler statement.
63633965Sjdp	   * A "symbol-name:" is a statement.
63733965Sjdp	   *
63833965Sjdp	   * Depending on what compiler is used, the order of these tests
63933965Sjdp	   * may vary to catch most common case 1st.
64033965Sjdp	   * Each test is independent of all other tests at the (top) level.
64133965Sjdp	   * PLEASE make a compiler that doesn't use this assembler.
64233965Sjdp	   * It is crufty to waste a compiler's time encoding things for this
64333965Sjdp	   * assembler, which then wastes more time decoding it.
64433965Sjdp	   * (And communicating via (linear) files is silly!
64533965Sjdp	   * If you must pass stuff, please pass a tree!)
64633965Sjdp	   */
64733965Sjdp	  if ((c = *input_line_pointer++) == '\t'
64833965Sjdp	      || c == ' '
64933965Sjdp	      || c == '\f'
65033965Sjdp	      || c == 0)
65133965Sjdp	    {
65233965Sjdp	      c = *input_line_pointer++;
65333965Sjdp	    }
65433965Sjdp	  know (c != ' ');	/* No further leading whitespace. */
65538889Sjdp
65638889Sjdp#ifndef NO_LISTING
65738889Sjdp	  /* If listing is on, and we are expanding a macro, then give
65838889Sjdp	     the listing code the contents of the expanded line.  */
65938889Sjdp	  if (listing)
66038889Sjdp	    {
66138889Sjdp	      if ((listing & LISTING_MACEXP) && macro_nest > 0)
66238889Sjdp		{
66338889Sjdp		  char *copy;
66438889Sjdp		  int len;
66538889Sjdp
66638889Sjdp		  /* Find the end of the current expanded macro line.  */
66738889Sjdp		  for (s = input_line_pointer-1; *s ; ++s)
66838889Sjdp		    if (is_end_of_line[(unsigned char) *s])
66938889Sjdp		      break;
67038889Sjdp
67138889Sjdp		  /* Copy it for safe keeping.  Also give an indication of
67238889Sjdp		     how much macro nesting is involved at this point.  */
67338889Sjdp		  len = s - (input_line_pointer-1);
67438889Sjdp		  copy = (char *) xmalloc (len + macro_nest + 2);
67538889Sjdp		  memset (copy, '>', macro_nest);
67638889Sjdp		  copy[macro_nest] = ' ';
67738889Sjdp		  memcpy (copy + macro_nest + 1, input_line_pointer-1, len);
67838889Sjdp		  copy[macro_nest+1+len] = '\0';
67938889Sjdp
68038889Sjdp		  /* Install the line with the listing facility.  */
68138889Sjdp		  listing_newline (copy);
68238889Sjdp		}
68338889Sjdp	      else
68438889Sjdp		listing_newline (NULL);
68538889Sjdp	    }
68638889Sjdp#endif
68738889Sjdp
68833965Sjdp	  /*
68933965Sjdp	   * C is the 1st significant character.
69033965Sjdp	   * Input_line_pointer points after that character.
69133965Sjdp	   */
69233965Sjdp	  if (is_name_beginner (c))
69333965Sjdp	    {
69433965Sjdp	      /* want user-defined label or pseudo/opcode */
69533965Sjdp	      HANDLE_CONDITIONAL_ASSEMBLY ();
69633965Sjdp
69733965Sjdp	      s = --input_line_pointer;
69833965Sjdp	      c = get_symbol_end ();	/* name's delimiter */
69933965Sjdp	      /*
70033965Sjdp	       * C is character after symbol.
70133965Sjdp	       * That character's place in the input line is now '\0'.
70233965Sjdp	       * S points to the beginning of the symbol.
70333965Sjdp	       *   [In case of pseudo-op, s->'.'.]
70433965Sjdp	       * Input_line_pointer->'\0' where c was.
70533965Sjdp	       */
70633965Sjdp	      if (TC_START_LABEL(c, input_line_pointer))
70733965Sjdp		{
70833965Sjdp		  if (flag_m68k_mri)
70933965Sjdp		    {
71033965Sjdp		      char *rest = input_line_pointer + 1;
71133965Sjdp
71233965Sjdp		      /* In MRI mode, \tsym: set 0 is permitted.  */
71333965Sjdp
71433965Sjdp		      if (*rest == ':')
71533965Sjdp			++rest;
71633965Sjdp		      if (*rest == ' ' || *rest == '\t')
71733965Sjdp			++rest;
71833965Sjdp		      if ((strncasecmp (rest, "EQU", 3) == 0
71933965Sjdp			   || strncasecmp (rest, "SET", 3) == 0)
72033965Sjdp			  && (rest[3] == ' ' || rest[3] == '\t'))
72133965Sjdp			{
72233965Sjdp			  input_line_pointer = rest + 3;
72333965Sjdp			  equals (s, 1);
72433965Sjdp			  continue;
72533965Sjdp			}
72633965Sjdp		    }
72733965Sjdp
72833965Sjdp		  line_label = colon (s);	/* user-defined label */
72933965Sjdp		  *input_line_pointer++ = ':';	/* Put ':' back for error messages' sake. */
73033965Sjdp		  /* Input_line_pointer->after ':'. */
73133965Sjdp		  SKIP_WHITESPACE ();
73233965Sjdp
73333965Sjdp
73433965Sjdp		}
73533965Sjdp	      else if (c == '='
73633965Sjdp		       || ((c == ' ' || c == '\t')
73733965Sjdp			   && input_line_pointer[1] == '='
73833965Sjdp#ifdef TC_EQUAL_IN_INSN
73933965Sjdp			   && ! TC_EQUAL_IN_INSN (c, input_line_pointer)
74033965Sjdp#endif
74133965Sjdp			   ))
74233965Sjdp		{
74333965Sjdp		  equals (s, 1);
74433965Sjdp		  demand_empty_rest_of_line ();
74533965Sjdp		}
74633965Sjdp	      else
74733965Sjdp		{		/* expect pseudo-op or machine instruction */
74833965Sjdp		  pop = NULL;
74933965Sjdp
75033965Sjdp#define IGNORE_OPCODE_CASE
75133965Sjdp#ifdef IGNORE_OPCODE_CASE
75233965Sjdp		  {
75333965Sjdp		    char *s2 = s;
75433965Sjdp		    while (*s2)
75533965Sjdp		      {
75638889Sjdp			if (isupper ((unsigned char) *s2))
75733965Sjdp			  *s2 = tolower (*s2);
75833965Sjdp			s2++;
75933965Sjdp		      }
76033965Sjdp		  }
76133965Sjdp#endif
76233965Sjdp
76360484Sobrien		  if (NO_PSEUDO_DOT || flag_m68k_mri)
76433965Sjdp		    {
76533965Sjdp		      /* The MRI assembler and the m88k use pseudo-ops
76633965Sjdp                         without a period.  */
76733965Sjdp		      pop = (pseudo_typeS *) hash_find (po_hash, s);
76833965Sjdp		      if (pop != NULL && pop->poc_handler == NULL)
76933965Sjdp			pop = NULL;
77033965Sjdp		    }
77133965Sjdp
77233965Sjdp		  if (pop != NULL
77333965Sjdp		      || (! flag_m68k_mri && *s == '.'))
77433965Sjdp		    {
77533965Sjdp		      /*
77633965Sjdp		       * PSEUDO - OP.
77733965Sjdp		       *
77833965Sjdp		       * WARNING: c has next char, which may be end-of-line.
77933965Sjdp		       * We lookup the pseudo-op table with s+1 because we
78033965Sjdp		       * already know that the pseudo-op begins with a '.'.
78133965Sjdp		       */
78233965Sjdp
78333965Sjdp		      if (pop == NULL)
78433965Sjdp			pop = (pseudo_typeS *) hash_find (po_hash, s + 1);
78533965Sjdp
78633965Sjdp		      /* In MRI mode, we may need to insert an
78733965Sjdp                         automatic alignment directive.  What a hack
78833965Sjdp                         this is.  */
78933965Sjdp		      if (mri_pending_align
79033965Sjdp			  && (pop == NULL
79133965Sjdp			      || ! ((pop->poc_handler == cons
79233965Sjdp				     && pop->poc_val == 1)
79333965Sjdp				    || (pop->poc_handler == s_space
79433965Sjdp					&& pop->poc_val == 1)
79533965Sjdp#ifdef tc_conditional_pseudoop
79633965Sjdp				    || tc_conditional_pseudoop (pop)
79733965Sjdp#endif
79833965Sjdp				    || pop->poc_handler == s_if
79933965Sjdp				    || pop->poc_handler == s_ifdef
80033965Sjdp				    || pop->poc_handler == s_ifc
80133965Sjdp				    || pop->poc_handler == s_ifeqs
80233965Sjdp				    || pop->poc_handler == s_else
80333965Sjdp				    || pop->poc_handler == s_endif
80433965Sjdp				    || pop->poc_handler == s_globl
80533965Sjdp				    || pop->poc_handler == s_ignore)))
80633965Sjdp			{
80733965Sjdp			  do_align (1, (char *) NULL, 0, 0);
80833965Sjdp			  mri_pending_align = 0;
80933965Sjdp			  if (line_label != NULL)
81033965Sjdp			    {
81160484Sobrien			      symbol_set_frag (line_label, frag_now);
81233965Sjdp			      S_SET_VALUE (line_label, frag_now_fix ());
81333965Sjdp			    }
81433965Sjdp			}
81533965Sjdp
81633965Sjdp		      /* Print the error msg now, while we still can */
81733965Sjdp		      if (pop == NULL)
81833965Sjdp			{
81960484Sobrien			  as_bad (_("Unknown pseudo-op:  `%s'"), s);
82033965Sjdp			  *input_line_pointer = c;
82133965Sjdp			  s_ignore (0);
82233965Sjdp			  continue;
82333965Sjdp			}
82433965Sjdp
82533965Sjdp		      /* Put it back for error messages etc. */
82633965Sjdp		      *input_line_pointer = c;
82733965Sjdp		      /* The following skip of whitespace is compulsory.
82833965Sjdp			 A well shaped space is sometimes all that separates
82933965Sjdp			 keyword from operands. */
83033965Sjdp		      if (c == ' ' || c == '\t')
83133965Sjdp			input_line_pointer++;
83233965Sjdp		      /*
83333965Sjdp		       * Input_line is restored.
83433965Sjdp		       * Input_line_pointer->1st non-blank char
83533965Sjdp		       * after pseudo-operation.
83633965Sjdp		       */
83733965Sjdp		      (*pop->poc_handler) (pop->poc_val);
83833965Sjdp
83933965Sjdp		      /* If that was .end, just get out now.  */
84033965Sjdp		      if (pop->poc_handler == s_end)
84133965Sjdp			goto quit;
84233965Sjdp		    }
84333965Sjdp		  else
84433965Sjdp		    {
84533965Sjdp		      int inquote = 0;
84660484Sobrien#ifdef QUOTES_IN_INSN
84760484Sobrien		      int inescape = 0;
84860484Sobrien#endif
84933965Sjdp
85033965Sjdp		      /* WARNING: c has char, which may be end-of-line. */
85133965Sjdp		      /* Also: input_line_pointer->`\0` where c was. */
85233965Sjdp		      *input_line_pointer = c;
85333965Sjdp		      while (!is_end_of_line[(unsigned char) *input_line_pointer]
85433965Sjdp			     || inquote
85533965Sjdp#ifdef TC_EOL_IN_INSN
85633965Sjdp			     || TC_EOL_IN_INSN (input_line_pointer)
85733965Sjdp#endif
85833965Sjdp			     )
85933965Sjdp			{
86033965Sjdp			  if (flag_m68k_mri && *input_line_pointer == '\'')
86133965Sjdp			    inquote = ! inquote;
86260484Sobrien#ifdef QUOTES_IN_INSN
86360484Sobrien			  if (inescape)
86460484Sobrien			    inescape = 0;
86560484Sobrien			  else if (*input_line_pointer == '"')
86660484Sobrien			    inquote = ! inquote;
86760484Sobrien			  else if (*input_line_pointer == '\\')
86860484Sobrien			    inescape = 1;
86960484Sobrien#endif
87033965Sjdp			  input_line_pointer++;
87133965Sjdp			}
87233965Sjdp
87333965Sjdp		      c = *input_line_pointer;
87433965Sjdp		      *input_line_pointer = '\0';
87533965Sjdp
87660484Sobrien		      generate_lineno_debug ();
87738889Sjdp
87833965Sjdp		      if (macro_defined)
87933965Sjdp			{
88033965Sjdp			  sb out;
88133965Sjdp			  const char *err;
88260484Sobrien                          macro_entry *macro;
88333965Sjdp
88460484Sobrien			  if (check_macro (s, &out, '\0', &err, &macro))
88533965Sjdp			    {
88633965Sjdp			      if (err != NULL)
88760484Sobrien				as_bad ("%s", err);
88833965Sjdp			      *input_line_pointer++ = c;
88933965Sjdp			      input_scrub_include_sb (&out,
89060484Sobrien						      input_line_pointer, 1);
89133965Sjdp			      sb_kill (&out);
89233965Sjdp			      buffer_limit =
89333965Sjdp				input_scrub_next_buffer (&input_line_pointer);
89460484Sobrien#ifdef md_macro_info
89560484Sobrien                              md_macro_info (macro);
89660484Sobrien#endif
89733965Sjdp			      continue;
89833965Sjdp			    }
89933965Sjdp			}
90033965Sjdp
90133965Sjdp		      if (mri_pending_align)
90233965Sjdp			{
90333965Sjdp			  do_align (1, (char *) NULL, 0, 0);
90433965Sjdp			  mri_pending_align = 0;
90533965Sjdp			  if (line_label != NULL)
90633965Sjdp			    {
90760484Sobrien			      symbol_set_frag (line_label, frag_now);
90833965Sjdp			      S_SET_VALUE (line_label, frag_now_fix ());
90933965Sjdp			    }
91033965Sjdp			}
91133965Sjdp
91233965Sjdp		      md_assemble (s);	/* Assemble 1 instruction. */
91333965Sjdp
91433965Sjdp		      *input_line_pointer++ = c;
91533965Sjdp
91633965Sjdp		      /* We resume loop AFTER the end-of-line from
91733965Sjdp			 this instruction. */
91833965Sjdp		    }		/* if (*s=='.') */
91933965Sjdp		}		/* if c==':' */
92033965Sjdp	      continue;
92133965Sjdp	    }			/* if (is_name_beginner(c) */
92233965Sjdp
92333965Sjdp
92433965Sjdp	  /* Empty statement?  */
92533965Sjdp	  if (is_end_of_line[(unsigned char) c])
92633965Sjdp	    continue;
92733965Sjdp
92833965Sjdp	  if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB)
92938889Sjdp	      && isdigit ((unsigned char) c))
93033965Sjdp	    {
93133965Sjdp	      /* local label  ("4:") */
93233965Sjdp	      char *backup = input_line_pointer;
93333965Sjdp
93433965Sjdp	      HANDLE_CONDITIONAL_ASSEMBLY ();
93533965Sjdp
93633965Sjdp	      temp = c - '0';
93733965Sjdp
93838889Sjdp	      while (isdigit ((unsigned char) *input_line_pointer))
93933965Sjdp		{
94033965Sjdp		  temp = (temp * 10) + *input_line_pointer - '0';
94133965Sjdp		  ++input_line_pointer;
94233965Sjdp		}		/* read the whole number */
94333965Sjdp
94433965Sjdp	      if (LOCAL_LABELS_DOLLAR
94533965Sjdp		  && *input_line_pointer == '$'
94633965Sjdp		  && *(input_line_pointer + 1) == ':')
94733965Sjdp		{
94833965Sjdp		  input_line_pointer += 2;
94933965Sjdp
95033965Sjdp		  if (dollar_label_defined (temp))
95133965Sjdp		    {
95260484Sobrien		      as_fatal (_("label \"%d$\" redefined"), temp);
95333965Sjdp		    }
95433965Sjdp
95533965Sjdp		  define_dollar_label (temp);
95633965Sjdp		  colon (dollar_label_name (temp, 0));
95733965Sjdp		  continue;
95833965Sjdp		}
95933965Sjdp
96033965Sjdp	      if (LOCAL_LABELS_FB
96133965Sjdp		  && *input_line_pointer++ == ':')
96233965Sjdp		{
96333965Sjdp		  fb_label_instance_inc (temp);
96433965Sjdp		  colon (fb_label_name (temp, 0));
96533965Sjdp		  continue;
96633965Sjdp		}
96733965Sjdp
96833965Sjdp	      input_line_pointer = backup;
96933965Sjdp	    }			/* local label  ("4:") */
97033965Sjdp
97133965Sjdp	  if (c && strchr (line_comment_chars, c))
97233965Sjdp	    {			/* Its a comment.  Better say APP or NO_APP */
97333965Sjdp	      char *ends;
97433965Sjdp	      char *new_buf;
97533965Sjdp	      char *new_tmp;
97633965Sjdp	      unsigned int new_length;
97733965Sjdp	      char *tmp_buf = 0;
97833965Sjdp
97933965Sjdp	      bump_line_counters ();
98033965Sjdp	      s = input_line_pointer;
98133965Sjdp	      if (strncmp (s, "APP\n", 4))
98233965Sjdp		continue;	/* We ignore it */
98333965Sjdp	      s += 4;
98433965Sjdp
98533965Sjdp	      ends = strstr (s, "#NO_APP\n");
98633965Sjdp
98733965Sjdp	      if (!ends)
98833965Sjdp		{
98933965Sjdp		  unsigned int tmp_len;
99033965Sjdp		  unsigned int num;
99133965Sjdp
99233965Sjdp		  /* The end of the #APP wasn't in this buffer.  We
99333965Sjdp		     keep reading in buffers until we find the #NO_APP
99433965Sjdp		     that goes with this #APP  There is one.  The specs
99533965Sjdp		     guarentee it. . . */
99633965Sjdp		  tmp_len = buffer_limit - s;
99733965Sjdp		  tmp_buf = xmalloc (tmp_len + 1);
99833965Sjdp		  memcpy (tmp_buf, s, tmp_len);
99933965Sjdp		  do
100033965Sjdp		    {
100133965Sjdp		      new_tmp = input_scrub_next_buffer (&buffer);
100233965Sjdp		      if (!new_tmp)
100333965Sjdp			break;
100433965Sjdp		      else
100533965Sjdp			buffer_limit = new_tmp;
100633965Sjdp		      input_line_pointer = buffer;
100733965Sjdp		      ends = strstr (buffer, "#NO_APP\n");
100833965Sjdp		      if (ends)
100933965Sjdp			num = ends - buffer;
101033965Sjdp		      else
101133965Sjdp			num = buffer_limit - buffer;
101233965Sjdp
101333965Sjdp		      tmp_buf = xrealloc (tmp_buf, tmp_len + num);
101433965Sjdp		      memcpy (tmp_buf + tmp_len, buffer, num);
101533965Sjdp		      tmp_len += num;
101633965Sjdp		    }
101733965Sjdp		  while (!ends);
101833965Sjdp
101933965Sjdp		  input_line_pointer = ends ? ends + 8 : NULL;
102033965Sjdp
102133965Sjdp		  s = tmp_buf;
102233965Sjdp		  ends = s + tmp_len;
102333965Sjdp
102433965Sjdp		}
102533965Sjdp	      else
102633965Sjdp		{
102733965Sjdp		  input_line_pointer = ends + 8;
102833965Sjdp		}
102933965Sjdp
103033965Sjdp	      scrub_string = s;
103133965Sjdp	      scrub_string_end = ends;
103233965Sjdp
103333965Sjdp	      new_length = ends - s;
103433965Sjdp	      new_buf = (char *) xmalloc (new_length);
103533965Sjdp	      new_tmp = new_buf;
103633965Sjdp	      for (;;)
103733965Sjdp		{
103833965Sjdp		  int space;
103933965Sjdp		  int size;
104033965Sjdp
104133965Sjdp		  space = (new_buf + new_length) - new_tmp;
104233965Sjdp		  size = do_scrub_chars (scrub_from_string, new_tmp, space);
104333965Sjdp
104433965Sjdp		  if (size < space)
104533965Sjdp		    {
104633965Sjdp		      new_tmp += size;
104733965Sjdp		      break;
104833965Sjdp		    }
104933965Sjdp
105033965Sjdp		  new_buf = xrealloc (new_buf, new_length + 100);
105133965Sjdp		  new_tmp = new_buf + new_length;
105233965Sjdp		  new_length += 100;
105333965Sjdp		}
105433965Sjdp
105533965Sjdp	      if (tmp_buf)
105633965Sjdp		free (tmp_buf);
105733965Sjdp	      old_buffer = buffer;
105833965Sjdp	      old_input = input_line_pointer;
105933965Sjdp	      old_limit = buffer_limit;
106033965Sjdp	      buffer = new_buf;
106133965Sjdp	      input_line_pointer = new_buf;
106233965Sjdp	      buffer_limit = new_tmp;
106333965Sjdp	      continue;
106433965Sjdp	    }
106533965Sjdp
106633965Sjdp	  HANDLE_CONDITIONAL_ASSEMBLY ();
106733965Sjdp
106833965Sjdp#ifdef tc_unrecognized_line
106933965Sjdp	  if (tc_unrecognized_line (c))
107033965Sjdp	    continue;
107133965Sjdp#endif
107233965Sjdp
107333965Sjdp	  /* as_warn("Junk character %d.",c);  Now done by ignore_rest */
107433965Sjdp	  input_line_pointer--;	/* Report unknown char as ignored. */
107533965Sjdp	  ignore_rest_of_line ();
107633965Sjdp	}			/* while (input_line_pointer<buffer_limit) */
107733965Sjdp
107833965Sjdp#ifdef md_after_pass_hook
107933965Sjdp      md_after_pass_hook ();
108033965Sjdp#endif
108133965Sjdp
108233965Sjdp      if (old_buffer)
108333965Sjdp	{
108433965Sjdp	  free (buffer);
108533965Sjdp	  bump_line_counters ();
108633965Sjdp	  if (old_input != 0)
108733965Sjdp	    {
108833965Sjdp	      buffer = old_buffer;
108933965Sjdp	      input_line_pointer = old_input;
109033965Sjdp	      buffer_limit = old_limit;
109133965Sjdp	      old_buffer = 0;
109233965Sjdp	      goto contin;
109333965Sjdp	    }
109433965Sjdp	}
109533965Sjdp    }				/* while (more buffers to scan) */
109633965Sjdp
109733965Sjdp quit:
109833965Sjdp
109933965Sjdp#ifdef md_cleanup
110033965Sjdp  md_cleanup();
110133965Sjdp#endif
110233965Sjdp  input_scrub_close ();		/* Close the input file */
110333965Sjdp}
110433965Sjdp
110533965Sjdp/* For most MRI pseudo-ops, the line actually ends at the first
110633965Sjdp   nonquoted space.  This function looks for that point, stuffs a null
110733965Sjdp   in, and sets *STOPCP to the character that used to be there, and
110833965Sjdp   returns the location.
110933965Sjdp
111033965Sjdp   Until I hear otherwise, I am going to assume that this is only true
111133965Sjdp   for the m68k MRI assembler.  */
111233965Sjdp
111333965Sjdpchar *
111433965Sjdpmri_comment_field (stopcp)
111533965Sjdp     char *stopcp;
111633965Sjdp{
111733965Sjdp#ifdef TC_M68K
111833965Sjdp
111933965Sjdp  char *s;
112033965Sjdp  int inquote = 0;
112133965Sjdp
112233965Sjdp  know (flag_m68k_mri);
112333965Sjdp
112433965Sjdp  for (s = input_line_pointer;
112533965Sjdp       ((! is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t')
112633965Sjdp	|| inquote);
112733965Sjdp       s++)
112833965Sjdp    {
112933965Sjdp      if (*s == '\'')
113033965Sjdp	inquote = ! inquote;
113133965Sjdp    }
113233965Sjdp  *stopcp = *s;
113333965Sjdp  *s = '\0';
113433965Sjdp  return s;
113533965Sjdp
113633965Sjdp#else
113733965Sjdp
113833965Sjdp  char *s;
113933965Sjdp
114033965Sjdp  for (s = input_line_pointer; ! is_end_of_line[(unsigned char) *s]; s++)
114133965Sjdp    ;
114233965Sjdp  *stopcp = *s;
114333965Sjdp  *s = '\0';
114433965Sjdp  return s;
114533965Sjdp
114633965Sjdp#endif
114733965Sjdp
114833965Sjdp}
114933965Sjdp
115033965Sjdp/* Skip to the end of an MRI comment field.  */
115133965Sjdp
115233965Sjdpvoid
115333965Sjdpmri_comment_end (stop, stopc)
115433965Sjdp     char *stop;
115533965Sjdp     int stopc;
115633965Sjdp{
115733965Sjdp  know (flag_mri);
115833965Sjdp
115933965Sjdp  input_line_pointer = stop;
116033965Sjdp  *stop = stopc;
116133965Sjdp  while (! is_end_of_line[(unsigned char) *input_line_pointer])
116233965Sjdp    ++input_line_pointer;
116333965Sjdp}
116433965Sjdp
116533965Sjdpvoid
116633965Sjdps_abort (ignore)
116760484Sobrien     int ignore ATTRIBUTE_UNUSED;
116833965Sjdp{
116960484Sobrien  as_fatal (_(".abort detected.  Abandoning ship."));
117033965Sjdp}
117133965Sjdp
117233965Sjdp/* Guts of .align directive.  N is the power of two to which to align.
117333965Sjdp   FILL may be NULL, or it may point to the bytes of the fill pattern.
117433965Sjdp   LEN is the length of whatever FILL points to, if anything.  MAX is
117533965Sjdp   the maximum number of characters to skip when doing the alignment,
117633965Sjdp   or 0 if there is no maximum.  */
117733965Sjdp
117833965Sjdpstatic void
117933965Sjdpdo_align (n, fill, len, max)
118033965Sjdp     int n;
118133965Sjdp     char *fill;
118233965Sjdp     int len;
118333965Sjdp     int max;
118433965Sjdp{
118533965Sjdp  char default_fill;
118633965Sjdp
118733965Sjdp#ifdef md_do_align
118833965Sjdp  md_do_align (n, fill, len, max, just_record_alignment);
118933965Sjdp#endif
119033965Sjdp
119133965Sjdp  if (fill == NULL)
119233965Sjdp    {
119360484Sobrien      if (subseg_text_p (now_seg))
119433965Sjdp	default_fill = NOP_OPCODE;
119533965Sjdp      else
119633965Sjdp	default_fill = 0;
119733965Sjdp      fill = &default_fill;
119833965Sjdp      len = 1;
119933965Sjdp    }
120033965Sjdp
120133965Sjdp  /* Only make a frag if we HAVE to. . . */
120233965Sjdp  if (n != 0 && !need_pass_2)
120333965Sjdp    {
120433965Sjdp      if (len <= 1)
120533965Sjdp	frag_align (n, *fill, max);
120633965Sjdp      else
120733965Sjdp	frag_align_pattern (n, fill, len, max);
120833965Sjdp    }
120933965Sjdp
121033965Sjdp#ifdef md_do_align
121133965Sjdp just_record_alignment:
121233965Sjdp#endif
121333965Sjdp
121460484Sobrien  record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
121533965Sjdp}
121633965Sjdp
121733965Sjdp/* Handle the .align pseudo-op.  A positive ARG is a default alignment
121833965Sjdp   (in bytes).  A negative ARG is the negative of the length of the
121933965Sjdp   fill pattern.  BYTES_P is non-zero if the alignment value should be
122033965Sjdp   interpreted as the byte boundary, rather than the power of 2.  */
122133965Sjdp
122233965Sjdpstatic void
122333965Sjdps_align (arg, bytes_p)
122433965Sjdp     int arg;
122533965Sjdp     int bytes_p;
122633965Sjdp{
122733965Sjdp  register unsigned int align;
122833965Sjdp  char *stop = NULL;
122933965Sjdp  char stopc;
123033965Sjdp  offsetT fill = 0;
123133965Sjdp  int max;
123233965Sjdp  int fill_p;
123333965Sjdp
123433965Sjdp  if (flag_mri)
123533965Sjdp    stop = mri_comment_field (&stopc);
123633965Sjdp
123733965Sjdp  if (is_end_of_line[(unsigned char) *input_line_pointer])
123833965Sjdp    {
123933965Sjdp      if (arg < 0)
124033965Sjdp	align = 0;
124133965Sjdp      else
124233965Sjdp	align = arg;	/* Default value from pseudo-op table */
124333965Sjdp    }
124433965Sjdp  else
124533965Sjdp    {
124633965Sjdp      align = get_absolute_expression ();
124733965Sjdp      SKIP_WHITESPACE ();
124833965Sjdp    }
124933965Sjdp
125033965Sjdp  if (bytes_p)
125133965Sjdp    {
125233965Sjdp      /* Convert to a power of 2.  */
125333965Sjdp      if (align != 0)
125433965Sjdp	{
125533965Sjdp	  unsigned int i;
125633965Sjdp
125733965Sjdp	  for (i = 0; (align & 1) == 0; align >>= 1, ++i)
125833965Sjdp	    ;
125933965Sjdp	  if (align != 1)
126060484Sobrien	    as_bad (_("Alignment not a power of 2"));
126133965Sjdp	  align = i;
126233965Sjdp	}
126333965Sjdp    }
126433965Sjdp
126533965Sjdp  if (align > 15)
126633965Sjdp    {
126733965Sjdp      align = 15;
126860484Sobrien      as_bad (_("Alignment too large: %u assumed"), align);
126933965Sjdp    }
127033965Sjdp
127133965Sjdp  if (*input_line_pointer != ',')
127233965Sjdp    {
127333965Sjdp      fill_p = 0;
127433965Sjdp      max = 0;
127533965Sjdp    }
127633965Sjdp  else
127733965Sjdp    {
127833965Sjdp      ++input_line_pointer;
127933965Sjdp      if (*input_line_pointer == ',')
128033965Sjdp	fill_p = 0;
128133965Sjdp      else
128233965Sjdp	{
128333965Sjdp	  fill = get_absolute_expression ();
128433965Sjdp	  SKIP_WHITESPACE ();
128533965Sjdp	  fill_p = 1;
128633965Sjdp	}
128733965Sjdp
128833965Sjdp      if (*input_line_pointer != ',')
128933965Sjdp	max = 0;
129033965Sjdp      else
129133965Sjdp	{
129233965Sjdp	  ++input_line_pointer;
129333965Sjdp	  max = get_absolute_expression ();
129433965Sjdp	}
129533965Sjdp    }
129633965Sjdp
129733965Sjdp  if (! fill_p)
129833965Sjdp    {
129933965Sjdp      if (arg < 0)
130060484Sobrien	as_warn (_("expected fill pattern missing"));
130133965Sjdp      do_align (align, (char *) NULL, 0, max);
130233965Sjdp    }
130333965Sjdp  else
130433965Sjdp    {
130533965Sjdp      int fill_len;
130633965Sjdp
130733965Sjdp      if (arg >= 0)
130833965Sjdp	fill_len = 1;
130933965Sjdp      else
131033965Sjdp	fill_len = - arg;
131133965Sjdp      if (fill_len <= 1)
131233965Sjdp	{
131333965Sjdp	  char fill_char;
131433965Sjdp
131533965Sjdp	  fill_char = fill;
131633965Sjdp	  do_align (align, &fill_char, fill_len, max);
131733965Sjdp	}
131833965Sjdp      else
131933965Sjdp	{
132033965Sjdp	  char ab[16];
132133965Sjdp
132238889Sjdp	  if ((size_t) fill_len > sizeof ab)
132333965Sjdp	    abort ();
132433965Sjdp	  md_number_to_chars (ab, fill, fill_len);
132533965Sjdp	  do_align (align, ab, fill_len, max);
132633965Sjdp	}
132733965Sjdp    }
132833965Sjdp
132960484Sobrien  demand_empty_rest_of_line ();
133060484Sobrien
133133965Sjdp  if (flag_mri)
133233965Sjdp    mri_comment_end (stop, stopc);
133333965Sjdp}
133433965Sjdp
133533965Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means
133633965Sjdp   align to a 4 byte boundary.  */
133733965Sjdp
133833965Sjdpvoid
133933965Sjdps_align_bytes (arg)
134033965Sjdp     int arg;
134133965Sjdp{
134233965Sjdp  s_align (arg, 1);
134333965Sjdp}
134433965Sjdp
134538889Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means align
134633965Sjdp   to a 2**4 boundary.  */
134733965Sjdp
134833965Sjdpvoid
134933965Sjdps_align_ptwo (arg)
135033965Sjdp     int arg;
135133965Sjdp{
135233965Sjdp  s_align (arg, 0);
135333965Sjdp}
135433965Sjdp
135533965Sjdpvoid
135633965Sjdps_comm (ignore)
135760484Sobrien     int ignore ATTRIBUTE_UNUSED;
135833965Sjdp{
135933965Sjdp  register char *name;
136033965Sjdp  register char c;
136133965Sjdp  register char *p;
136233965Sjdp  offsetT temp;
136333965Sjdp  register symbolS *symbolP;
136433965Sjdp  char *stop = NULL;
136533965Sjdp  char stopc;
136633965Sjdp
136733965Sjdp  if (flag_mri)
136833965Sjdp    stop = mri_comment_field (&stopc);
136933965Sjdp
137033965Sjdp  name = input_line_pointer;
137133965Sjdp  c = get_symbol_end ();
137233965Sjdp  /* just after name is now '\0' */
137333965Sjdp  p = input_line_pointer;
137433965Sjdp  *p = c;
137533965Sjdp  SKIP_WHITESPACE ();
137633965Sjdp  if (*input_line_pointer != ',')
137733965Sjdp    {
137860484Sobrien      as_bad (_("Expected comma after symbol-name: rest of line ignored."));
137960484Sobrien      ignore_rest_of_line ();
138033965Sjdp      if (flag_mri)
138133965Sjdp	mri_comment_end (stop, stopc);
138233965Sjdp      return;
138333965Sjdp    }
138433965Sjdp  input_line_pointer++;		/* skip ',' */
138533965Sjdp  if ((temp = get_absolute_expression ()) < 0)
138633965Sjdp    {
138760484Sobrien      as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp);
138860484Sobrien      ignore_rest_of_line ();
138933965Sjdp      if (flag_mri)
139033965Sjdp	mri_comment_end (stop, stopc);
139133965Sjdp      return;
139233965Sjdp    }
139333965Sjdp  *p = 0;
139433965Sjdp  symbolP = symbol_find_or_make (name);
139533965Sjdp  *p = c;
139633965Sjdp  if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
139733965Sjdp    {
139860484Sobrien      as_bad (_("Ignoring attempt to re-define symbol `%s'."),
139933965Sjdp	      S_GET_NAME (symbolP));
140060484Sobrien      ignore_rest_of_line ();
140133965Sjdp      if (flag_mri)
140233965Sjdp	mri_comment_end (stop, stopc);
140333965Sjdp      return;
140433965Sjdp    }
140533965Sjdp  if (S_GET_VALUE (symbolP))
140633965Sjdp    {
140733965Sjdp      if (S_GET_VALUE (symbolP) != (valueT) temp)
140860484Sobrien	as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
140933965Sjdp		S_GET_NAME (symbolP),
141033965Sjdp		(long) S_GET_VALUE (symbolP),
141133965Sjdp		(long) temp);
141233965Sjdp    }
141333965Sjdp  else
141433965Sjdp    {
141533965Sjdp      S_SET_VALUE (symbolP, (valueT) temp);
141633965Sjdp      S_SET_EXTERNAL (symbolP);
141733965Sjdp    }
141833965Sjdp#ifdef OBJ_VMS
141933965Sjdp  {
142033965Sjdp    extern int flag_one;
142133965Sjdp    if ( (!temp) || !flag_one)
142233965Sjdp      S_GET_OTHER(symbolP) = const_flag;
142333965Sjdp  }
142433965Sjdp#endif /* not OBJ_VMS */
142533965Sjdp  know (symbolP->sy_frag == &zero_address_frag);
142633965Sjdp
142760484Sobrien  demand_empty_rest_of_line ();
142860484Sobrien
142933965Sjdp  if (flag_mri)
143033965Sjdp    mri_comment_end (stop, stopc);
143133965Sjdp}				/* s_comm() */
143233965Sjdp
143333965Sjdp/* The MRI COMMON pseudo-op.  We handle this by creating a common
143433965Sjdp   symbol with the appropriate name.  We make s_space do the right
143533965Sjdp   thing by increasing the size.  */
143633965Sjdp
143733965Sjdpvoid
143833965Sjdps_mri_common (small)
143960484Sobrien     int small ATTRIBUTE_UNUSED;
144033965Sjdp{
144133965Sjdp  char *name;
144233965Sjdp  char c;
144333965Sjdp  char *alc = NULL;
144433965Sjdp  symbolS *sym;
144533965Sjdp  offsetT align;
144633965Sjdp  char *stop = NULL;
144733965Sjdp  char stopc;
144833965Sjdp
144933965Sjdp  if (! flag_mri)
145033965Sjdp    {
145133965Sjdp      s_comm (0);
145233965Sjdp      return;
145333965Sjdp    }
145433965Sjdp
145533965Sjdp  stop = mri_comment_field (&stopc);
145633965Sjdp
145733965Sjdp  SKIP_WHITESPACE ();
145833965Sjdp
145933965Sjdp  name = input_line_pointer;
146033965Sjdp  if (! isdigit ((unsigned char) *name))
146133965Sjdp    c = get_symbol_end ();
146233965Sjdp  else
146333965Sjdp    {
146433965Sjdp      do
146533965Sjdp	{
146633965Sjdp	  ++input_line_pointer;
146733965Sjdp	}
146833965Sjdp      while (isdigit ((unsigned char) *input_line_pointer));
146933965Sjdp      c = *input_line_pointer;
147033965Sjdp      *input_line_pointer = '\0';
147133965Sjdp
147233965Sjdp      if (line_label != NULL)
147333965Sjdp	{
147433965Sjdp	  alc = (char *) xmalloc (strlen (S_GET_NAME (line_label))
147533965Sjdp				  + (input_line_pointer - name)
147633965Sjdp				  + 1);
147733965Sjdp	  sprintf (alc, "%s%s", name, S_GET_NAME (line_label));
147833965Sjdp	  name = alc;
147933965Sjdp	}
148033965Sjdp    }
148133965Sjdp
148233965Sjdp  sym = symbol_find_or_make (name);
148333965Sjdp  *input_line_pointer = c;
148433965Sjdp  if (alc != NULL)
148533965Sjdp    free (alc);
148633965Sjdp
148733965Sjdp  if (*input_line_pointer != ',')
148833965Sjdp    align = 0;
148933965Sjdp  else
149033965Sjdp    {
149133965Sjdp      ++input_line_pointer;
149233965Sjdp      align = get_absolute_expression ();
149333965Sjdp    }
149433965Sjdp
149533965Sjdp  if (S_IS_DEFINED (sym) && ! S_IS_COMMON (sym))
149633965Sjdp    {
149760484Sobrien      as_bad (_("attempt to re-define symbol `%s'"), S_GET_NAME (sym));
149860484Sobrien      ignore_rest_of_line ();
149933965Sjdp      mri_comment_end (stop, stopc);
150033965Sjdp      return;
150133965Sjdp    }
150233965Sjdp
150333965Sjdp  S_SET_EXTERNAL (sym);
150433965Sjdp  mri_common_symbol = sym;
150533965Sjdp
150633965Sjdp#ifdef S_SET_ALIGN
150733965Sjdp  if (align != 0)
150833965Sjdp    S_SET_ALIGN (sym, align);
150933965Sjdp#endif
151033965Sjdp
151133965Sjdp  if (line_label != NULL)
151233965Sjdp    {
151360484Sobrien      expressionS exp;
151460484Sobrien      exp.X_op = O_symbol;
151560484Sobrien      exp.X_add_symbol = sym;
151660484Sobrien      exp.X_add_number = 0;
151760484Sobrien      symbol_set_value_expression (line_label, &exp);
151860484Sobrien      symbol_set_frag (line_label, &zero_address_frag);
151933965Sjdp      S_SET_SEGMENT (line_label, expr_section);
152033965Sjdp    }
152133965Sjdp
152233965Sjdp  /* FIXME: We just ignore the small argument, which distinguishes
152333965Sjdp     COMMON and COMMON.S.  I don't know what we can do about it.  */
152433965Sjdp
152533965Sjdp  /* Ignore the type and hptype.  */
152633965Sjdp  if (*input_line_pointer == ',')
152733965Sjdp    input_line_pointer += 2;
152833965Sjdp  if (*input_line_pointer == ',')
152933965Sjdp    input_line_pointer += 2;
153033965Sjdp
153160484Sobrien  demand_empty_rest_of_line ();
153260484Sobrien
153333965Sjdp  mri_comment_end (stop, stopc);
153433965Sjdp}
153533965Sjdp
153633965Sjdpvoid
153733965Sjdps_data (ignore)
153860484Sobrien     int ignore ATTRIBUTE_UNUSED;
153933965Sjdp{
154033965Sjdp  segT section;
154133965Sjdp  register int temp;
154233965Sjdp
154333965Sjdp  temp = get_absolute_expression ();
154433965Sjdp  if (flag_readonly_data_in_text)
154533965Sjdp    {
154633965Sjdp      section = text_section;
154733965Sjdp      temp += 1000;
154833965Sjdp    }
154933965Sjdp  else
155033965Sjdp    section = data_section;
155133965Sjdp
155233965Sjdp  subseg_set (section, (subsegT) temp);
155333965Sjdp
155433965Sjdp#ifdef OBJ_VMS
155533965Sjdp  const_flag = 0;
155633965Sjdp#endif
155733965Sjdp  demand_empty_rest_of_line ();
155833965Sjdp}
155933965Sjdp
156033965Sjdp/* Handle the .appfile pseudo-op.  This is automatically generated by
156133965Sjdp   do_scrub_chars when a preprocessor # line comment is seen with a
156233965Sjdp   file name.  This default definition may be overridden by the object
156333965Sjdp   or CPU specific pseudo-ops.  This function is also the default
156433965Sjdp   definition for .file; the APPFILE argument is 1 for .appfile, 0 for
156533965Sjdp   .file.  */
156633965Sjdp
156733965Sjdpvoid
156833965Sjdps_app_file (appfile)
156933965Sjdp     int appfile;
157033965Sjdp{
157133965Sjdp  register char *s;
157233965Sjdp  int length;
157333965Sjdp
157433965Sjdp  /* Some assemblers tolerate immediately following '"' */
157533965Sjdp  if ((s = demand_copy_string (&length)) != 0)
157633965Sjdp    {
157733965Sjdp      /* If this is a fake .appfile, a fake newline was inserted into
157833965Sjdp	 the buffer.  Passing -2 to new_logical_line tells it to
157933965Sjdp	 account for it.  */
158038889Sjdp      int may_omit
158138889Sjdp	= (! new_logical_line (s, appfile ? -2 : -1) && appfile);
158233965Sjdp
158333965Sjdp      /* In MRI mode, the preprocessor may have inserted an extraneous
158433965Sjdp         backquote.  */
158533965Sjdp      if (flag_m68k_mri
158633965Sjdp	  && *input_line_pointer == '\''
158733965Sjdp	  && is_end_of_line[(unsigned char) input_line_pointer[1]])
158833965Sjdp	++input_line_pointer;
158933965Sjdp
159033965Sjdp      demand_empty_rest_of_line ();
159138889Sjdp      if (! may_omit)
159238889Sjdp	{
159333965Sjdp#ifdef LISTING
159438889Sjdp	  if (listing)
159538889Sjdp	    listing_source_file (s);
159633965Sjdp#endif
159738889Sjdp	  register_dependency (s);
159833965Sjdp#ifdef obj_app_file
159938889Sjdp	  obj_app_file (s);
160033965Sjdp#endif
160138889Sjdp	}
160238889Sjdp    }
160333965Sjdp}
160433965Sjdp
160533965Sjdp/* Handle the .appline pseudo-op.  This is automatically generated by
160633965Sjdp   do_scrub_chars when a preprocessor # line comment is seen.  This
160733965Sjdp   default definition may be overridden by the object or CPU specific
160833965Sjdp   pseudo-ops.  */
160933965Sjdp
161033965Sjdpvoid
161133965Sjdps_app_line (ignore)
161260484Sobrien     int ignore ATTRIBUTE_UNUSED;
161333965Sjdp{
161433965Sjdp  int l;
161533965Sjdp
161633965Sjdp  /* The given number is that of the next line.  */
161733965Sjdp  l = get_absolute_expression () - 1;
161833965Sjdp  if (l < 0)
161933965Sjdp    /* Some of the back ends can't deal with non-positive line numbers.
162033965Sjdp       Besides, it's silly.  */
162160484Sobrien    as_warn (_("Line numbers must be positive; line number %d rejected."), l+1);
162233965Sjdp  else
162333965Sjdp    {
162433965Sjdp      new_logical_line ((char *) NULL, l);
162533965Sjdp#ifdef LISTING
162633965Sjdp      if (listing)
162733965Sjdp	listing_source_line (l);
162833965Sjdp#endif
162933965Sjdp    }
163033965Sjdp  demand_empty_rest_of_line ();
163133965Sjdp}
163233965Sjdp
163333965Sjdp/* Handle the .end pseudo-op.  Actually, the real work is done in
163433965Sjdp   read_a_source_file.  */
163533965Sjdp
163633965Sjdpvoid
163733965Sjdps_end (ignore)
163860484Sobrien     int ignore ATTRIBUTE_UNUSED;
163933965Sjdp{
164033965Sjdp  if (flag_mri)
164133965Sjdp    {
164233965Sjdp      /* The MRI assembler permits the start symbol to follow .end,
164333965Sjdp         but we don't support that.  */
164433965Sjdp      SKIP_WHITESPACE ();
164533965Sjdp      if (! is_end_of_line[(unsigned char) *input_line_pointer]
164633965Sjdp	  && *input_line_pointer != '*'
164733965Sjdp	  && *input_line_pointer != '!')
164860484Sobrien	as_warn (_("start address not supported"));
164933965Sjdp    }
165033965Sjdp}
165133965Sjdp
165233965Sjdp/* Handle the .err pseudo-op.  */
165333965Sjdp
165433965Sjdpvoid
165533965Sjdps_err (ignore)
165660484Sobrien     int ignore ATTRIBUTE_UNUSED;
165733965Sjdp{
165860484Sobrien  as_bad (_(".err encountered"));
165933965Sjdp  demand_empty_rest_of_line ();
166033965Sjdp}
166133965Sjdp
166233965Sjdp/* Handle the MRI fail pseudo-op.  */
166333965Sjdp
166433965Sjdpvoid
166533965Sjdps_fail (ignore)
166660484Sobrien     int ignore ATTRIBUTE_UNUSED;
166733965Sjdp{
166833965Sjdp  offsetT temp;
166933965Sjdp  char *stop = NULL;
167033965Sjdp  char stopc;
167133965Sjdp
167233965Sjdp  if (flag_mri)
167333965Sjdp    stop = mri_comment_field (&stopc);
167433965Sjdp
167533965Sjdp  temp = get_absolute_expression ();
167633965Sjdp  if (temp >= 500)
167760484Sobrien    as_warn (_(".fail %ld encountered"), (long) temp);
167833965Sjdp  else
167960484Sobrien    as_bad (_(".fail %ld encountered"), (long) temp);
168033965Sjdp
168160484Sobrien  demand_empty_rest_of_line ();
168260484Sobrien
168333965Sjdp  if (flag_mri)
168433965Sjdp    mri_comment_end (stop, stopc);
168533965Sjdp}
168633965Sjdp
168733965Sjdpvoid
168833965Sjdps_fill (ignore)
168960484Sobrien     int ignore ATTRIBUTE_UNUSED;
169033965Sjdp{
169138889Sjdp  expressionS rep_exp;
169238889Sjdp  long size = 1;
169338889Sjdp  register long fill = 0;
169433965Sjdp  char *p;
169533965Sjdp
169633965Sjdp#ifdef md_flush_pending_output
169733965Sjdp  md_flush_pending_output ();
169833965Sjdp#endif
169933965Sjdp
170038889Sjdp  get_known_segmented_expression (&rep_exp);
170133965Sjdp  if (*input_line_pointer == ',')
170233965Sjdp    {
170333965Sjdp      input_line_pointer++;
170438889Sjdp      size = get_absolute_expression ();
170533965Sjdp      if (*input_line_pointer == ',')
170633965Sjdp	{
170733965Sjdp	  input_line_pointer++;
170838889Sjdp	  fill = get_absolute_expression ();
170933965Sjdp	}
171033965Sjdp    }
171138889Sjdp
171233965Sjdp  /* This is to be compatible with BSD 4.2 AS, not for any rational reason.  */
171333965Sjdp#define BSD_FILL_SIZE_CROCK_8 (8)
171438889Sjdp  if (size > BSD_FILL_SIZE_CROCK_8)
171533965Sjdp    {
171660484Sobrien      as_warn (_(".fill size clamped to %d."), BSD_FILL_SIZE_CROCK_8);
171738889Sjdp      size = BSD_FILL_SIZE_CROCK_8;
171833965Sjdp    }
171938889Sjdp  if (size < 0)
172033965Sjdp    {
172160484Sobrien      as_warn (_("Size negative: .fill ignored."));
172238889Sjdp      size = 0;
172333965Sjdp    }
172438889Sjdp  else if (rep_exp.X_op == O_constant && rep_exp.X_add_number <= 0)
172533965Sjdp    {
172638889Sjdp      if (rep_exp.X_add_number < 0)
172760484Sobrien	as_warn (_("Repeat < 0, .fill ignored"));
172838889Sjdp      size = 0;
172933965Sjdp    }
173033965Sjdp
173138889Sjdp  if (size && !need_pass_2)
173233965Sjdp    {
173338889Sjdp      if (rep_exp.X_op == O_constant)
173438889Sjdp	{
173538889Sjdp	  p = frag_var (rs_fill, (int) size, (int) size,
173638889Sjdp			(relax_substateT) 0, (symbolS *) 0,
173738889Sjdp			(offsetT) rep_exp.X_add_number,
173838889Sjdp			(char *) 0);
173938889Sjdp	}
174038889Sjdp      else
174138889Sjdp	{
174238889Sjdp	  /* We don't have a constant repeat count, so we can't use
174338889Sjdp	     rs_fill.  We can get the same results out of rs_space,
174438889Sjdp	     but its argument is in bytes, so we must multiply the
174538889Sjdp	     repeat count by size.  */
174638889Sjdp
174738889Sjdp	  symbolS *rep_sym;
174838889Sjdp	  rep_sym = make_expr_symbol (&rep_exp);
174938889Sjdp	  if (size != 1)
175038889Sjdp	    {
175138889Sjdp	      expressionS size_exp;
175238889Sjdp	      size_exp.X_op = O_constant;
175338889Sjdp	      size_exp.X_add_number = size;
175438889Sjdp
175538889Sjdp	      rep_exp.X_op = O_multiply;
175638889Sjdp	      rep_exp.X_add_symbol = rep_sym;
175738889Sjdp	      rep_exp.X_op_symbol = make_expr_symbol (&size_exp);
175838889Sjdp	      rep_exp.X_add_number = 0;
175938889Sjdp	      rep_sym = make_expr_symbol (&rep_exp);
176038889Sjdp	    }
176138889Sjdp
176238889Sjdp	  p = frag_var (rs_space, (int) size, (int) size,
176338889Sjdp			(relax_substateT) 0, rep_sym, (offsetT) 0, (char *) 0);
176438889Sjdp	}
176538889Sjdp      memset (p, 0, (unsigned int) size);
176633965Sjdp      /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX
176733965Sjdp       * flavoured AS.  The following bizzare behaviour is to be
176833965Sjdp       * compatible with above.  I guess they tried to take up to 8
176933965Sjdp       * bytes from a 4-byte expression and they forgot to sign
177033965Sjdp       * extend. Un*x Sux. */
177133965Sjdp#define BSD_FILL_SIZE_CROCK_4 (4)
177238889Sjdp      md_number_to_chars (p, (valueT) fill,
177338889Sjdp			  (size > BSD_FILL_SIZE_CROCK_4
177433965Sjdp			   ? BSD_FILL_SIZE_CROCK_4
177538889Sjdp			   : (int) size));
177633965Sjdp      /* Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes)
177733965Sjdp       * but emits no error message because it seems a legal thing to do.
177833965Sjdp       * It is a degenerate case of .fill but could be emitted by a compiler.
177933965Sjdp       */
178033965Sjdp    }
178133965Sjdp  demand_empty_rest_of_line ();
178233965Sjdp}
178333965Sjdp
178433965Sjdpvoid
178533965Sjdps_globl (ignore)
178660484Sobrien     int ignore ATTRIBUTE_UNUSED;
178733965Sjdp{
178833965Sjdp  char *name;
178933965Sjdp  int c;
179033965Sjdp  symbolS *symbolP;
179133965Sjdp  char *stop = NULL;
179233965Sjdp  char stopc;
179333965Sjdp
179433965Sjdp  if (flag_mri)
179533965Sjdp    stop = mri_comment_field (&stopc);
179633965Sjdp
179733965Sjdp  do
179833965Sjdp    {
179933965Sjdp      name = input_line_pointer;
180033965Sjdp      c = get_symbol_end ();
180133965Sjdp      symbolP = symbol_find_or_make (name);
180260484Sobrien      S_SET_EXTERNAL (symbolP);
180360484Sobrien
180433965Sjdp      *input_line_pointer = c;
180533965Sjdp      SKIP_WHITESPACE ();
180660484Sobrien      c = *input_line_pointer;
180733965Sjdp      if (c == ',')
180833965Sjdp	{
180933965Sjdp	  input_line_pointer++;
181033965Sjdp	  SKIP_WHITESPACE ();
181133965Sjdp	  if (*input_line_pointer == '\n')
181233965Sjdp	    c = '\n';
181333965Sjdp	}
181433965Sjdp    }
181533965Sjdp  while (c == ',');
181633965Sjdp
181760484Sobrien  demand_empty_rest_of_line ();
181860484Sobrien
181933965Sjdp  if (flag_mri)
182033965Sjdp    mri_comment_end (stop, stopc);
182133965Sjdp}
182233965Sjdp
182333965Sjdp/* Handle the MRI IRP and IRPC pseudo-ops.  */
182433965Sjdp
182533965Sjdpvoid
182633965Sjdps_irp (irpc)
182733965Sjdp     int irpc;
182833965Sjdp{
182933965Sjdp  char *file;
183033965Sjdp  unsigned int line;
183133965Sjdp  sb s;
183233965Sjdp  const char *err;
183333965Sjdp  sb out;
183433965Sjdp
183533965Sjdp  as_where (&file, &line);
183633965Sjdp
183733965Sjdp  sb_new (&s);
183833965Sjdp  while (! is_end_of_line[(unsigned char) *input_line_pointer])
183933965Sjdp    sb_add_char (&s, *input_line_pointer++);
184033965Sjdp
184133965Sjdp  sb_new (&out);
184233965Sjdp
184333965Sjdp  err = expand_irp (irpc, 0, &s, &out, get_line_sb, '\0');
184433965Sjdp  if (err != NULL)
184533965Sjdp    as_bad_where (file, line, "%s", err);
184633965Sjdp
184733965Sjdp  sb_kill (&s);
184833965Sjdp
184960484Sobrien  input_scrub_include_sb (&out, input_line_pointer, 1);
185033965Sjdp  sb_kill (&out);
185133965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
185233965Sjdp}
185333965Sjdp
185433965Sjdp/* Handle the .linkonce pseudo-op.  This tells the assembler to mark
185533965Sjdp   the section to only be linked once.  However, this is not supported
185633965Sjdp   by most object file formats.  This takes an optional argument,
185733965Sjdp   which is what to do about duplicates.  */
185833965Sjdp
185933965Sjdpvoid
186033965Sjdps_linkonce (ignore)
186160484Sobrien     int ignore ATTRIBUTE_UNUSED;
186233965Sjdp{
186333965Sjdp  enum linkonce_type type;
186433965Sjdp
186533965Sjdp  SKIP_WHITESPACE ();
186633965Sjdp
186733965Sjdp  type = LINKONCE_DISCARD;
186833965Sjdp
186933965Sjdp  if (! is_end_of_line[(unsigned char) *input_line_pointer])
187033965Sjdp    {
187133965Sjdp      char *s;
187233965Sjdp      char c;
187333965Sjdp
187433965Sjdp      s = input_line_pointer;
187533965Sjdp      c = get_symbol_end ();
187633965Sjdp      if (strcasecmp (s, "discard") == 0)
187733965Sjdp	type = LINKONCE_DISCARD;
187833965Sjdp      else if (strcasecmp (s, "one_only") == 0)
187933965Sjdp	type = LINKONCE_ONE_ONLY;
188033965Sjdp      else if (strcasecmp (s, "same_size") == 0)
188133965Sjdp	type = LINKONCE_SAME_SIZE;
188233965Sjdp      else if (strcasecmp (s, "same_contents") == 0)
188333965Sjdp	type = LINKONCE_SAME_CONTENTS;
188433965Sjdp      else
188560484Sobrien	as_warn (_("unrecognized .linkonce type `%s'"), s);
188633965Sjdp
188733965Sjdp      *input_line_pointer = c;
188833965Sjdp    }
188933965Sjdp
189033965Sjdp#ifdef obj_handle_link_once
189133965Sjdp  obj_handle_link_once (type);
189233965Sjdp#else /* ! defined (obj_handle_link_once) */
189333965Sjdp#ifdef BFD_ASSEMBLER
189433965Sjdp  {
189533965Sjdp    flagword flags;
189633965Sjdp
189733965Sjdp    if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0)
189860484Sobrien      as_warn (_(".linkonce is not supported for this object file format"));
189933965Sjdp
190033965Sjdp    flags = bfd_get_section_flags (stdoutput, now_seg);
190133965Sjdp    flags |= SEC_LINK_ONCE;
190233965Sjdp    switch (type)
190333965Sjdp      {
190433965Sjdp      default:
190533965Sjdp	abort ();
190633965Sjdp      case LINKONCE_DISCARD:
190733965Sjdp	flags |= SEC_LINK_DUPLICATES_DISCARD;
190833965Sjdp	break;
190933965Sjdp      case LINKONCE_ONE_ONLY:
191033965Sjdp	flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
191133965Sjdp	break;
191233965Sjdp      case LINKONCE_SAME_SIZE:
191333965Sjdp	flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
191433965Sjdp	break;
191533965Sjdp      case LINKONCE_SAME_CONTENTS:
191633965Sjdp	flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
191733965Sjdp	break;
191833965Sjdp      }
191933965Sjdp    if (! bfd_set_section_flags (stdoutput, now_seg, flags))
192060484Sobrien      as_bad (_("bfd_set_section_flags: %s"),
192133965Sjdp	      bfd_errmsg (bfd_get_error ()));
192233965Sjdp  }
192333965Sjdp#else /* ! defined (BFD_ASSEMBLER) */
192460484Sobrien  as_warn (_(".linkonce is not supported for this object file format"));
192533965Sjdp#endif /* ! defined (BFD_ASSEMBLER) */
192633965Sjdp#endif /* ! defined (obj_handle_link_once) */
192733965Sjdp
192833965Sjdp  demand_empty_rest_of_line ();
192933965Sjdp}
193033965Sjdp
193138889Sjdpstatic void
193238889Sjdps_lcomm_internal (needs_align, bytes_p)
193333965Sjdp     /* 1 if this was a ".bss" directive, which may require a 3rd argument
193433965Sjdp	(alignment); 0 if it was an ".lcomm" (2 args only)  */
193533965Sjdp     int needs_align;
193638889Sjdp     /* 1 if the alignment value should be interpreted as the byte boundary,
193738889Sjdp	rather than the power of 2. */
193838889Sjdp     int bytes_p;
193933965Sjdp{
194033965Sjdp  register char *name;
194133965Sjdp  register char c;
194233965Sjdp  register char *p;
194333965Sjdp  register int temp;
194433965Sjdp  register symbolS *symbolP;
194533965Sjdp  segT current_seg = now_seg;
194633965Sjdp  subsegT current_subseg = now_subseg;
194733965Sjdp  const int max_alignment = 15;
194833965Sjdp  int align = 0;
194933965Sjdp  segT bss_seg = bss_section;
195033965Sjdp
195133965Sjdp  name = input_line_pointer;
195233965Sjdp  c = get_symbol_end ();
195333965Sjdp  p = input_line_pointer;
195433965Sjdp  *p = c;
195533965Sjdp  SKIP_WHITESPACE ();
195633965Sjdp
195733965Sjdp  /* Accept an optional comma after the name.  The comma used to be
195833965Sjdp     required, but Irix 5 cc does not generate it.  */
195933965Sjdp  if (*input_line_pointer == ',')
196033965Sjdp    {
196133965Sjdp      ++input_line_pointer;
196233965Sjdp      SKIP_WHITESPACE ();
196333965Sjdp    }
196433965Sjdp
196533965Sjdp  if (*input_line_pointer == '\n')
196633965Sjdp    {
196760484Sobrien      as_bad (_("Missing size expression"));
196833965Sjdp      return;
196933965Sjdp    }
197033965Sjdp
197133965Sjdp  if ((temp = get_absolute_expression ()) < 0)
197233965Sjdp    {
197360484Sobrien      as_warn (_("BSS length (%d.) <0! Ignored."), temp);
197433965Sjdp      ignore_rest_of_line ();
197533965Sjdp      return;
197633965Sjdp    }
197733965Sjdp
197833965Sjdp#if defined (TC_MIPS) || defined (TC_ALPHA)
197933965Sjdp  if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
198033965Sjdp      || OUTPUT_FLAVOR == bfd_target_elf_flavour)
198133965Sjdp    {
198233965Sjdp      /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss.  */
198333965Sjdp      if (temp <= bfd_get_gp_size (stdoutput))
198433965Sjdp	{
198533965Sjdp	  bss_seg = subseg_new (".sbss", 1);
198633965Sjdp	  seg_info (bss_seg)->bss = 1;
198733965Sjdp#ifdef BFD_ASSEMBLER
198833965Sjdp	  if (! bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
198960484Sobrien	    as_warn (_("error setting flags for \".sbss\": %s"),
199033965Sjdp		     bfd_errmsg (bfd_get_error ()));
199133965Sjdp#endif
199233965Sjdp	}
199333965Sjdp    }
199433965Sjdp#endif
199560484Sobrien
199633965Sjdp   if (!needs_align)
199733965Sjdp     {
199860484Sobrien       TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
199933965Sjdp
200060484Sobrien       /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
200160484Sobrien       if (align)
200260484Sobrien         record_alignment(bss_seg, align);
200333965Sjdp     }
200433965Sjdp
200533965Sjdp  if (needs_align)
200633965Sjdp    {
200733965Sjdp      align = 0;
200833965Sjdp      SKIP_WHITESPACE ();
200933965Sjdp      if (*input_line_pointer != ',')
201033965Sjdp	{
201160484Sobrien	  as_bad (_("Expected comma after size"));
201233965Sjdp	  ignore_rest_of_line ();
201333965Sjdp	  return;
201433965Sjdp	}
201533965Sjdp      input_line_pointer++;
201633965Sjdp      SKIP_WHITESPACE ();
201733965Sjdp      if (*input_line_pointer == '\n')
201833965Sjdp	{
201960484Sobrien	  as_bad (_("Missing alignment"));
202033965Sjdp	  return;
202133965Sjdp	}
202233965Sjdp      align = get_absolute_expression ();
202338889Sjdp      if (bytes_p)
202438889Sjdp	{
202538889Sjdp	  /* Convert to a power of 2.  */
202638889Sjdp	  if (align != 0)
202738889Sjdp	    {
202838889Sjdp	      unsigned int i;
202938889Sjdp
203038889Sjdp	      for (i = 0; (align & 1) == 0; align >>= 1, ++i)
203138889Sjdp		;
203238889Sjdp	      if (align != 1)
203360484Sobrien		as_bad (_("Alignment not a power of 2"));
203438889Sjdp	      align = i;
203538889Sjdp	    }
203638889Sjdp	}
203733965Sjdp      if (align > max_alignment)
203833965Sjdp	{
203933965Sjdp	  align = max_alignment;
204060484Sobrien	  as_warn (_("Alignment too large: %d. assumed."), align);
204133965Sjdp	}
204233965Sjdp      else if (align < 0)
204333965Sjdp	{
204433965Sjdp	  align = 0;
204560484Sobrien	  as_warn (_("Alignment negative. 0 assumed."));
204633965Sjdp	}
204733965Sjdp      record_alignment (bss_seg, align);
204833965Sjdp    }				/* if needs align */
204933965Sjdp  else
205033965Sjdp    {
205133965Sjdp      /* Assume some objects may require alignment on some systems.  */
205233965Sjdp#if defined (TC_ALPHA) && ! defined (VMS)
205333965Sjdp      if (temp > 1)
205433965Sjdp	{
205533965Sjdp	  align = ffs (temp) - 1;
205633965Sjdp	  if (temp % (1 << align))
205733965Sjdp	    abort ();
205833965Sjdp	}
205933965Sjdp#endif
206033965Sjdp    }
206133965Sjdp
206233965Sjdp  *p = 0;
206333965Sjdp  symbolP = symbol_find_or_make (name);
206433965Sjdp  *p = c;
206533965Sjdp
206633965Sjdp  if (
206760484Sobrien#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
206860484Sobrien     || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
206960484Sobrien#ifdef BFD_ASSEMBLER
207060484Sobrien      (OUTPUT_FLAVOR != bfd_target_aout_flavour
207160484Sobrien       || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
207260484Sobrien#else
207360484Sobrien      (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
207460484Sobrien#endif
207560484Sobrien#endif
207660484Sobrien      (S_GET_SEGMENT (symbolP) == bss_seg
207760484Sobrien       || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
207833965Sjdp    {
207933965Sjdp      char *pfrag;
208033965Sjdp
208133965Sjdp      subseg_set (bss_seg, 1);
208233965Sjdp
208333965Sjdp      if (align)
208433965Sjdp	frag_align (align, 0, 0);
208533965Sjdp					/* detach from old frag	*/
208633965Sjdp      if (S_GET_SEGMENT (symbolP) == bss_seg)
208760484Sobrien	symbol_get_frag (symbolP)->fr_symbol = NULL;
208833965Sjdp
208960484Sobrien      symbol_set_frag (symbolP, frag_now);
209033965Sjdp      pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
209133965Sjdp			(offsetT) temp, (char *) 0);
209233965Sjdp      *pfrag = 0;
209333965Sjdp
209433965Sjdp      S_SET_SEGMENT (symbolP, bss_seg);
209533965Sjdp
209633965Sjdp#ifdef OBJ_COFF
209733965Sjdp      /* The symbol may already have been created with a preceding
209833965Sjdp         ".globl" directive -- be careful not to step on storage class
209933965Sjdp         in that case.  Otherwise, set it to static. */
210033965Sjdp      if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
210133965Sjdp	{
210233965Sjdp	  S_SET_STORAGE_CLASS (symbolP, C_STAT);
210333965Sjdp	}
210433965Sjdp#endif /* OBJ_COFF */
210533965Sjdp
210633965Sjdp#ifdef S_SET_SIZE
210733965Sjdp      S_SET_SIZE (symbolP, temp);
210833965Sjdp#endif
210933965Sjdp    }
211033965Sjdp  else
211160484Sobrien    as_bad (_("Ignoring attempt to re-define symbol `%s'."),
211233965Sjdp	    S_GET_NAME (symbolP));
211333965Sjdp
211433965Sjdp  subseg_set (current_seg, current_subseg);
211533965Sjdp
211633965Sjdp  demand_empty_rest_of_line ();
211738889Sjdp}				/* s_lcomm_internal() */
211833965Sjdp
211938889Sjdpvoid
212038889Sjdps_lcomm (needs_align)
212138889Sjdp     int needs_align;
212238889Sjdp{
212338889Sjdp  s_lcomm_internal (needs_align, 0);
212438889Sjdp}
212538889Sjdp
212638889Sjdpvoid s_lcomm_bytes (needs_align)
212738889Sjdp     int needs_align;
212838889Sjdp{
212938889Sjdp  s_lcomm_internal (needs_align, 1);
213038889Sjdp}
213138889Sjdp
213233965Sjdpvoid
213333965Sjdps_lsym (ignore)
213460484Sobrien     int ignore ATTRIBUTE_UNUSED;
213533965Sjdp{
213633965Sjdp  register char *name;
213733965Sjdp  register char c;
213833965Sjdp  register char *p;
213933965Sjdp  expressionS exp;
214033965Sjdp  register symbolS *symbolP;
214133965Sjdp
214233965Sjdp  /* we permit ANY defined expression: BSD4.2 demands constants */
214333965Sjdp  name = input_line_pointer;
214433965Sjdp  c = get_symbol_end ();
214533965Sjdp  p = input_line_pointer;
214633965Sjdp  *p = c;
214733965Sjdp  SKIP_WHITESPACE ();
214833965Sjdp  if (*input_line_pointer != ',')
214933965Sjdp    {
215033965Sjdp      *p = 0;
215160484Sobrien      as_bad (_("Expected comma after name \"%s\""), name);
215233965Sjdp      *p = c;
215333965Sjdp      ignore_rest_of_line ();
215433965Sjdp      return;
215533965Sjdp    }
215633965Sjdp  input_line_pointer++;
215733965Sjdp  expression (&exp);
215833965Sjdp  if (exp.X_op != O_constant
215933965Sjdp      && exp.X_op != O_register)
216033965Sjdp    {
216160484Sobrien      as_bad (_("bad expression"));
216233965Sjdp      ignore_rest_of_line ();
216333965Sjdp      return;
216433965Sjdp    }
216533965Sjdp  *p = 0;
216633965Sjdp  symbolP = symbol_find_or_make (name);
216733965Sjdp
216833965Sjdp  /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0 &&
216933965Sjdp     symbolP->sy_desc == 0) out of this test because coff doesn't have
217033965Sjdp     those fields, and I can't see when they'd ever be tripped.  I
217133965Sjdp     don't think I understand why they were here so I may have
217233965Sjdp     introduced a bug. As recently as 1.37 didn't have this test
217333965Sjdp     anyway.  xoxorich. */
217433965Sjdp
217533965Sjdp  if (S_GET_SEGMENT (symbolP) == undefined_section
217633965Sjdp      && S_GET_VALUE (symbolP) == 0)
217733965Sjdp    {
217833965Sjdp      /* The name might be an undefined .global symbol; be sure to
217933965Sjdp	 keep the "external" bit. */
218033965Sjdp      S_SET_SEGMENT (symbolP,
218133965Sjdp		     (exp.X_op == O_constant
218233965Sjdp		      ? absolute_section
218333965Sjdp		      : reg_section));
218433965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
218533965Sjdp    }
218633965Sjdp  else
218733965Sjdp    {
218860484Sobrien      as_bad (_("Symbol %s already defined"), name);
218933965Sjdp    }
219033965Sjdp  *p = c;
219133965Sjdp  demand_empty_rest_of_line ();
219233965Sjdp}				/* s_lsym() */
219333965Sjdp
219433965Sjdp/* Read a line into an sb.  */
219533965Sjdp
219633965Sjdpstatic int
219733965Sjdpget_line_sb (line)
219833965Sjdp     sb *line;
219933965Sjdp{
220033965Sjdp  char quote1, quote2, inquote;
220133965Sjdp
220233965Sjdp  if (input_line_pointer[-1] == '\n')
220333965Sjdp    bump_line_counters ();
220433965Sjdp
220533965Sjdp  if (input_line_pointer >= buffer_limit)
220633965Sjdp    {
220733965Sjdp      buffer_limit = input_scrub_next_buffer (&input_line_pointer);
220833965Sjdp      if (buffer_limit == 0)
220933965Sjdp	return 0;
221033965Sjdp    }
221133965Sjdp
221233965Sjdp  /* If app.c sets any other characters to LEX_IS_STRINGQUOTE, this
221333965Sjdp     code needs to be changed.  */
221433965Sjdp  if (! flag_m68k_mri)
221533965Sjdp    quote1 = '"';
221633965Sjdp  else
221733965Sjdp    quote1 = '\0';
221833965Sjdp
221933965Sjdp  quote2 = '\0';
222033965Sjdp  if (flag_m68k_mri)
222133965Sjdp    quote2 = '\'';
222233965Sjdp#ifdef LEX_IS_STRINGQUOTE
222333965Sjdp  quote2 = '\'';
222433965Sjdp#endif
222533965Sjdp
222633965Sjdp  inquote = '\0';
222733965Sjdp  while (! is_end_of_line[(unsigned char) *input_line_pointer]
222833965Sjdp	 || (inquote != '\0' && *input_line_pointer != '\n'))
222933965Sjdp    {
223033965Sjdp      if (inquote == *input_line_pointer)
223133965Sjdp	inquote = '\0';
223233965Sjdp      else if (inquote == '\0')
223333965Sjdp	{
223433965Sjdp	  if (*input_line_pointer == quote1)
223533965Sjdp	    inquote = quote1;
223633965Sjdp	  else if (*input_line_pointer == quote2)
223733965Sjdp	    inquote = quote2;
223833965Sjdp	}
223933965Sjdp      sb_add_char (line, *input_line_pointer++);
224033965Sjdp    }
224138889Sjdp  while (input_line_pointer < buffer_limit
224238889Sjdp	 && is_end_of_line[(unsigned char) *input_line_pointer])
224333965Sjdp    {
224433965Sjdp      if (input_line_pointer[-1] == '\n')
224533965Sjdp	bump_line_counters ();
224633965Sjdp      ++input_line_pointer;
224733965Sjdp    }
224833965Sjdp  return 1;
224933965Sjdp}
225033965Sjdp
225133965Sjdp/* Define a macro.  This is an interface to macro.c, which is shared
225233965Sjdp   between gas and gasp.  */
225333965Sjdp
225433965Sjdpvoid
225533965Sjdps_macro (ignore)
225660484Sobrien     int ignore ATTRIBUTE_UNUSED;
225733965Sjdp{
225833965Sjdp  char *file;
225933965Sjdp  unsigned int line;
226033965Sjdp  sb s;
226133965Sjdp  sb label;
226233965Sjdp  const char *err;
226333965Sjdp  const char *name;
226433965Sjdp
226533965Sjdp  as_where (&file, &line);
226633965Sjdp
226733965Sjdp  sb_new (&s);
226833965Sjdp  while (! is_end_of_line[(unsigned char) *input_line_pointer])
226933965Sjdp    sb_add_char (&s, *input_line_pointer++);
227033965Sjdp
227133965Sjdp  sb_new (&label);
227233965Sjdp  if (line_label != NULL)
227333965Sjdp    sb_add_string (&label, S_GET_NAME (line_label));
227433965Sjdp
227533965Sjdp  err = define_macro (0, &s, &label, get_line_sb, &name);
227633965Sjdp  if (err != NULL)
227733965Sjdp    as_bad_where (file, line, "%s", err);
227833965Sjdp  else
227933965Sjdp    {
228033965Sjdp      if (line_label != NULL)
228133965Sjdp	{
228233965Sjdp	  S_SET_SEGMENT (line_label, undefined_section);
228333965Sjdp	  S_SET_VALUE (line_label, 0);
228460484Sobrien	  symbol_set_frag (line_label, &zero_address_frag);
228533965Sjdp	}
228633965Sjdp
228760484Sobrien      if (((NO_PSEUDO_DOT || flag_m68k_mri)
228833965Sjdp	   && hash_find (po_hash, name) != NULL)
228933965Sjdp	  || (! flag_m68k_mri
229033965Sjdp	      && *name == '.'
229133965Sjdp	      && hash_find (po_hash, name + 1) != NULL))
229260484Sobrien	as_warn (_("attempt to redefine pseudo-op `%s' ignored"),
229333965Sjdp		 name);
229433965Sjdp    }
229533965Sjdp
229633965Sjdp  sb_kill (&s);
229733965Sjdp}
229833965Sjdp
229933965Sjdp/* Handle the .mexit pseudo-op, which immediately exits a macro
230033965Sjdp   expansion.  */
230133965Sjdp
230233965Sjdpvoid
230333965Sjdps_mexit (ignore)
230460484Sobrien     int ignore ATTRIBUTE_UNUSED;
230533965Sjdp{
230633965Sjdp  cond_exit_macro (macro_nest);
230733965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
230833965Sjdp}
230933965Sjdp
231033965Sjdp/* Switch in and out of MRI mode.  */
231133965Sjdp
231233965Sjdpvoid
231333965Sjdps_mri (ignore)
231460484Sobrien     int ignore ATTRIBUTE_UNUSED;
231533965Sjdp{
231633965Sjdp  int on, old_flag;
231733965Sjdp
231833965Sjdp  on = get_absolute_expression ();
231933965Sjdp  old_flag = flag_mri;
232033965Sjdp  if (on != 0)
232133965Sjdp    {
232233965Sjdp      flag_mri = 1;
232333965Sjdp#ifdef TC_M68K
232433965Sjdp      flag_m68k_mri = 1;
232533965Sjdp#endif
232660484Sobrien      macro_mri_mode (1);
232733965Sjdp    }
232833965Sjdp  else
232933965Sjdp    {
233033965Sjdp      flag_mri = 0;
233160484Sobrien#ifdef TC_M68K
233233965Sjdp      flag_m68k_mri = 0;
233360484Sobrien#endif
233460484Sobrien      macro_mri_mode (0);
233533965Sjdp    }
233633965Sjdp
233760484Sobrien  /* Operator precedence changes in m68k MRI mode, so we need to
233860484Sobrien     update the operator rankings.  */
233960484Sobrien  expr_set_precedence ();
234060484Sobrien
234133965Sjdp#ifdef MRI_MODE_CHANGE
234233965Sjdp  if (on != old_flag)
234333965Sjdp    MRI_MODE_CHANGE (on);
234433965Sjdp#endif
234533965Sjdp
234633965Sjdp  demand_empty_rest_of_line ();
234733965Sjdp}
234833965Sjdp
234933965Sjdp/* Handle changing the location counter.  */
235033965Sjdp
235133965Sjdpstatic void
235233965Sjdpdo_org (segment, exp, fill)
235333965Sjdp     segT segment;
235433965Sjdp     expressionS *exp;
235533965Sjdp     int fill;
235633965Sjdp{
235733965Sjdp  if (segment != now_seg && segment != absolute_section)
235860484Sobrien    as_bad (_("invalid segment \"%s\"; segment \"%s\" assumed"),
235933965Sjdp	    segment_name (segment), segment_name (now_seg));
236033965Sjdp
236133965Sjdp  if (now_seg == absolute_section)
236233965Sjdp    {
236333965Sjdp      if (fill != 0)
236460484Sobrien	as_warn (_("ignoring fill value in absolute section"));
236533965Sjdp      if (exp->X_op != O_constant)
236633965Sjdp	{
236760484Sobrien	  as_bad (_("only constant offsets supported in absolute section"));
236833965Sjdp	  exp->X_add_number = 0;
236933965Sjdp	}
237033965Sjdp      abs_section_offset = exp->X_add_number;
237133965Sjdp    }
237233965Sjdp  else
237333965Sjdp    {
237433965Sjdp      char *p;
237533965Sjdp
237633965Sjdp      p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp->X_add_symbol,
237760484Sobrien		    exp->X_add_number * OCTETS_PER_BYTE, (char *) NULL);
237833965Sjdp      *p = fill;
237933965Sjdp    }
238033965Sjdp}
238133965Sjdp
238233965Sjdpvoid
238333965Sjdps_org (ignore)
238460484Sobrien     int ignore ATTRIBUTE_UNUSED;
238533965Sjdp{
238633965Sjdp  register segT segment;
238733965Sjdp  expressionS exp;
238833965Sjdp  register long temp_fill;
238933965Sjdp
239060484Sobrien#ifdef md_flush_pending_output
239160484Sobrien  md_flush_pending_output ();
239260484Sobrien#endif
239360484Sobrien
239433965Sjdp  /* The m68k MRI assembler has a different meaning for .org.  It
239533965Sjdp     means to create an absolute section at a given address.  We can't
239633965Sjdp     support that--use a linker script instead.  */
239733965Sjdp  if (flag_m68k_mri)
239833965Sjdp    {
239960484Sobrien      as_bad (_("MRI style ORG pseudo-op not supported"));
240033965Sjdp      ignore_rest_of_line ();
240133965Sjdp      return;
240233965Sjdp    }
240333965Sjdp
240433965Sjdp  /* Don't believe the documentation of BSD 4.2 AS.  There is no such
240533965Sjdp     thing as a sub-segment-relative origin.  Any absolute origin is
240633965Sjdp     given a warning, then assumed to be segment-relative.  Any
240733965Sjdp     segmented origin expression ("foo+42") had better be in the right
240833965Sjdp     segment or the .org is ignored.
240933965Sjdp
241033965Sjdp     BSD 4.2 AS warns if you try to .org backwards. We cannot because
241133965Sjdp     we never know sub-segment sizes when we are reading code.  BSD
241233965Sjdp     will crash trying to emit negative numbers of filler bytes in
241333965Sjdp     certain .orgs. We don't crash, but see as-write for that code.
241433965Sjdp
241533965Sjdp     Don't make frag if need_pass_2==1.  */
241633965Sjdp  segment = get_known_segmented_expression (&exp);
241733965Sjdp  if (*input_line_pointer == ',')
241833965Sjdp    {
241933965Sjdp      input_line_pointer++;
242033965Sjdp      temp_fill = get_absolute_expression ();
242133965Sjdp    }
242233965Sjdp  else
242333965Sjdp    temp_fill = 0;
242433965Sjdp
242533965Sjdp  if (!need_pass_2)
242633965Sjdp    do_org (segment, &exp, temp_fill);
242733965Sjdp
242833965Sjdp  demand_empty_rest_of_line ();
242933965Sjdp}				/* s_org() */
243033965Sjdp
243133965Sjdp/* Handle parsing for the MRI SECT/SECTION pseudo-op.  This should be
243233965Sjdp   called by the obj-format routine which handles section changing
243333965Sjdp   when in MRI mode.  It will create a new section, and return it.  It
243433965Sjdp   will set *TYPE to the section type: one of 'C' (code), 'D' (data),
243533965Sjdp   'M' (mixed), or 'R' (romable).  If BFD_ASSEMBLER is defined, the
243633965Sjdp   flags will be set in the section.  */
243733965Sjdp
243833965Sjdpvoid
243933965Sjdps_mri_sect (type)
244060484Sobrien     char *type ATTRIBUTE_UNUSED;
244133965Sjdp{
244233965Sjdp#ifdef TC_M68K
244333965Sjdp
244433965Sjdp  char *name;
244533965Sjdp  char c;
244633965Sjdp  segT seg;
244733965Sjdp
244833965Sjdp  SKIP_WHITESPACE ();
244933965Sjdp
245033965Sjdp  name = input_line_pointer;
245133965Sjdp  if (! isdigit ((unsigned char) *name))
245233965Sjdp    c = get_symbol_end ();
245333965Sjdp  else
245433965Sjdp    {
245533965Sjdp      do
245633965Sjdp	{
245733965Sjdp	  ++input_line_pointer;
245833965Sjdp	}
245933965Sjdp      while (isdigit ((unsigned char) *input_line_pointer));
246033965Sjdp      c = *input_line_pointer;
246133965Sjdp      *input_line_pointer = '\0';
246233965Sjdp    }
246333965Sjdp
246433965Sjdp  name = xstrdup (name);
246533965Sjdp
246633965Sjdp  *input_line_pointer = c;
246733965Sjdp
246833965Sjdp  seg = subseg_new (name, 0);
246933965Sjdp
247033965Sjdp  if (*input_line_pointer == ',')
247133965Sjdp    {
247233965Sjdp      int align;
247333965Sjdp
247433965Sjdp      ++input_line_pointer;
247533965Sjdp      align = get_absolute_expression ();
247633965Sjdp      record_alignment (seg, align);
247733965Sjdp    }
247833965Sjdp
247933965Sjdp  *type = 'C';
248033965Sjdp  if (*input_line_pointer == ',')
248133965Sjdp    {
248233965Sjdp      c = *++input_line_pointer;
248333965Sjdp      c = toupper ((unsigned char) c);
248433965Sjdp      if (c == 'C' || c == 'D' || c == 'M' || c == 'R')
248533965Sjdp	*type = c;
248633965Sjdp      else
248760484Sobrien	as_bad (_("unrecognized section type"));
248833965Sjdp      ++input_line_pointer;
248933965Sjdp
249033965Sjdp#ifdef BFD_ASSEMBLER
249133965Sjdp      {
249233965Sjdp	flagword flags;
249333965Sjdp
249433965Sjdp	flags = SEC_NO_FLAGS;
249533965Sjdp	if (*type == 'C')
249633965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE;
249733965Sjdp	else if (*type == 'D' || *type == 'M')
249833965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_DATA;
249933965Sjdp	else if (*type == 'R')
250033965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM;
250133965Sjdp	if (flags != SEC_NO_FLAGS)
250233965Sjdp	  {
250333965Sjdp	    if (! bfd_set_section_flags (stdoutput, seg, flags))
250460484Sobrien	      as_warn (_("error setting flags for \"%s\": %s"),
250533965Sjdp		       bfd_section_name (stdoutput, seg),
250633965Sjdp		       bfd_errmsg (bfd_get_error ()));
250733965Sjdp	  }
250833965Sjdp      }
250933965Sjdp#endif
251033965Sjdp    }
251133965Sjdp
251233965Sjdp  /* Ignore the HP type.  */
251333965Sjdp  if (*input_line_pointer == ',')
251433965Sjdp    input_line_pointer += 2;
251533965Sjdp
251633965Sjdp  demand_empty_rest_of_line ();
251733965Sjdp
251833965Sjdp#else /* ! TC_M68K */
251933965Sjdp#ifdef TC_I960
252033965Sjdp
252133965Sjdp  char *name;
252233965Sjdp  char c;
252333965Sjdp  segT seg;
252433965Sjdp
252533965Sjdp  SKIP_WHITESPACE ();
252633965Sjdp
252733965Sjdp  name = input_line_pointer;
252833965Sjdp  c = get_symbol_end ();
252933965Sjdp
253033965Sjdp  name = xstrdup (name);
253133965Sjdp
253233965Sjdp  *input_line_pointer = c;
253333965Sjdp
253433965Sjdp  seg = subseg_new (name, 0);
253533965Sjdp
253633965Sjdp  if (*input_line_pointer != ',')
253733965Sjdp    *type = 'C';
253833965Sjdp  else
253933965Sjdp    {
254033965Sjdp      char *sectype;
254133965Sjdp
254233965Sjdp      ++input_line_pointer;
254333965Sjdp      SKIP_WHITESPACE ();
254433965Sjdp      sectype = input_line_pointer;
254533965Sjdp      c = get_symbol_end ();
254633965Sjdp      if (*sectype == '\0')
254733965Sjdp	*type = 'C';
254833965Sjdp      else if (strcasecmp (sectype, "text") == 0)
254933965Sjdp	*type = 'C';
255033965Sjdp      else if (strcasecmp (sectype, "data") == 0)
255133965Sjdp	*type = 'D';
255233965Sjdp      else if (strcasecmp (sectype, "romdata") == 0)
255333965Sjdp	*type = 'R';
255433965Sjdp      else
255560484Sobrien	as_warn (_("unrecognized section type `%s'"), sectype);
255633965Sjdp      *input_line_pointer = c;
255733965Sjdp    }
255833965Sjdp
255933965Sjdp  if (*input_line_pointer == ',')
256033965Sjdp    {
256133965Sjdp      char *seccmd;
256233965Sjdp
256333965Sjdp      ++input_line_pointer;
256433965Sjdp      SKIP_WHITESPACE ();
256533965Sjdp      seccmd = input_line_pointer;
256633965Sjdp      c = get_symbol_end ();
256733965Sjdp      if (strcasecmp (seccmd, "absolute") == 0)
256833965Sjdp	{
256960484Sobrien	  as_bad (_("absolute sections are not supported"));
257033965Sjdp	  *input_line_pointer = c;
257133965Sjdp	  ignore_rest_of_line ();
257233965Sjdp	  return;
257333965Sjdp	}
257433965Sjdp      else if (strcasecmp (seccmd, "align") == 0)
257533965Sjdp	{
257633965Sjdp	  int align;
257733965Sjdp
257833965Sjdp	  *input_line_pointer = c;
257933965Sjdp	  align = get_absolute_expression ();
258033965Sjdp	  record_alignment (seg, align);
258133965Sjdp	}
258233965Sjdp      else
258333965Sjdp	{
258460484Sobrien	  as_warn (_("unrecognized section command `%s'"), seccmd);
258533965Sjdp	  *input_line_pointer = c;
258633965Sjdp	}
258733965Sjdp    }
258833965Sjdp
258933965Sjdp  demand_empty_rest_of_line ();
259033965Sjdp
259133965Sjdp#else /* ! TC_I960 */
259233965Sjdp  /* The MRI assembler seems to use different forms of .sect for
259333965Sjdp     different targets.  */
259460484Sobrien  as_bad ("MRI mode not supported for this target");
259560484Sobrien  ignore_rest_of_line ();
259633965Sjdp#endif /* ! TC_I960 */
259733965Sjdp#endif /* ! TC_M68K */
259833965Sjdp}
259933965Sjdp
260033965Sjdp/* Handle the .print pseudo-op.  */
260133965Sjdp
260233965Sjdpvoid
260333965Sjdps_print (ignore)
260460484Sobrien     int ignore ATTRIBUTE_UNUSED;
260533965Sjdp{
260633965Sjdp  char *s;
260733965Sjdp  int len;
260833965Sjdp
260933965Sjdp  s = demand_copy_C_string (&len);
261033965Sjdp  printf ("%s\n", s);
261133965Sjdp  demand_empty_rest_of_line ();
261233965Sjdp}
261333965Sjdp
261433965Sjdp/* Handle the .purgem pseudo-op.  */
261533965Sjdp
261633965Sjdpvoid
261733965Sjdps_purgem (ignore)
261860484Sobrien     int ignore ATTRIBUTE_UNUSED;
261933965Sjdp{
262033965Sjdp  if (is_it_end_of_statement ())
262133965Sjdp    {
262233965Sjdp      demand_empty_rest_of_line ();
262333965Sjdp      return;
262433965Sjdp    }
262533965Sjdp
262633965Sjdp  do
262733965Sjdp    {
262833965Sjdp      char *name;
262933965Sjdp      char c;
263033965Sjdp
263133965Sjdp      SKIP_WHITESPACE ();
263233965Sjdp      name = input_line_pointer;
263333965Sjdp      c = get_symbol_end ();
263433965Sjdp      delete_macro (name);
263533965Sjdp      *input_line_pointer = c;
263633965Sjdp      SKIP_WHITESPACE ();
263733965Sjdp    }
263833965Sjdp  while (*input_line_pointer++ == ',');
263933965Sjdp
264033965Sjdp  --input_line_pointer;
264133965Sjdp  demand_empty_rest_of_line ();
264233965Sjdp}
264333965Sjdp
264433965Sjdp/* Handle the .rept pseudo-op.  */
264533965Sjdp
264633965Sjdpvoid
264733965Sjdps_rept (ignore)
264860484Sobrien     int ignore ATTRIBUTE_UNUSED;
264933965Sjdp{
265033965Sjdp  int count;
265160484Sobrien
265260484Sobrien  count = get_absolute_expression ();
265360484Sobrien
265460484Sobrien  do_repeat(count, "REPT", "ENDR");
265560484Sobrien}
265660484Sobrien
265760484Sobrien/* This function provides a generic repeat block implementation.   It allows
265860484Sobrien   different directives to be used as the start/end keys. */
265960484Sobrien
266060484Sobrienvoid
266160484Sobriendo_repeat (count, start, end)
266260484Sobrien      int count;
266360484Sobrien      const char *start;
266460484Sobrien      const char *end;
266560484Sobrien{
266633965Sjdp  sb one;
266733965Sjdp  sb many;
266833965Sjdp
266933965Sjdp  sb_new (&one);
267060484Sobrien  if (! buffer_and_nest (start, end, &one, get_line_sb))
267133965Sjdp    {
267260484Sobrien      as_bad (_("%s without %s"), start, end);
267333965Sjdp      return;
267433965Sjdp    }
267533965Sjdp
267633965Sjdp  sb_new (&many);
267733965Sjdp  while (count-- > 0)
267833965Sjdp    sb_add_sb (&many, &one);
267933965Sjdp
268033965Sjdp  sb_kill (&one);
268133965Sjdp
268260484Sobrien  input_scrub_include_sb (&many, input_line_pointer, 1);
268333965Sjdp  sb_kill (&many);
268433965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
268533965Sjdp}
268633965Sjdp
268760484Sobrien/* Skip to end of current repeat loop; EXTRA indicates how many additional
268860484Sobrien   input buffers to skip.  Assumes that conditionals preceding the loop end
268960484Sobrien   are properly nested.
269060484Sobrien
269160484Sobrien   This function makes it easier to implement a premature "break" out of the
269260484Sobrien   loop.  The EXTRA arg accounts for other buffers we might have inserted,
269360484Sobrien   such as line substitutions. */
269460484Sobrien
269560484Sobrienvoid
269660484Sobrienend_repeat (extra)
269760484Sobrien  int extra;
269860484Sobrien{
269960484Sobrien  cond_exit_macro (macro_nest);
270060484Sobrien  while (extra-- >= 0)
270160484Sobrien    buffer_limit = input_scrub_next_buffer (&input_line_pointer);
270260484Sobrien}
270360484Sobrien
270433965Sjdp/* Handle the .equ, .equiv and .set directives.  If EQUIV is 1, then
270533965Sjdp   this is .equiv, and it is an error if the symbol is already
270633965Sjdp   defined.  */
270733965Sjdp
270833965Sjdpvoid
270933965Sjdps_set (equiv)
271033965Sjdp     int equiv;
271133965Sjdp{
271233965Sjdp  register char *name;
271333965Sjdp  register char delim;
271433965Sjdp  register char *end_name;
271533965Sjdp  register symbolS *symbolP;
271633965Sjdp
271733965Sjdp  /*
271833965Sjdp   * Especial apologies for the random logic:
271933965Sjdp   * this just grew, and could be parsed much more simply!
272033965Sjdp   * Dean in haste.
272133965Sjdp   */
272233965Sjdp  name = input_line_pointer;
272333965Sjdp  delim = get_symbol_end ();
272433965Sjdp  end_name = input_line_pointer;
272533965Sjdp  *end_name = delim;
272633965Sjdp  SKIP_WHITESPACE ();
272733965Sjdp
272833965Sjdp  if (*input_line_pointer != ',')
272933965Sjdp    {
273033965Sjdp      *end_name = 0;
273160484Sobrien      as_bad (_("Expected comma after name \"%s\""), name);
273233965Sjdp      *end_name = delim;
273333965Sjdp      ignore_rest_of_line ();
273433965Sjdp      return;
273533965Sjdp    }
273633965Sjdp
273733965Sjdp  input_line_pointer++;
273833965Sjdp  *end_name = 0;
273933965Sjdp
274033965Sjdp  if (name[0] == '.' && name[1] == '\0')
274133965Sjdp    {
274233965Sjdp      /* Turn '. = mumble' into a .org mumble */
274333965Sjdp      register segT segment;
274433965Sjdp      expressionS exp;
274533965Sjdp
274633965Sjdp      segment = get_known_segmented_expression (&exp);
274733965Sjdp
274833965Sjdp      if (!need_pass_2)
274933965Sjdp	do_org (segment, &exp, 0);
275033965Sjdp
275133965Sjdp      *end_name = delim;
275233965Sjdp      return;
275333965Sjdp    }
275433965Sjdp
275533965Sjdp  if ((symbolP = symbol_find (name)) == NULL
275633965Sjdp      && (symbolP = md_undefined_symbol (name)) == NULL)
275733965Sjdp    {
275838889Sjdp#ifndef NO_LISTING
275938889Sjdp      /* When doing symbol listings, play games with dummy fragments living
276038889Sjdp	 outside the normal fragment chain to record the file and line info
276138889Sjdp         for this symbol.  */
276238889Sjdp      if (listing & LISTING_SYMBOLS)
276338889Sjdp	{
276438889Sjdp	  extern struct list_info_struct *listing_tail;
276538889Sjdp	  fragS *dummy_frag = (fragS *) xmalloc (sizeof(fragS));
276638889Sjdp	  memset (dummy_frag, 0, sizeof(fragS));
276738889Sjdp	  dummy_frag->fr_type = rs_fill;
276838889Sjdp	  dummy_frag->line = listing_tail;
276938889Sjdp	  symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
277038889Sjdp	  dummy_frag->fr_symbol = symbolP;
277138889Sjdp	}
277238889Sjdp      else
277338889Sjdp#endif
277438889Sjdp        symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
277538889Sjdp
277633965Sjdp#ifdef OBJ_COFF
277733965Sjdp      /* "set" symbols are local unless otherwise specified. */
277833965Sjdp      SF_SET_LOCAL (symbolP);
277933965Sjdp#endif /* OBJ_COFF */
278033965Sjdp
278133965Sjdp    }				/* make a new symbol */
278233965Sjdp
278333965Sjdp  symbol_table_insert (symbolP);
278433965Sjdp
278533965Sjdp  *end_name = delim;
278633965Sjdp
278733965Sjdp  if (equiv
278833965Sjdp      && S_IS_DEFINED (symbolP)
278933965Sjdp      && S_GET_SEGMENT (symbolP) != reg_section)
279060484Sobrien    as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
279133965Sjdp
279233965Sjdp  pseudo_set (symbolP);
279333965Sjdp  demand_empty_rest_of_line ();
279433965Sjdp}				/* s_set() */
279533965Sjdp
279633965Sjdpvoid
279733965Sjdps_space (mult)
279833965Sjdp     int mult;
279933965Sjdp{
280033965Sjdp  expressionS exp;
280133965Sjdp  expressionS val;
280233965Sjdp  char *p = 0;
280333965Sjdp  char *stop = NULL;
280433965Sjdp  char stopc;
280533965Sjdp  int bytes;
280633965Sjdp
280733965Sjdp#ifdef md_flush_pending_output
280833965Sjdp  md_flush_pending_output ();
280933965Sjdp#endif
281033965Sjdp
281133965Sjdp  if (flag_mri)
281233965Sjdp    stop = mri_comment_field (&stopc);
281333965Sjdp
281433965Sjdp  /* In m68k MRI mode, we need to align to a word boundary, unless
281533965Sjdp     this is ds.b.  */
281633965Sjdp  if (flag_m68k_mri && mult > 1)
281733965Sjdp    {
281833965Sjdp      if (now_seg == absolute_section)
281933965Sjdp	{
282033965Sjdp	  abs_section_offset += abs_section_offset & 1;
282133965Sjdp	  if (line_label != NULL)
282233965Sjdp	    S_SET_VALUE (line_label, abs_section_offset);
282333965Sjdp	}
282433965Sjdp      else if (mri_common_symbol != NULL)
282533965Sjdp	{
282633965Sjdp	  valueT val;
282733965Sjdp
282833965Sjdp	  val = S_GET_VALUE (mri_common_symbol);
282933965Sjdp	  if ((val & 1) != 0)
283033965Sjdp	    {
283133965Sjdp	      S_SET_VALUE (mri_common_symbol, val + 1);
283233965Sjdp	      if (line_label != NULL)
283333965Sjdp		{
283460484Sobrien		  expressionS *symexp;
283560484Sobrien
283660484Sobrien		  symexp = symbol_get_value_expression (line_label);
283760484Sobrien		  know (symexp->X_op == O_symbol);
283860484Sobrien		  know (symexp->X_add_symbol == mri_common_symbol);
283960484Sobrien		  symexp->X_add_number += 1;
284033965Sjdp		}
284133965Sjdp	    }
284233965Sjdp	}
284333965Sjdp      else
284433965Sjdp	{
284533965Sjdp	  do_align (1, (char *) NULL, 0, 0);
284633965Sjdp	  if (line_label != NULL)
284733965Sjdp	    {
284860484Sobrien	      symbol_set_frag (line_label, frag_now);
284933965Sjdp	      S_SET_VALUE (line_label, frag_now_fix ());
285033965Sjdp	    }
285133965Sjdp	}
285233965Sjdp    }
285333965Sjdp
285433965Sjdp  bytes = mult;
285533965Sjdp
285633965Sjdp  expression (&exp);
285733965Sjdp
285833965Sjdp  SKIP_WHITESPACE ();
285933965Sjdp  if (*input_line_pointer == ',')
286033965Sjdp    {
286133965Sjdp      ++input_line_pointer;
286233965Sjdp      expression (&val);
286333965Sjdp    }
286433965Sjdp  else
286533965Sjdp    {
286633965Sjdp      val.X_op = O_constant;
286733965Sjdp      val.X_add_number = 0;
286833965Sjdp    }
286933965Sjdp
287033965Sjdp  if (val.X_op != O_constant
287133965Sjdp      || val.X_add_number < - 0x80
287233965Sjdp      || val.X_add_number > 0xff
287333965Sjdp      || (mult != 0 && mult != 1 && val.X_add_number != 0))
287433965Sjdp    {
287533965Sjdp      if (exp.X_op != O_constant)
287660484Sobrien	as_bad (_("Unsupported variable size or fill value"));
287733965Sjdp      else
287833965Sjdp	{
287933965Sjdp	  offsetT i;
288033965Sjdp
288133965Sjdp	  if (mult == 0)
288233965Sjdp	    mult = 1;
288333965Sjdp	  bytes = mult * exp.X_add_number;
288433965Sjdp	  for (i = 0; i < exp.X_add_number; i++)
288533965Sjdp	    emit_expr (&val, mult);
288633965Sjdp	}
288733965Sjdp    }
288833965Sjdp  else
288933965Sjdp    {
289033965Sjdp      if (exp.X_op == O_constant)
289133965Sjdp	{
289233965Sjdp	  long repeat;
289333965Sjdp
289433965Sjdp	  repeat = exp.X_add_number;
289533965Sjdp	  if (mult)
289633965Sjdp	    repeat *= mult;
289733965Sjdp	  bytes = repeat;
289833965Sjdp	  if (repeat <= 0)
289933965Sjdp	    {
290060484Sobrien	      if (! flag_mri)
290160484Sobrien		as_warn (_(".space repeat count is zero, ignored"));
290260484Sobrien	      else if (repeat < 0)
290360484Sobrien		as_warn (_(".space repeat count is negative, ignored"));
290433965Sjdp	      goto getout;
290533965Sjdp	    }
290633965Sjdp
290733965Sjdp	  /* If we are in the absolute section, just bump the offset.  */
290833965Sjdp	  if (now_seg == absolute_section)
290933965Sjdp	    {
291033965Sjdp	      abs_section_offset += repeat;
291133965Sjdp	      goto getout;
291233965Sjdp	    }
291333965Sjdp
291433965Sjdp	  /* If we are secretly in an MRI common section, then
291533965Sjdp	     creating space just increases the size of the common
291633965Sjdp	     symbol.  */
291733965Sjdp	  if (mri_common_symbol != NULL)
291833965Sjdp	    {
291933965Sjdp	      S_SET_VALUE (mri_common_symbol,
292033965Sjdp			   S_GET_VALUE (mri_common_symbol) + repeat);
292133965Sjdp	      goto getout;
292233965Sjdp	    }
292333965Sjdp
292433965Sjdp	  if (!need_pass_2)
292533965Sjdp	    p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
292633965Sjdp			  (offsetT) repeat, (char *) 0);
292733965Sjdp	}
292833965Sjdp      else
292933965Sjdp	{
293033965Sjdp	  if (now_seg == absolute_section)
293133965Sjdp	    {
293260484Sobrien	      as_bad (_("space allocation too complex in absolute section"));
293333965Sjdp	      subseg_set (text_section, 0);
293433965Sjdp	    }
293533965Sjdp	  if (mri_common_symbol != NULL)
293633965Sjdp	    {
293760484Sobrien	      as_bad (_("space allocation too complex in common section"));
293833965Sjdp	      mri_common_symbol = NULL;
293933965Sjdp	    }
294033965Sjdp	  if (!need_pass_2)
294133965Sjdp	    p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
294233965Sjdp			  make_expr_symbol (&exp), (offsetT) 0, (char *) 0);
294333965Sjdp	}
294433965Sjdp
294533965Sjdp      if (p)
294633965Sjdp	*p = val.X_add_number;
294733965Sjdp    }
294833965Sjdp
294933965Sjdp getout:
295033965Sjdp
295133965Sjdp  /* In MRI mode, after an odd number of bytes, we must align to an
295233965Sjdp     even word boundary, unless the next instruction is a dc.b, ds.b
295333965Sjdp     or dcb.b.  */
295433965Sjdp  if (flag_mri && (bytes & 1) != 0)
295533965Sjdp    mri_pending_align = 1;
295633965Sjdp
295760484Sobrien  demand_empty_rest_of_line ();
295860484Sobrien
295933965Sjdp  if (flag_mri)
296033965Sjdp    mri_comment_end (stop, stopc);
296133965Sjdp}
296233965Sjdp
296333965Sjdp/* This is like s_space, but the value is a floating point number with
296433965Sjdp   the given precision.  This is for the MRI dcb.s pseudo-op and
296533965Sjdp   friends.  */
296633965Sjdp
296733965Sjdpvoid
296833965Sjdps_float_space (float_type)
296933965Sjdp     int float_type;
297033965Sjdp{
297133965Sjdp  offsetT count;
297233965Sjdp  int flen;
297333965Sjdp  char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
297433965Sjdp  char *stop = NULL;
297533965Sjdp  char stopc;
297633965Sjdp
297733965Sjdp  if (flag_mri)
297833965Sjdp    stop = mri_comment_field (&stopc);
297933965Sjdp
298033965Sjdp  count = get_absolute_expression ();
298133965Sjdp
298233965Sjdp  SKIP_WHITESPACE ();
298333965Sjdp  if (*input_line_pointer != ',')
298433965Sjdp    {
298560484Sobrien      as_bad (_("missing value"));
298660484Sobrien      ignore_rest_of_line ();
298733965Sjdp      if (flag_mri)
298833965Sjdp	mri_comment_end (stop, stopc);
298933965Sjdp      return;
299033965Sjdp    }
299133965Sjdp
299233965Sjdp  ++input_line_pointer;
299333965Sjdp
299433965Sjdp  SKIP_WHITESPACE ();
299533965Sjdp
299633965Sjdp  /* Skip any 0{letter} that may be present.  Don't even check if the
299733965Sjdp   * letter is legal.  */
299838889Sjdp  if (input_line_pointer[0] == '0'
299938889Sjdp      && isalpha ((unsigned char) input_line_pointer[1]))
300033965Sjdp    input_line_pointer += 2;
300133965Sjdp
300233965Sjdp  /* Accept :xxxx, where the x's are hex digits, for a floating point
300333965Sjdp     with the exact digits specified.  */
300433965Sjdp  if (input_line_pointer[0] == ':')
300533965Sjdp    {
300633965Sjdp      flen = hex_float (float_type, temp);
300733965Sjdp      if (flen < 0)
300833965Sjdp	{
300960484Sobrien	  ignore_rest_of_line ();
301033965Sjdp	  if (flag_mri)
301133965Sjdp	    mri_comment_end (stop, stopc);
301233965Sjdp	  return;
301333965Sjdp	}
301433965Sjdp    }
301533965Sjdp  else
301633965Sjdp    {
301733965Sjdp      char *err;
301833965Sjdp
301933965Sjdp      err = md_atof (float_type, temp, &flen);
302033965Sjdp      know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
302133965Sjdp      know (flen > 0);
302233965Sjdp      if (err)
302333965Sjdp	{
302460484Sobrien	  as_bad (_("Bad floating literal: %s"), err);
302560484Sobrien	  ignore_rest_of_line ();
302633965Sjdp	  if (flag_mri)
302733965Sjdp	    mri_comment_end (stop, stopc);
302833965Sjdp	  return;
302933965Sjdp	}
303033965Sjdp    }
303133965Sjdp
303233965Sjdp  while (--count >= 0)
303333965Sjdp    {
303433965Sjdp      char *p;
303533965Sjdp
303633965Sjdp      p = frag_more (flen);
303733965Sjdp      memcpy (p, temp, (unsigned int) flen);
303833965Sjdp    }
303933965Sjdp
304060484Sobrien  demand_empty_rest_of_line ();
304160484Sobrien
304233965Sjdp  if (flag_mri)
304333965Sjdp    mri_comment_end (stop, stopc);
304433965Sjdp}
304533965Sjdp
304633965Sjdp/* Handle the .struct pseudo-op, as found in MIPS assemblers.  */
304733965Sjdp
304833965Sjdpvoid
304933965Sjdps_struct (ignore)
305060484Sobrien     int ignore ATTRIBUTE_UNUSED;
305133965Sjdp{
305233965Sjdp  char *stop = NULL;
305333965Sjdp  char stopc;
305433965Sjdp
305533965Sjdp  if (flag_mri)
305633965Sjdp    stop = mri_comment_field (&stopc);
305733965Sjdp  abs_section_offset = get_absolute_expression ();
305833965Sjdp  subseg_set (absolute_section, 0);
305960484Sobrien  demand_empty_rest_of_line ();
306033965Sjdp  if (flag_mri)
306133965Sjdp    mri_comment_end (stop, stopc);
306233965Sjdp}
306333965Sjdp
306433965Sjdpvoid
306533965Sjdps_text (ignore)
306660484Sobrien     int ignore ATTRIBUTE_UNUSED;
306733965Sjdp{
306833965Sjdp  register int temp;
306933965Sjdp
307033965Sjdp  temp = get_absolute_expression ();
307133965Sjdp  subseg_set (text_section, (subsegT) temp);
307233965Sjdp  demand_empty_rest_of_line ();
307333965Sjdp#ifdef OBJ_VMS
307433965Sjdp  const_flag &= ~IN_DEFAULT_SECTION;
307533965Sjdp#endif
307633965Sjdp}				/* s_text() */
307733965Sjdp
307833965Sjdp
307933965Sjdpvoid
308033965Sjdpdemand_empty_rest_of_line ()
308133965Sjdp{
308233965Sjdp  SKIP_WHITESPACE ();
308333965Sjdp  if (is_end_of_line[(unsigned char) *input_line_pointer])
308433965Sjdp    {
308533965Sjdp      input_line_pointer++;
308633965Sjdp    }
308733965Sjdp  else
308833965Sjdp    {
308933965Sjdp      ignore_rest_of_line ();
309033965Sjdp    }
309133965Sjdp  /* Return having already swallowed end-of-line. */
309233965Sjdp}				/* Return pointing just after end-of-line. */
309333965Sjdp
309433965Sjdpvoid
309533965Sjdpignore_rest_of_line ()		/* For suspect lines: gives warning. */
309633965Sjdp{
309733965Sjdp  if (!is_end_of_line[(unsigned char) *input_line_pointer])
309833965Sjdp    {
309938889Sjdp      if (isprint ((unsigned char) *input_line_pointer))
310060484Sobrien	as_bad (_("Rest of line ignored. First ignored character is `%c'."),
310133965Sjdp		*input_line_pointer);
310233965Sjdp      else
310360484Sobrien	as_bad (_("Rest of line ignored. First ignored character valued 0x%x."),
310433965Sjdp		*input_line_pointer);
310533965Sjdp      while (input_line_pointer < buffer_limit
310633965Sjdp	     && !is_end_of_line[(unsigned char) *input_line_pointer])
310733965Sjdp	{
310833965Sjdp	  input_line_pointer++;
310933965Sjdp	}
311033965Sjdp    }
311133965Sjdp  input_line_pointer++;		/* Return pointing just after end-of-line. */
311233965Sjdp  know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
311333965Sjdp}
311433965Sjdp
311560484Sobrienvoid
311660484Sobriendiscard_rest_of_line ()
311760484Sobrien{
311860484Sobrien  while (input_line_pointer < buffer_limit
311960484Sobrien         && !is_end_of_line[(unsigned char) *input_line_pointer])
312060484Sobrien    {
312160484Sobrien      input_line_pointer++;
312260484Sobrien    }
312360484Sobrien  input_line_pointer++;         /* Return pointing just after end-of-line. */
312460484Sobrien  know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
312560484Sobrien}
312660484Sobrien
312733965Sjdp/*
312833965Sjdp *			pseudo_set()
312933965Sjdp *
313033965Sjdp * In:	Pointer to a symbol.
313133965Sjdp *	Input_line_pointer->expression.
313233965Sjdp *
313333965Sjdp * Out:	Input_line_pointer->just after any whitespace after expression.
313433965Sjdp *	Tried to set symbol to value of expression.
313533965Sjdp *	Will change symbols type, value, and frag;
313633965Sjdp */
313733965Sjdpvoid
313833965Sjdppseudo_set (symbolP)
313933965Sjdp     symbolS *symbolP;
314033965Sjdp{
314133965Sjdp  expressionS exp;
314233965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
314333965Sjdp  int ext;
314433965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
314533965Sjdp
314633965Sjdp  know (symbolP);		/* NULL pointer is logic error. */
314733965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
314833965Sjdp  ext = S_IS_EXTERNAL (symbolP);
314933965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
315033965Sjdp
315133965Sjdp  (void) expression (&exp);
315233965Sjdp
315333965Sjdp  if (exp.X_op == O_illegal)
315460484Sobrien    as_bad (_("illegal expression; zero assumed"));
315533965Sjdp  else if (exp.X_op == O_absent)
315660484Sobrien    as_bad (_("missing expression; zero assumed"));
315733965Sjdp  else if (exp.X_op == O_big)
315860484Sobrien    {
315960484Sobrien      if (exp.X_add_number > 0)
316060484Sobrien	as_bad (_("bignum invalid; zero assumed"));
316160484Sobrien      else
316260484Sobrien	as_bad (_("floating point number invalid; zero assumed"));
316360484Sobrien    }
316433965Sjdp  else if (exp.X_op == O_subtract
316533965Sjdp	   && (S_GET_SEGMENT (exp.X_add_symbol)
316633965Sjdp	       == S_GET_SEGMENT (exp.X_op_symbol))
316733965Sjdp	   && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol))
316860484Sobrien	   && (symbol_get_frag (exp.X_add_symbol)
316960484Sobrien	       == symbol_get_frag (exp.X_op_symbol)))
317033965Sjdp    {
317133965Sjdp      exp.X_op = O_constant;
317233965Sjdp      exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol)
317333965Sjdp			  - S_GET_VALUE (exp.X_op_symbol));
317433965Sjdp    }
317533965Sjdp
317633965Sjdp  switch (exp.X_op)
317733965Sjdp    {
317833965Sjdp    case O_illegal:
317933965Sjdp    case O_absent:
318033965Sjdp    case O_big:
318133965Sjdp      exp.X_add_number = 0;
318233965Sjdp      /* Fall through.  */
318333965Sjdp    case O_constant:
318433965Sjdp      S_SET_SEGMENT (symbolP, absolute_section);
318533965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
318633965Sjdp      if (ext)
318733965Sjdp	S_SET_EXTERNAL (symbolP);
318833965Sjdp      else
318933965Sjdp	S_CLEAR_EXTERNAL (symbolP);
319033965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
319133965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
319238889Sjdp      if (exp.X_op != O_constant)
319360484Sobrien        symbol_set_frag (symbolP, &zero_address_frag);
319433965Sjdp      break;
319533965Sjdp
319633965Sjdp    case O_register:
319733965Sjdp      S_SET_SEGMENT (symbolP, reg_section);
319833965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
319960484Sobrien      symbol_set_frag (symbolP, &zero_address_frag);
320033965Sjdp      break;
320133965Sjdp
320233965Sjdp    case O_symbol:
320333965Sjdp      if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section
320433965Sjdp	  || exp.X_add_number != 0)
320560484Sobrien	symbol_set_value_expression (symbolP, &exp);
320660484Sobrien      else if (symbol_section_p (symbolP))
320760484Sobrien	as_bad ("invalid attempt to set value of section symbol");
320833965Sjdp      else
320933965Sjdp	{
321033965Sjdp	  symbolS *s = exp.X_add_symbol;
321133965Sjdp
321233965Sjdp	  S_SET_SEGMENT (symbolP, S_GET_SEGMENT (s));
321333965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
321433965Sjdp	  if (ext)
321533965Sjdp	    S_SET_EXTERNAL (symbolP);
321633965Sjdp	  else
321733965Sjdp	    S_CLEAR_EXTERNAL (symbolP);
321833965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
321933965Sjdp	  S_SET_VALUE (symbolP,
322033965Sjdp		       exp.X_add_number + S_GET_VALUE (s));
322160484Sobrien	  symbol_set_frag (symbolP, symbol_get_frag (s));
322233965Sjdp	  copy_symbol_attributes (symbolP, s);
322333965Sjdp	}
322433965Sjdp      break;
322533965Sjdp
322633965Sjdp    default:
322733965Sjdp      /* The value is some complex expression.
322833965Sjdp	 FIXME: Should we set the segment to anything?  */
322960484Sobrien      symbol_set_value_expression (symbolP, &exp);
323033965Sjdp      break;
323133965Sjdp    }
323233965Sjdp}
323333965Sjdp
323433965Sjdp/*
323533965Sjdp *			cons()
323633965Sjdp *
323733965Sjdp * CONStruct more frag of .bytes, or .words etc.
323833965Sjdp * Should need_pass_2 be 1 then emit no frag(s).
323933965Sjdp * This understands EXPRESSIONS.
324033965Sjdp *
324133965Sjdp * Bug (?)
324233965Sjdp *
324333965Sjdp * This has a split personality. We use expression() to read the
324433965Sjdp * value. We can detect if the value won't fit in a byte or word.
324533965Sjdp * But we can't detect if expression() discarded significant digits
324633965Sjdp * in the case of a long. Not worth the crocks required to fix it.
324733965Sjdp */
324833965Sjdp
324933965Sjdp/* Select a parser for cons expressions.  */
325033965Sjdp
325133965Sjdp/* Some targets need to parse the expression in various fancy ways.
325233965Sjdp   You can define TC_PARSE_CONS_EXPRESSION to do whatever you like
325333965Sjdp   (for example, the HPPA does this).  Otherwise, you can define
325433965Sjdp   BITFIELD_CONS_EXPRESSIONS to permit bitfields to be specified, or
325533965Sjdp   REPEAT_CONS_EXPRESSIONS to permit repeat counts.  If none of these
325633965Sjdp   are defined, which is the normal case, then only simple expressions
325733965Sjdp   are permitted.  */
325833965Sjdp
325960484Sobrien#ifdef TC_M68K
326033965Sjdpstatic void
326133965Sjdpparse_mri_cons PARAMS ((expressionS *exp, unsigned int nbytes));
326260484Sobrien#endif
326333965Sjdp
326433965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION
326533965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS
326633965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES)
326733965Sjdpstatic void
326833965Sjdpparse_bitfield_cons PARAMS ((expressionS *exp, unsigned int nbytes));
326933965Sjdp#endif
327033965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
327133965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES)
327233965Sjdpstatic void
327333965Sjdpparse_repeat_cons PARAMS ((expressionS *exp, unsigned int nbytes));
327433965Sjdp#endif
327533965Sjdp
327633965Sjdp/* If we haven't gotten one yet, just call expression.  */
327733965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION
327833965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP)
327933965Sjdp#endif
328033965Sjdp#endif
328133965Sjdp
328233965Sjdp/* worker to do .byte etc statements */
328333965Sjdp/* clobbers input_line_pointer, checks */
328433965Sjdp/* end-of-line. */
328533965Sjdpstatic void
328633965Sjdpcons_worker (nbytes, rva)
328733965Sjdp     register int nbytes;	/* 1=.byte, 2=.word, 4=.long */
328833965Sjdp     int rva;
328933965Sjdp{
329033965Sjdp  int c;
329133965Sjdp  expressionS exp;
329233965Sjdp  char *stop = NULL;
329333965Sjdp  char stopc;
329433965Sjdp
329533965Sjdp#ifdef md_flush_pending_output
329633965Sjdp  md_flush_pending_output ();
329733965Sjdp#endif
329833965Sjdp
329933965Sjdp  if (flag_mri)
330033965Sjdp    stop = mri_comment_field (&stopc);
330133965Sjdp
330233965Sjdp  if (is_it_end_of_statement ())
330333965Sjdp    {
330460484Sobrien      demand_empty_rest_of_line ();
330533965Sjdp      if (flag_mri)
330633965Sjdp	mri_comment_end (stop, stopc);
330733965Sjdp      return;
330833965Sjdp    }
330933965Sjdp
331033965Sjdp#ifdef md_cons_align
331133965Sjdp  md_cons_align (nbytes);
331233965Sjdp#endif
331333965Sjdp
331433965Sjdp  c = 0;
331533965Sjdp  do
331633965Sjdp    {
331760484Sobrien#ifdef TC_M68K
331833965Sjdp      if (flag_m68k_mri)
331933965Sjdp	parse_mri_cons (&exp, (unsigned int) nbytes);
332033965Sjdp      else
332160484Sobrien#endif
332233965Sjdp	TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
332333965Sjdp
332433965Sjdp      if (rva)
332533965Sjdp	{
332633965Sjdp	  if (exp.X_op == O_symbol)
332733965Sjdp	    exp.X_op = O_symbol_rva;
332833965Sjdp	  else
332960484Sobrien	    as_fatal (_("rva without symbol"));
333033965Sjdp	}
333133965Sjdp      emit_expr (&exp, (unsigned int) nbytes);
333233965Sjdp      ++c;
333333965Sjdp    }
333433965Sjdp  while (*input_line_pointer++ == ',');
333533965Sjdp
333633965Sjdp  /* In MRI mode, after an odd number of bytes, we must align to an
333733965Sjdp     even word boundary, unless the next instruction is a dc.b, ds.b
333833965Sjdp     or dcb.b.  */
333933965Sjdp  if (flag_mri && nbytes == 1 && (c & 1) != 0)
334033965Sjdp    mri_pending_align = 1;
334133965Sjdp
334233965Sjdp  input_line_pointer--;		/* Put terminator back into stream. */
334333965Sjdp
334460484Sobrien  demand_empty_rest_of_line ();
334560484Sobrien
334633965Sjdp  if (flag_mri)
334733965Sjdp    mri_comment_end (stop, stopc);
334833965Sjdp}
334933965Sjdp
335033965Sjdp
335133965Sjdpvoid
335233965Sjdpcons (size)
335333965Sjdp     int size;
335433965Sjdp{
335533965Sjdp  cons_worker (size, 0);
335633965Sjdp}
335733965Sjdp
335833965Sjdpvoid
335933965Sjdps_rva (size)
336033965Sjdp     int size;
336133965Sjdp{
336233965Sjdp  cons_worker (size, 1);
336333965Sjdp}
336433965Sjdp
336533965Sjdp/* Put the contents of expression EXP into the object file using
336633965Sjdp   NBYTES bytes.  If need_pass_2 is 1, this does nothing.  */
336733965Sjdp
336833965Sjdpvoid
336933965Sjdpemit_expr (exp, nbytes)
337033965Sjdp     expressionS *exp;
337133965Sjdp     unsigned int nbytes;
337233965Sjdp{
337333965Sjdp  operatorT op;
337433965Sjdp  register char *p;
337533965Sjdp  valueT extra_digit = 0;
337633965Sjdp
337733965Sjdp  /* Don't do anything if we are going to make another pass.  */
337833965Sjdp  if (need_pass_2)
337933965Sjdp    return;
338033965Sjdp
338138889Sjdp#ifndef NO_LISTING
338238889Sjdp#ifdef OBJ_ELF
338338889Sjdp  /* When gcc emits DWARF 1 debugging pseudo-ops, a line number will
338438889Sjdp     appear as a four byte positive constant in the .line section,
338538889Sjdp     followed by a 2 byte 0xffff.  Look for that case here.  */
338638889Sjdp  {
338738889Sjdp    static int dwarf_line = -1;
338838889Sjdp
338938889Sjdp    if (strcmp (segment_name (now_seg), ".line") != 0)
339038889Sjdp      dwarf_line = -1;
339138889Sjdp    else if (dwarf_line >= 0
339238889Sjdp	     && nbytes == 2
339338889Sjdp	     && exp->X_op == O_constant
339438889Sjdp	     && (exp->X_add_number == -1 || exp->X_add_number == 0xffff))
339538889Sjdp      listing_source_line ((unsigned int) dwarf_line);
339638889Sjdp    else if (nbytes == 4
339738889Sjdp	     && exp->X_op == O_constant
339838889Sjdp	     && exp->X_add_number >= 0)
339938889Sjdp      dwarf_line = exp->X_add_number;
340038889Sjdp    else
340138889Sjdp      dwarf_line = -1;
340238889Sjdp  }
340338889Sjdp
340438889Sjdp  /* When gcc emits DWARF 1 debugging pseudo-ops, a file name will
340538889Sjdp     appear as a 2 byte TAG_compile_unit (0x11) followed by a 2 byte
340638889Sjdp     AT_sibling (0x12) followed by a four byte address of the sibling
340738889Sjdp     followed by a 2 byte AT_name (0x38) followed by the name of the
340838889Sjdp     file.  We look for that case here.  */
340938889Sjdp  {
341038889Sjdp    static int dwarf_file = 0;
341138889Sjdp
341238889Sjdp    if (strcmp (segment_name (now_seg), ".debug") != 0)
341338889Sjdp      dwarf_file = 0;
341438889Sjdp    else if (dwarf_file == 0
341538889Sjdp	     && nbytes == 2
341638889Sjdp	     && exp->X_op == O_constant
341738889Sjdp	     && exp->X_add_number == 0x11)
341838889Sjdp      dwarf_file = 1;
341938889Sjdp    else if (dwarf_file == 1
342038889Sjdp	     && nbytes == 2
342138889Sjdp	     && exp->X_op == O_constant
342238889Sjdp	     && exp->X_add_number == 0x12)
342338889Sjdp      dwarf_file = 2;
342438889Sjdp    else if (dwarf_file == 2
342538889Sjdp	     && nbytes == 4)
342638889Sjdp      dwarf_file = 3;
342738889Sjdp    else if (dwarf_file == 3
342838889Sjdp	     && nbytes == 2
342938889Sjdp	     && exp->X_op == O_constant
343038889Sjdp	     && exp->X_add_number == 0x38)
343138889Sjdp      dwarf_file = 4;
343238889Sjdp    else
343338889Sjdp      dwarf_file = 0;
343438889Sjdp
343538889Sjdp    /* The variable dwarf_file_string tells stringer that the string
343638889Sjdp       may be the name of the source file.  */
343738889Sjdp    if (dwarf_file == 4)
343838889Sjdp      dwarf_file_string = 1;
343938889Sjdp    else
344038889Sjdp      dwarf_file_string = 0;
344138889Sjdp  }
344238889Sjdp#endif
344338889Sjdp#endif
344438889Sjdp
344538889Sjdp  if (check_eh_frame (exp, &nbytes))
344638889Sjdp    return;
344738889Sjdp
344833965Sjdp  op = exp->X_op;
344933965Sjdp
345033965Sjdp  /* Allow `.word 0' in the absolute section.  */
345133965Sjdp  if (now_seg == absolute_section)
345233965Sjdp    {
345333965Sjdp      if (op != O_constant || exp->X_add_number != 0)
345460484Sobrien	as_bad (_("attempt to store value in absolute section"));
345533965Sjdp      abs_section_offset += nbytes;
345633965Sjdp      return;
345733965Sjdp    }
345833965Sjdp
345933965Sjdp  /* Handle a negative bignum.  */
346033965Sjdp  if (op == O_uminus
346133965Sjdp      && exp->X_add_number == 0
346260484Sobrien      && symbol_get_value_expression (exp->X_add_symbol)->X_op == O_big
346360484Sobrien      && symbol_get_value_expression (exp->X_add_symbol)->X_add_number > 0)
346433965Sjdp    {
346533965Sjdp      int i;
346633965Sjdp      unsigned long carry;
346733965Sjdp
346860484Sobrien      exp = symbol_get_value_expression (exp->X_add_symbol);
346933965Sjdp
347033965Sjdp      /* Negate the bignum: one's complement each digit and add 1.  */
347133965Sjdp      carry = 1;
347233965Sjdp      for (i = 0; i < exp->X_add_number; i++)
347333965Sjdp	{
347433965Sjdp	  unsigned long next;
347533965Sjdp
347633965Sjdp	  next = (((~ (generic_bignum[i] & LITTLENUM_MASK))
347733965Sjdp		   & LITTLENUM_MASK)
347833965Sjdp		  + carry);
347933965Sjdp	  generic_bignum[i] = next & LITTLENUM_MASK;
348033965Sjdp	  carry = next >> LITTLENUM_NUMBER_OF_BITS;
348133965Sjdp	}
348233965Sjdp
348333965Sjdp      /* We can ignore any carry out, because it will be handled by
348433965Sjdp	 extra_digit if it is needed.  */
348533965Sjdp
348633965Sjdp      extra_digit = (valueT) -1;
348733965Sjdp      op = O_big;
348833965Sjdp    }
348933965Sjdp
349033965Sjdp  if (op == O_absent || op == O_illegal)
349133965Sjdp    {
349260484Sobrien      as_warn (_("zero assumed for missing expression"));
349333965Sjdp      exp->X_add_number = 0;
349433965Sjdp      op = O_constant;
349533965Sjdp    }
349633965Sjdp  else if (op == O_big && exp->X_add_number <= 0)
349733965Sjdp    {
349860484Sobrien      as_bad (_("floating point number invalid; zero assumed"));
349933965Sjdp      exp->X_add_number = 0;
350033965Sjdp      op = O_constant;
350133965Sjdp    }
350233965Sjdp  else if (op == O_register)
350333965Sjdp    {
350460484Sobrien      as_warn (_("register value used as expression"));
350533965Sjdp      op = O_constant;
350633965Sjdp    }
350733965Sjdp
350833965Sjdp  p = frag_more ((int) nbytes);
350933965Sjdp
351033965Sjdp#ifndef WORKING_DOT_WORD
351133965Sjdp  /* If we have the difference of two symbols in a word, save it on
351233965Sjdp     the broken_words list.  See the code in write.c.  */
351333965Sjdp  if (op == O_subtract && nbytes == 2)
351433965Sjdp    {
351533965Sjdp      struct broken_word *x;
351633965Sjdp
351733965Sjdp      x = (struct broken_word *) xmalloc (sizeof (struct broken_word));
351833965Sjdp      x->next_broken_word = broken_words;
351933965Sjdp      broken_words = x;
352060484Sobrien      x->seg = now_seg;
352160484Sobrien      x->subseg = now_subseg;
352233965Sjdp      x->frag = frag_now;
352333965Sjdp      x->word_goes_here = p;
352433965Sjdp      x->dispfrag = 0;
352533965Sjdp      x->add = exp->X_add_symbol;
352633965Sjdp      x->sub = exp->X_op_symbol;
352733965Sjdp      x->addnum = exp->X_add_number;
352833965Sjdp      x->added = 0;
352933965Sjdp      new_broken_words++;
353033965Sjdp      return;
353133965Sjdp    }
353233965Sjdp#endif
353333965Sjdp
353433965Sjdp  /* If we have an integer, but the number of bytes is too large to
353533965Sjdp     pass to md_number_to_chars, handle it as a bignum.  */
353633965Sjdp  if (op == O_constant && nbytes > sizeof (valueT))
353733965Sjdp    {
353833965Sjdp      valueT val;
353933965Sjdp      int gencnt;
354033965Sjdp
354133965Sjdp      if (! exp->X_unsigned && exp->X_add_number < 0)
354233965Sjdp	extra_digit = (valueT) -1;
354333965Sjdp      val = (valueT) exp->X_add_number;
354433965Sjdp      gencnt = 0;
354533965Sjdp      do
354633965Sjdp	{
354733965Sjdp	  generic_bignum[gencnt] = val & LITTLENUM_MASK;
354833965Sjdp	  val >>= LITTLENUM_NUMBER_OF_BITS;
354933965Sjdp	  ++gencnt;
355033965Sjdp	}
355133965Sjdp      while (val != 0);
355233965Sjdp      op = exp->X_op = O_big;
355333965Sjdp      exp->X_add_number = gencnt;
355433965Sjdp    }
355533965Sjdp
355633965Sjdp  if (op == O_constant)
355733965Sjdp    {
355833965Sjdp      register valueT get;
355933965Sjdp      register valueT use;
356033965Sjdp      register valueT mask;
356133965Sjdp      valueT hibit;
356233965Sjdp      register valueT unmask;
356333965Sjdp
356433965Sjdp      /* JF << of >= number of bits in the object is undefined.  In
356533965Sjdp	 particular SPARC (Sun 4) has problems */
356633965Sjdp      if (nbytes >= sizeof (valueT))
356733965Sjdp	{
356833965Sjdp	  mask = 0;
356933965Sjdp	  if (nbytes > sizeof (valueT))
357033965Sjdp	    hibit = 0;
357133965Sjdp	  else
357233965Sjdp	    hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
357333965Sjdp	}
357433965Sjdp      else
357533965Sjdp	{
357633965Sjdp	  /* Don't store these bits. */
357733965Sjdp	  mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes);
357833965Sjdp	  hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
357933965Sjdp	}
358033965Sjdp
358133965Sjdp      unmask = ~mask;		/* Do store these bits. */
358233965Sjdp
358333965Sjdp#ifdef NEVER
358433965Sjdp      "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
358533965Sjdp      mask = ~(unmask >> 1);	/* Includes sign bit now. */
358633965Sjdp#endif
358733965Sjdp
358833965Sjdp      get = exp->X_add_number;
358933965Sjdp      use = get & unmask;
359033965Sjdp      if ((get & mask) != 0
359133965Sjdp	  && ((get & mask) != mask
359233965Sjdp	      || (get & hibit) == 0))
359333965Sjdp	{		/* Leading bits contain both 0s & 1s. */
359460484Sobrien	  as_warn (_("Value 0x%lx truncated to 0x%lx."),
359533965Sjdp		   (unsigned long) get, (unsigned long) use);
359633965Sjdp	}
359733965Sjdp      /* put bytes in right order. */
359833965Sjdp      md_number_to_chars (p, use, (int) nbytes);
359933965Sjdp    }
360033965Sjdp  else if (op == O_big)
360133965Sjdp    {
360238889Sjdp      unsigned int size;
360333965Sjdp      LITTLENUM_TYPE *nums;
360433965Sjdp
360533965Sjdp      know (nbytes % CHARS_PER_LITTLENUM == 0);
360633965Sjdp
360733965Sjdp      size = exp->X_add_number * CHARS_PER_LITTLENUM;
360833965Sjdp      if (nbytes < size)
360933965Sjdp	{
361060484Sobrien	  as_warn (_("Bignum truncated to %d bytes"), nbytes);
361133965Sjdp	  size = nbytes;
361233965Sjdp	}
361333965Sjdp
361433965Sjdp      if (target_big_endian)
361533965Sjdp	{
361633965Sjdp	  while (nbytes > size)
361733965Sjdp	    {
361833965Sjdp	      md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
361933965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
362033965Sjdp	      p += CHARS_PER_LITTLENUM;
362133965Sjdp	    }
362233965Sjdp
362333965Sjdp	  nums = generic_bignum + size / CHARS_PER_LITTLENUM;
362433965Sjdp	  while (size > 0)
362533965Sjdp	    {
362633965Sjdp	      --nums;
362733965Sjdp	      md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
362833965Sjdp	      size -= CHARS_PER_LITTLENUM;
362933965Sjdp	      p += CHARS_PER_LITTLENUM;
363033965Sjdp	    }
363133965Sjdp	}
363233965Sjdp      else
363333965Sjdp	{
363433965Sjdp	  nums = generic_bignum;
363533965Sjdp	  while (size > 0)
363633965Sjdp	    {
363733965Sjdp	      md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
363833965Sjdp	      ++nums;
363933965Sjdp	      size -= CHARS_PER_LITTLENUM;
364033965Sjdp	      p += CHARS_PER_LITTLENUM;
364133965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
364233965Sjdp	    }
364333965Sjdp
364433965Sjdp	  while (nbytes > 0)
364533965Sjdp	    {
364633965Sjdp	      md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
364733965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
364833965Sjdp	      p += CHARS_PER_LITTLENUM;
364933965Sjdp	    }
365033965Sjdp	}
365133965Sjdp    }
365233965Sjdp  else
365333965Sjdp    {
365433965Sjdp      memset (p, 0, nbytes);
365533965Sjdp
365633965Sjdp      /* Now we need to generate a fixS to record the symbol value.
365733965Sjdp	 This is easy for BFD.  For other targets it can be more
365833965Sjdp	 complex.  For very complex cases (currently, the HPPA and
365933965Sjdp	 NS32K), you can define TC_CONS_FIX_NEW to do whatever you
366033965Sjdp	 want.  For simpler cases, you can define TC_CONS_RELOC to be
366133965Sjdp	 the name of the reloc code that should be stored in the fixS.
366233965Sjdp	 If neither is defined, the code uses NO_RELOC if it is
366333965Sjdp	 defined, and otherwise uses 0.  */
366433965Sjdp
366533965Sjdp#ifdef BFD_ASSEMBLER
366633965Sjdp#ifdef TC_CONS_FIX_NEW
366733965Sjdp      TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
366833965Sjdp#else
366933965Sjdp      {
367033965Sjdp	bfd_reloc_code_real_type r;
367133965Sjdp
367233965Sjdp	switch (nbytes)
367333965Sjdp	  {
367433965Sjdp	  case 1:
367533965Sjdp	    r = BFD_RELOC_8;
367633965Sjdp	    break;
367733965Sjdp	  case 2:
367833965Sjdp	    r = BFD_RELOC_16;
367933965Sjdp	    break;
368033965Sjdp	  case 4:
368133965Sjdp	    r = BFD_RELOC_32;
368233965Sjdp	    break;
368333965Sjdp	  case 8:
368433965Sjdp	    r = BFD_RELOC_64;
368533965Sjdp	    break;
368633965Sjdp	  default:
368760484Sobrien	    as_bad (_("unsupported BFD relocation size %u"), nbytes);
368833965Sjdp	    r = BFD_RELOC_32;
368933965Sjdp	    break;
369033965Sjdp	  }
369133965Sjdp	fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp,
369233965Sjdp		     0, r);
369333965Sjdp      }
369433965Sjdp#endif
369533965Sjdp#else
369633965Sjdp#ifdef TC_CONS_FIX_NEW
369733965Sjdp      TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
369833965Sjdp#else
369933965Sjdp      /* Figure out which reloc number to use.  Use TC_CONS_RELOC if
370033965Sjdp	 it is defined, otherwise use NO_RELOC if it is defined,
370133965Sjdp	 otherwise use 0.  */
370233965Sjdp#ifndef TC_CONS_RELOC
370333965Sjdp#ifdef NO_RELOC
370433965Sjdp#define TC_CONS_RELOC NO_RELOC
370533965Sjdp#else
370633965Sjdp#define TC_CONS_RELOC 0
370733965Sjdp#endif
370833965Sjdp#endif
370933965Sjdp      fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0,
371033965Sjdp		   TC_CONS_RELOC);
371133965Sjdp#endif /* TC_CONS_FIX_NEW */
371233965Sjdp#endif /* BFD_ASSEMBLER */
371333965Sjdp    }
371433965Sjdp}
371533965Sjdp
371633965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS
371733965Sjdp
371833965Sjdp/* i960 assemblers, (eg, asm960), allow bitfields after ".byte" as
371933965Sjdp   w:x,y:z, where w and y are bitwidths and x and y are values.  They
372033965Sjdp   then pack them all together. We do a little better in that we allow
372133965Sjdp   them in words, longs, etc. and we'll pack them in target byte order
372233965Sjdp   for you.
372333965Sjdp
372433965Sjdp   The rules are: pack least significat bit first, if a field doesn't
372533965Sjdp   entirely fit, put it in the next unit.  Overflowing the bitfield is
372633965Sjdp   explicitly *not* even a warning.  The bitwidth should be considered
372733965Sjdp   a "mask".
372833965Sjdp
372933965Sjdp   To use this function the tc-XXX.h file should define
373033965Sjdp   BITFIELD_CONS_EXPRESSIONS.  */
373133965Sjdp
373233965Sjdpstatic void
373333965Sjdpparse_bitfield_cons (exp, nbytes)
373433965Sjdp     expressionS *exp;
373533965Sjdp     unsigned int nbytes;
373633965Sjdp{
373733965Sjdp  unsigned int bits_available = BITS_PER_CHAR * nbytes;
373833965Sjdp  char *hold = input_line_pointer;
373933965Sjdp
374033965Sjdp  (void) expression (exp);
374133965Sjdp
374233965Sjdp  if (*input_line_pointer == ':')
374333965Sjdp    {			/* bitfields */
374433965Sjdp      long value = 0;
374533965Sjdp
374633965Sjdp      for (;;)
374733965Sjdp	{
374833965Sjdp	  unsigned long width;
374933965Sjdp
375033965Sjdp	  if (*input_line_pointer != ':')
375133965Sjdp	    {
375233965Sjdp	      input_line_pointer = hold;
375333965Sjdp	      break;
375433965Sjdp	    }			/* next piece is not a bitfield */
375533965Sjdp
375633965Sjdp	  /* In the general case, we can't allow
375733965Sjdp	     full expressions with symbol
375833965Sjdp	     differences and such.  The relocation
375933965Sjdp	     entries for symbols not defined in this
376033965Sjdp	     assembly would require arbitrary field
376133965Sjdp	     widths, positions, and masks which most
376233965Sjdp	     of our current object formats don't
376333965Sjdp	     support.
376433965Sjdp
376533965Sjdp	     In the specific case where a symbol
376633965Sjdp	     *is* defined in this assembly, we
376733965Sjdp	     *could* build fixups and track it, but
376833965Sjdp	     this could lead to confusion for the
376933965Sjdp	     backends.  I'm lazy. I'll take any
377033965Sjdp	     SEG_ABSOLUTE. I think that means that
377133965Sjdp	     you can use a previous .set or
377233965Sjdp	     .equ type symbol.  xoxorich. */
377333965Sjdp
377433965Sjdp	  if (exp->X_op == O_absent)
377533965Sjdp	    {
377660484Sobrien	      as_warn (_("using a bit field width of zero"));
377733965Sjdp	      exp->X_add_number = 0;
377833965Sjdp	      exp->X_op = O_constant;
377933965Sjdp	    }			/* implied zero width bitfield */
378033965Sjdp
378133965Sjdp	  if (exp->X_op != O_constant)
378233965Sjdp	    {
378333965Sjdp	      *input_line_pointer = '\0';
378460484Sobrien	      as_bad (_("field width \"%s\" too complex for a bitfield"), hold);
378533965Sjdp	      *input_line_pointer = ':';
378633965Sjdp	      demand_empty_rest_of_line ();
378733965Sjdp	      return;
378833965Sjdp	    }			/* too complex */
378933965Sjdp
379033965Sjdp	  if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes))
379133965Sjdp	    {
379260484Sobrien	      as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"),
379333965Sjdp		       width, nbytes, (BITS_PER_CHAR * nbytes));
379433965Sjdp	      width = BITS_PER_CHAR * nbytes;
379533965Sjdp	    }			/* too big */
379633965Sjdp
379733965Sjdp	  if (width > bits_available)
379833965Sjdp	    {
379933965Sjdp	      /* FIXME-SOMEDAY: backing up and reparsing is wasteful.  */
380033965Sjdp	      input_line_pointer = hold;
380133965Sjdp	      exp->X_add_number = value;
380233965Sjdp	      break;
380333965Sjdp	    }			/* won't fit */
380433965Sjdp
380533965Sjdp	  hold = ++input_line_pointer; /* skip ':' */
380633965Sjdp
380733965Sjdp	  (void) expression (exp);
380833965Sjdp	  if (exp->X_op != O_constant)
380933965Sjdp	    {
381033965Sjdp	      char cache = *input_line_pointer;
381133965Sjdp
381233965Sjdp	      *input_line_pointer = '\0';
381360484Sobrien	      as_bad (_("field value \"%s\" too complex for a bitfield"), hold);
381433965Sjdp	      *input_line_pointer = cache;
381533965Sjdp	      demand_empty_rest_of_line ();
381633965Sjdp	      return;
381733965Sjdp	    }			/* too complex */
381833965Sjdp
381933965Sjdp	  value |= ((~(-1 << width) & exp->X_add_number)
382033965Sjdp		    << ((BITS_PER_CHAR * nbytes) - bits_available));
382133965Sjdp
382233965Sjdp	  if ((bits_available -= width) == 0
382333965Sjdp	      || is_it_end_of_statement ()
382433965Sjdp	      || *input_line_pointer != ',')
382533965Sjdp	    {
382633965Sjdp	      break;
382733965Sjdp	    }			/* all the bitfields we're gonna get */
382833965Sjdp
382933965Sjdp	  hold = ++input_line_pointer;
383033965Sjdp	  (void) expression (exp);
383133965Sjdp	}			/* forever loop */
383233965Sjdp
383333965Sjdp      exp->X_add_number = value;
383433965Sjdp      exp->X_op = O_constant;
383533965Sjdp      exp->X_unsigned = 1;
383633965Sjdp    }				/* if looks like a bitfield */
383733965Sjdp}				/* parse_bitfield_cons() */
383833965Sjdp
383933965Sjdp#endif /* BITFIELD_CONS_EXPRESSIONS */
384033965Sjdp
384133965Sjdp/* Handle an MRI style string expression.  */
384233965Sjdp
384360484Sobrien#ifdef TC_M68K
384433965Sjdpstatic void
384533965Sjdpparse_mri_cons (exp, nbytes)
384633965Sjdp     expressionS *exp;
384733965Sjdp     unsigned int nbytes;
384833965Sjdp{
384933965Sjdp  if (*input_line_pointer != '\''
385033965Sjdp      && (input_line_pointer[1] != '\''
385133965Sjdp	  || (*input_line_pointer != 'A'
385233965Sjdp	      && *input_line_pointer != 'E')))
385333965Sjdp    TC_PARSE_CONS_EXPRESSION (exp, nbytes);
385433965Sjdp  else
385533965Sjdp    {
385638889Sjdp      unsigned int scan;
385733965Sjdp      unsigned int result = 0;
385833965Sjdp
385933965Sjdp      /* An MRI style string.  Cut into as many bytes as will fit into
386033965Sjdp	 a nbyte chunk, left justify if necessary, and separate with
386133965Sjdp	 commas so we can try again later.  */
386233965Sjdp      if (*input_line_pointer == 'A')
386333965Sjdp	++input_line_pointer;
386433965Sjdp      else if (*input_line_pointer == 'E')
386533965Sjdp	{
386660484Sobrien	  as_bad (_("EBCDIC constants are not supported"));
386733965Sjdp	  ++input_line_pointer;
386833965Sjdp	}
386933965Sjdp
387033965Sjdp      input_line_pointer++;
387133965Sjdp      for (scan = 0; scan < nbytes; scan++)
387233965Sjdp	{
387333965Sjdp	  if (*input_line_pointer == '\'')
387433965Sjdp	    {
387533965Sjdp	      if (input_line_pointer[1] == '\'')
387633965Sjdp		{
387733965Sjdp		  input_line_pointer++;
387833965Sjdp		}
387933965Sjdp	      else
388033965Sjdp		break;
388133965Sjdp	    }
388233965Sjdp	  result = (result << 8) | (*input_line_pointer++);
388333965Sjdp	}
388433965Sjdp
388533965Sjdp      /* Left justify */
388633965Sjdp      while (scan < nbytes)
388733965Sjdp	{
388833965Sjdp	  result <<= 8;
388933965Sjdp	  scan++;
389033965Sjdp	}
389133965Sjdp      /* Create correct expression */
389233965Sjdp      exp->X_op = O_constant;
389333965Sjdp      exp->X_add_number = result;
389433965Sjdp      /* Fake it so that we can read the next char too */
389533965Sjdp      if (input_line_pointer[0] != '\'' ||
389633965Sjdp	  (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\''))
389733965Sjdp	{
389833965Sjdp	  input_line_pointer -= 2;
389933965Sjdp	  input_line_pointer[0] = ',';
390033965Sjdp	  input_line_pointer[1] = '\'';
390133965Sjdp	}
390233965Sjdp      else
390333965Sjdp	input_line_pointer++;
390433965Sjdp    }
390533965Sjdp}
390660484Sobrien#endif /* TC_M68K */
390733965Sjdp
390833965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
390933965Sjdp
391033965Sjdp/* Parse a repeat expression for cons.  This is used by the MIPS
391133965Sjdp   assembler.  The format is NUMBER:COUNT; NUMBER appears in the
391233965Sjdp   object file COUNT times.
391333965Sjdp
391433965Sjdp   To use this for a target, define REPEAT_CONS_EXPRESSIONS.  */
391533965Sjdp
391633965Sjdpstatic void
391733965Sjdpparse_repeat_cons (exp, nbytes)
391833965Sjdp     expressionS *exp;
391933965Sjdp     unsigned int nbytes;
392033965Sjdp{
392133965Sjdp  expressionS count;
392233965Sjdp  register int i;
392333965Sjdp
392433965Sjdp  expression (exp);
392533965Sjdp
392633965Sjdp  if (*input_line_pointer != ':')
392733965Sjdp    {
392833965Sjdp      /* No repeat count.  */
392933965Sjdp      return;
393033965Sjdp    }
393133965Sjdp
393233965Sjdp  ++input_line_pointer;
393333965Sjdp  expression (&count);
393433965Sjdp  if (count.X_op != O_constant
393533965Sjdp      || count.X_add_number <= 0)
393633965Sjdp    {
393760484Sobrien      as_warn (_("Unresolvable or nonpositive repeat count; using 1"));
393833965Sjdp      return;
393933965Sjdp    }
394033965Sjdp
394133965Sjdp  /* The cons function is going to output this expression once.  So we
394233965Sjdp     output it count - 1 times.  */
394333965Sjdp  for (i = count.X_add_number - 1; i > 0; i--)
394433965Sjdp    emit_expr (exp, nbytes);
394533965Sjdp}
394633965Sjdp
394733965Sjdp#endif /* REPEAT_CONS_EXPRESSIONS */
394833965Sjdp
394933965Sjdp/* Parse a floating point number represented as a hex constant.  This
395033965Sjdp   permits users to specify the exact bits they want in the floating
395133965Sjdp   point number.  */
395233965Sjdp
395333965Sjdpstatic int
395433965Sjdphex_float (float_type, bytes)
395533965Sjdp     int float_type;
395633965Sjdp     char *bytes;
395733965Sjdp{
395833965Sjdp  int length;
395933965Sjdp  int i;
396033965Sjdp
396133965Sjdp  switch (float_type)
396233965Sjdp    {
396333965Sjdp    case 'f':
396433965Sjdp    case 'F':
396533965Sjdp    case 's':
396633965Sjdp    case 'S':
396733965Sjdp      length = 4;
396833965Sjdp      break;
396933965Sjdp
397033965Sjdp    case 'd':
397133965Sjdp    case 'D':
397233965Sjdp    case 'r':
397333965Sjdp    case 'R':
397433965Sjdp      length = 8;
397533965Sjdp      break;
397633965Sjdp
397733965Sjdp    case 'x':
397833965Sjdp    case 'X':
397933965Sjdp      length = 12;
398033965Sjdp      break;
398133965Sjdp
398233965Sjdp    case 'p':
398333965Sjdp    case 'P':
398433965Sjdp      length = 12;
398533965Sjdp      break;
398633965Sjdp
398733965Sjdp    default:
398860484Sobrien      as_bad (_("Unknown floating type type '%c'"), float_type);
398933965Sjdp      return -1;
399033965Sjdp    }
399133965Sjdp
399233965Sjdp  /* It would be nice if we could go through expression to parse the
399333965Sjdp     hex constant, but if we get a bignum it's a pain to sort it into
399433965Sjdp     the buffer correctly.  */
399533965Sjdp  i = 0;
399633965Sjdp  while (hex_p (*input_line_pointer) || *input_line_pointer == '_')
399733965Sjdp    {
399833965Sjdp      int d;
399933965Sjdp
400033965Sjdp      /* The MRI assembler accepts arbitrary underscores strewn about
400133965Sjdp	 through the hex constant, so we ignore them as well. */
400233965Sjdp      if (*input_line_pointer == '_')
400333965Sjdp	{
400433965Sjdp	  ++input_line_pointer;
400533965Sjdp	  continue;
400633965Sjdp	}
400733965Sjdp
400833965Sjdp      if (i >= length)
400933965Sjdp	{
401060484Sobrien	  as_warn (_("Floating point constant too large"));
401133965Sjdp	  return -1;
401233965Sjdp	}
401333965Sjdp      d = hex_value (*input_line_pointer) << 4;
401433965Sjdp      ++input_line_pointer;
401533965Sjdp      while (*input_line_pointer == '_')
401633965Sjdp	++input_line_pointer;
401733965Sjdp      if (hex_p (*input_line_pointer))
401833965Sjdp	{
401933965Sjdp	  d += hex_value (*input_line_pointer);
402033965Sjdp	  ++input_line_pointer;
402133965Sjdp	}
402233965Sjdp      if (target_big_endian)
402333965Sjdp	bytes[i] = d;
402433965Sjdp      else
402533965Sjdp	bytes[length - i - 1] = d;
402633965Sjdp      ++i;
402733965Sjdp    }
402833965Sjdp
402933965Sjdp  if (i < length)
403033965Sjdp    {
403133965Sjdp      if (target_big_endian)
403233965Sjdp	memset (bytes + i, 0, length - i);
403333965Sjdp      else
403433965Sjdp	memset (bytes, 0, length - i);
403533965Sjdp    }
403633965Sjdp
403733965Sjdp  return length;
403833965Sjdp}
403933965Sjdp
404033965Sjdp/*
404133965Sjdp *			float_cons()
404233965Sjdp *
404333965Sjdp * CONStruct some more frag chars of .floats .ffloats etc.
404433965Sjdp * Makes 0 or more new frags.
404533965Sjdp * If need_pass_2 == 1, no frags are emitted.
404633965Sjdp * This understands only floating literals, not expressions. Sorry.
404733965Sjdp *
404833965Sjdp * A floating constant is defined by atof_generic(), except it is preceded
404933965Sjdp * by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its
405033965Sjdp * reading, I decided to be incompatible. This always tries to give you
405133965Sjdp * rounded bits to the precision of the pseudo-op. Former AS did premature
405233965Sjdp * truncatation, restored noisy bits instead of trailing 0s AND gave you
405333965Sjdp * a choice of 2 flavours of noise according to which of 2 floating-point
405433965Sjdp * scanners you directed AS to use.
405533965Sjdp *
405633965Sjdp * In:	input_line_pointer->whitespace before, or '0' of flonum.
405733965Sjdp *
405833965Sjdp */
405933965Sjdp
406033965Sjdpvoid
406133965Sjdpfloat_cons (float_type)
406233965Sjdp     /* Clobbers input_line-pointer, checks end-of-line. */
406333965Sjdp     register int float_type;	/* 'f':.ffloat ... 'F':.float ... */
406433965Sjdp{
406533965Sjdp  register char *p;
406633965Sjdp  int length;			/* Number of chars in an object. */
406733965Sjdp  register char *err;		/* Error from scanning floating literal. */
406833965Sjdp  char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
406933965Sjdp
407033965Sjdp  if (is_it_end_of_statement ())
407133965Sjdp    {
407233965Sjdp      demand_empty_rest_of_line ();
407333965Sjdp      return;
407433965Sjdp    }
407533965Sjdp
407633965Sjdp#ifdef md_flush_pending_output
407733965Sjdp  md_flush_pending_output ();
407833965Sjdp#endif
407933965Sjdp
408033965Sjdp  do
408133965Sjdp    {
408233965Sjdp      /* input_line_pointer->1st char of a flonum (we hope!). */
408333965Sjdp      SKIP_WHITESPACE ();
408433965Sjdp
408533965Sjdp      /* Skip any 0{letter} that may be present. Don't even check if the
408633965Sjdp       * letter is legal. Someone may invent a "z" format and this routine
408733965Sjdp       * has no use for such information. Lusers beware: you get
408833965Sjdp       * diagnostics if your input is ill-conditioned.
408933965Sjdp       */
409038889Sjdp      if (input_line_pointer[0] == '0'
409138889Sjdp	  && isalpha ((unsigned char) input_line_pointer[1]))
409233965Sjdp	input_line_pointer += 2;
409333965Sjdp
409433965Sjdp      /* Accept :xxxx, where the x's are hex digits, for a floating
409533965Sjdp         point with the exact digits specified.  */
409633965Sjdp      if (input_line_pointer[0] == ':')
409733965Sjdp	{
409833965Sjdp	  ++input_line_pointer;
409933965Sjdp	  length = hex_float (float_type, temp);
410033965Sjdp	  if (length < 0)
410133965Sjdp	    {
410233965Sjdp	      ignore_rest_of_line ();
410333965Sjdp	      return;
410433965Sjdp	    }
410533965Sjdp	}
410633965Sjdp      else
410733965Sjdp	{
410833965Sjdp	  err = md_atof (float_type, temp, &length);
410933965Sjdp	  know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
411033965Sjdp	  know (length > 0);
411133965Sjdp	  if (err)
411233965Sjdp	    {
411360484Sobrien	      as_bad (_("Bad floating literal: %s"), err);
411433965Sjdp	      ignore_rest_of_line ();
411533965Sjdp	      return;
411633965Sjdp	    }
411733965Sjdp	}
411833965Sjdp
411933965Sjdp      if (!need_pass_2)
412033965Sjdp	{
412133965Sjdp	  int count;
412233965Sjdp
412333965Sjdp	  count = 1;
412433965Sjdp
412533965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
412633965Sjdp	  if (*input_line_pointer == ':')
412733965Sjdp	    {
412833965Sjdp	      expressionS count_exp;
412933965Sjdp
413033965Sjdp	      ++input_line_pointer;
413133965Sjdp	      expression (&count_exp);
413233965Sjdp	      if (count_exp.X_op != O_constant
413333965Sjdp		  || count_exp.X_add_number <= 0)
413433965Sjdp		{
413560484Sobrien		  as_warn (_("unresolvable or nonpositive repeat count; using 1"));
413633965Sjdp		}
413733965Sjdp	      else
413833965Sjdp		count = count_exp.X_add_number;
413933965Sjdp	    }
414033965Sjdp#endif
414133965Sjdp
414233965Sjdp	  while (--count >= 0)
414333965Sjdp	    {
414433965Sjdp	      p = frag_more (length);
414533965Sjdp	      memcpy (p, temp, (unsigned int) length);
414633965Sjdp	    }
414733965Sjdp	}
414833965Sjdp      SKIP_WHITESPACE ();
414933965Sjdp    }
415033965Sjdp  while (*input_line_pointer++ == ',');
415133965Sjdp
415233965Sjdp  --input_line_pointer;		/* Put terminator back into stream.  */
415333965Sjdp  demand_empty_rest_of_line ();
415433965Sjdp}				/* float_cons() */
415533965Sjdp
415638889Sjdp/* Return the size of a LEB128 value */
415738889Sjdp
415838889Sjdpstatic inline int
415938889Sjdpsizeof_sleb128 (value)
416038889Sjdp     offsetT value;
416138889Sjdp{
416238889Sjdp  register int size = 0;
416338889Sjdp  register unsigned byte;
416438889Sjdp
416538889Sjdp  do
416638889Sjdp    {
416738889Sjdp      byte = (value & 0x7f);
416838889Sjdp      /* Sadly, we cannot rely on typical arithmetic right shift behaviour.
416938889Sjdp	 Fortunately, we can structure things so that the extra work reduces
417038889Sjdp	 to a noop on systems that do things "properly".  */
417138889Sjdp      value = (value >> 7) | ~(-(offsetT)1 >> 7);
417238889Sjdp      size += 1;
417338889Sjdp    }
417438889Sjdp  while (!(((value == 0) && ((byte & 0x40) == 0))
417538889Sjdp	   || ((value == -1) && ((byte & 0x40) != 0))));
417638889Sjdp
417738889Sjdp  return size;
417838889Sjdp}
417938889Sjdp
418038889Sjdpstatic inline int
418138889Sjdpsizeof_uleb128 (value)
418238889Sjdp     valueT value;
418338889Sjdp{
418438889Sjdp  register int size = 0;
418538889Sjdp  register unsigned byte;
418638889Sjdp
418738889Sjdp  do
418838889Sjdp    {
418938889Sjdp      byte = (value & 0x7f);
419038889Sjdp      value >>= 7;
419138889Sjdp      size += 1;
419238889Sjdp    }
419338889Sjdp  while (value != 0);
419438889Sjdp
419538889Sjdp  return size;
419638889Sjdp}
419738889Sjdp
419860484Sobrienint
419938889Sjdpsizeof_leb128 (value, sign)
420038889Sjdp     valueT value;
420138889Sjdp     int sign;
420238889Sjdp{
420338889Sjdp  if (sign)
420438889Sjdp    return sizeof_sleb128 ((offsetT) value);
420538889Sjdp  else
420638889Sjdp    return sizeof_uleb128 (value);
420738889Sjdp}
420838889Sjdp
420938889Sjdp/* Output a LEB128 value.  */
421038889Sjdp
421138889Sjdpstatic inline int
421238889Sjdpoutput_sleb128 (p, value)
421338889Sjdp     char *p;
421438889Sjdp     offsetT value;
421538889Sjdp{
421638889Sjdp  register char *orig = p;
421738889Sjdp  register int more;
421838889Sjdp
421938889Sjdp  do
422038889Sjdp    {
422138889Sjdp      unsigned byte = (value & 0x7f);
422238889Sjdp
422338889Sjdp      /* Sadly, we cannot rely on typical arithmetic right shift behaviour.
422438889Sjdp	 Fortunately, we can structure things so that the extra work reduces
422538889Sjdp	 to a noop on systems that do things "properly".  */
422638889Sjdp      value = (value >> 7) | ~(-(offsetT)1 >> 7);
422738889Sjdp
422838889Sjdp      more = !((((value == 0) && ((byte & 0x40) == 0))
422938889Sjdp		|| ((value == -1) && ((byte & 0x40) != 0))));
423038889Sjdp      if (more)
423138889Sjdp	byte |= 0x80;
423238889Sjdp
423338889Sjdp      *p++ = byte;
423438889Sjdp    }
423538889Sjdp  while (more);
423638889Sjdp
423738889Sjdp  return p - orig;
423838889Sjdp}
423938889Sjdp
424038889Sjdpstatic inline int
424138889Sjdpoutput_uleb128 (p, value)
424238889Sjdp     char *p;
424338889Sjdp     valueT value;
424438889Sjdp{
424538889Sjdp  char *orig = p;
424638889Sjdp
424738889Sjdp  do
424838889Sjdp    {
424938889Sjdp      unsigned byte = (value & 0x7f);
425038889Sjdp      value >>= 7;
425138889Sjdp      if (value != 0)
425238889Sjdp	/* More bytes to follow.  */
425338889Sjdp	byte |= 0x80;
425438889Sjdp
425538889Sjdp      *p++ = byte;
425638889Sjdp    }
425738889Sjdp  while (value != 0);
425838889Sjdp
425938889Sjdp  return p - orig;
426038889Sjdp}
426138889Sjdp
426260484Sobrienint
426338889Sjdpoutput_leb128 (p, value, sign)
426438889Sjdp     char *p;
426538889Sjdp     valueT value;
426638889Sjdp     int sign;
426738889Sjdp{
426838889Sjdp  if (sign)
426938889Sjdp    return output_sleb128 (p, (offsetT) value);
427038889Sjdp  else
427138889Sjdp    return output_uleb128 (p, value);
427238889Sjdp}
427338889Sjdp
427438889Sjdp/* Do the same for bignums.  We combine sizeof with output here in that
427538889Sjdp   we don't output for NULL values of P.  It isn't really as critical as
427638889Sjdp   for "normal" values that this be streamlined.  */
427738889Sjdp
427860484Sobrienstatic inline int
427938889Sjdpoutput_big_sleb128 (p, bignum, size)
428038889Sjdp     char *p;
428138889Sjdp     LITTLENUM_TYPE *bignum;
428238889Sjdp     int size;
428338889Sjdp{
428438889Sjdp  char *orig = p;
428538889Sjdp  valueT val = 0;
428638889Sjdp  int loaded = 0;
428738889Sjdp  unsigned byte;
428838889Sjdp
428938889Sjdp  /* Strip leading sign extensions off the bignum.  */
429038889Sjdp  while (size > 0 && bignum[size-1] == (LITTLENUM_TYPE)-1)
429138889Sjdp    size--;
429238889Sjdp
429338889Sjdp  do
429438889Sjdp    {
429538889Sjdp      if (loaded < 7 && size > 0)
429638889Sjdp	{
429738889Sjdp	  val |= (*bignum << loaded);
429838889Sjdp	  loaded += 8 * CHARS_PER_LITTLENUM;
429938889Sjdp	  size--;
430038889Sjdp	  bignum++;
430138889Sjdp	}
430238889Sjdp
430338889Sjdp      byte = val & 0x7f;
430438889Sjdp      loaded -= 7;
430538889Sjdp      val >>= 7;
430638889Sjdp
430738889Sjdp      if (size == 0)
430838889Sjdp	{
430938889Sjdp	  if ((val == 0 && (byte & 0x40) == 0)
431038889Sjdp	      || (~(val | ~(((valueT)1 << loaded) - 1)) == 0
431138889Sjdp		  && (byte & 0x40) != 0))
431238889Sjdp	    byte |= 0x80;
431338889Sjdp	}
431438889Sjdp
431538889Sjdp      if (orig)
431638889Sjdp	*p = byte;
431738889Sjdp      p++;
431838889Sjdp    }
431938889Sjdp  while (byte & 0x80);
432038889Sjdp
432138889Sjdp  return p - orig;
432238889Sjdp}
432338889Sjdp
432460484Sobrienstatic inline int
432538889Sjdpoutput_big_uleb128 (p, bignum, size)
432638889Sjdp     char *p;
432738889Sjdp     LITTLENUM_TYPE *bignum;
432838889Sjdp     int size;
432938889Sjdp{
433038889Sjdp  char *orig = p;
433138889Sjdp  valueT val = 0;
433238889Sjdp  int loaded = 0;
433338889Sjdp  unsigned byte;
433438889Sjdp
433538889Sjdp  /* Strip leading zeros off the bignum.  */
433638889Sjdp  /* XXX: Is this needed?  */
433738889Sjdp  while (size > 0 && bignum[size-1] == 0)
433838889Sjdp    size--;
433938889Sjdp
434038889Sjdp  do
434138889Sjdp    {
434238889Sjdp      if (loaded < 7 && size > 0)
434338889Sjdp	{
434438889Sjdp	  val |= (*bignum << loaded);
434538889Sjdp	  loaded += 8 * CHARS_PER_LITTLENUM;
434638889Sjdp	  size--;
434738889Sjdp	  bignum++;
434838889Sjdp	}
434938889Sjdp
435038889Sjdp      byte = val & 0x7f;
435138889Sjdp      loaded -= 7;
435238889Sjdp      val >>= 7;
435338889Sjdp
435438889Sjdp      if (size > 0 || val)
435538889Sjdp	byte |= 0x80;
435638889Sjdp
435738889Sjdp      if (orig)
435838889Sjdp	*p = byte;
435938889Sjdp      p++;
436038889Sjdp    }
436138889Sjdp  while (byte & 0x80);
436238889Sjdp
436338889Sjdp  return p - orig;
436438889Sjdp}
436538889Sjdp
436660484Sobrienstatic int
436738889Sjdpoutput_big_leb128 (p, bignum, size, sign)
436838889Sjdp     char *p;
436938889Sjdp     LITTLENUM_TYPE *bignum;
437038889Sjdp     int size, sign;
437138889Sjdp{
437238889Sjdp  if (sign)
437338889Sjdp    return output_big_sleb128 (p, bignum, size);
437438889Sjdp  else
437538889Sjdp    return output_big_uleb128 (p, bignum, size);
437638889Sjdp}
437738889Sjdp
437838889Sjdp/* Generate the appropriate fragments for a given expression to emit a
437938889Sjdp   leb128 value.  */
438038889Sjdp
438138889Sjdpvoid
438238889Sjdpemit_leb128_expr(exp, sign)
438338889Sjdp     expressionS *exp;
438438889Sjdp     int sign;
438538889Sjdp{
438638889Sjdp  operatorT op = exp->X_op;
438738889Sjdp
438838889Sjdp  if (op == O_absent || op == O_illegal)
438938889Sjdp    {
439060484Sobrien      as_warn (_("zero assumed for missing expression"));
439138889Sjdp      exp->X_add_number = 0;
439238889Sjdp      op = O_constant;
439338889Sjdp    }
439438889Sjdp  else if (op == O_big && exp->X_add_number <= 0)
439538889Sjdp    {
439660484Sobrien      as_bad (_("floating point number invalid; zero assumed"));
439738889Sjdp      exp->X_add_number = 0;
439838889Sjdp      op = O_constant;
439938889Sjdp    }
440038889Sjdp  else if (op == O_register)
440138889Sjdp    {
440260484Sobrien      as_warn (_("register value used as expression"));
440338889Sjdp      op = O_constant;
440438889Sjdp    }
440538889Sjdp
440638889Sjdp  if (op == O_constant)
440738889Sjdp    {
440838889Sjdp      /* If we've got a constant, emit the thing directly right now.  */
440938889Sjdp
441038889Sjdp      valueT value = exp->X_add_number;
441138889Sjdp      int size;
441238889Sjdp      char *p;
441338889Sjdp
441438889Sjdp      size = sizeof_leb128 (value, sign);
441538889Sjdp      p = frag_more (size);
441638889Sjdp      output_leb128 (p, value, sign);
441738889Sjdp    }
441838889Sjdp  else if (op == O_big)
441938889Sjdp    {
442038889Sjdp      /* O_big is a different sort of constant.  */
442138889Sjdp
442238889Sjdp      int size;
442338889Sjdp      char *p;
442438889Sjdp
442538889Sjdp      size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign);
442638889Sjdp      p = frag_more (size);
442738889Sjdp      output_big_leb128 (p, generic_bignum, exp->X_add_number, sign);
442838889Sjdp    }
442938889Sjdp  else
443038889Sjdp    {
443138889Sjdp      /* Otherwise, we have to create a variable sized fragment and
443238889Sjdp	 resolve things later.  */
443338889Sjdp
443438889Sjdp      frag_var (rs_leb128, sizeof_uleb128 (~(valueT)0), 0, sign,
443538889Sjdp		make_expr_symbol (exp), 0, (char *) NULL);
443638889Sjdp    }
443738889Sjdp}
443838889Sjdp
443938889Sjdp/* Parse the .sleb128 and .uleb128 pseudos.  */
444038889Sjdp
444138889Sjdpvoid
444238889Sjdps_leb128 (sign)
444338889Sjdp     int sign;
444438889Sjdp{
444538889Sjdp  expressionS exp;
444638889Sjdp
444738889Sjdp  do {
444838889Sjdp    expression (&exp);
444938889Sjdp    emit_leb128_expr (&exp, sign);
445038889Sjdp  } while (*input_line_pointer++ == ',');
445138889Sjdp
445238889Sjdp  input_line_pointer--;
445338889Sjdp  demand_empty_rest_of_line ();
445438889Sjdp}
445538889Sjdp
445633965Sjdp/*
445733965Sjdp *			stringer()
445833965Sjdp *
445960484Sobrien * We read 0 or more ',' separated, double-quoted strings.
446033965Sjdp *
446133965Sjdp * Caller should have checked need_pass_2 is FALSE because we don't check it.
446233965Sjdp */
446333965Sjdp
446433965Sjdp
446533965Sjdpvoid
446633965Sjdpstringer (append_zero)		/* Worker to do .ascii etc statements. */
446733965Sjdp     /* Checks end-of-line. */
446833965Sjdp     register int append_zero;	/* 0: don't append '\0', else 1 */
446933965Sjdp{
447033965Sjdp  register unsigned int c;
447138889Sjdp  char *start;
447233965Sjdp
447333965Sjdp#ifdef md_flush_pending_output
447433965Sjdp  md_flush_pending_output ();
447533965Sjdp#endif
447633965Sjdp
447733965Sjdp  /*
447833965Sjdp   * The following awkward logic is to parse ZERO or more strings,
447960484Sobrien   * comma separated. Recall a string expression includes spaces
448033965Sjdp   * before the opening '\"' and spaces after the closing '\"'.
448133965Sjdp   * We fake a leading ',' if there is (supposed to be)
448233965Sjdp   * a 1st, expression. We keep demanding expressions for each
448333965Sjdp   * ','.
448433965Sjdp   */
448533965Sjdp  if (is_it_end_of_statement ())
448633965Sjdp    {
448733965Sjdp      c = 0;			/* Skip loop. */
448833965Sjdp      ++input_line_pointer;	/* Compensate for end of loop. */
448933965Sjdp    }
449033965Sjdp  else
449133965Sjdp    {
449233965Sjdp      c = ',';			/* Do loop. */
449333965Sjdp    }
449433965Sjdp  while (c == ',' || c == '<' || c == '"')
449533965Sjdp    {
449633965Sjdp      SKIP_WHITESPACE ();
449733965Sjdp      switch (*input_line_pointer)
449833965Sjdp	{
449933965Sjdp	case '\"':
450033965Sjdp	  ++input_line_pointer;	/*->1st char of string. */
450138889Sjdp	  start = input_line_pointer;
450233965Sjdp	  while (is_a_char (c = next_char_of_string ()))
450333965Sjdp	    {
450433965Sjdp	      FRAG_APPEND_1_CHAR (c);
450533965Sjdp	    }
450633965Sjdp	  if (append_zero)
450733965Sjdp	    {
450833965Sjdp	      FRAG_APPEND_1_CHAR (0);
450933965Sjdp	    }
451033965Sjdp	  know (input_line_pointer[-1] == '\"');
451138889Sjdp
451238889Sjdp#ifndef NO_LISTING
451338889Sjdp#ifdef OBJ_ELF
451438889Sjdp	  /* In ELF, when gcc is emitting DWARF 1 debugging output, it
451538889Sjdp             will emit .string with a filename in the .debug section
451638889Sjdp             after a sequence of constants.  See the comment in
451738889Sjdp             emit_expr for the sequence.  emit_expr will set
451838889Sjdp             dwarf_file_string to non-zero if this string might be a
451938889Sjdp             source file name.  */
452038889Sjdp	  if (strcmp (segment_name (now_seg), ".debug") != 0)
452138889Sjdp	    dwarf_file_string = 0;
452238889Sjdp	  else if (dwarf_file_string)
452338889Sjdp	    {
452438889Sjdp	      c = input_line_pointer[-1];
452538889Sjdp	      input_line_pointer[-1] = '\0';
452638889Sjdp	      listing_source_file (start);
452738889Sjdp	      input_line_pointer[-1] = c;
452838889Sjdp	    }
452938889Sjdp#endif
453038889Sjdp#endif
453138889Sjdp
453233965Sjdp	  break;
453333965Sjdp	case '<':
453433965Sjdp	  input_line_pointer++;
453533965Sjdp	  c = get_single_number ();
453633965Sjdp	  FRAG_APPEND_1_CHAR (c);
453733965Sjdp	  if (*input_line_pointer != '>')
453833965Sjdp	    {
453960484Sobrien	      as_bad (_("Expected <nn>"));
454033965Sjdp	    }
454133965Sjdp	  input_line_pointer++;
454233965Sjdp	  break;
454333965Sjdp	case ',':
454433965Sjdp	  input_line_pointer++;
454533965Sjdp	  break;
454633965Sjdp	}
454733965Sjdp      SKIP_WHITESPACE ();
454833965Sjdp      c = *input_line_pointer;
454933965Sjdp    }
455033965Sjdp
455133965Sjdp  demand_empty_rest_of_line ();
455233965Sjdp}				/* stringer() */
455333965Sjdp
455433965Sjdp/* FIXME-SOMEDAY: I had trouble here on characters with the
455533965Sjdp    high bits set.  We'll probably also have trouble with
455633965Sjdp    multibyte chars, wide chars, etc.  Also be careful about
455733965Sjdp    returning values bigger than 1 byte.  xoxorich. */
455833965Sjdp
455933965Sjdpunsigned int
456033965Sjdpnext_char_of_string ()
456133965Sjdp{
456233965Sjdp  register unsigned int c;
456333965Sjdp
456433965Sjdp  c = *input_line_pointer++ & CHAR_MASK;
456533965Sjdp  switch (c)
456633965Sjdp    {
456733965Sjdp    case '\"':
456833965Sjdp      c = NOT_A_CHAR;
456933965Sjdp      break;
457033965Sjdp
457133965Sjdp    case '\n':
457260484Sobrien      as_warn (_("Unterminated string: Newline inserted."));
457333965Sjdp      bump_line_counters ();
457433965Sjdp      break;
457533965Sjdp
457633965Sjdp#ifndef NO_STRING_ESCAPES
457733965Sjdp    case '\\':
457833965Sjdp      switch (c = *input_line_pointer++)
457933965Sjdp	{
458033965Sjdp	case 'b':
458133965Sjdp	  c = '\b';
458233965Sjdp	  break;
458333965Sjdp
458433965Sjdp	case 'f':
458533965Sjdp	  c = '\f';
458633965Sjdp	  break;
458733965Sjdp
458833965Sjdp	case 'n':
458933965Sjdp	  c = '\n';
459033965Sjdp	  break;
459133965Sjdp
459233965Sjdp	case 'r':
459333965Sjdp	  c = '\r';
459433965Sjdp	  break;
459533965Sjdp
459633965Sjdp	case 't':
459733965Sjdp	  c = '\t';
459833965Sjdp	  break;
459933965Sjdp
460033965Sjdp	case 'v':
460133965Sjdp	  c = '\013';
460233965Sjdp	  break;
460333965Sjdp
460433965Sjdp	case '\\':
460533965Sjdp	case '"':
460633965Sjdp	  break;		/* As itself. */
460733965Sjdp
460833965Sjdp	case '0':
460933965Sjdp	case '1':
461033965Sjdp	case '2':
461133965Sjdp	case '3':
461233965Sjdp	case '4':
461333965Sjdp	case '5':
461433965Sjdp	case '6':
461533965Sjdp	case '7':
461633965Sjdp	case '8':
461733965Sjdp	case '9':
461833965Sjdp	  {
461933965Sjdp	    long number;
462033965Sjdp	    int i;
462133965Sjdp
462233965Sjdp	    for (i = 0, number = 0; isdigit (c) && i < 3; c = *input_line_pointer++, i++)
462333965Sjdp	      {
462433965Sjdp		number = number * 8 + c - '0';
462533965Sjdp	      }
462633965Sjdp	    c = number & 0xff;
462733965Sjdp	  }
462833965Sjdp	  --input_line_pointer;
462933965Sjdp	  break;
463033965Sjdp
463133965Sjdp	case 'x':
463233965Sjdp	case 'X':
463333965Sjdp	  {
463433965Sjdp	    long number;
463533965Sjdp
463633965Sjdp	    number = 0;
463733965Sjdp	    c = *input_line_pointer++;
463833965Sjdp	    while (isxdigit (c))
463933965Sjdp	      {
464033965Sjdp		if (isdigit (c))
464133965Sjdp		  number = number * 16 + c - '0';
464233965Sjdp		else if (isupper (c))
464333965Sjdp		  number = number * 16 + c - 'A' + 10;
464433965Sjdp		else
464533965Sjdp		  number = number * 16 + c - 'a' + 10;
464633965Sjdp		c = *input_line_pointer++;
464733965Sjdp	      }
464833965Sjdp	    c = number & 0xff;
464933965Sjdp	    --input_line_pointer;
465033965Sjdp	  }
465133965Sjdp	  break;
465233965Sjdp
465333965Sjdp	case '\n':
465433965Sjdp	  /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */
465560484Sobrien	  as_warn (_("Unterminated string: Newline inserted."));
465633965Sjdp	  c = '\n';
465733965Sjdp	  bump_line_counters ();
465833965Sjdp	  break;
465933965Sjdp
466033965Sjdp	default:
466133965Sjdp
466233965Sjdp#ifdef ONLY_STANDARD_ESCAPES
466360484Sobrien	  as_bad (_("Bad escaped character in string, '?' assumed"));
466433965Sjdp	  c = '?';
466533965Sjdp#endif /* ONLY_STANDARD_ESCAPES */
466633965Sjdp
466733965Sjdp	  break;
466833965Sjdp	}			/* switch on escaped char */
466933965Sjdp      break;
467033965Sjdp#endif /* ! defined (NO_STRING_ESCAPES) */
467133965Sjdp
467233965Sjdp    default:
467333965Sjdp      break;
467433965Sjdp    }				/* switch on char */
467533965Sjdp  return (c);
467633965Sjdp}				/* next_char_of_string() */
467733965Sjdp
467833965Sjdpstatic segT
467933965Sjdpget_segmented_expression (expP)
468033965Sjdp     register expressionS *expP;
468133965Sjdp{
468233965Sjdp  register segT retval;
468333965Sjdp
468433965Sjdp  retval = expression (expP);
468533965Sjdp  if (expP->X_op == O_illegal
468633965Sjdp      || expP->X_op == O_absent
468733965Sjdp      || expP->X_op == O_big)
468833965Sjdp    {
468960484Sobrien      as_bad (_("expected address expression; zero assumed"));
469033965Sjdp      expP->X_op = O_constant;
469133965Sjdp      expP->X_add_number = 0;
469233965Sjdp      retval = absolute_section;
469333965Sjdp    }
469433965Sjdp  return retval;
469533965Sjdp}
469633965Sjdp
469733965Sjdpstatic segT
469833965Sjdpget_known_segmented_expression (expP)
469933965Sjdp     register expressionS *expP;
470033965Sjdp{
470133965Sjdp  register segT retval;
470233965Sjdp
470333965Sjdp  if ((retval = get_segmented_expression (expP)) == undefined_section)
470433965Sjdp    {
470533965Sjdp      /* There is no easy way to extract the undefined symbol from the
470633965Sjdp	 expression.  */
470733965Sjdp      if (expP->X_add_symbol != NULL
470833965Sjdp	  && S_GET_SEGMENT (expP->X_add_symbol) != expr_section)
470960484Sobrien	as_warn (_("symbol \"%s\" undefined; zero assumed"),
471033965Sjdp		 S_GET_NAME (expP->X_add_symbol));
471133965Sjdp      else
471260484Sobrien	as_warn (_("some symbol undefined; zero assumed"));
471333965Sjdp      retval = absolute_section;
471433965Sjdp      expP->X_op = O_constant;
471533965Sjdp      expP->X_add_number = 0;
471633965Sjdp    }
471733965Sjdp  know (retval == absolute_section || SEG_NORMAL (retval));
471833965Sjdp  return (retval);
471933965Sjdp}				/* get_known_segmented_expression() */
472033965Sjdp
472133965SjdpoffsetT
472233965Sjdpget_absolute_expression ()
472333965Sjdp{
472433965Sjdp  expressionS exp;
472533965Sjdp
472633965Sjdp  expression (&exp);
472733965Sjdp  if (exp.X_op != O_constant)
472833965Sjdp    {
472933965Sjdp      if (exp.X_op != O_absent)
473060484Sobrien	as_bad (_("bad or irreducible absolute expression; zero assumed"));
473133965Sjdp      exp.X_add_number = 0;
473233965Sjdp    }
473333965Sjdp  return exp.X_add_number;
473433965Sjdp}
473533965Sjdp
473633965Sjdpchar				/* return terminator */
473733965Sjdpget_absolute_expression_and_terminator (val_pointer)
473833965Sjdp     long *val_pointer;		/* return value of expression */
473933965Sjdp{
474033965Sjdp  /* FIXME: val_pointer should probably be offsetT *.  */
474133965Sjdp  *val_pointer = (long) get_absolute_expression ();
474233965Sjdp  return (*input_line_pointer++);
474333965Sjdp}
474433965Sjdp
474533965Sjdp/*
474633965Sjdp *			demand_copy_C_string()
474733965Sjdp *
474833965Sjdp * Like demand_copy_string, but return NULL if the string contains any '\0's.
474933965Sjdp * Give a warning if that happens.
475033965Sjdp */
475133965Sjdpchar *
475233965Sjdpdemand_copy_C_string (len_pointer)
475333965Sjdp     int *len_pointer;
475433965Sjdp{
475533965Sjdp  register char *s;
475633965Sjdp
475733965Sjdp  if ((s = demand_copy_string (len_pointer)) != 0)
475833965Sjdp    {
475933965Sjdp      register int len;
476033965Sjdp
476133965Sjdp      for (len = *len_pointer; len > 0; len--)
476233965Sjdp	{
476333965Sjdp	  if (*s == 0)
476433965Sjdp	    {
476533965Sjdp	      s = 0;
476633965Sjdp	      len = 1;
476733965Sjdp	      *len_pointer = 0;
476860484Sobrien	      as_bad (_("This string may not contain \'\\0\'"));
476933965Sjdp	    }
477033965Sjdp	}
477133965Sjdp    }
477233965Sjdp  return s;
477333965Sjdp}
477433965Sjdp
477533965Sjdp/*
477633965Sjdp *			demand_copy_string()
477733965Sjdp *
477833965Sjdp * Demand string, but return a safe (=private) copy of the string.
477933965Sjdp * Return NULL if we can't read a string here.
478033965Sjdp */
478133965Sjdpchar *
478233965Sjdpdemand_copy_string (lenP)
478333965Sjdp     int *lenP;
478433965Sjdp{
478533965Sjdp  register unsigned int c;
478633965Sjdp  register int len;
478733965Sjdp  char *retval;
478833965Sjdp
478933965Sjdp  len = 0;
479033965Sjdp  SKIP_WHITESPACE ();
479133965Sjdp  if (*input_line_pointer == '\"')
479233965Sjdp    {
479333965Sjdp      input_line_pointer++;	/* Skip opening quote. */
479433965Sjdp
479533965Sjdp      while (is_a_char (c = next_char_of_string ()))
479633965Sjdp	{
479733965Sjdp	  obstack_1grow (&notes, c);
479833965Sjdp	  len++;
479933965Sjdp	}
480033965Sjdp      /* JF this next line is so demand_copy_C_string will return a
480133965Sjdp	 null terminated string. */
480233965Sjdp      obstack_1grow (&notes, '\0');
480333965Sjdp      retval = obstack_finish (&notes);
480433965Sjdp    }
480533965Sjdp  else
480633965Sjdp    {
480760484Sobrien      as_warn (_("Missing string"));
480833965Sjdp      retval = NULL;
480933965Sjdp      ignore_rest_of_line ();
481033965Sjdp    }
481133965Sjdp  *lenP = len;
481233965Sjdp  return (retval);
481333965Sjdp}				/* demand_copy_string() */
481433965Sjdp
481533965Sjdp/*
481633965Sjdp *		is_it_end_of_statement()
481733965Sjdp *
481833965Sjdp * In:	Input_line_pointer->next character.
481933965Sjdp *
482033965Sjdp * Do:	Skip input_line_pointer over all whitespace.
482133965Sjdp *
482233965Sjdp * Out:	1 if input_line_pointer->end-of-line.
482333965Sjdp*/
482433965Sjdpint
482533965Sjdpis_it_end_of_statement ()
482633965Sjdp{
482733965Sjdp  SKIP_WHITESPACE ();
482833965Sjdp  return (is_end_of_line[(unsigned char) *input_line_pointer]);
482933965Sjdp}				/* is_it_end_of_statement() */
483033965Sjdp
483133965Sjdpvoid
483233965Sjdpequals (sym_name, reassign)
483333965Sjdp     char *sym_name;
483433965Sjdp     int reassign;
483533965Sjdp{
483633965Sjdp  register symbolS *symbolP;	/* symbol we are working with */
483738889Sjdp  char *stop = NULL;
483833965Sjdp  char stopc;
483933965Sjdp
484033965Sjdp  input_line_pointer++;
484133965Sjdp  if (*input_line_pointer == '=')
484233965Sjdp    input_line_pointer++;
484333965Sjdp
484433965Sjdp  while (*input_line_pointer == ' ' || *input_line_pointer == '\t')
484533965Sjdp    input_line_pointer++;
484633965Sjdp
484733965Sjdp  if (flag_mri)
484833965Sjdp    stop = mri_comment_field (&stopc);
484933965Sjdp
485033965Sjdp  if (sym_name[0] == '.' && sym_name[1] == '\0')
485133965Sjdp    {
485233965Sjdp      /* Turn '. = mumble' into a .org mumble */
485333965Sjdp      register segT segment;
485433965Sjdp      expressionS exp;
485533965Sjdp
485633965Sjdp      segment = get_known_segmented_expression (&exp);
485733965Sjdp      if (!need_pass_2)
485833965Sjdp	do_org (segment, &exp, 0);
485933965Sjdp    }
486033965Sjdp  else
486133965Sjdp    {
486233965Sjdp      symbolP = symbol_find_or_make (sym_name);
486333965Sjdp      /* Permit register names to be redefined.  */
486433965Sjdp      if (! reassign
486533965Sjdp	  && S_IS_DEFINED (symbolP)
486633965Sjdp	  && S_GET_SEGMENT (symbolP) != reg_section)
486760484Sobrien	as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
486833965Sjdp      pseudo_set (symbolP);
486933965Sjdp    }
487033965Sjdp
487133965Sjdp  if (flag_mri)
487260484Sobrien     {
487360484Sobrien       ignore_rest_of_line (); /* check garbage after the expression */
487460484Sobrien       mri_comment_end (stop, stopc);
487560484Sobrien     }
487633965Sjdp}				/* equals() */
487733965Sjdp
487833965Sjdp/* .include -- include a file at this point. */
487933965Sjdp
488033965Sjdp/* ARGSUSED */
488133965Sjdpvoid
488233965Sjdps_include (arg)
488360484Sobrien     int arg ATTRIBUTE_UNUSED;
488433965Sjdp{
488533965Sjdp  char *filename;
488633965Sjdp  int i;
488733965Sjdp  FILE *try;
488833965Sjdp  char *path;
488933965Sjdp
489033965Sjdp  if (! flag_m68k_mri)
489138889Sjdp    {
489238889Sjdp      filename = demand_copy_string (&i);
489338889Sjdp      if (filename == NULL)
489438889Sjdp	{
489538889Sjdp	  /* demand_copy_string has already printed an error and
489638889Sjdp             called ignore_rest_of_line.  */
489738889Sjdp	  return;
489838889Sjdp	}
489938889Sjdp    }
490033965Sjdp  else
490133965Sjdp    {
490233965Sjdp      SKIP_WHITESPACE ();
490333965Sjdp      i = 0;
490433965Sjdp      while (! is_end_of_line[(unsigned char) *input_line_pointer]
490533965Sjdp	     && *input_line_pointer != ' '
490633965Sjdp	     && *input_line_pointer != '\t')
490733965Sjdp	{
490833965Sjdp	  obstack_1grow (&notes, *input_line_pointer);
490933965Sjdp	  ++input_line_pointer;
491033965Sjdp	  ++i;
491133965Sjdp	}
491233965Sjdp      obstack_1grow (&notes, '\0');
491333965Sjdp      filename = obstack_finish (&notes);
491433965Sjdp      while (! is_end_of_line[(unsigned char) *input_line_pointer])
491533965Sjdp	++input_line_pointer;
491633965Sjdp    }
491733965Sjdp  demand_empty_rest_of_line ();
491833965Sjdp  path = xmalloc ((unsigned long) i + include_dir_maxlen + 5 /* slop */ );
491933965Sjdp  for (i = 0; i < include_dir_count; i++)
492033965Sjdp    {
492133965Sjdp      strcpy (path, include_dirs[i]);
492233965Sjdp      strcat (path, "/");
492333965Sjdp      strcat (path, filename);
492433965Sjdp      if (0 != (try = fopen (path, "r")))
492533965Sjdp	{
492633965Sjdp	  fclose (try);
492733965Sjdp	  goto gotit;
492833965Sjdp	}
492933965Sjdp    }
493033965Sjdp  free (path);
493133965Sjdp  path = filename;
493233965Sjdpgotit:
493333965Sjdp  /* malloc Storage leak when file is found on path.  FIXME-SOMEDAY. */
493438889Sjdp  register_dependency (path);
493560484Sobrien  input_scrub_insert_file (path);
493633965Sjdp}				/* s_include() */
493733965Sjdp
493833965Sjdpvoid
493933965Sjdpadd_include_dir (path)
494033965Sjdp     char *path;
494133965Sjdp{
494233965Sjdp  int i;
494333965Sjdp
494433965Sjdp  if (include_dir_count == 0)
494533965Sjdp    {
494633965Sjdp      include_dirs = (char **) xmalloc (2 * sizeof (*include_dirs));
494733965Sjdp      include_dirs[0] = ".";	/* Current dir */
494833965Sjdp      include_dir_count = 2;
494933965Sjdp    }
495033965Sjdp  else
495133965Sjdp    {
495233965Sjdp      include_dir_count++;
495333965Sjdp      include_dirs = (char **) realloc (include_dirs,
495433965Sjdp				include_dir_count * sizeof (*include_dirs));
495533965Sjdp    }
495633965Sjdp
495733965Sjdp  include_dirs[include_dir_count - 1] = path;	/* New one */
495833965Sjdp
495933965Sjdp  i = strlen (path);
496033965Sjdp  if (i > include_dir_maxlen)
496133965Sjdp    include_dir_maxlen = i;
496233965Sjdp}				/* add_include_dir() */
496360484Sobrien
496460484Sobrien/* Output debugging information to denote the source file.  */
496533965Sjdp
496660484Sobrienstatic void
496760484Sobriengenerate_file_debug ()
496860484Sobrien{
496960484Sobrien  if (debug_type == DEBUG_STABS)
497060484Sobrien    stabs_generate_asm_file ();
497160484Sobrien}
497260484Sobrien
497360484Sobrien/* Output line number debugging information for the current source line.  */
497460484Sobrien
497560484Sobrienvoid
497660484Sobriengenerate_lineno_debug ()
497760484Sobrien{
497860484Sobrien#ifdef ECOFF_DEBUGGING
497960484Sobrien  /* ECOFF assemblers automatically generate debugging information.
498060484Sobrien     FIXME: This should probably be handled elsewhere.  */
498160484Sobrien  if (debug_type == DEBUG_UNSPECIFIED)
498260484Sobrien    {
498360484Sobrien      if (ECOFF_DEBUGGING && ecoff_no_current_file ())
498460484Sobrien        debug_type = DEBUG_ECOFF;
498560484Sobrien      else
498660484Sobrien	debug_type = DEBUG_NONE;
498760484Sobrien    }
498860484Sobrien#endif
498960484Sobrien
499060484Sobrien  switch (debug_type)
499160484Sobrien    {
499260484Sobrien    case DEBUG_UNSPECIFIED:
499360484Sobrien    case DEBUG_NONE:
499460484Sobrien      break;
499560484Sobrien    case DEBUG_STABS:
499660484Sobrien      stabs_generate_asm_lineno ();
499760484Sobrien      break;
499860484Sobrien    case DEBUG_ECOFF:
499960484Sobrien      ecoff_generate_asm_lineno ();
500060484Sobrien      break;
500160484Sobrien    case DEBUG_DWARF:
500260484Sobrien    case DEBUG_DWARF2:
500360484Sobrien      /* FIXME.  */
500460484Sobrien      break;
500560484Sobrien    }
500660484Sobrien}
500760484Sobrien
500860484Sobrien/* Output debugging information to mark a function entry point or end point.
500960484Sobrien   END_P is zero for .func, and non-zero for .endfunc.  */
501060484Sobrien
501160484Sobrienvoid
501260484Sobriens_func (end_p)
501360484Sobrien     int end_p;
501460484Sobrien{
501560484Sobrien  do_s_func (end_p, NULL);
501660484Sobrien}
501760484Sobrien
501860484Sobrien/* Subroutine of s_func so targets can choose a different default prefix.
501960484Sobrien   If DEFAULT_PREFIX is NULL, use the target's "leading char".  */
502060484Sobrien
502160484Sobrienvoid
502260484Sobriendo_s_func (end_p, default_prefix)
502360484Sobrien     int end_p;
502460484Sobrien     const char *default_prefix;
502560484Sobrien{
502660484Sobrien  /* Record the current function so that we can issue an error message for
502760484Sobrien     misplaced .func,.endfunc, and also so that .endfunc needs no
502860484Sobrien     arguments.  */
502960484Sobrien  static char *current_name;
503060484Sobrien  static char *current_label;
503160484Sobrien
503260484Sobrien  if (end_p)
503360484Sobrien    {
503460484Sobrien      if (current_name == NULL)
503560484Sobrien	{
503660484Sobrien	  as_bad (_("missing .func"));
503760484Sobrien	  ignore_rest_of_line ();
503860484Sobrien	  return;
503960484Sobrien	}
504060484Sobrien
504160484Sobrien      if (debug_type == DEBUG_STABS)
504260484Sobrien	stabs_generate_asm_endfunc (current_name, current_label);
504360484Sobrien
504460484Sobrien      current_name = current_label = NULL;
504560484Sobrien    }
504660484Sobrien  else /* ! end_p */
504760484Sobrien    {
504860484Sobrien      char *name,*label;
504960484Sobrien      char delim1,delim2;
505060484Sobrien
505160484Sobrien      if (current_name != NULL)
505260484Sobrien	{
505360484Sobrien	  as_bad (_(".endfunc missing for previous .func"));
505460484Sobrien	  ignore_rest_of_line ();
505560484Sobrien	  return;
505660484Sobrien	}
505760484Sobrien
505860484Sobrien      name = input_line_pointer;
505960484Sobrien      delim1 = get_symbol_end ();
506060484Sobrien      name = xstrdup (name);
506160484Sobrien      *input_line_pointer = delim1;
506260484Sobrien      SKIP_WHITESPACE ();
506360484Sobrien      if (*input_line_pointer != ',')
506460484Sobrien	{
506560484Sobrien	  if (default_prefix)
506660484Sobrien	    asprintf (&label, "%s%s", default_prefix, name);
506760484Sobrien	  else
506860484Sobrien	    {
506960484Sobrien	      char leading_char = 0;
507060484Sobrien#ifdef BFD_ASSEMBLER
507160484Sobrien	      leading_char = bfd_get_symbol_leading_char (stdoutput);
507260484Sobrien#endif
507360484Sobrien	      /* Missing entry point, use function's name with the leading
507460484Sobrien		 char prepended.  */
507560484Sobrien	      if (leading_char)
507660484Sobrien		asprintf (&label, "%c%s", leading_char, name);
507760484Sobrien	      else
507860484Sobrien		label = name;
507960484Sobrien	    }
508060484Sobrien	}
508160484Sobrien      else
508260484Sobrien	{
508360484Sobrien	  ++input_line_pointer;
508460484Sobrien	  SKIP_WHITESPACE ();
508560484Sobrien	  label = input_line_pointer;
508660484Sobrien	  delim2 = get_symbol_end ();
508760484Sobrien	  label = xstrdup (label);
508860484Sobrien	  *input_line_pointer = delim2;
508960484Sobrien	}
509060484Sobrien
509160484Sobrien      if (debug_type == DEBUG_STABS)
509260484Sobrien	stabs_generate_asm_func (name, label);
509360484Sobrien
509460484Sobrien      current_name = name;
509560484Sobrien      current_label = label;
509660484Sobrien    }
509760484Sobrien
509860484Sobrien  demand_empty_rest_of_line ();
509960484Sobrien}
510060484Sobrien
510133965Sjdpvoid
510233965Sjdps_ignore (arg)
510360484Sobrien     int arg ATTRIBUTE_UNUSED;
510433965Sjdp{
510533965Sjdp  while (!is_end_of_line[(unsigned char) *input_line_pointer])
510633965Sjdp    {
510733965Sjdp      ++input_line_pointer;
510833965Sjdp    }
510933965Sjdp  ++input_line_pointer;
511033965Sjdp}
511133965Sjdp
511233965Sjdp
511333965Sjdpvoid
511433965Sjdpread_print_statistics (file)
511533965Sjdp     FILE *file;
511633965Sjdp{
511733965Sjdp  hash_print_statistics (file, "pseudo-op table", po_hash);
511833965Sjdp}
511933965Sjdp
512060484Sobrien/* Inserts the given line into the input stream.
512160484Sobrien
512260484Sobrien   This call avoids macro/conditionals nesting checking, since the contents of
512360484Sobrien   the line are assumed to replace the contents of a line already scanned.
512460484Sobrien
512560484Sobrien   An appropriate use of this function would be substition of input lines when
512660484Sobrien   called by md_start_line_hook().  The given line is assumed to already be
512760484Sobrien   properly scrubbed.  */
512860484Sobrien
512960484Sobrienvoid
513060484Sobrieninput_scrub_insert_line (line)
513160484Sobrien  const char *line;
513260484Sobrien{
513360484Sobrien  sb newline;
513460484Sobrien  sb_new (&newline);
513560484Sobrien  sb_add_string (&newline, line);
513660484Sobrien  input_scrub_include_sb (&newline, input_line_pointer, 0);
513760484Sobrien  sb_kill (&newline);
513860484Sobrien  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
513960484Sobrien}
514060484Sobrien
514160484Sobrien/* Insert a file into the input stream; the path must resolve to an actual
514260484Sobrien   file; no include path searching or dependency registering is performed.  */
514360484Sobrien
514460484Sobrienvoid
514560484Sobrieninput_scrub_insert_file (path)
514660484Sobrien  char *path;
514760484Sobrien{
514860484Sobrien  input_scrub_include_file (path, input_line_pointer);
514960484Sobrien  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
515060484Sobrien}
515160484Sobrien
515233965Sjdp/* end of read.c */
5153