read.c revision 33965
133965Sjdp/* read.c - read a source file -
233965Sjdp   Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 1997
333965Sjdp   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
5633965Sjdp/* The NOP_OPCODE is for the alignment fill value.
5733965Sjdp * fill it a nop instruction so that the disassembler does not choke
5833965Sjdp * on it
5933965Sjdp */
6033965Sjdp#ifndef NOP_OPCODE
6133965Sjdp#define NOP_OPCODE 0x00
6233965Sjdp#endif
6333965Sjdp
6433965Sjdpchar *input_line_pointer;	/*->next char of source file to parse. */
6533965Sjdp
6633965Sjdpint generate_asm_lineno = 0;	/* flag to generate line stab for .s file */
6733965Sjdp
6833965Sjdp#if BITS_PER_CHAR != 8
6933965Sjdp/*  The following table is indexed by[(char)] and will break if
7033965Sjdp    a char does not have exactly 256 states (hopefully 0:255!)!  */
7133965Sjdpdie horribly;
7233965Sjdp#endif
7333965Sjdp
7433965Sjdp#ifndef LEX_AT
7533965Sjdp/* The m88k unfortunately uses @ as a label beginner.  */
7633965Sjdp#define LEX_AT 0
7733965Sjdp#endif
7833965Sjdp
7933965Sjdp#ifndef LEX_BR
8033965Sjdp/* The RS/6000 assembler uses {,},[,] as parts of symbol names.  */
8133965Sjdp#define LEX_BR 0
8233965Sjdp#endif
8333965Sjdp
8433965Sjdp#ifndef LEX_PCT
8533965Sjdp/* The Delta 68k assembler permits % inside label names.  */
8633965Sjdp#define LEX_PCT 0
8733965Sjdp#endif
8833965Sjdp
8933965Sjdp#ifndef LEX_QM
9033965Sjdp/* The PowerPC Windows NT assemblers permits ? inside label names.  */
9133965Sjdp#define LEX_QM 0
9233965Sjdp#endif
9333965Sjdp
9433965Sjdp#ifndef LEX_DOLLAR
9533965Sjdp/* The a29k assembler does not permits labels to start with $.  */
9633965Sjdp#define LEX_DOLLAR 3
9733965Sjdp#endif
9833965Sjdp
9933965Sjdp#ifndef LEX_TILDE
10033965Sjdp/* The Delta 68k assembler permits ~ at start of label names.  */
10133965Sjdp#define LEX_TILDE 0
10233965Sjdp#endif
10333965Sjdp
10433965Sjdp/* used by is_... macros. our ctype[] */
10533965Sjdpchar lex_type[256] =
10633965Sjdp{
10733965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* @ABCDEFGHIJKLMNO */
10833965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* PQRSTUVWXYZ[\]^_ */
10933965Sjdp  0, 0, 0, 0, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
11033965Sjdp  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM,	/* 0123456789:;<=>? */
11133965Sjdp  LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,	/* @ABCDEFGHIJKLMNO */
11233965Sjdp  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
11333965Sjdp  0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,	/* `abcdefghijklmno */
11433965Sjdp  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~. */
11533965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11633965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11733965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11833965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11933965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12033965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12133965Sjdp  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12233965Sjdp};
12333965Sjdp
12433965Sjdp
12533965Sjdp/*
12633965Sjdp * In: a character.
12733965Sjdp * Out: 1 if this character ends a line.
12833965Sjdp */
12933965Sjdp#define _ (0)
13033965Sjdpchar is_end_of_line[256] =
13133965Sjdp{
13233965Sjdp#ifdef CR_EOL
13333965Sjdp  _, _, _, _, _, _, _, _, _, _, 99, _, _, 99, _, _,	/* @abcdefghijklmno */
13433965Sjdp#else
13533965Sjdp  _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, _,	/* @abcdefghijklmno */
13633965Sjdp#endif
13733965Sjdp  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,	/* */
13833965Sjdp#ifdef TC_HPPA
13933965Sjdp  _,99, _, _, _, _, _, _, _, _, _, _, _, _, _, _,	/* _!"#$%&'()*+,-./ */
14033965Sjdp  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,	/* 0123456789:;<=>? */
14133965Sjdp#else
14233965Sjdp  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,	/* */
14333965Sjdp  _, _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _,	/* 0123456789:;<=>? */
14433965Sjdp#endif
14533965Sjdp  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,	/* */
14633965Sjdp  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,	/* */
14733965Sjdp  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,	/* */
14833965Sjdp  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,	/* */
14933965Sjdp  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,	/* */
15033965Sjdp  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,	/* */
15133965Sjdp  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,	/* */
15233965Sjdp  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,	/* */
15333965Sjdp  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,	/* */
15433965Sjdp};
15533965Sjdp#undef _
15633965Sjdp
15733965Sjdp/* Functions private to this file. */
15833965Sjdp
15933965Sjdpstatic char *buffer;	/* 1st char of each buffer of lines is here. */
16033965Sjdpstatic char *buffer_limit;	/*->1 + last char in buffer. */
16133965Sjdp
16233965Sjdp/* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1 in the
16333965Sjdp   tc-<CPU>.h file.  See the "Porting GAS" section of the internals manual. */
16433965Sjdpint target_big_endian = TARGET_BYTES_BIG_ENDIAN;
16533965Sjdp
16633965Sjdpstatic char *old_buffer;	/* JF a hack */
16733965Sjdpstatic char *old_input;
16833965Sjdpstatic char *old_limit;
16933965Sjdp
17033965Sjdp/* Variables for handling include file directory list. */
17133965Sjdp
17233965Sjdpchar **include_dirs;	/* List of pointers to directories to
17333965Sjdp			   search for .include's */
17433965Sjdpint include_dir_count;	/* How many are in the list */
17533965Sjdpint include_dir_maxlen = 1;/* Length of longest in list */
17633965Sjdp
17733965Sjdp#ifndef WORKING_DOT_WORD
17833965Sjdpstruct broken_word *broken_words;
17933965Sjdpint new_broken_words;
18033965Sjdp#endif
18133965Sjdp
18233965Sjdp/* The current offset into the absolute section.  We don't try to
18333965Sjdp   build frags in the absolute section, since no data can be stored
18433965Sjdp   there.  We just keep track of the current offset.  */
18533965SjdpaddressT abs_section_offset;
18633965Sjdp
18733965Sjdp/* If this line had an MRI style label, it is stored in this variable.
18833965Sjdp   This is used by some of the MRI pseudo-ops.  */
18933965SjdpsymbolS *line_label;
19033965Sjdp
19133965Sjdp/* This global variable is used to support MRI common sections.  We
19233965Sjdp   translate such sections into a common symbol.  This variable is
19333965Sjdp   non-NULL when we are in an MRI common section.  */
19433965SjdpsymbolS *mri_common_symbol;
19533965Sjdp
19633965Sjdp/* In MRI mode, after a dc.b pseudo-op with an odd number of bytes, we
19733965Sjdp   need to align to an even byte boundary unless the next pseudo-op is
19833965Sjdp   dc.b, ds.b, or dcb.b.  This variable is set to 1 if an alignment
19933965Sjdp   may be needed.  */
20033965Sjdpstatic int mri_pending_align;
20133965Sjdp
20233965Sjdpstatic void cons_worker PARAMS ((int, int));
20333965Sjdpstatic int scrub_from_string PARAMS ((char **));
20433965Sjdpstatic void do_align PARAMS ((int, char *, int, int));
20533965Sjdpstatic void s_align PARAMS ((int, int));
20633965Sjdpstatic int hex_float PARAMS ((int, char *));
20733965Sjdpstatic void do_org PARAMS ((segT, expressionS *, int));
20833965Sjdpchar *demand_copy_string PARAMS ((int *lenP));
20933965Sjdpstatic segT get_segmented_expression PARAMS ((expressionS *expP));
21033965Sjdpstatic segT get_known_segmented_expression PARAMS ((expressionS * expP));
21133965Sjdpstatic void pobegin PARAMS ((void));
21233965Sjdpstatic int get_line_sb PARAMS ((sb *));
21333965Sjdp
21433965Sjdp
21533965Sjdpvoid
21633965Sjdpread_begin ()
21733965Sjdp{
21833965Sjdp  const char *p;
21933965Sjdp
22033965Sjdp  pobegin ();
22133965Sjdp  obj_read_begin_hook ();
22233965Sjdp
22333965Sjdp  /* Something close -- but not too close -- to a multiple of 1024.
22433965Sjdp     The debugging malloc I'm using has 24 bytes of overhead.  */
22533965Sjdp  obstack_begin (&notes, chunksize);
22633965Sjdp  obstack_begin (&cond_obstack, chunksize);
22733965Sjdp
22833965Sjdp  /* Use machine dependent syntax */
22933965Sjdp  for (p = line_separator_chars; *p; p++)
23033965Sjdp    is_end_of_line[(unsigned char) *p] = 1;
23133965Sjdp  /* Use more.  FIXME-SOMEDAY. */
23233965Sjdp
23333965Sjdp  if (flag_mri)
23433965Sjdp    lex_type['?'] = 3;
23533965Sjdp}
23633965Sjdp
23733965Sjdp/* set up pseudo-op tables */
23833965Sjdp
23933965Sjdpstatic struct hash_control *po_hash;
24033965Sjdp
24133965Sjdpstatic const pseudo_typeS potable[] =
24233965Sjdp{
24333965Sjdp  {"abort", s_abort, 0},
24433965Sjdp  {"align", s_align_ptwo, 0},
24533965Sjdp  {"ascii", stringer, 0},
24633965Sjdp  {"asciz", stringer, 1},
24733965Sjdp  {"balign", s_align_bytes, 0},
24833965Sjdp  {"balignw", s_align_bytes, -2},
24933965Sjdp  {"balignl", s_align_bytes, -4},
25033965Sjdp/* block */
25133965Sjdp  {"byte", cons, 1},
25233965Sjdp  {"comm", s_comm, 0},
25333965Sjdp  {"common", s_mri_common, 0},
25433965Sjdp  {"common.s", s_mri_common, 1},
25533965Sjdp  {"data", s_data, 0},
25633965Sjdp  {"dc", cons, 2},
25733965Sjdp  {"dc.b", cons, 1},
25833965Sjdp  {"dc.d", float_cons, 'd'},
25933965Sjdp  {"dc.l", cons, 4},
26033965Sjdp  {"dc.s", float_cons, 'f'},
26133965Sjdp  {"dc.w", cons, 2},
26233965Sjdp  {"dc.x", float_cons, 'x'},
26333965Sjdp  {"dcb", s_space, 2},
26433965Sjdp  {"dcb.b", s_space, 1},
26533965Sjdp  {"dcb.d", s_float_space, 'd'},
26633965Sjdp  {"dcb.l", s_space, 4},
26733965Sjdp  {"dcb.s", s_float_space, 'f'},
26833965Sjdp  {"dcb.w", s_space, 2},
26933965Sjdp  {"dcb.x", s_float_space, 'x'},
27033965Sjdp  {"ds", s_space, 2},
27133965Sjdp  {"ds.b", s_space, 1},
27233965Sjdp  {"ds.d", s_space, 8},
27333965Sjdp  {"ds.l", s_space, 4},
27433965Sjdp  {"ds.p", s_space, 12},
27533965Sjdp  {"ds.s", s_space, 4},
27633965Sjdp  {"ds.w", s_space, 2},
27733965Sjdp  {"ds.x", s_space, 12},
27833965Sjdp  {"debug", s_ignore, 0},
27933965Sjdp#ifdef S_SET_DESC
28033965Sjdp  {"desc", s_desc, 0},
28133965Sjdp#endif
28233965Sjdp/* dim */
28333965Sjdp  {"double", float_cons, 'd'},
28433965Sjdp/* dsect */
28533965Sjdp  {"eject", listing_eject, 0},	/* Formfeed listing */
28633965Sjdp  {"else", s_else, 0},
28733965Sjdp  {"elsec", s_else, 0},
28833965Sjdp  {"end", s_end, 0},
28933965Sjdp  {"endc", s_endif, 0},
29033965Sjdp  {"endif", s_endif, 0},
29133965Sjdp/* endef */
29233965Sjdp  {"equ", s_set, 0},
29333965Sjdp  {"equiv", s_set, 1},
29433965Sjdp  {"err", s_err, 0},
29533965Sjdp  {"exitm", s_mexit, 0},
29633965Sjdp/* extend */
29733965Sjdp  {"extern", s_ignore, 0},	/* We treat all undef as ext */
29833965Sjdp  {"appfile", s_app_file, 1},
29933965Sjdp  {"appline", s_app_line, 0},
30033965Sjdp  {"fail", s_fail, 0},
30133965Sjdp  {"file", s_app_file, 0},
30233965Sjdp  {"fill", s_fill, 0},
30333965Sjdp  {"float", float_cons, 'f'},
30433965Sjdp  {"format", s_ignore, 0},
30533965Sjdp  {"global", s_globl, 0},
30633965Sjdp  {"globl", s_globl, 0},
30733965Sjdp  {"hword", cons, 2},
30833965Sjdp  {"if", s_if, (int) O_ne},
30933965Sjdp  {"ifc", s_ifc, 0},
31033965Sjdp  {"ifdef", s_ifdef, 0},
31133965Sjdp  {"ifeq", s_if, (int) O_eq},
31233965Sjdp  {"ifeqs", s_ifeqs, 0},
31333965Sjdp  {"ifge", s_if, (int) O_ge},
31433965Sjdp  {"ifgt", s_if, (int) O_gt},
31533965Sjdp  {"ifle", s_if, (int) O_le},
31633965Sjdp  {"iflt", s_if, (int) O_lt},
31733965Sjdp  {"ifnc", s_ifc, 1},
31833965Sjdp  {"ifndef", s_ifdef, 1},
31933965Sjdp  {"ifne", s_if, (int) O_ne},
32033965Sjdp  {"ifnes", s_ifeqs, 1},
32133965Sjdp  {"ifnotdef", s_ifdef, 1},
32233965Sjdp  {"include", s_include, 0},
32333965Sjdp  {"int", cons, 4},
32433965Sjdp  {"irp", s_irp, 0},
32533965Sjdp  {"irep", s_irp, 0},
32633965Sjdp  {"irpc", s_irp, 1},
32733965Sjdp  {"irepc", s_irp, 1},
32833965Sjdp  {"lcomm", s_lcomm, 0},
32933965Sjdp  {"lflags", listing_flags, 0},	/* Listing flags */
33033965Sjdp  {"linkonce", s_linkonce, 0},
33133965Sjdp  {"list", listing_list, 1},	/* Turn listing on */
33233965Sjdp  {"llen", listing_psize, 1},
33333965Sjdp  {"long", cons, 4},
33433965Sjdp  {"lsym", s_lsym, 0},
33533965Sjdp  {"macro", s_macro, 0},
33633965Sjdp  {"mexit", s_mexit, 0},
33733965Sjdp  {"mri", s_mri, 0},
33833965Sjdp  {".mri", s_mri, 0},	/* Special case so .mri works in MRI mode.  */
33933965Sjdp  {"name", s_ignore, 0},
34033965Sjdp  {"noformat", s_ignore, 0},
34133965Sjdp  {"nolist", listing_list, 0},	/* Turn listing off */
34233965Sjdp  {"nopage", listing_nopage, 0},
34333965Sjdp  {"octa", cons, 16},
34433965Sjdp  {"offset", s_struct, 0},
34533965Sjdp  {"org", s_org, 0},
34633965Sjdp  {"p2align", s_align_ptwo, 0},
34733965Sjdp  {"p2alignw", s_align_ptwo, -2},
34833965Sjdp  {"p2alignl", s_align_ptwo, -4},
34933965Sjdp  {"page", listing_eject, 0},
35033965Sjdp  {"plen", listing_psize, 0},
35133965Sjdp  {"print", s_print, 0},
35233965Sjdp  {"psize", listing_psize, 0},	/* set paper size */
35333965Sjdp  {"purgem", s_purgem, 0},
35433965Sjdp  {"quad", cons, 8},
35533965Sjdp  {"rep", s_rept, 0},
35633965Sjdp  {"rept", s_rept, 0},
35733965Sjdp  {"rva", s_rva, 4},
35833965Sjdp  {"sbttl", listing_title, 1},	/* Subtitle of listing */
35933965Sjdp/* scl */
36033965Sjdp/* sect */
36133965Sjdp  {"set", s_set, 0},
36233965Sjdp  {"short", cons, 2},
36333965Sjdp  {"single", float_cons, 'f'},
36433965Sjdp/* size */
36533965Sjdp  {"space", s_space, 0},
36633965Sjdp  {"skip", s_space, 0},
36733965Sjdp  {"spc", s_ignore, 0},
36833965Sjdp  {"stabd", s_stab, 'd'},
36933965Sjdp  {"stabn", s_stab, 'n'},
37033965Sjdp  {"stabs", s_stab, 's'},
37133965Sjdp  {"string", stringer, 1},
37233965Sjdp  {"struct", s_struct, 0},
37333965Sjdp/* tag */
37433965Sjdp  {"text", s_text, 0},
37533965Sjdp
37633965Sjdp  /* This is for gcc to use.  It's only just been added (2/94), so gcc
37733965Sjdp     won't be able to use it for a while -- probably a year or more.
37833965Sjdp     But once this has been released, check with gcc maintainers
37933965Sjdp     before deleting it or even changing the spelling.  */
38033965Sjdp  {"this_GCC_requires_the_GNU_assembler", s_ignore, 0},
38133965Sjdp  /* If we're folding case -- done for some targets, not necessarily
38233965Sjdp     all -- the above string in an input file will be converted to
38333965Sjdp     this one.  Match it either way...  */
38433965Sjdp  {"this_gcc_requires_the_gnu_assembler", s_ignore, 0},
38533965Sjdp
38633965Sjdp  {"title", listing_title, 0},	/* Listing title */
38733965Sjdp  {"ttl", listing_title, 0},
38833965Sjdp/* type */
38933965Sjdp/* use */
39033965Sjdp/* val */
39133965Sjdp  {"xcom", s_comm, 0},
39233965Sjdp  {"xdef", s_globl, 0},
39333965Sjdp  {"xref", s_ignore, 0},
39433965Sjdp  {"xstabs", s_xstab, 's'},
39533965Sjdp  {"word", cons, 2},
39633965Sjdp  {"zero", s_space, 0},
39733965Sjdp  {NULL}			/* end sentinel */
39833965Sjdp};
39933965Sjdp
40033965Sjdpstatic int pop_override_ok = 0;
40133965Sjdpstatic const char *pop_table_name;
40233965Sjdp
40333965Sjdpvoid
40433965Sjdppop_insert (table)
40533965Sjdp     const pseudo_typeS *table;
40633965Sjdp{
40733965Sjdp  const char *errtxt;
40833965Sjdp  const pseudo_typeS *pop;
40933965Sjdp  for (pop = table; pop->poc_name; pop++)
41033965Sjdp    {
41133965Sjdp      errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
41233965Sjdp      if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists")))
41333965Sjdp	as_fatal ("error constructing %s pseudo-op table: %s", pop_table_name,
41433965Sjdp		  errtxt);
41533965Sjdp    }
41633965Sjdp}
41733965Sjdp
41833965Sjdp#ifndef md_pop_insert
41933965Sjdp#define md_pop_insert()		pop_insert(md_pseudo_table)
42033965Sjdp#endif
42133965Sjdp
42233965Sjdp#ifndef obj_pop_insert
42333965Sjdp#define obj_pop_insert()	pop_insert(obj_pseudo_table)
42433965Sjdp#endif
42533965Sjdp
42633965Sjdpstatic void
42733965Sjdppobegin ()
42833965Sjdp{
42933965Sjdp  po_hash = hash_new ();
43033965Sjdp
43133965Sjdp  /* Do the target-specific pseudo ops. */
43233965Sjdp  pop_table_name = "md";
43333965Sjdp  md_pop_insert ();
43433965Sjdp
43533965Sjdp  /* Now object specific.  Skip any that were in the target table. */
43633965Sjdp  pop_table_name = "obj";
43733965Sjdp  pop_override_ok = 1;
43833965Sjdp  obj_pop_insert ();
43933965Sjdp
44033965Sjdp  /* Now portable ones.  Skip any that we've seen already. */
44133965Sjdp  pop_table_name = "standard";
44233965Sjdp  pop_insert (potable);
44333965Sjdp}
44433965Sjdp
44533965Sjdp#define HANDLE_CONDITIONAL_ASSEMBLY()					\
44633965Sjdp  if (ignore_input ())							\
44733965Sjdp    {									\
44833965Sjdp      while (! is_end_of_line[(unsigned char) *input_line_pointer++])	\
44933965Sjdp	if (input_line_pointer == buffer_limit)				\
45033965Sjdp	  break;							\
45133965Sjdp      continue;								\
45233965Sjdp    }
45333965Sjdp
45433965Sjdp
45533965Sjdp/* This function is used when scrubbing the characters between #APP
45633965Sjdp   and #NO_APP.  */
45733965Sjdp
45833965Sjdpstatic char *scrub_string;
45933965Sjdpstatic char *scrub_string_end;
46033965Sjdp
46133965Sjdpstatic int
46233965Sjdpscrub_from_string (from)
46333965Sjdp     char **from;
46433965Sjdp{
46533965Sjdp  int size;
46633965Sjdp
46733965Sjdp  *from = scrub_string;
46833965Sjdp  size = scrub_string_end - scrub_string;
46933965Sjdp  scrub_string = scrub_string_end;
47033965Sjdp  return size;
47133965Sjdp}
47233965Sjdp
47333965Sjdp/*	read_a_source_file()
47433965Sjdp *
47533965Sjdp * We read the file, putting things into a web that
47633965Sjdp * represents what we have been reading.
47733965Sjdp */
47833965Sjdpvoid
47933965Sjdpread_a_source_file (name)
48033965Sjdp     char *name;
48133965Sjdp{
48233965Sjdp  register char c;
48333965Sjdp  register char *s;		/* string of symbol, '\0' appended */
48433965Sjdp  register int temp;
48533965Sjdp  pseudo_typeS *pop;
48633965Sjdp
48733965Sjdp  buffer = input_scrub_new_file (name);
48833965Sjdp
48933965Sjdp  listing_file (name);
49033965Sjdp  listing_newline ("");
49133965Sjdp
49233965Sjdp  while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0)
49333965Sjdp    {				/* We have another line to parse. */
49433965Sjdp      know (buffer_limit[-1] == '\n');	/* Must have a sentinel. */
49533965Sjdp    contin:			/* JF this goto is my fault I admit it.
49633965Sjdp				   Someone brave please re-write the whole
49733965Sjdp				   input section here?  Pleeze???  */
49833965Sjdp      while (input_line_pointer < buffer_limit)
49933965Sjdp	{
50033965Sjdp	  /* We have more of this buffer to parse. */
50133965Sjdp
50233965Sjdp	  /*
50333965Sjdp	   * We now have input_line_pointer->1st char of next line.
50433965Sjdp	   * If input_line_pointer [-1] == '\n' then we just
50533965Sjdp	   * scanned another line: so bump line counters.
50633965Sjdp	   */
50733965Sjdp	  if (is_end_of_line[(unsigned char) input_line_pointer[-1]])
50833965Sjdp	    {
50933965Sjdp#ifdef md_start_line_hook
51033965Sjdp	      md_start_line_hook ();
51133965Sjdp#endif
51233965Sjdp
51333965Sjdp	      if (input_line_pointer[-1] == '\n')
51433965Sjdp		bump_line_counters ();
51533965Sjdp
51633965Sjdp	      line_label = NULL;
51733965Sjdp
51833965Sjdp	      if (flag_m68k_mri
51933965Sjdp#ifdef LABELS_WITHOUT_COLONS
52033965Sjdp		  || 1
52133965Sjdp#endif
52233965Sjdp		  )
52333965Sjdp		{
52433965Sjdp		  /* Text at the start of a line must be a label, we
52533965Sjdp		     run down and stick a colon in.  */
52633965Sjdp		  if (is_name_beginner (*input_line_pointer))
52733965Sjdp		    {
52833965Sjdp		      char *line_start = input_line_pointer;
52933965Sjdp		      char c;
53033965Sjdp		      int mri_line_macro;
53133965Sjdp
53233965Sjdp		      LISTING_NEWLINE ();
53333965Sjdp		      HANDLE_CONDITIONAL_ASSEMBLY ();
53433965Sjdp
53533965Sjdp		      c = get_symbol_end ();
53633965Sjdp
53733965Sjdp		      /* In MRI mode, the EQU and MACRO pseudoops must
53833965Sjdp			 be handled specially.  */
53933965Sjdp		      mri_line_macro = 0;
54033965Sjdp		      if (flag_m68k_mri)
54133965Sjdp			{
54233965Sjdp			  char *rest = input_line_pointer + 1;
54333965Sjdp
54433965Sjdp			  if (*rest == ':')
54533965Sjdp			    ++rest;
54633965Sjdp			  if (*rest == ' ' || *rest == '\t')
54733965Sjdp			    ++rest;
54833965Sjdp			  if ((strncasecmp (rest, "EQU", 3) == 0
54933965Sjdp			       || strncasecmp (rest, "SET", 3) == 0)
55033965Sjdp			      && (rest[3] == ' ' || rest[3] == '\t'))
55133965Sjdp			    {
55233965Sjdp			      input_line_pointer = rest + 3;
55333965Sjdp			      equals (line_start,
55433965Sjdp				      strncasecmp (rest, "SET", 3) == 0);
55533965Sjdp			      continue;
55633965Sjdp			    }
55733965Sjdp			  if (strncasecmp (rest, "MACRO", 5) == 0
55833965Sjdp			      && (rest[5] == ' '
55933965Sjdp				  || rest[5] == '\t'
56033965Sjdp				  || is_end_of_line[(unsigned char) rest[5]]))
56133965Sjdp			    mri_line_macro = 1;
56233965Sjdp			}
56333965Sjdp
56433965Sjdp		      /* In MRI mode, we need to handle the MACRO
56533965Sjdp                         pseudo-op specially: we don't want to put the
56633965Sjdp                         symbol in the symbol table.  */
56733965Sjdp		      if (! mri_line_macro)
56833965Sjdp			line_label = colon (line_start);
56933965Sjdp		      else
57033965Sjdp			line_label = symbol_create (line_start,
57133965Sjdp						    absolute_section,
57233965Sjdp						    (valueT) 0,
57333965Sjdp						    &zero_address_frag);
57433965Sjdp
57533965Sjdp		      *input_line_pointer = c;
57633965Sjdp		      if (c == ':')
57733965Sjdp			input_line_pointer++;
57833965Sjdp		    }
57933965Sjdp		}
58033965Sjdp	    }
58133965Sjdp
58233965Sjdp	  /*
58333965Sjdp	   * We are at the begining of a line, or similar place.
58433965Sjdp	   * We expect a well-formed assembler statement.
58533965Sjdp	   * A "symbol-name:" is a statement.
58633965Sjdp	   *
58733965Sjdp	   * Depending on what compiler is used, the order of these tests
58833965Sjdp	   * may vary to catch most common case 1st.
58933965Sjdp	   * Each test is independent of all other tests at the (top) level.
59033965Sjdp	   * PLEASE make a compiler that doesn't use this assembler.
59133965Sjdp	   * It is crufty to waste a compiler's time encoding things for this
59233965Sjdp	   * assembler, which then wastes more time decoding it.
59333965Sjdp	   * (And communicating via (linear) files is silly!
59433965Sjdp	   * If you must pass stuff, please pass a tree!)
59533965Sjdp	   */
59633965Sjdp	  if ((c = *input_line_pointer++) == '\t'
59733965Sjdp	      || c == ' '
59833965Sjdp	      || c == '\f'
59933965Sjdp	      || c == 0)
60033965Sjdp	    {
60133965Sjdp	      c = *input_line_pointer++;
60233965Sjdp	    }
60333965Sjdp	  know (c != ' ');	/* No further leading whitespace. */
60433965Sjdp	  LISTING_NEWLINE ();
60533965Sjdp	  /*
60633965Sjdp	   * C is the 1st significant character.
60733965Sjdp	   * Input_line_pointer points after that character.
60833965Sjdp	   */
60933965Sjdp	  if (is_name_beginner (c))
61033965Sjdp	    {
61133965Sjdp	      /* want user-defined label or pseudo/opcode */
61233965Sjdp	      HANDLE_CONDITIONAL_ASSEMBLY ();
61333965Sjdp
61433965Sjdp	      s = --input_line_pointer;
61533965Sjdp	      c = get_symbol_end ();	/* name's delimiter */
61633965Sjdp	      /*
61733965Sjdp	       * C is character after symbol.
61833965Sjdp	       * That character's place in the input line is now '\0'.
61933965Sjdp	       * S points to the beginning of the symbol.
62033965Sjdp	       *   [In case of pseudo-op, s->'.'.]
62133965Sjdp	       * Input_line_pointer->'\0' where c was.
62233965Sjdp	       */
62333965Sjdp	      if (TC_START_LABEL(c, input_line_pointer))
62433965Sjdp		{
62533965Sjdp		  if (flag_m68k_mri)
62633965Sjdp		    {
62733965Sjdp		      char *rest = input_line_pointer + 1;
62833965Sjdp
62933965Sjdp		      /* In MRI mode, \tsym: set 0 is permitted.  */
63033965Sjdp
63133965Sjdp		      if (*rest == ':')
63233965Sjdp			++rest;
63333965Sjdp		      if (*rest == ' ' || *rest == '\t')
63433965Sjdp			++rest;
63533965Sjdp		      if ((strncasecmp (rest, "EQU", 3) == 0
63633965Sjdp			   || strncasecmp (rest, "SET", 3) == 0)
63733965Sjdp			  && (rest[3] == ' ' || rest[3] == '\t'))
63833965Sjdp			{
63933965Sjdp			  input_line_pointer = rest + 3;
64033965Sjdp			  equals (s, 1);
64133965Sjdp			  continue;
64233965Sjdp			}
64333965Sjdp		    }
64433965Sjdp
64533965Sjdp		  line_label = colon (s);	/* user-defined label */
64633965Sjdp		  *input_line_pointer++ = ':';	/* Put ':' back for error messages' sake. */
64733965Sjdp		  /* Input_line_pointer->after ':'. */
64833965Sjdp		  SKIP_WHITESPACE ();
64933965Sjdp
65033965Sjdp
65133965Sjdp		}
65233965Sjdp	      else if (c == '='
65333965Sjdp		       || ((c == ' ' || c == '\t')
65433965Sjdp			   && input_line_pointer[1] == '='
65533965Sjdp#ifdef TC_EQUAL_IN_INSN
65633965Sjdp			   && ! TC_EQUAL_IN_INSN (c, input_line_pointer)
65733965Sjdp#endif
65833965Sjdp			   ))
65933965Sjdp		{
66033965Sjdp		  equals (s, 1);
66133965Sjdp		  demand_empty_rest_of_line ();
66233965Sjdp		}
66333965Sjdp	      else
66433965Sjdp		{		/* expect pseudo-op or machine instruction */
66533965Sjdp		  pop = NULL;
66633965Sjdp
66733965Sjdp#define IGNORE_OPCODE_CASE
66833965Sjdp#ifdef IGNORE_OPCODE_CASE
66933965Sjdp		  {
67033965Sjdp		    char *s2 = s;
67133965Sjdp		    while (*s2)
67233965Sjdp		      {
67333965Sjdp			if (isupper (*s2))
67433965Sjdp			  *s2 = tolower (*s2);
67533965Sjdp			s2++;
67633965Sjdp		      }
67733965Sjdp		  }
67833965Sjdp#endif
67933965Sjdp
68033965Sjdp		  if (flag_m68k_mri
68133965Sjdp#ifdef NO_PSEUDO_DOT
68233965Sjdp		      || 1
68333965Sjdp#endif
68433965Sjdp		      )
68533965Sjdp		    {
68633965Sjdp		      /* The MRI assembler and the m88k use pseudo-ops
68733965Sjdp                         without a period.  */
68833965Sjdp		      pop = (pseudo_typeS *) hash_find (po_hash, s);
68933965Sjdp		      if (pop != NULL && pop->poc_handler == NULL)
69033965Sjdp			pop = NULL;
69133965Sjdp		    }
69233965Sjdp
69333965Sjdp		  if (pop != NULL
69433965Sjdp		      || (! flag_m68k_mri && *s == '.'))
69533965Sjdp		    {
69633965Sjdp		      /*
69733965Sjdp		       * PSEUDO - OP.
69833965Sjdp		       *
69933965Sjdp		       * WARNING: c has next char, which may be end-of-line.
70033965Sjdp		       * We lookup the pseudo-op table with s+1 because we
70133965Sjdp		       * already know that the pseudo-op begins with a '.'.
70233965Sjdp		       */
70333965Sjdp
70433965Sjdp		      if (pop == NULL)
70533965Sjdp			pop = (pseudo_typeS *) hash_find (po_hash, s + 1);
70633965Sjdp
70733965Sjdp		      /* In MRI mode, we may need to insert an
70833965Sjdp                         automatic alignment directive.  What a hack
70933965Sjdp                         this is.  */
71033965Sjdp		      if (mri_pending_align
71133965Sjdp			  && (pop == NULL
71233965Sjdp			      || ! ((pop->poc_handler == cons
71333965Sjdp				     && pop->poc_val == 1)
71433965Sjdp				    || (pop->poc_handler == s_space
71533965Sjdp					&& pop->poc_val == 1)
71633965Sjdp#ifdef tc_conditional_pseudoop
71733965Sjdp				    || tc_conditional_pseudoop (pop)
71833965Sjdp#endif
71933965Sjdp				    || pop->poc_handler == s_if
72033965Sjdp				    || pop->poc_handler == s_ifdef
72133965Sjdp				    || pop->poc_handler == s_ifc
72233965Sjdp				    || pop->poc_handler == s_ifeqs
72333965Sjdp				    || pop->poc_handler == s_else
72433965Sjdp				    || pop->poc_handler == s_endif
72533965Sjdp				    || pop->poc_handler == s_globl
72633965Sjdp				    || pop->poc_handler == s_ignore)))
72733965Sjdp			{
72833965Sjdp			  do_align (1, (char *) NULL, 0, 0);
72933965Sjdp			  mri_pending_align = 0;
73033965Sjdp			  if (line_label != NULL)
73133965Sjdp			    {
73233965Sjdp			      line_label->sy_frag = frag_now;
73333965Sjdp			      S_SET_VALUE (line_label, frag_now_fix ());
73433965Sjdp			    }
73533965Sjdp			}
73633965Sjdp
73733965Sjdp		      /* Print the error msg now, while we still can */
73833965Sjdp		      if (pop == NULL)
73933965Sjdp			{
74033965Sjdp			  as_bad ("Unknown pseudo-op:  `%s'", s);
74133965Sjdp			  *input_line_pointer = c;
74233965Sjdp			  s_ignore (0);
74333965Sjdp			  continue;
74433965Sjdp			}
74533965Sjdp
74633965Sjdp		      /* Put it back for error messages etc. */
74733965Sjdp		      *input_line_pointer = c;
74833965Sjdp		      /* The following skip of whitespace is compulsory.
74933965Sjdp			 A well shaped space is sometimes all that separates
75033965Sjdp			 keyword from operands. */
75133965Sjdp		      if (c == ' ' || c == '\t')
75233965Sjdp			input_line_pointer++;
75333965Sjdp		      /*
75433965Sjdp		       * Input_line is restored.
75533965Sjdp		       * Input_line_pointer->1st non-blank char
75633965Sjdp		       * after pseudo-operation.
75733965Sjdp		       */
75833965Sjdp		      (*pop->poc_handler) (pop->poc_val);
75933965Sjdp
76033965Sjdp		      /* If that was .end, just get out now.  */
76133965Sjdp		      if (pop->poc_handler == s_end)
76233965Sjdp			goto quit;
76333965Sjdp		    }
76433965Sjdp		  else
76533965Sjdp		    {
76633965Sjdp		      int inquote = 0;
76733965Sjdp
76833965Sjdp		      /* WARNING: c has char, which may be end-of-line. */
76933965Sjdp		      /* Also: input_line_pointer->`\0` where c was. */
77033965Sjdp		      *input_line_pointer = c;
77133965Sjdp		      while (!is_end_of_line[(unsigned char) *input_line_pointer]
77233965Sjdp			     || inquote
77333965Sjdp#ifdef TC_EOL_IN_INSN
77433965Sjdp			     || TC_EOL_IN_INSN (input_line_pointer)
77533965Sjdp#endif
77633965Sjdp			     )
77733965Sjdp			{
77833965Sjdp			  if (flag_m68k_mri && *input_line_pointer == '\'')
77933965Sjdp			    inquote = ! inquote;
78033965Sjdp			  input_line_pointer++;
78133965Sjdp			}
78233965Sjdp
78333965Sjdp		      c = *input_line_pointer;
78433965Sjdp		      *input_line_pointer = '\0';
78533965Sjdp
78633965Sjdp#ifdef OBJ_GENERATE_ASM_LINENO
78733965Sjdp		      if (generate_asm_lineno == 0)
78833965Sjdp			{
78933965Sjdp		          if (ecoff_no_current_file ())
79033965Sjdp			    generate_asm_lineno = 1;
79133965Sjdp			}
79233965Sjdp		      if (generate_asm_lineno == 1)
79333965Sjdp		        {
79433965Sjdp			  unsigned int lineno;
79533965Sjdp			  char *s;
79633965Sjdp
79733965Sjdp			  as_where (&s, &lineno);
79833965Sjdp			  OBJ_GENERATE_ASM_LINENO (s, lineno);
79933965Sjdp		        }
80033965Sjdp#endif
80133965Sjdp
80233965Sjdp		      if (macro_defined)
80333965Sjdp			{
80433965Sjdp			  sb out;
80533965Sjdp			  const char *err;
80633965Sjdp
80733965Sjdp			  if (check_macro (s, &out, '\0', &err))
80833965Sjdp			    {
80933965Sjdp			      if (err != NULL)
81033965Sjdp				as_bad (err);
81133965Sjdp			      *input_line_pointer++ = c;
81233965Sjdp			      input_scrub_include_sb (&out,
81333965Sjdp						      input_line_pointer);
81433965Sjdp			      sb_kill (&out);
81533965Sjdp			      buffer_limit =
81633965Sjdp				input_scrub_next_buffer (&input_line_pointer);
81733965Sjdp			      continue;
81833965Sjdp			    }
81933965Sjdp			}
82033965Sjdp
82133965Sjdp		      if (mri_pending_align)
82233965Sjdp			{
82333965Sjdp			  do_align (1, (char *) NULL, 0, 0);
82433965Sjdp			  mri_pending_align = 0;
82533965Sjdp			  if (line_label != NULL)
82633965Sjdp			    {
82733965Sjdp			      line_label->sy_frag = frag_now;
82833965Sjdp			      S_SET_VALUE (line_label, frag_now_fix ());
82933965Sjdp			    }
83033965Sjdp			}
83133965Sjdp
83233965Sjdp		      md_assemble (s);	/* Assemble 1 instruction. */
83333965Sjdp
83433965Sjdp		      *input_line_pointer++ = c;
83533965Sjdp
83633965Sjdp		      /* We resume loop AFTER the end-of-line from
83733965Sjdp			 this instruction. */
83833965Sjdp		    }		/* if (*s=='.') */
83933965Sjdp		}		/* if c==':' */
84033965Sjdp	      continue;
84133965Sjdp	    }			/* if (is_name_beginner(c) */
84233965Sjdp
84333965Sjdp
84433965Sjdp	  /* Empty statement?  */
84533965Sjdp	  if (is_end_of_line[(unsigned char) c])
84633965Sjdp	    continue;
84733965Sjdp
84833965Sjdp	  if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB)
84933965Sjdp	      && isdigit (c))
85033965Sjdp	    {
85133965Sjdp	      /* local label  ("4:") */
85233965Sjdp	      char *backup = input_line_pointer;
85333965Sjdp
85433965Sjdp	      HANDLE_CONDITIONAL_ASSEMBLY ();
85533965Sjdp
85633965Sjdp	      temp = c - '0';
85733965Sjdp
85833965Sjdp	      while (isdigit (*input_line_pointer))
85933965Sjdp		{
86033965Sjdp		  temp = (temp * 10) + *input_line_pointer - '0';
86133965Sjdp		  ++input_line_pointer;
86233965Sjdp		}		/* read the whole number */
86333965Sjdp
86433965Sjdp	      if (LOCAL_LABELS_DOLLAR
86533965Sjdp		  && *input_line_pointer == '$'
86633965Sjdp		  && *(input_line_pointer + 1) == ':')
86733965Sjdp		{
86833965Sjdp		  input_line_pointer += 2;
86933965Sjdp
87033965Sjdp		  if (dollar_label_defined (temp))
87133965Sjdp		    {
87233965Sjdp		      as_fatal ("label \"%d$\" redefined", temp);
87333965Sjdp		    }
87433965Sjdp
87533965Sjdp		  define_dollar_label (temp);
87633965Sjdp		  colon (dollar_label_name (temp, 0));
87733965Sjdp		  continue;
87833965Sjdp		}
87933965Sjdp
88033965Sjdp	      if (LOCAL_LABELS_FB
88133965Sjdp		  && *input_line_pointer++ == ':')
88233965Sjdp		{
88333965Sjdp		  fb_label_instance_inc (temp);
88433965Sjdp		  colon (fb_label_name (temp, 0));
88533965Sjdp		  continue;
88633965Sjdp		}
88733965Sjdp
88833965Sjdp	      input_line_pointer = backup;
88933965Sjdp	    }			/* local label  ("4:") */
89033965Sjdp
89133965Sjdp	  if (c && strchr (line_comment_chars, c))
89233965Sjdp	    {			/* Its a comment.  Better say APP or NO_APP */
89333965Sjdp	      char *ends;
89433965Sjdp	      char *new_buf;
89533965Sjdp	      char *new_tmp;
89633965Sjdp	      unsigned int new_length;
89733965Sjdp	      char *tmp_buf = 0;
89833965Sjdp
89933965Sjdp	      bump_line_counters ();
90033965Sjdp	      s = input_line_pointer;
90133965Sjdp	      if (strncmp (s, "APP\n", 4))
90233965Sjdp		continue;	/* We ignore it */
90333965Sjdp	      s += 4;
90433965Sjdp
90533965Sjdp	      ends = strstr (s, "#NO_APP\n");
90633965Sjdp
90733965Sjdp	      if (!ends)
90833965Sjdp		{
90933965Sjdp		  unsigned int tmp_len;
91033965Sjdp		  unsigned int num;
91133965Sjdp
91233965Sjdp		  /* The end of the #APP wasn't in this buffer.  We
91333965Sjdp		     keep reading in buffers until we find the #NO_APP
91433965Sjdp		     that goes with this #APP  There is one.  The specs
91533965Sjdp		     guarentee it. . . */
91633965Sjdp		  tmp_len = buffer_limit - s;
91733965Sjdp		  tmp_buf = xmalloc (tmp_len + 1);
91833965Sjdp		  memcpy (tmp_buf, s, tmp_len);
91933965Sjdp		  do
92033965Sjdp		    {
92133965Sjdp		      new_tmp = input_scrub_next_buffer (&buffer);
92233965Sjdp		      if (!new_tmp)
92333965Sjdp			break;
92433965Sjdp		      else
92533965Sjdp			buffer_limit = new_tmp;
92633965Sjdp		      input_line_pointer = buffer;
92733965Sjdp		      ends = strstr (buffer, "#NO_APP\n");
92833965Sjdp		      if (ends)
92933965Sjdp			num = ends - buffer;
93033965Sjdp		      else
93133965Sjdp			num = buffer_limit - buffer;
93233965Sjdp
93333965Sjdp		      tmp_buf = xrealloc (tmp_buf, tmp_len + num);
93433965Sjdp		      memcpy (tmp_buf + tmp_len, buffer, num);
93533965Sjdp		      tmp_len += num;
93633965Sjdp		    }
93733965Sjdp		  while (!ends);
93833965Sjdp
93933965Sjdp		  input_line_pointer = ends ? ends + 8 : NULL;
94033965Sjdp
94133965Sjdp		  s = tmp_buf;
94233965Sjdp		  ends = s + tmp_len;
94333965Sjdp
94433965Sjdp		}
94533965Sjdp	      else
94633965Sjdp		{
94733965Sjdp		  input_line_pointer = ends + 8;
94833965Sjdp		}
94933965Sjdp
95033965Sjdp	      scrub_string = s;
95133965Sjdp	      scrub_string_end = ends;
95233965Sjdp
95333965Sjdp	      new_length = ends - s;
95433965Sjdp	      new_buf = (char *) xmalloc (new_length);
95533965Sjdp	      new_tmp = new_buf;
95633965Sjdp	      for (;;)
95733965Sjdp		{
95833965Sjdp		  int space;
95933965Sjdp		  int size;
96033965Sjdp
96133965Sjdp		  space = (new_buf + new_length) - new_tmp;
96233965Sjdp		  size = do_scrub_chars (scrub_from_string, new_tmp, space);
96333965Sjdp
96433965Sjdp		  if (size < space)
96533965Sjdp		    {
96633965Sjdp		      new_tmp += size;
96733965Sjdp		      break;
96833965Sjdp		    }
96933965Sjdp
97033965Sjdp		  new_buf = xrealloc (new_buf, new_length + 100);
97133965Sjdp		  new_tmp = new_buf + new_length;
97233965Sjdp		  new_length += 100;
97333965Sjdp		}
97433965Sjdp
97533965Sjdp	      if (tmp_buf)
97633965Sjdp		free (tmp_buf);
97733965Sjdp	      old_buffer = buffer;
97833965Sjdp	      old_input = input_line_pointer;
97933965Sjdp	      old_limit = buffer_limit;
98033965Sjdp	      buffer = new_buf;
98133965Sjdp	      input_line_pointer = new_buf;
98233965Sjdp	      buffer_limit = new_tmp;
98333965Sjdp	      continue;
98433965Sjdp	    }
98533965Sjdp
98633965Sjdp	  HANDLE_CONDITIONAL_ASSEMBLY ();
98733965Sjdp
98833965Sjdp#ifdef tc_unrecognized_line
98933965Sjdp	  if (tc_unrecognized_line (c))
99033965Sjdp	    continue;
99133965Sjdp#endif
99233965Sjdp
99333965Sjdp	  /* as_warn("Junk character %d.",c);  Now done by ignore_rest */
99433965Sjdp	  input_line_pointer--;	/* Report unknown char as ignored. */
99533965Sjdp	  ignore_rest_of_line ();
99633965Sjdp	}			/* while (input_line_pointer<buffer_limit) */
99733965Sjdp
99833965Sjdp#ifdef md_after_pass_hook
99933965Sjdp      md_after_pass_hook ();
100033965Sjdp#endif
100133965Sjdp
100233965Sjdp      if (old_buffer)
100333965Sjdp	{
100433965Sjdp	  free (buffer);
100533965Sjdp	  bump_line_counters ();
100633965Sjdp	  if (old_input != 0)
100733965Sjdp	    {
100833965Sjdp	      buffer = old_buffer;
100933965Sjdp	      input_line_pointer = old_input;
101033965Sjdp	      buffer_limit = old_limit;
101133965Sjdp	      old_buffer = 0;
101233965Sjdp	      goto contin;
101333965Sjdp	    }
101433965Sjdp	}
101533965Sjdp    }				/* while (more buffers to scan) */
101633965Sjdp
101733965Sjdp quit:
101833965Sjdp
101933965Sjdp#ifdef md_cleanup
102033965Sjdp  md_cleanup();
102133965Sjdp#endif
102233965Sjdp  input_scrub_close ();		/* Close the input file */
102333965Sjdp}
102433965Sjdp
102533965Sjdp/* For most MRI pseudo-ops, the line actually ends at the first
102633965Sjdp   nonquoted space.  This function looks for that point, stuffs a null
102733965Sjdp   in, and sets *STOPCP to the character that used to be there, and
102833965Sjdp   returns the location.
102933965Sjdp
103033965Sjdp   Until I hear otherwise, I am going to assume that this is only true
103133965Sjdp   for the m68k MRI assembler.  */
103233965Sjdp
103333965Sjdpchar *
103433965Sjdpmri_comment_field (stopcp)
103533965Sjdp     char *stopcp;
103633965Sjdp{
103733965Sjdp#ifdef TC_M68K
103833965Sjdp
103933965Sjdp  char *s;
104033965Sjdp  int inquote = 0;
104133965Sjdp
104233965Sjdp  know (flag_m68k_mri);
104333965Sjdp
104433965Sjdp  for (s = input_line_pointer;
104533965Sjdp       ((! is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t')
104633965Sjdp	|| inquote);
104733965Sjdp       s++)
104833965Sjdp    {
104933965Sjdp      if (*s == '\'')
105033965Sjdp	inquote = ! inquote;
105133965Sjdp    }
105233965Sjdp  *stopcp = *s;
105333965Sjdp  *s = '\0';
105433965Sjdp  return s;
105533965Sjdp
105633965Sjdp#else
105733965Sjdp
105833965Sjdp  char *s;
105933965Sjdp
106033965Sjdp  for (s = input_line_pointer; ! is_end_of_line[(unsigned char) *s]; s++)
106133965Sjdp    ;
106233965Sjdp  *stopcp = *s;
106333965Sjdp  *s = '\0';
106433965Sjdp  return s;
106533965Sjdp
106633965Sjdp#endif
106733965Sjdp
106833965Sjdp}
106933965Sjdp
107033965Sjdp/* Skip to the end of an MRI comment field.  */
107133965Sjdp
107233965Sjdpvoid
107333965Sjdpmri_comment_end (stop, stopc)
107433965Sjdp     char *stop;
107533965Sjdp     int stopc;
107633965Sjdp{
107733965Sjdp  know (flag_mri);
107833965Sjdp
107933965Sjdp  input_line_pointer = stop;
108033965Sjdp  *stop = stopc;
108133965Sjdp  while (! is_end_of_line[(unsigned char) *input_line_pointer])
108233965Sjdp    ++input_line_pointer;
108333965Sjdp}
108433965Sjdp
108533965Sjdpvoid
108633965Sjdps_abort (ignore)
108733965Sjdp     int ignore;
108833965Sjdp{
108933965Sjdp  as_fatal (".abort detected.  Abandoning ship.");
109033965Sjdp}
109133965Sjdp
109233965Sjdp/* Guts of .align directive.  N is the power of two to which to align.
109333965Sjdp   FILL may be NULL, or it may point to the bytes of the fill pattern.
109433965Sjdp   LEN is the length of whatever FILL points to, if anything.  MAX is
109533965Sjdp   the maximum number of characters to skip when doing the alignment,
109633965Sjdp   or 0 if there is no maximum.  */
109733965Sjdp
109833965Sjdpstatic void
109933965Sjdpdo_align (n, fill, len, max)
110033965Sjdp     int n;
110133965Sjdp     char *fill;
110233965Sjdp     int len;
110333965Sjdp     int max;
110433965Sjdp{
110533965Sjdp  char default_fill;
110633965Sjdp
110733965Sjdp#ifdef md_do_align
110833965Sjdp  md_do_align (n, fill, len, max, just_record_alignment);
110933965Sjdp#endif
111033965Sjdp
111133965Sjdp  if (fill == NULL)
111233965Sjdp    {
111333965Sjdp      /* FIXME: Fix this right for BFD!  */
111433965Sjdp      if (now_seg != data_section && now_seg != bss_section)
111533965Sjdp	default_fill = NOP_OPCODE;
111633965Sjdp      else
111733965Sjdp	default_fill = 0;
111833965Sjdp      fill = &default_fill;
111933965Sjdp      len = 1;
112033965Sjdp    }
112133965Sjdp
112233965Sjdp  /* Only make a frag if we HAVE to. . . */
112333965Sjdp  if (n != 0 && !need_pass_2)
112433965Sjdp    {
112533965Sjdp      if (len <= 1)
112633965Sjdp	frag_align (n, *fill, max);
112733965Sjdp      else
112833965Sjdp	frag_align_pattern (n, fill, len, max);
112933965Sjdp    }
113033965Sjdp
113133965Sjdp#ifdef md_do_align
113233965Sjdp just_record_alignment:
113333965Sjdp#endif
113433965Sjdp
113533965Sjdp  record_alignment (now_seg, n);
113633965Sjdp}
113733965Sjdp
113833965Sjdp/* Handle the .align pseudo-op.  A positive ARG is a default alignment
113933965Sjdp   (in bytes).  A negative ARG is the negative of the length of the
114033965Sjdp   fill pattern.  BYTES_P is non-zero if the alignment value should be
114133965Sjdp   interpreted as the byte boundary, rather than the power of 2.  */
114233965Sjdp
114333965Sjdpstatic void
114433965Sjdps_align (arg, bytes_p)
114533965Sjdp     int arg;
114633965Sjdp     int bytes_p;
114733965Sjdp{
114833965Sjdp  register unsigned int align;
114933965Sjdp  char *stop = NULL;
115033965Sjdp  char stopc;
115133965Sjdp  offsetT fill = 0;
115233965Sjdp  int max;
115333965Sjdp  int fill_p;
115433965Sjdp
115533965Sjdp  if (flag_mri)
115633965Sjdp    stop = mri_comment_field (&stopc);
115733965Sjdp
115833965Sjdp  if (is_end_of_line[(unsigned char) *input_line_pointer])
115933965Sjdp    {
116033965Sjdp      if (arg < 0)
116133965Sjdp	align = 0;
116233965Sjdp      else
116333965Sjdp	align = arg;	/* Default value from pseudo-op table */
116433965Sjdp    }
116533965Sjdp  else
116633965Sjdp    {
116733965Sjdp      align = get_absolute_expression ();
116833965Sjdp      SKIP_WHITESPACE ();
116933965Sjdp    }
117033965Sjdp
117133965Sjdp  if (bytes_p)
117233965Sjdp    {
117333965Sjdp      /* Convert to a power of 2.  */
117433965Sjdp      if (align != 0)
117533965Sjdp	{
117633965Sjdp	  unsigned int i;
117733965Sjdp
117833965Sjdp	  for (i = 0; (align & 1) == 0; align >>= 1, ++i)
117933965Sjdp	    ;
118033965Sjdp	  if (align != 1)
118133965Sjdp	    as_bad ("Alignment not a power of 2");
118233965Sjdp	  align = i;
118333965Sjdp	}
118433965Sjdp    }
118533965Sjdp
118633965Sjdp  if (align > 15)
118733965Sjdp    {
118833965Sjdp      align = 15;
118933965Sjdp      as_bad ("Alignment too large: %u assumed", align);
119033965Sjdp    }
119133965Sjdp
119233965Sjdp  if (*input_line_pointer != ',')
119333965Sjdp    {
119433965Sjdp      fill_p = 0;
119533965Sjdp      max = 0;
119633965Sjdp    }
119733965Sjdp  else
119833965Sjdp    {
119933965Sjdp      ++input_line_pointer;
120033965Sjdp      if (*input_line_pointer == ',')
120133965Sjdp	fill_p = 0;
120233965Sjdp      else
120333965Sjdp	{
120433965Sjdp	  fill = get_absolute_expression ();
120533965Sjdp	  SKIP_WHITESPACE ();
120633965Sjdp	  fill_p = 1;
120733965Sjdp	}
120833965Sjdp
120933965Sjdp      if (*input_line_pointer != ',')
121033965Sjdp	max = 0;
121133965Sjdp      else
121233965Sjdp	{
121333965Sjdp	  ++input_line_pointer;
121433965Sjdp	  max = get_absolute_expression ();
121533965Sjdp	}
121633965Sjdp    }
121733965Sjdp
121833965Sjdp  if (! fill_p)
121933965Sjdp    {
122033965Sjdp      if (arg < 0)
122133965Sjdp	as_warn ("expected fill pattern missing");
122233965Sjdp      do_align (align, (char *) NULL, 0, max);
122333965Sjdp    }
122433965Sjdp  else
122533965Sjdp    {
122633965Sjdp      int fill_len;
122733965Sjdp
122833965Sjdp      if (arg >= 0)
122933965Sjdp	fill_len = 1;
123033965Sjdp      else
123133965Sjdp	fill_len = - arg;
123233965Sjdp      if (fill_len <= 1)
123333965Sjdp	{
123433965Sjdp	  char fill_char;
123533965Sjdp
123633965Sjdp	  fill_char = fill;
123733965Sjdp	  do_align (align, &fill_char, fill_len, max);
123833965Sjdp	}
123933965Sjdp      else
124033965Sjdp	{
124133965Sjdp	  char ab[16];
124233965Sjdp
124333965Sjdp	  if (fill_len > sizeof ab)
124433965Sjdp	    abort ();
124533965Sjdp	  md_number_to_chars (ab, fill, fill_len);
124633965Sjdp	  do_align (align, ab, fill_len, max);
124733965Sjdp	}
124833965Sjdp    }
124933965Sjdp
125033965Sjdp  if (flag_mri)
125133965Sjdp    mri_comment_end (stop, stopc);
125233965Sjdp
125333965Sjdp  demand_empty_rest_of_line ();
125433965Sjdp}
125533965Sjdp
125633965Sjdp/* Handle the .align pseudo-op on machines where ".align 4" means
125733965Sjdp   align to a 4 byte boundary.  */
125833965Sjdp
125933965Sjdpvoid
126033965Sjdps_align_bytes (arg)
126133965Sjdp     int arg;
126233965Sjdp{
126333965Sjdp  s_align (arg, 1);
126433965Sjdp}
126533965Sjdp
126633965Sjdp/* Handle the .align pseud-op on machines where ".align 4" means align
126733965Sjdp   to a 2**4 boundary.  */
126833965Sjdp
126933965Sjdpvoid
127033965Sjdps_align_ptwo (arg)
127133965Sjdp     int arg;
127233965Sjdp{
127333965Sjdp  s_align (arg, 0);
127433965Sjdp}
127533965Sjdp
127633965Sjdpvoid
127733965Sjdps_comm (ignore)
127833965Sjdp     int ignore;
127933965Sjdp{
128033965Sjdp  register char *name;
128133965Sjdp  register char c;
128233965Sjdp  register char *p;
128333965Sjdp  offsetT temp;
128433965Sjdp  register symbolS *symbolP;
128533965Sjdp  char *stop = NULL;
128633965Sjdp  char stopc;
128733965Sjdp
128833965Sjdp  if (flag_mri)
128933965Sjdp    stop = mri_comment_field (&stopc);
129033965Sjdp
129133965Sjdp  name = input_line_pointer;
129233965Sjdp  c = get_symbol_end ();
129333965Sjdp  /* just after name is now '\0' */
129433965Sjdp  p = input_line_pointer;
129533965Sjdp  *p = c;
129633965Sjdp  SKIP_WHITESPACE ();
129733965Sjdp  if (*input_line_pointer != ',')
129833965Sjdp    {
129933965Sjdp      as_bad ("Expected comma after symbol-name: rest of line ignored.");
130033965Sjdp      if (flag_mri)
130133965Sjdp	mri_comment_end (stop, stopc);
130233965Sjdp      ignore_rest_of_line ();
130333965Sjdp      return;
130433965Sjdp    }
130533965Sjdp  input_line_pointer++;		/* skip ',' */
130633965Sjdp  if ((temp = get_absolute_expression ()) < 0)
130733965Sjdp    {
130833965Sjdp      as_warn (".COMMon length (%ld.) <0! Ignored.", (long) temp);
130933965Sjdp      if (flag_mri)
131033965Sjdp	mri_comment_end (stop, stopc);
131133965Sjdp      ignore_rest_of_line ();
131233965Sjdp      return;
131333965Sjdp    }
131433965Sjdp  *p = 0;
131533965Sjdp  symbolP = symbol_find_or_make (name);
131633965Sjdp  *p = c;
131733965Sjdp  if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
131833965Sjdp    {
131933965Sjdp      as_bad ("Ignoring attempt to re-define symbol `%s'.",
132033965Sjdp	      S_GET_NAME (symbolP));
132133965Sjdp      if (flag_mri)
132233965Sjdp	mri_comment_end (stop, stopc);
132333965Sjdp      ignore_rest_of_line ();
132433965Sjdp      return;
132533965Sjdp    }
132633965Sjdp  if (S_GET_VALUE (symbolP))
132733965Sjdp    {
132833965Sjdp      if (S_GET_VALUE (symbolP) != (valueT) temp)
132933965Sjdp	as_bad ("Length of .comm \"%s\" is already %ld. Not changed to %ld.",
133033965Sjdp		S_GET_NAME (symbolP),
133133965Sjdp		(long) S_GET_VALUE (symbolP),
133233965Sjdp		(long) temp);
133333965Sjdp    }
133433965Sjdp  else
133533965Sjdp    {
133633965Sjdp      S_SET_VALUE (symbolP, (valueT) temp);
133733965Sjdp      S_SET_EXTERNAL (symbolP);
133833965Sjdp    }
133933965Sjdp#ifdef OBJ_VMS
134033965Sjdp  {
134133965Sjdp    extern int flag_one;
134233965Sjdp    if ( (!temp) || !flag_one)
134333965Sjdp      S_GET_OTHER(symbolP) = const_flag;
134433965Sjdp  }
134533965Sjdp#endif /* not OBJ_VMS */
134633965Sjdp  know (symbolP->sy_frag == &zero_address_frag);
134733965Sjdp
134833965Sjdp  if (flag_mri)
134933965Sjdp    mri_comment_end (stop, stopc);
135033965Sjdp
135133965Sjdp  demand_empty_rest_of_line ();
135233965Sjdp}				/* s_comm() */
135333965Sjdp
135433965Sjdp/* The MRI COMMON pseudo-op.  We handle this by creating a common
135533965Sjdp   symbol with the appropriate name.  We make s_space do the right
135633965Sjdp   thing by increasing the size.  */
135733965Sjdp
135833965Sjdpvoid
135933965Sjdps_mri_common (small)
136033965Sjdp     int small;
136133965Sjdp{
136233965Sjdp  char *name;
136333965Sjdp  char c;
136433965Sjdp  char *alc = NULL;
136533965Sjdp  symbolS *sym;
136633965Sjdp  offsetT align;
136733965Sjdp  char *stop = NULL;
136833965Sjdp  char stopc;
136933965Sjdp
137033965Sjdp  if (! flag_mri)
137133965Sjdp    {
137233965Sjdp      s_comm (0);
137333965Sjdp      return;
137433965Sjdp    }
137533965Sjdp
137633965Sjdp  stop = mri_comment_field (&stopc);
137733965Sjdp
137833965Sjdp  SKIP_WHITESPACE ();
137933965Sjdp
138033965Sjdp  name = input_line_pointer;
138133965Sjdp  if (! isdigit ((unsigned char) *name))
138233965Sjdp    c = get_symbol_end ();
138333965Sjdp  else
138433965Sjdp    {
138533965Sjdp      do
138633965Sjdp	{
138733965Sjdp	  ++input_line_pointer;
138833965Sjdp	}
138933965Sjdp      while (isdigit ((unsigned char) *input_line_pointer));
139033965Sjdp      c = *input_line_pointer;
139133965Sjdp      *input_line_pointer = '\0';
139233965Sjdp
139333965Sjdp      if (line_label != NULL)
139433965Sjdp	{
139533965Sjdp	  alc = (char *) xmalloc (strlen (S_GET_NAME (line_label))
139633965Sjdp				  + (input_line_pointer - name)
139733965Sjdp				  + 1);
139833965Sjdp	  sprintf (alc, "%s%s", name, S_GET_NAME (line_label));
139933965Sjdp	  name = alc;
140033965Sjdp	}
140133965Sjdp    }
140233965Sjdp
140333965Sjdp  sym = symbol_find_or_make (name);
140433965Sjdp  *input_line_pointer = c;
140533965Sjdp  if (alc != NULL)
140633965Sjdp    free (alc);
140733965Sjdp
140833965Sjdp  if (*input_line_pointer != ',')
140933965Sjdp    align = 0;
141033965Sjdp  else
141133965Sjdp    {
141233965Sjdp      ++input_line_pointer;
141333965Sjdp      align = get_absolute_expression ();
141433965Sjdp    }
141533965Sjdp
141633965Sjdp  if (S_IS_DEFINED (sym) && ! S_IS_COMMON (sym))
141733965Sjdp    {
141833965Sjdp      as_bad ("attempt to re-define symbol `%s'", S_GET_NAME (sym));
141933965Sjdp      mri_comment_end (stop, stopc);
142033965Sjdp      ignore_rest_of_line ();
142133965Sjdp      return;
142233965Sjdp    }
142333965Sjdp
142433965Sjdp  S_SET_EXTERNAL (sym);
142533965Sjdp  mri_common_symbol = sym;
142633965Sjdp
142733965Sjdp#ifdef S_SET_ALIGN
142833965Sjdp  if (align != 0)
142933965Sjdp    S_SET_ALIGN (sym, align);
143033965Sjdp#endif
143133965Sjdp
143233965Sjdp  if (line_label != NULL)
143333965Sjdp    {
143433965Sjdp      line_label->sy_value.X_op = O_symbol;
143533965Sjdp      line_label->sy_value.X_add_symbol = sym;
143633965Sjdp      line_label->sy_value.X_add_number = S_GET_VALUE (sym);
143733965Sjdp      line_label->sy_frag = &zero_address_frag;
143833965Sjdp      S_SET_SEGMENT (line_label, expr_section);
143933965Sjdp    }
144033965Sjdp
144133965Sjdp  /* FIXME: We just ignore the small argument, which distinguishes
144233965Sjdp     COMMON and COMMON.S.  I don't know what we can do about it.  */
144333965Sjdp
144433965Sjdp  /* Ignore the type and hptype.  */
144533965Sjdp  if (*input_line_pointer == ',')
144633965Sjdp    input_line_pointer += 2;
144733965Sjdp  if (*input_line_pointer == ',')
144833965Sjdp    input_line_pointer += 2;
144933965Sjdp
145033965Sjdp  mri_comment_end (stop, stopc);
145133965Sjdp
145233965Sjdp  demand_empty_rest_of_line ();
145333965Sjdp}
145433965Sjdp
145533965Sjdpvoid
145633965Sjdps_data (ignore)
145733965Sjdp     int ignore;
145833965Sjdp{
145933965Sjdp  segT section;
146033965Sjdp  register int temp;
146133965Sjdp
146233965Sjdp  temp = get_absolute_expression ();
146333965Sjdp  if (flag_readonly_data_in_text)
146433965Sjdp    {
146533965Sjdp      section = text_section;
146633965Sjdp      temp += 1000;
146733965Sjdp    }
146833965Sjdp  else
146933965Sjdp    section = data_section;
147033965Sjdp
147133965Sjdp  subseg_set (section, (subsegT) temp);
147233965Sjdp
147333965Sjdp#ifdef OBJ_VMS
147433965Sjdp  const_flag = 0;
147533965Sjdp#endif
147633965Sjdp  demand_empty_rest_of_line ();
147733965Sjdp}
147833965Sjdp
147933965Sjdp/* Handle the .appfile pseudo-op.  This is automatically generated by
148033965Sjdp   do_scrub_chars when a preprocessor # line comment is seen with a
148133965Sjdp   file name.  This default definition may be overridden by the object
148233965Sjdp   or CPU specific pseudo-ops.  This function is also the default
148333965Sjdp   definition for .file; the APPFILE argument is 1 for .appfile, 0 for
148433965Sjdp   .file.  */
148533965Sjdp
148633965Sjdpvoid
148733965Sjdps_app_file (appfile)
148833965Sjdp     int appfile;
148933965Sjdp{
149033965Sjdp  register char *s;
149133965Sjdp  int length;
149233965Sjdp
149333965Sjdp  /* Some assemblers tolerate immediately following '"' */
149433965Sjdp  if ((s = demand_copy_string (&length)) != 0)
149533965Sjdp    {
149633965Sjdp      /* If this is a fake .appfile, a fake newline was inserted into
149733965Sjdp	 the buffer.  Passing -2 to new_logical_line tells it to
149833965Sjdp	 account for it.  */
149933965Sjdp      new_logical_line (s, appfile ? -2 : -1);
150033965Sjdp
150133965Sjdp      /* In MRI mode, the preprocessor may have inserted an extraneous
150233965Sjdp         backquote.  */
150333965Sjdp      if (flag_m68k_mri
150433965Sjdp	  && *input_line_pointer == '\''
150533965Sjdp	  && is_end_of_line[(unsigned char) input_line_pointer[1]])
150633965Sjdp	++input_line_pointer;
150733965Sjdp
150833965Sjdp      demand_empty_rest_of_line ();
150933965Sjdp#ifdef LISTING
151033965Sjdp      if (listing)
151133965Sjdp	listing_source_file (s);
151233965Sjdp#endif
151333965Sjdp    }
151433965Sjdp#ifdef obj_app_file
151533965Sjdp  obj_app_file (s);
151633965Sjdp#endif
151733965Sjdp}
151833965Sjdp
151933965Sjdp/* Handle the .appline pseudo-op.  This is automatically generated by
152033965Sjdp   do_scrub_chars when a preprocessor # line comment is seen.  This
152133965Sjdp   default definition may be overridden by the object or CPU specific
152233965Sjdp   pseudo-ops.  */
152333965Sjdp
152433965Sjdpvoid
152533965Sjdps_app_line (ignore)
152633965Sjdp     int ignore;
152733965Sjdp{
152833965Sjdp  int l;
152933965Sjdp
153033965Sjdp  /* The given number is that of the next line.  */
153133965Sjdp  l = get_absolute_expression () - 1;
153233965Sjdp  if (l < 0)
153333965Sjdp    /* Some of the back ends can't deal with non-positive line numbers.
153433965Sjdp       Besides, it's silly.  */
153533965Sjdp    as_warn ("Line numbers must be positive; line number %d rejected.", l+1);
153633965Sjdp  else
153733965Sjdp    {
153833965Sjdp      new_logical_line ((char *) NULL, l);
153933965Sjdp#ifdef LISTING
154033965Sjdp      if (listing)
154133965Sjdp	listing_source_line (l);
154233965Sjdp#endif
154333965Sjdp    }
154433965Sjdp  demand_empty_rest_of_line ();
154533965Sjdp}
154633965Sjdp
154733965Sjdp/* Handle the .end pseudo-op.  Actually, the real work is done in
154833965Sjdp   read_a_source_file.  */
154933965Sjdp
155033965Sjdpvoid
155133965Sjdps_end (ignore)
155233965Sjdp     int ignore;
155333965Sjdp{
155433965Sjdp  if (flag_mri)
155533965Sjdp    {
155633965Sjdp      /* The MRI assembler permits the start symbol to follow .end,
155733965Sjdp         but we don't support that.  */
155833965Sjdp      SKIP_WHITESPACE ();
155933965Sjdp      if (! is_end_of_line[(unsigned char) *input_line_pointer]
156033965Sjdp	  && *input_line_pointer != '*'
156133965Sjdp	  && *input_line_pointer != '!')
156233965Sjdp	as_warn ("start address not supported");
156333965Sjdp    }
156433965Sjdp}
156533965Sjdp
156633965Sjdp/* Handle the .err pseudo-op.  */
156733965Sjdp
156833965Sjdpvoid
156933965Sjdps_err (ignore)
157033965Sjdp     int ignore;
157133965Sjdp{
157233965Sjdp  as_bad (".err encountered");
157333965Sjdp  demand_empty_rest_of_line ();
157433965Sjdp}
157533965Sjdp
157633965Sjdp/* Handle the MRI fail pseudo-op.  */
157733965Sjdp
157833965Sjdpvoid
157933965Sjdps_fail (ignore)
158033965Sjdp     int ignore;
158133965Sjdp{
158233965Sjdp  offsetT temp;
158333965Sjdp  char *stop = NULL;
158433965Sjdp  char stopc;
158533965Sjdp
158633965Sjdp  if (flag_mri)
158733965Sjdp    stop = mri_comment_field (&stopc);
158833965Sjdp
158933965Sjdp  temp = get_absolute_expression ();
159033965Sjdp  if (temp >= 500)
159133965Sjdp    as_warn (".fail %ld encountered", (long) temp);
159233965Sjdp  else
159333965Sjdp    as_bad (".fail %ld encountered", (long) temp);
159433965Sjdp
159533965Sjdp  if (flag_mri)
159633965Sjdp    mri_comment_end (stop, stopc);
159733965Sjdp
159833965Sjdp  demand_empty_rest_of_line ();
159933965Sjdp}
160033965Sjdp
160133965Sjdpvoid
160233965Sjdps_fill (ignore)
160333965Sjdp     int ignore;
160433965Sjdp{
160533965Sjdp  long temp_repeat = 0;
160633965Sjdp  long temp_size = 1;
160733965Sjdp  register long temp_fill = 0;
160833965Sjdp  char *p;
160933965Sjdp
161033965Sjdp#ifdef md_flush_pending_output
161133965Sjdp  md_flush_pending_output ();
161233965Sjdp#endif
161333965Sjdp
161433965Sjdp  temp_repeat = get_absolute_expression ();
161533965Sjdp  if (*input_line_pointer == ',')
161633965Sjdp    {
161733965Sjdp      input_line_pointer++;
161833965Sjdp      temp_size = get_absolute_expression ();
161933965Sjdp      if (*input_line_pointer == ',')
162033965Sjdp	{
162133965Sjdp	  input_line_pointer++;
162233965Sjdp	  temp_fill = get_absolute_expression ();
162333965Sjdp	}
162433965Sjdp    }
162533965Sjdp  /* This is to be compatible with BSD 4.2 AS, not for any rational reason.  */
162633965Sjdp#define BSD_FILL_SIZE_CROCK_8 (8)
162733965Sjdp  if (temp_size > BSD_FILL_SIZE_CROCK_8)
162833965Sjdp    {
162933965Sjdp      as_warn (".fill size clamped to %d.", BSD_FILL_SIZE_CROCK_8);
163033965Sjdp      temp_size = BSD_FILL_SIZE_CROCK_8;
163133965Sjdp    }
163233965Sjdp  if (temp_size < 0)
163333965Sjdp    {
163433965Sjdp      as_warn ("Size negative: .fill ignored.");
163533965Sjdp      temp_size = 0;
163633965Sjdp    }
163733965Sjdp  else if (temp_repeat <= 0)
163833965Sjdp    {
163933965Sjdp      if (temp_repeat < 0)
164033965Sjdp	as_warn ("Repeat < 0, .fill ignored");
164133965Sjdp      temp_size = 0;
164233965Sjdp    }
164333965Sjdp
164433965Sjdp  if (temp_size && !need_pass_2)
164533965Sjdp    {
164633965Sjdp      p = frag_var (rs_fill, (int) temp_size, (int) temp_size,
164733965Sjdp		    (relax_substateT) 0, (symbolS *) 0, (offsetT) temp_repeat,
164833965Sjdp		    (char *) 0);
164933965Sjdp      memset (p, 0, (unsigned int) temp_size);
165033965Sjdp      /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX
165133965Sjdp       * flavoured AS.  The following bizzare behaviour is to be
165233965Sjdp       * compatible with above.  I guess they tried to take up to 8
165333965Sjdp       * bytes from a 4-byte expression and they forgot to sign
165433965Sjdp       * extend. Un*x Sux. */
165533965Sjdp#define BSD_FILL_SIZE_CROCK_4 (4)
165633965Sjdp      md_number_to_chars (p, (valueT) temp_fill,
165733965Sjdp			  (temp_size > BSD_FILL_SIZE_CROCK_4
165833965Sjdp			   ? BSD_FILL_SIZE_CROCK_4
165933965Sjdp			   : (int) temp_size));
166033965Sjdp      /* Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes)
166133965Sjdp       * but emits no error message because it seems a legal thing to do.
166233965Sjdp       * It is a degenerate case of .fill but could be emitted by a compiler.
166333965Sjdp       */
166433965Sjdp    }
166533965Sjdp  demand_empty_rest_of_line ();
166633965Sjdp}
166733965Sjdp
166833965Sjdpvoid
166933965Sjdps_globl (ignore)
167033965Sjdp     int ignore;
167133965Sjdp{
167233965Sjdp  char *name;
167333965Sjdp  int c;
167433965Sjdp  symbolS *symbolP;
167533965Sjdp  char *stop = NULL;
167633965Sjdp  char stopc;
167733965Sjdp
167833965Sjdp  if (flag_mri)
167933965Sjdp    stop = mri_comment_field (&stopc);
168033965Sjdp
168133965Sjdp  do
168233965Sjdp    {
168333965Sjdp      name = input_line_pointer;
168433965Sjdp      c = get_symbol_end ();
168533965Sjdp      symbolP = symbol_find_or_make (name);
168633965Sjdp      *input_line_pointer = c;
168733965Sjdp      SKIP_WHITESPACE ();
168833965Sjdp      S_SET_EXTERNAL (symbolP);
168933965Sjdp      if (c == ',')
169033965Sjdp	{
169133965Sjdp	  input_line_pointer++;
169233965Sjdp	  SKIP_WHITESPACE ();
169333965Sjdp	  if (*input_line_pointer == '\n')
169433965Sjdp	    c = '\n';
169533965Sjdp	}
169633965Sjdp    }
169733965Sjdp  while (c == ',');
169833965Sjdp
169933965Sjdp  if (flag_mri)
170033965Sjdp    mri_comment_end (stop, stopc);
170133965Sjdp
170233965Sjdp  demand_empty_rest_of_line ();
170333965Sjdp}
170433965Sjdp
170533965Sjdp/* Handle the MRI IRP and IRPC pseudo-ops.  */
170633965Sjdp
170733965Sjdpvoid
170833965Sjdps_irp (irpc)
170933965Sjdp     int irpc;
171033965Sjdp{
171133965Sjdp  char *file;
171233965Sjdp  unsigned int line;
171333965Sjdp  sb s;
171433965Sjdp  const char *err;
171533965Sjdp  sb out;
171633965Sjdp
171733965Sjdp  as_where (&file, &line);
171833965Sjdp
171933965Sjdp  sb_new (&s);
172033965Sjdp  while (! is_end_of_line[(unsigned char) *input_line_pointer])
172133965Sjdp    sb_add_char (&s, *input_line_pointer++);
172233965Sjdp
172333965Sjdp  sb_new (&out);
172433965Sjdp
172533965Sjdp  err = expand_irp (irpc, 0, &s, &out, get_line_sb, '\0');
172633965Sjdp  if (err != NULL)
172733965Sjdp    as_bad_where (file, line, "%s", err);
172833965Sjdp
172933965Sjdp  sb_kill (&s);
173033965Sjdp
173133965Sjdp  input_scrub_include_sb (&out, input_line_pointer);
173233965Sjdp  sb_kill (&out);
173333965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
173433965Sjdp}
173533965Sjdp
173633965Sjdp/* Handle the .linkonce pseudo-op.  This tells the assembler to mark
173733965Sjdp   the section to only be linked once.  However, this is not supported
173833965Sjdp   by most object file formats.  This takes an optional argument,
173933965Sjdp   which is what to do about duplicates.  */
174033965Sjdp
174133965Sjdpvoid
174233965Sjdps_linkonce (ignore)
174333965Sjdp     int ignore;
174433965Sjdp{
174533965Sjdp  enum linkonce_type type;
174633965Sjdp
174733965Sjdp  SKIP_WHITESPACE ();
174833965Sjdp
174933965Sjdp  type = LINKONCE_DISCARD;
175033965Sjdp
175133965Sjdp  if (! is_end_of_line[(unsigned char) *input_line_pointer])
175233965Sjdp    {
175333965Sjdp      char *s;
175433965Sjdp      char c;
175533965Sjdp
175633965Sjdp      s = input_line_pointer;
175733965Sjdp      c = get_symbol_end ();
175833965Sjdp      if (strcasecmp (s, "discard") == 0)
175933965Sjdp	type = LINKONCE_DISCARD;
176033965Sjdp      else if (strcasecmp (s, "one_only") == 0)
176133965Sjdp	type = LINKONCE_ONE_ONLY;
176233965Sjdp      else if (strcasecmp (s, "same_size") == 0)
176333965Sjdp	type = LINKONCE_SAME_SIZE;
176433965Sjdp      else if (strcasecmp (s, "same_contents") == 0)
176533965Sjdp	type = LINKONCE_SAME_CONTENTS;
176633965Sjdp      else
176733965Sjdp	as_warn ("unrecognized .linkonce type `%s'", s);
176833965Sjdp
176933965Sjdp      *input_line_pointer = c;
177033965Sjdp    }
177133965Sjdp
177233965Sjdp#ifdef obj_handle_link_once
177333965Sjdp  obj_handle_link_once (type);
177433965Sjdp#else /* ! defined (obj_handle_link_once) */
177533965Sjdp#ifdef BFD_ASSEMBLER
177633965Sjdp  {
177733965Sjdp    flagword flags;
177833965Sjdp
177933965Sjdp    if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0)
178033965Sjdp      as_warn (".linkonce is not supported for this object file format");
178133965Sjdp
178233965Sjdp    flags = bfd_get_section_flags (stdoutput, now_seg);
178333965Sjdp    flags |= SEC_LINK_ONCE;
178433965Sjdp    switch (type)
178533965Sjdp      {
178633965Sjdp      default:
178733965Sjdp	abort ();
178833965Sjdp      case LINKONCE_DISCARD:
178933965Sjdp	flags |= SEC_LINK_DUPLICATES_DISCARD;
179033965Sjdp	break;
179133965Sjdp      case LINKONCE_ONE_ONLY:
179233965Sjdp	flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
179333965Sjdp	break;
179433965Sjdp      case LINKONCE_SAME_SIZE:
179533965Sjdp	flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
179633965Sjdp	break;
179733965Sjdp      case LINKONCE_SAME_CONTENTS:
179833965Sjdp	flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
179933965Sjdp	break;
180033965Sjdp      }
180133965Sjdp    if (! bfd_set_section_flags (stdoutput, now_seg, flags))
180233965Sjdp      as_bad ("bfd_set_section_flags: %s",
180333965Sjdp	      bfd_errmsg (bfd_get_error ()));
180433965Sjdp  }
180533965Sjdp#else /* ! defined (BFD_ASSEMBLER) */
180633965Sjdp  as_warn (".linkonce is not supported for this object file format");
180733965Sjdp#endif /* ! defined (BFD_ASSEMBLER) */
180833965Sjdp#endif /* ! defined (obj_handle_link_once) */
180933965Sjdp
181033965Sjdp  demand_empty_rest_of_line ();
181133965Sjdp}
181233965Sjdp
181333965Sjdpvoid
181433965Sjdps_lcomm (needs_align)
181533965Sjdp     /* 1 if this was a ".bss" directive, which may require a 3rd argument
181633965Sjdp	(alignment); 0 if it was an ".lcomm" (2 args only)  */
181733965Sjdp     int needs_align;
181833965Sjdp{
181933965Sjdp  register char *name;
182033965Sjdp  register char c;
182133965Sjdp  register char *p;
182233965Sjdp  register int temp;
182333965Sjdp  register symbolS *symbolP;
182433965Sjdp  segT current_seg = now_seg;
182533965Sjdp  subsegT current_subseg = now_subseg;
182633965Sjdp  const int max_alignment = 15;
182733965Sjdp  int align = 0;
182833965Sjdp  segT bss_seg = bss_section;
182933965Sjdp
183033965Sjdp  name = input_line_pointer;
183133965Sjdp  c = get_symbol_end ();
183233965Sjdp  p = input_line_pointer;
183333965Sjdp  *p = c;
183433965Sjdp  SKIP_WHITESPACE ();
183533965Sjdp
183633965Sjdp  /* Accept an optional comma after the name.  The comma used to be
183733965Sjdp     required, but Irix 5 cc does not generate it.  */
183833965Sjdp  if (*input_line_pointer == ',')
183933965Sjdp    {
184033965Sjdp      ++input_line_pointer;
184133965Sjdp      SKIP_WHITESPACE ();
184233965Sjdp    }
184333965Sjdp
184433965Sjdp  if (*input_line_pointer == '\n')
184533965Sjdp    {
184633965Sjdp      as_bad ("Missing size expression");
184733965Sjdp      return;
184833965Sjdp    }
184933965Sjdp
185033965Sjdp  if ((temp = get_absolute_expression ()) < 0)
185133965Sjdp    {
185233965Sjdp      as_warn ("BSS length (%d.) <0! Ignored.", temp);
185333965Sjdp      ignore_rest_of_line ();
185433965Sjdp      return;
185533965Sjdp    }
185633965Sjdp
185733965Sjdp#if defined (TC_MIPS) || defined (TC_ALPHA)
185833965Sjdp  if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
185933965Sjdp      || OUTPUT_FLAVOR == bfd_target_elf_flavour)
186033965Sjdp    {
186133965Sjdp      /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss.  */
186233965Sjdp      if (temp <= bfd_get_gp_size (stdoutput))
186333965Sjdp	{
186433965Sjdp	  bss_seg = subseg_new (".sbss", 1);
186533965Sjdp	  seg_info (bss_seg)->bss = 1;
186633965Sjdp#ifdef BFD_ASSEMBLER
186733965Sjdp	  if (! bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
186833965Sjdp	    as_warn ("error setting flags for \".sbss\": %s",
186933965Sjdp		     bfd_errmsg (bfd_get_error ()));
187033965Sjdp#endif
187133965Sjdp	}
187233965Sjdp    }
187333965Sjdp#endif
187433965Sjdp   if (!needs_align)
187533965Sjdp     {
187633965Sjdp       /* FIXME. This needs to be machine independent. */
187733965Sjdp       if (temp >= 8)
187833965Sjdp	 align = 3;
187933965Sjdp       else if (temp >= 4)
188033965Sjdp	 align = 2;
188133965Sjdp       else if (temp >= 2)
188233965Sjdp	 align = 1;
188333965Sjdp       else
188433965Sjdp	 align = 0;
188533965Sjdp
188633965Sjdp#ifdef OBJ_EVAX
188733965Sjdp       /* FIXME: This needs to be done in a more general fashion.  */
188833965Sjdp       align = 3;
188933965Sjdp#endif
189033965Sjdp
189133965Sjdp       record_alignment(bss_seg, align);
189233965Sjdp     }
189333965Sjdp
189433965Sjdp  if (needs_align)
189533965Sjdp    {
189633965Sjdp      align = 0;
189733965Sjdp      SKIP_WHITESPACE ();
189833965Sjdp      if (*input_line_pointer != ',')
189933965Sjdp	{
190033965Sjdp	  as_bad ("Expected comma after size");
190133965Sjdp	  ignore_rest_of_line ();
190233965Sjdp	  return;
190333965Sjdp	}
190433965Sjdp      input_line_pointer++;
190533965Sjdp      SKIP_WHITESPACE ();
190633965Sjdp      if (*input_line_pointer == '\n')
190733965Sjdp	{
190833965Sjdp	  as_bad ("Missing alignment");
190933965Sjdp	  return;
191033965Sjdp	}
191133965Sjdp      align = get_absolute_expression ();
191233965Sjdp      if (align > max_alignment)
191333965Sjdp	{
191433965Sjdp	  align = max_alignment;
191533965Sjdp	  as_warn ("Alignment too large: %d. assumed.", align);
191633965Sjdp	}
191733965Sjdp      else if (align < 0)
191833965Sjdp	{
191933965Sjdp	  align = 0;
192033965Sjdp	  as_warn ("Alignment negative. 0 assumed.");
192133965Sjdp	}
192233965Sjdp      record_alignment (bss_seg, align);
192333965Sjdp    }				/* if needs align */
192433965Sjdp  else
192533965Sjdp    {
192633965Sjdp      /* Assume some objects may require alignment on some systems.  */
192733965Sjdp#if defined (TC_ALPHA) && ! defined (VMS)
192833965Sjdp      if (temp > 1)
192933965Sjdp	{
193033965Sjdp	  align = ffs (temp) - 1;
193133965Sjdp	  if (temp % (1 << align))
193233965Sjdp	    abort ();
193333965Sjdp	}
193433965Sjdp#endif
193533965Sjdp    }
193633965Sjdp
193733965Sjdp  *p = 0;
193833965Sjdp  symbolP = symbol_find_or_make (name);
193933965Sjdp  *p = c;
194033965Sjdp
194133965Sjdp  if (
194233965Sjdp#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
194333965Sjdp       S_GET_OTHER (symbolP) == 0 &&
194433965Sjdp       S_GET_DESC (symbolP) == 0 &&
194533965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
194633965Sjdp       (S_GET_SEGMENT (symbolP) == bss_seg
194733965Sjdp	|| (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
194833965Sjdp    {
194933965Sjdp      char *pfrag;
195033965Sjdp
195133965Sjdp      subseg_set (bss_seg, 1);
195233965Sjdp
195333965Sjdp      if (align)
195433965Sjdp	frag_align (align, 0, 0);
195533965Sjdp					/* detach from old frag	*/
195633965Sjdp      if (S_GET_SEGMENT (symbolP) == bss_seg)
195733965Sjdp	symbolP->sy_frag->fr_symbol = NULL;
195833965Sjdp
195933965Sjdp      symbolP->sy_frag = frag_now;
196033965Sjdp      pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
196133965Sjdp			(offsetT) temp, (char *) 0);
196233965Sjdp      *pfrag = 0;
196333965Sjdp
196433965Sjdp      S_SET_SEGMENT (symbolP, bss_seg);
196533965Sjdp
196633965Sjdp#ifdef OBJ_COFF
196733965Sjdp      /* The symbol may already have been created with a preceding
196833965Sjdp         ".globl" directive -- be careful not to step on storage class
196933965Sjdp         in that case.  Otherwise, set it to static. */
197033965Sjdp      if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
197133965Sjdp	{
197233965Sjdp	  S_SET_STORAGE_CLASS (symbolP, C_STAT);
197333965Sjdp	}
197433965Sjdp#endif /* OBJ_COFF */
197533965Sjdp
197633965Sjdp#ifdef S_SET_SIZE
197733965Sjdp      S_SET_SIZE (symbolP, temp);
197833965Sjdp#endif
197933965Sjdp    }
198033965Sjdp  else
198133965Sjdp    as_bad ("Ignoring attempt to re-define symbol `%s'.",
198233965Sjdp	    S_GET_NAME (symbolP));
198333965Sjdp
198433965Sjdp  subseg_set (current_seg, current_subseg);
198533965Sjdp
198633965Sjdp  demand_empty_rest_of_line ();
198733965Sjdp}				/* s_lcomm() */
198833965Sjdp
198933965Sjdpvoid
199033965Sjdps_lsym (ignore)
199133965Sjdp     int ignore;
199233965Sjdp{
199333965Sjdp  register char *name;
199433965Sjdp  register char c;
199533965Sjdp  register char *p;
199633965Sjdp  expressionS exp;
199733965Sjdp  register symbolS *symbolP;
199833965Sjdp
199933965Sjdp  /* we permit ANY defined expression: BSD4.2 demands constants */
200033965Sjdp  name = input_line_pointer;
200133965Sjdp  c = get_symbol_end ();
200233965Sjdp  p = input_line_pointer;
200333965Sjdp  *p = c;
200433965Sjdp  SKIP_WHITESPACE ();
200533965Sjdp  if (*input_line_pointer != ',')
200633965Sjdp    {
200733965Sjdp      *p = 0;
200833965Sjdp      as_bad ("Expected comma after name \"%s\"", name);
200933965Sjdp      *p = c;
201033965Sjdp      ignore_rest_of_line ();
201133965Sjdp      return;
201233965Sjdp    }
201333965Sjdp  input_line_pointer++;
201433965Sjdp  expression (&exp);
201533965Sjdp  if (exp.X_op != O_constant
201633965Sjdp      && exp.X_op != O_register)
201733965Sjdp    {
201833965Sjdp      as_bad ("bad expression");
201933965Sjdp      ignore_rest_of_line ();
202033965Sjdp      return;
202133965Sjdp    }
202233965Sjdp  *p = 0;
202333965Sjdp  symbolP = symbol_find_or_make (name);
202433965Sjdp
202533965Sjdp  /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0 &&
202633965Sjdp     symbolP->sy_desc == 0) out of this test because coff doesn't have
202733965Sjdp     those fields, and I can't see when they'd ever be tripped.  I
202833965Sjdp     don't think I understand why they were here so I may have
202933965Sjdp     introduced a bug. As recently as 1.37 didn't have this test
203033965Sjdp     anyway.  xoxorich. */
203133965Sjdp
203233965Sjdp  if (S_GET_SEGMENT (symbolP) == undefined_section
203333965Sjdp      && S_GET_VALUE (symbolP) == 0)
203433965Sjdp    {
203533965Sjdp      /* The name might be an undefined .global symbol; be sure to
203633965Sjdp	 keep the "external" bit. */
203733965Sjdp      S_SET_SEGMENT (symbolP,
203833965Sjdp		     (exp.X_op == O_constant
203933965Sjdp		      ? absolute_section
204033965Sjdp		      : reg_section));
204133965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
204233965Sjdp    }
204333965Sjdp  else
204433965Sjdp    {
204533965Sjdp      as_bad ("Symbol %s already defined", name);
204633965Sjdp    }
204733965Sjdp  *p = c;
204833965Sjdp  demand_empty_rest_of_line ();
204933965Sjdp}				/* s_lsym() */
205033965Sjdp
205133965Sjdp/* Read a line into an sb.  */
205233965Sjdp
205333965Sjdpstatic int
205433965Sjdpget_line_sb (line)
205533965Sjdp     sb *line;
205633965Sjdp{
205733965Sjdp  char quote1, quote2, inquote;
205833965Sjdp
205933965Sjdp  if (input_line_pointer[-1] == '\n')
206033965Sjdp    bump_line_counters ();
206133965Sjdp
206233965Sjdp  if (input_line_pointer >= buffer_limit)
206333965Sjdp    {
206433965Sjdp      buffer_limit = input_scrub_next_buffer (&input_line_pointer);
206533965Sjdp      if (buffer_limit == 0)
206633965Sjdp	return 0;
206733965Sjdp    }
206833965Sjdp
206933965Sjdp  /* If app.c sets any other characters to LEX_IS_STRINGQUOTE, this
207033965Sjdp     code needs to be changed.  */
207133965Sjdp  if (! flag_m68k_mri)
207233965Sjdp    quote1 = '"';
207333965Sjdp  else
207433965Sjdp    quote1 = '\0';
207533965Sjdp
207633965Sjdp  quote2 = '\0';
207733965Sjdp  if (flag_m68k_mri)
207833965Sjdp    quote2 = '\'';
207933965Sjdp#ifdef LEX_IS_STRINGQUOTE
208033965Sjdp  quote2 = '\'';
208133965Sjdp#endif
208233965Sjdp
208333965Sjdp  inquote = '\0';
208433965Sjdp  while (! is_end_of_line[(unsigned char) *input_line_pointer]
208533965Sjdp	 || (inquote != '\0' && *input_line_pointer != '\n'))
208633965Sjdp    {
208733965Sjdp      if (inquote == *input_line_pointer)
208833965Sjdp	inquote = '\0';
208933965Sjdp      else if (inquote == '\0')
209033965Sjdp	{
209133965Sjdp	  if (*input_line_pointer == quote1)
209233965Sjdp	    inquote = quote1;
209333965Sjdp	  else if (*input_line_pointer == quote2)
209433965Sjdp	    inquote = quote2;
209533965Sjdp	}
209633965Sjdp      sb_add_char (line, *input_line_pointer++);
209733965Sjdp    }
209833965Sjdp  while (input_line_pointer < buffer_limit && *input_line_pointer == '\n')
209933965Sjdp    {
210033965Sjdp      if (input_line_pointer[-1] == '\n')
210133965Sjdp	bump_line_counters ();
210233965Sjdp      ++input_line_pointer;
210333965Sjdp    }
210433965Sjdp  return 1;
210533965Sjdp}
210633965Sjdp
210733965Sjdp/* Define a macro.  This is an interface to macro.c, which is shared
210833965Sjdp   between gas and gasp.  */
210933965Sjdp
211033965Sjdpvoid
211133965Sjdps_macro (ignore)
211233965Sjdp     int ignore;
211333965Sjdp{
211433965Sjdp  char *file;
211533965Sjdp  unsigned int line;
211633965Sjdp  sb s;
211733965Sjdp  sb label;
211833965Sjdp  const char *err;
211933965Sjdp  const char *name;
212033965Sjdp
212133965Sjdp  as_where (&file, &line);
212233965Sjdp
212333965Sjdp  sb_new (&s);
212433965Sjdp  while (! is_end_of_line[(unsigned char) *input_line_pointer])
212533965Sjdp    sb_add_char (&s, *input_line_pointer++);
212633965Sjdp
212733965Sjdp  sb_new (&label);
212833965Sjdp  if (line_label != NULL)
212933965Sjdp    sb_add_string (&label, S_GET_NAME (line_label));
213033965Sjdp
213133965Sjdp  err = define_macro (0, &s, &label, get_line_sb, &name);
213233965Sjdp  if (err != NULL)
213333965Sjdp    as_bad_where (file, line, "%s", err);
213433965Sjdp  else
213533965Sjdp    {
213633965Sjdp      if (line_label != NULL)
213733965Sjdp	{
213833965Sjdp	  S_SET_SEGMENT (line_label, undefined_section);
213933965Sjdp	  S_SET_VALUE (line_label, 0);
214033965Sjdp	  line_label->sy_frag = &zero_address_frag;
214133965Sjdp	}
214233965Sjdp
214333965Sjdp      if (((flag_m68k_mri
214433965Sjdp#ifdef NO_PSEUDO_DOT
214533965Sjdp	    || 1
214633965Sjdp#endif
214733965Sjdp	    )
214833965Sjdp	   && hash_find (po_hash, name) != NULL)
214933965Sjdp	  || (! flag_m68k_mri
215033965Sjdp	      && *name == '.'
215133965Sjdp	      && hash_find (po_hash, name + 1) != NULL))
215233965Sjdp	as_warn ("attempt to redefine pseudo-op `%s' ignored",
215333965Sjdp		 name);
215433965Sjdp    }
215533965Sjdp
215633965Sjdp  sb_kill (&s);
215733965Sjdp}
215833965Sjdp
215933965Sjdp/* Handle the .mexit pseudo-op, which immediately exits a macro
216033965Sjdp   expansion.  */
216133965Sjdp
216233965Sjdpvoid
216333965Sjdps_mexit (ignore)
216433965Sjdp     int ignore;
216533965Sjdp{
216633965Sjdp  cond_exit_macro (macro_nest);
216733965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
216833965Sjdp}
216933965Sjdp
217033965Sjdp/* Switch in and out of MRI mode.  */
217133965Sjdp
217233965Sjdpvoid
217333965Sjdps_mri (ignore)
217433965Sjdp     int ignore;
217533965Sjdp{
217633965Sjdp  int on, old_flag;
217733965Sjdp
217833965Sjdp  on = get_absolute_expression ();
217933965Sjdp  old_flag = flag_mri;
218033965Sjdp  if (on != 0)
218133965Sjdp    {
218233965Sjdp      flag_mri = 1;
218333965Sjdp#ifdef TC_M68K
218433965Sjdp      flag_m68k_mri = 1;
218533965Sjdp#endif
218633965Sjdp    }
218733965Sjdp  else
218833965Sjdp    {
218933965Sjdp      flag_mri = 0;
219033965Sjdp      flag_m68k_mri = 0;
219133965Sjdp    }
219233965Sjdp
219333965Sjdp#ifdef MRI_MODE_CHANGE
219433965Sjdp  if (on != old_flag)
219533965Sjdp    MRI_MODE_CHANGE (on);
219633965Sjdp#endif
219733965Sjdp
219833965Sjdp  demand_empty_rest_of_line ();
219933965Sjdp}
220033965Sjdp
220133965Sjdp/* Handle changing the location counter.  */
220233965Sjdp
220333965Sjdpstatic void
220433965Sjdpdo_org (segment, exp, fill)
220533965Sjdp     segT segment;
220633965Sjdp     expressionS *exp;
220733965Sjdp     int fill;
220833965Sjdp{
220933965Sjdp  if (segment != now_seg && segment != absolute_section)
221033965Sjdp    as_bad ("invalid segment \"%s\"; segment \"%s\" assumed",
221133965Sjdp	    segment_name (segment), segment_name (now_seg));
221233965Sjdp
221333965Sjdp  if (now_seg == absolute_section)
221433965Sjdp    {
221533965Sjdp      if (fill != 0)
221633965Sjdp	as_warn ("ignoring fill value in absolute section");
221733965Sjdp      if (exp->X_op != O_constant)
221833965Sjdp	{
221933965Sjdp	  as_bad ("only constant offsets supported in absolute section");
222033965Sjdp	  exp->X_add_number = 0;
222133965Sjdp	}
222233965Sjdp      abs_section_offset = exp->X_add_number;
222333965Sjdp    }
222433965Sjdp  else
222533965Sjdp    {
222633965Sjdp      char *p;
222733965Sjdp
222833965Sjdp      p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp->X_add_symbol,
222933965Sjdp		    exp->X_add_number, (char *) NULL);
223033965Sjdp      *p = fill;
223133965Sjdp    }
223233965Sjdp}
223333965Sjdp
223433965Sjdpvoid
223533965Sjdps_org (ignore)
223633965Sjdp     int ignore;
223733965Sjdp{
223833965Sjdp  register segT segment;
223933965Sjdp  expressionS exp;
224033965Sjdp  register long temp_fill;
224133965Sjdp
224233965Sjdp  /* The m68k MRI assembler has a different meaning for .org.  It
224333965Sjdp     means to create an absolute section at a given address.  We can't
224433965Sjdp     support that--use a linker script instead.  */
224533965Sjdp  if (flag_m68k_mri)
224633965Sjdp    {
224733965Sjdp      as_bad ("MRI style ORG pseudo-op not supported");
224833965Sjdp      ignore_rest_of_line ();
224933965Sjdp      return;
225033965Sjdp    }
225133965Sjdp
225233965Sjdp  /* Don't believe the documentation of BSD 4.2 AS.  There is no such
225333965Sjdp     thing as a sub-segment-relative origin.  Any absolute origin is
225433965Sjdp     given a warning, then assumed to be segment-relative.  Any
225533965Sjdp     segmented origin expression ("foo+42") had better be in the right
225633965Sjdp     segment or the .org is ignored.
225733965Sjdp
225833965Sjdp     BSD 4.2 AS warns if you try to .org backwards. We cannot because
225933965Sjdp     we never know sub-segment sizes when we are reading code.  BSD
226033965Sjdp     will crash trying to emit negative numbers of filler bytes in
226133965Sjdp     certain .orgs. We don't crash, but see as-write for that code.
226233965Sjdp
226333965Sjdp     Don't make frag if need_pass_2==1.  */
226433965Sjdp  segment = get_known_segmented_expression (&exp);
226533965Sjdp  if (*input_line_pointer == ',')
226633965Sjdp    {
226733965Sjdp      input_line_pointer++;
226833965Sjdp      temp_fill = get_absolute_expression ();
226933965Sjdp    }
227033965Sjdp  else
227133965Sjdp    temp_fill = 0;
227233965Sjdp
227333965Sjdp  if (!need_pass_2)
227433965Sjdp    do_org (segment, &exp, temp_fill);
227533965Sjdp
227633965Sjdp  demand_empty_rest_of_line ();
227733965Sjdp}				/* s_org() */
227833965Sjdp
227933965Sjdp/* Handle parsing for the MRI SECT/SECTION pseudo-op.  This should be
228033965Sjdp   called by the obj-format routine which handles section changing
228133965Sjdp   when in MRI mode.  It will create a new section, and return it.  It
228233965Sjdp   will set *TYPE to the section type: one of 'C' (code), 'D' (data),
228333965Sjdp   'M' (mixed), or 'R' (romable).  If BFD_ASSEMBLER is defined, the
228433965Sjdp   flags will be set in the section.  */
228533965Sjdp
228633965Sjdpvoid
228733965Sjdps_mri_sect (type)
228833965Sjdp     char *type;
228933965Sjdp{
229033965Sjdp#ifdef TC_M68K
229133965Sjdp
229233965Sjdp  char *name;
229333965Sjdp  char c;
229433965Sjdp  segT seg;
229533965Sjdp
229633965Sjdp  SKIP_WHITESPACE ();
229733965Sjdp
229833965Sjdp  name = input_line_pointer;
229933965Sjdp  if (! isdigit ((unsigned char) *name))
230033965Sjdp    c = get_symbol_end ();
230133965Sjdp  else
230233965Sjdp    {
230333965Sjdp      do
230433965Sjdp	{
230533965Sjdp	  ++input_line_pointer;
230633965Sjdp	}
230733965Sjdp      while (isdigit ((unsigned char) *input_line_pointer));
230833965Sjdp      c = *input_line_pointer;
230933965Sjdp      *input_line_pointer = '\0';
231033965Sjdp    }
231133965Sjdp
231233965Sjdp  name = xstrdup (name);
231333965Sjdp
231433965Sjdp  *input_line_pointer = c;
231533965Sjdp
231633965Sjdp  seg = subseg_new (name, 0);
231733965Sjdp
231833965Sjdp  if (*input_line_pointer == ',')
231933965Sjdp    {
232033965Sjdp      int align;
232133965Sjdp
232233965Sjdp      ++input_line_pointer;
232333965Sjdp      align = get_absolute_expression ();
232433965Sjdp      record_alignment (seg, align);
232533965Sjdp    }
232633965Sjdp
232733965Sjdp  *type = 'C';
232833965Sjdp  if (*input_line_pointer == ',')
232933965Sjdp    {
233033965Sjdp      c = *++input_line_pointer;
233133965Sjdp      c = toupper ((unsigned char) c);
233233965Sjdp      if (c == 'C' || c == 'D' || c == 'M' || c == 'R')
233333965Sjdp	*type = c;
233433965Sjdp      else
233533965Sjdp	as_bad ("unrecognized section type");
233633965Sjdp      ++input_line_pointer;
233733965Sjdp
233833965Sjdp#ifdef BFD_ASSEMBLER
233933965Sjdp      {
234033965Sjdp	flagword flags;
234133965Sjdp
234233965Sjdp	flags = SEC_NO_FLAGS;
234333965Sjdp	if (*type == 'C')
234433965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE;
234533965Sjdp	else if (*type == 'D' || *type == 'M')
234633965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_DATA;
234733965Sjdp	else if (*type == 'R')
234833965Sjdp	  flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM;
234933965Sjdp	if (flags != SEC_NO_FLAGS)
235033965Sjdp	  {
235133965Sjdp	    if (! bfd_set_section_flags (stdoutput, seg, flags))
235233965Sjdp	      as_warn ("error setting flags for \"%s\": %s",
235333965Sjdp		       bfd_section_name (stdoutput, seg),
235433965Sjdp		       bfd_errmsg (bfd_get_error ()));
235533965Sjdp	  }
235633965Sjdp      }
235733965Sjdp#endif
235833965Sjdp    }
235933965Sjdp
236033965Sjdp  /* Ignore the HP type.  */
236133965Sjdp  if (*input_line_pointer == ',')
236233965Sjdp    input_line_pointer += 2;
236333965Sjdp
236433965Sjdp  demand_empty_rest_of_line ();
236533965Sjdp
236633965Sjdp#else /* ! TC_M68K */
236733965Sjdp#ifdef TC_I960
236833965Sjdp
236933965Sjdp  char *name;
237033965Sjdp  char c;
237133965Sjdp  segT seg;
237233965Sjdp
237333965Sjdp  SKIP_WHITESPACE ();
237433965Sjdp
237533965Sjdp  name = input_line_pointer;
237633965Sjdp  c = get_symbol_end ();
237733965Sjdp
237833965Sjdp  name = xstrdup (name);
237933965Sjdp
238033965Sjdp  *input_line_pointer = c;
238133965Sjdp
238233965Sjdp  seg = subseg_new (name, 0);
238333965Sjdp
238433965Sjdp  if (*input_line_pointer != ',')
238533965Sjdp    *type = 'C';
238633965Sjdp  else
238733965Sjdp    {
238833965Sjdp      char *sectype;
238933965Sjdp
239033965Sjdp      ++input_line_pointer;
239133965Sjdp      SKIP_WHITESPACE ();
239233965Sjdp      sectype = input_line_pointer;
239333965Sjdp      c = get_symbol_end ();
239433965Sjdp      if (*sectype == '\0')
239533965Sjdp	*type = 'C';
239633965Sjdp      else if (strcasecmp (sectype, "text") == 0)
239733965Sjdp	*type = 'C';
239833965Sjdp      else if (strcasecmp (sectype, "data") == 0)
239933965Sjdp	*type = 'D';
240033965Sjdp      else if (strcasecmp (sectype, "romdata") == 0)
240133965Sjdp	*type = 'R';
240233965Sjdp      else
240333965Sjdp	as_warn ("unrecognized section type `%s'", sectype);
240433965Sjdp      *input_line_pointer = c;
240533965Sjdp    }
240633965Sjdp
240733965Sjdp  if (*input_line_pointer == ',')
240833965Sjdp    {
240933965Sjdp      char *seccmd;
241033965Sjdp
241133965Sjdp      ++input_line_pointer;
241233965Sjdp      SKIP_WHITESPACE ();
241333965Sjdp      seccmd = input_line_pointer;
241433965Sjdp      c = get_symbol_end ();
241533965Sjdp      if (strcasecmp (seccmd, "absolute") == 0)
241633965Sjdp	{
241733965Sjdp	  as_bad ("absolute sections are not supported");
241833965Sjdp	  *input_line_pointer = c;
241933965Sjdp	  ignore_rest_of_line ();
242033965Sjdp	  return;
242133965Sjdp	}
242233965Sjdp      else if (strcasecmp (seccmd, "align") == 0)
242333965Sjdp	{
242433965Sjdp	  int align;
242533965Sjdp
242633965Sjdp	  *input_line_pointer = c;
242733965Sjdp	  align = get_absolute_expression ();
242833965Sjdp	  record_alignment (seg, align);
242933965Sjdp	}
243033965Sjdp      else
243133965Sjdp	{
243233965Sjdp	  as_warn ("unrecognized section command `%s'", seccmd);
243333965Sjdp	  *input_line_pointer = c;
243433965Sjdp	}
243533965Sjdp    }
243633965Sjdp
243733965Sjdp  demand_empty_rest_of_line ();
243833965Sjdp
243933965Sjdp#else /* ! TC_I960 */
244033965Sjdp  /* The MRI assembler seems to use different forms of .sect for
244133965Sjdp     different targets.  */
244233965Sjdp  abort ();
244333965Sjdp#endif /* ! TC_I960 */
244433965Sjdp#endif /* ! TC_M68K */
244533965Sjdp}
244633965Sjdp
244733965Sjdp/* Handle the .print pseudo-op.  */
244833965Sjdp
244933965Sjdpvoid
245033965Sjdps_print (ignore)
245133965Sjdp     int ignore;
245233965Sjdp{
245333965Sjdp  char *s;
245433965Sjdp  int len;
245533965Sjdp
245633965Sjdp  s = demand_copy_C_string (&len);
245733965Sjdp  printf ("%s\n", s);
245833965Sjdp  demand_empty_rest_of_line ();
245933965Sjdp}
246033965Sjdp
246133965Sjdp/* Handle the .purgem pseudo-op.  */
246233965Sjdp
246333965Sjdpvoid
246433965Sjdps_purgem (ignore)
246533965Sjdp     int ignore;
246633965Sjdp{
246733965Sjdp  if (is_it_end_of_statement ())
246833965Sjdp    {
246933965Sjdp      demand_empty_rest_of_line ();
247033965Sjdp      return;
247133965Sjdp    }
247233965Sjdp
247333965Sjdp  do
247433965Sjdp    {
247533965Sjdp      char *name;
247633965Sjdp      char c;
247733965Sjdp
247833965Sjdp      SKIP_WHITESPACE ();
247933965Sjdp      name = input_line_pointer;
248033965Sjdp      c = get_symbol_end ();
248133965Sjdp      delete_macro (name);
248233965Sjdp      *input_line_pointer = c;
248333965Sjdp      SKIP_WHITESPACE ();
248433965Sjdp    }
248533965Sjdp  while (*input_line_pointer++ == ',');
248633965Sjdp
248733965Sjdp  --input_line_pointer;
248833965Sjdp  demand_empty_rest_of_line ();
248933965Sjdp}
249033965Sjdp
249133965Sjdp/* Handle the .rept pseudo-op.  */
249233965Sjdp
249333965Sjdpvoid
249433965Sjdps_rept (ignore)
249533965Sjdp     int ignore;
249633965Sjdp{
249733965Sjdp  int count;
249833965Sjdp  sb one;
249933965Sjdp  sb many;
250033965Sjdp
250133965Sjdp  count = get_absolute_expression ();
250233965Sjdp
250333965Sjdp  sb_new (&one);
250433965Sjdp  if (! buffer_and_nest ("REPT", "ENDR", &one, get_line_sb))
250533965Sjdp    {
250633965Sjdp      as_bad ("rept without endr");
250733965Sjdp      return;
250833965Sjdp    }
250933965Sjdp
251033965Sjdp  sb_new (&many);
251133965Sjdp  while (count-- > 0)
251233965Sjdp    sb_add_sb (&many, &one);
251333965Sjdp
251433965Sjdp  sb_kill (&one);
251533965Sjdp
251633965Sjdp  input_scrub_include_sb (&many, input_line_pointer);
251733965Sjdp  sb_kill (&many);
251833965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
251933965Sjdp}
252033965Sjdp
252133965Sjdp/* Handle the .equ, .equiv and .set directives.  If EQUIV is 1, then
252233965Sjdp   this is .equiv, and it is an error if the symbol is already
252333965Sjdp   defined.  */
252433965Sjdp
252533965Sjdpvoid
252633965Sjdps_set (equiv)
252733965Sjdp     int equiv;
252833965Sjdp{
252933965Sjdp  register char *name;
253033965Sjdp  register char delim;
253133965Sjdp  register char *end_name;
253233965Sjdp  register symbolS *symbolP;
253333965Sjdp
253433965Sjdp  /*
253533965Sjdp   * Especial apologies for the random logic:
253633965Sjdp   * this just grew, and could be parsed much more simply!
253733965Sjdp   * Dean in haste.
253833965Sjdp   */
253933965Sjdp  name = input_line_pointer;
254033965Sjdp  delim = get_symbol_end ();
254133965Sjdp  end_name = input_line_pointer;
254233965Sjdp  *end_name = delim;
254333965Sjdp  SKIP_WHITESPACE ();
254433965Sjdp
254533965Sjdp  if (*input_line_pointer != ',')
254633965Sjdp    {
254733965Sjdp      *end_name = 0;
254833965Sjdp      as_bad ("Expected comma after name \"%s\"", name);
254933965Sjdp      *end_name = delim;
255033965Sjdp      ignore_rest_of_line ();
255133965Sjdp      return;
255233965Sjdp    }
255333965Sjdp
255433965Sjdp  input_line_pointer++;
255533965Sjdp  *end_name = 0;
255633965Sjdp
255733965Sjdp  if (name[0] == '.' && name[1] == '\0')
255833965Sjdp    {
255933965Sjdp      /* Turn '. = mumble' into a .org mumble */
256033965Sjdp      register segT segment;
256133965Sjdp      expressionS exp;
256233965Sjdp
256333965Sjdp      segment = get_known_segmented_expression (&exp);
256433965Sjdp
256533965Sjdp      if (!need_pass_2)
256633965Sjdp	do_org (segment, &exp, 0);
256733965Sjdp
256833965Sjdp      *end_name = delim;
256933965Sjdp      return;
257033965Sjdp    }
257133965Sjdp
257233965Sjdp  if ((symbolP = symbol_find (name)) == NULL
257333965Sjdp      && (symbolP = md_undefined_symbol (name)) == NULL)
257433965Sjdp    {
257533965Sjdp      symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
257633965Sjdp#ifdef OBJ_COFF
257733965Sjdp      /* "set" symbols are local unless otherwise specified. */
257833965Sjdp      SF_SET_LOCAL (symbolP);
257933965Sjdp#endif /* OBJ_COFF */
258033965Sjdp
258133965Sjdp    }				/* make a new symbol */
258233965Sjdp
258333965Sjdp  symbol_table_insert (symbolP);
258433965Sjdp
258533965Sjdp  *end_name = delim;
258633965Sjdp
258733965Sjdp  if (equiv
258833965Sjdp      && S_IS_DEFINED (symbolP)
258933965Sjdp      && S_GET_SEGMENT (symbolP) != reg_section)
259033965Sjdp    as_bad ("symbol `%s' already defined", S_GET_NAME (symbolP));
259133965Sjdp
259233965Sjdp  pseudo_set (symbolP);
259333965Sjdp  demand_empty_rest_of_line ();
259433965Sjdp}				/* s_set() */
259533965Sjdp
259633965Sjdpvoid
259733965Sjdps_space (mult)
259833965Sjdp     int mult;
259933965Sjdp{
260033965Sjdp  expressionS exp;
260133965Sjdp  expressionS val;
260233965Sjdp  char *p = 0;
260333965Sjdp  char *stop = NULL;
260433965Sjdp  char stopc;
260533965Sjdp  int bytes;
260633965Sjdp
260733965Sjdp#ifdef md_flush_pending_output
260833965Sjdp  md_flush_pending_output ();
260933965Sjdp#endif
261033965Sjdp
261133965Sjdp  if (flag_mri)
261233965Sjdp    stop = mri_comment_field (&stopc);
261333965Sjdp
261433965Sjdp  /* In m68k MRI mode, we need to align to a word boundary, unless
261533965Sjdp     this is ds.b.  */
261633965Sjdp  if (flag_m68k_mri && mult > 1)
261733965Sjdp    {
261833965Sjdp      if (now_seg == absolute_section)
261933965Sjdp	{
262033965Sjdp	  abs_section_offset += abs_section_offset & 1;
262133965Sjdp	  if (line_label != NULL)
262233965Sjdp	    S_SET_VALUE (line_label, abs_section_offset);
262333965Sjdp	}
262433965Sjdp      else if (mri_common_symbol != NULL)
262533965Sjdp	{
262633965Sjdp	  valueT val;
262733965Sjdp
262833965Sjdp	  val = S_GET_VALUE (mri_common_symbol);
262933965Sjdp	  if ((val & 1) != 0)
263033965Sjdp	    {
263133965Sjdp	      S_SET_VALUE (mri_common_symbol, val + 1);
263233965Sjdp	      if (line_label != NULL)
263333965Sjdp		{
263433965Sjdp		  know (line_label->sy_value.X_op == O_symbol);
263533965Sjdp		  know (line_label->sy_value.X_add_symbol == mri_common_symbol);
263633965Sjdp		  line_label->sy_value.X_add_number += 1;
263733965Sjdp		}
263833965Sjdp	    }
263933965Sjdp	}
264033965Sjdp      else
264133965Sjdp	{
264233965Sjdp	  do_align (1, (char *) NULL, 0, 0);
264333965Sjdp	  if (line_label != NULL)
264433965Sjdp	    {
264533965Sjdp	      line_label->sy_frag = frag_now;
264633965Sjdp	      S_SET_VALUE (line_label, frag_now_fix ());
264733965Sjdp	    }
264833965Sjdp	}
264933965Sjdp    }
265033965Sjdp
265133965Sjdp  bytes = mult;
265233965Sjdp
265333965Sjdp  expression (&exp);
265433965Sjdp
265533965Sjdp  SKIP_WHITESPACE ();
265633965Sjdp  if (*input_line_pointer == ',')
265733965Sjdp    {
265833965Sjdp      ++input_line_pointer;
265933965Sjdp      expression (&val);
266033965Sjdp    }
266133965Sjdp  else
266233965Sjdp    {
266333965Sjdp      val.X_op = O_constant;
266433965Sjdp      val.X_add_number = 0;
266533965Sjdp    }
266633965Sjdp
266733965Sjdp  if (val.X_op != O_constant
266833965Sjdp      || val.X_add_number < - 0x80
266933965Sjdp      || val.X_add_number > 0xff
267033965Sjdp      || (mult != 0 && mult != 1 && val.X_add_number != 0))
267133965Sjdp    {
267233965Sjdp      if (exp.X_op != O_constant)
267333965Sjdp	as_bad ("Unsupported variable size or fill value");
267433965Sjdp      else
267533965Sjdp	{
267633965Sjdp	  offsetT i;
267733965Sjdp
267833965Sjdp	  if (mult == 0)
267933965Sjdp	    mult = 1;
268033965Sjdp	  bytes = mult * exp.X_add_number;
268133965Sjdp	  for (i = 0; i < exp.X_add_number; i++)
268233965Sjdp	    emit_expr (&val, mult);
268333965Sjdp	}
268433965Sjdp    }
268533965Sjdp  else
268633965Sjdp    {
268733965Sjdp      if (exp.X_op == O_constant)
268833965Sjdp	{
268933965Sjdp	  long repeat;
269033965Sjdp
269133965Sjdp	  repeat = exp.X_add_number;
269233965Sjdp	  if (mult)
269333965Sjdp	    repeat *= mult;
269433965Sjdp	  bytes = repeat;
269533965Sjdp	  if (repeat <= 0)
269633965Sjdp	    {
269733965Sjdp	      if (! flag_mri || repeat < 0)
269833965Sjdp		as_warn (".space repeat count is %s, ignored",
269933965Sjdp			 repeat ? "negative" : "zero");
270033965Sjdp	      goto getout;
270133965Sjdp	    }
270233965Sjdp
270333965Sjdp	  /* If we are in the absolute section, just bump the offset.  */
270433965Sjdp	  if (now_seg == absolute_section)
270533965Sjdp	    {
270633965Sjdp	      abs_section_offset += repeat;
270733965Sjdp	      goto getout;
270833965Sjdp	    }
270933965Sjdp
271033965Sjdp	  /* If we are secretly in an MRI common section, then
271133965Sjdp	     creating space just increases the size of the common
271233965Sjdp	     symbol.  */
271333965Sjdp	  if (mri_common_symbol != NULL)
271433965Sjdp	    {
271533965Sjdp	      S_SET_VALUE (mri_common_symbol,
271633965Sjdp			   S_GET_VALUE (mri_common_symbol) + repeat);
271733965Sjdp	      goto getout;
271833965Sjdp	    }
271933965Sjdp
272033965Sjdp	  if (!need_pass_2)
272133965Sjdp	    p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
272233965Sjdp			  (offsetT) repeat, (char *) 0);
272333965Sjdp	}
272433965Sjdp      else
272533965Sjdp	{
272633965Sjdp	  if (now_seg == absolute_section)
272733965Sjdp	    {
272833965Sjdp	      as_bad ("space allocation too complex in absolute section");
272933965Sjdp	      subseg_set (text_section, 0);
273033965Sjdp	    }
273133965Sjdp	  if (mri_common_symbol != NULL)
273233965Sjdp	    {
273333965Sjdp	      as_bad ("space allocation too complex in common section");
273433965Sjdp	      mri_common_symbol = NULL;
273533965Sjdp	    }
273633965Sjdp	  if (!need_pass_2)
273733965Sjdp	    p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
273833965Sjdp			  make_expr_symbol (&exp), (offsetT) 0, (char *) 0);
273933965Sjdp	}
274033965Sjdp
274133965Sjdp      if (p)
274233965Sjdp	*p = val.X_add_number;
274333965Sjdp    }
274433965Sjdp
274533965Sjdp getout:
274633965Sjdp
274733965Sjdp  /* In MRI mode, after an odd number of bytes, we must align to an
274833965Sjdp     even word boundary, unless the next instruction is a dc.b, ds.b
274933965Sjdp     or dcb.b.  */
275033965Sjdp  if (flag_mri && (bytes & 1) != 0)
275133965Sjdp    mri_pending_align = 1;
275233965Sjdp
275333965Sjdp  if (flag_mri)
275433965Sjdp    mri_comment_end (stop, stopc);
275533965Sjdp
275633965Sjdp  demand_empty_rest_of_line ();
275733965Sjdp}
275833965Sjdp
275933965Sjdp/* This is like s_space, but the value is a floating point number with
276033965Sjdp   the given precision.  This is for the MRI dcb.s pseudo-op and
276133965Sjdp   friends.  */
276233965Sjdp
276333965Sjdpvoid
276433965Sjdps_float_space (float_type)
276533965Sjdp     int float_type;
276633965Sjdp{
276733965Sjdp  offsetT count;
276833965Sjdp  int flen;
276933965Sjdp  char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
277033965Sjdp  char *stop = NULL;
277133965Sjdp  char stopc;
277233965Sjdp
277333965Sjdp  if (flag_mri)
277433965Sjdp    stop = mri_comment_field (&stopc);
277533965Sjdp
277633965Sjdp  count = get_absolute_expression ();
277733965Sjdp
277833965Sjdp  SKIP_WHITESPACE ();
277933965Sjdp  if (*input_line_pointer != ',')
278033965Sjdp    {
278133965Sjdp      as_bad ("missing value");
278233965Sjdp      if (flag_mri)
278333965Sjdp	mri_comment_end (stop, stopc);
278433965Sjdp      ignore_rest_of_line ();
278533965Sjdp      return;
278633965Sjdp    }
278733965Sjdp
278833965Sjdp  ++input_line_pointer;
278933965Sjdp
279033965Sjdp  SKIP_WHITESPACE ();
279133965Sjdp
279233965Sjdp  /* Skip any 0{letter} that may be present.  Don't even check if the
279333965Sjdp   * letter is legal.  */
279433965Sjdp  if (input_line_pointer[0] == '0' && isalpha (input_line_pointer[1]))
279533965Sjdp    input_line_pointer += 2;
279633965Sjdp
279733965Sjdp  /* Accept :xxxx, where the x's are hex digits, for a floating point
279833965Sjdp     with the exact digits specified.  */
279933965Sjdp  if (input_line_pointer[0] == ':')
280033965Sjdp    {
280133965Sjdp      flen = hex_float (float_type, temp);
280233965Sjdp      if (flen < 0)
280333965Sjdp	{
280433965Sjdp	  if (flag_mri)
280533965Sjdp	    mri_comment_end (stop, stopc);
280633965Sjdp	  ignore_rest_of_line ();
280733965Sjdp	  return;
280833965Sjdp	}
280933965Sjdp    }
281033965Sjdp  else
281133965Sjdp    {
281233965Sjdp      char *err;
281333965Sjdp
281433965Sjdp      err = md_atof (float_type, temp, &flen);
281533965Sjdp      know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
281633965Sjdp      know (flen > 0);
281733965Sjdp      if (err)
281833965Sjdp	{
281933965Sjdp	  as_bad ("Bad floating literal: %s", err);
282033965Sjdp	  if (flag_mri)
282133965Sjdp	    mri_comment_end (stop, stopc);
282233965Sjdp	  ignore_rest_of_line ();
282333965Sjdp	  return;
282433965Sjdp	}
282533965Sjdp    }
282633965Sjdp
282733965Sjdp  while (--count >= 0)
282833965Sjdp    {
282933965Sjdp      char *p;
283033965Sjdp
283133965Sjdp      p = frag_more (flen);
283233965Sjdp      memcpy (p, temp, (unsigned int) flen);
283333965Sjdp    }
283433965Sjdp
283533965Sjdp  if (flag_mri)
283633965Sjdp    mri_comment_end (stop, stopc);
283733965Sjdp
283833965Sjdp  demand_empty_rest_of_line ();
283933965Sjdp}
284033965Sjdp
284133965Sjdp/* Handle the .struct pseudo-op, as found in MIPS assemblers.  */
284233965Sjdp
284333965Sjdpvoid
284433965Sjdps_struct (ignore)
284533965Sjdp     int ignore;
284633965Sjdp{
284733965Sjdp  char *stop = NULL;
284833965Sjdp  char stopc;
284933965Sjdp
285033965Sjdp  if (flag_mri)
285133965Sjdp    stop = mri_comment_field (&stopc);
285233965Sjdp  abs_section_offset = get_absolute_expression ();
285333965Sjdp  subseg_set (absolute_section, 0);
285433965Sjdp  if (flag_mri)
285533965Sjdp    mri_comment_end (stop, stopc);
285633965Sjdp  demand_empty_rest_of_line ();
285733965Sjdp}
285833965Sjdp
285933965Sjdpvoid
286033965Sjdps_text (ignore)
286133965Sjdp     int ignore;
286233965Sjdp{
286333965Sjdp  register int temp;
286433965Sjdp
286533965Sjdp  temp = get_absolute_expression ();
286633965Sjdp  subseg_set (text_section, (subsegT) temp);
286733965Sjdp  demand_empty_rest_of_line ();
286833965Sjdp#ifdef OBJ_VMS
286933965Sjdp  const_flag &= ~IN_DEFAULT_SECTION;
287033965Sjdp#endif
287133965Sjdp}				/* s_text() */
287233965Sjdp
287333965Sjdp
287433965Sjdpvoid
287533965Sjdpdemand_empty_rest_of_line ()
287633965Sjdp{
287733965Sjdp  SKIP_WHITESPACE ();
287833965Sjdp  if (is_end_of_line[(unsigned char) *input_line_pointer])
287933965Sjdp    {
288033965Sjdp      input_line_pointer++;
288133965Sjdp    }
288233965Sjdp  else
288333965Sjdp    {
288433965Sjdp      ignore_rest_of_line ();
288533965Sjdp    }
288633965Sjdp  /* Return having already swallowed end-of-line. */
288733965Sjdp}				/* Return pointing just after end-of-line. */
288833965Sjdp
288933965Sjdpvoid
289033965Sjdpignore_rest_of_line ()		/* For suspect lines: gives warning. */
289133965Sjdp{
289233965Sjdp  if (!is_end_of_line[(unsigned char) *input_line_pointer])
289333965Sjdp    {
289433965Sjdp      if (isprint (*input_line_pointer))
289533965Sjdp	as_bad ("Rest of line ignored. First ignored character is `%c'.",
289633965Sjdp		*input_line_pointer);
289733965Sjdp      else
289833965Sjdp	as_bad ("Rest of line ignored. First ignored character valued 0x%x.",
289933965Sjdp		*input_line_pointer);
290033965Sjdp      while (input_line_pointer < buffer_limit
290133965Sjdp	     && !is_end_of_line[(unsigned char) *input_line_pointer])
290233965Sjdp	{
290333965Sjdp	  input_line_pointer++;
290433965Sjdp	}
290533965Sjdp    }
290633965Sjdp  input_line_pointer++;		/* Return pointing just after end-of-line. */
290733965Sjdp  know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
290833965Sjdp}
290933965Sjdp
291033965Sjdp/*
291133965Sjdp *			pseudo_set()
291233965Sjdp *
291333965Sjdp * In:	Pointer to a symbol.
291433965Sjdp *	Input_line_pointer->expression.
291533965Sjdp *
291633965Sjdp * Out:	Input_line_pointer->just after any whitespace after expression.
291733965Sjdp *	Tried to set symbol to value of expression.
291833965Sjdp *	Will change symbols type, value, and frag;
291933965Sjdp */
292033965Sjdpvoid
292133965Sjdppseudo_set (symbolP)
292233965Sjdp     symbolS *symbolP;
292333965Sjdp{
292433965Sjdp  expressionS exp;
292533965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
292633965Sjdp  int ext;
292733965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
292833965Sjdp
292933965Sjdp  know (symbolP);		/* NULL pointer is logic error. */
293033965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
293133965Sjdp  ext = S_IS_EXTERNAL (symbolP);
293233965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
293333965Sjdp
293433965Sjdp  (void) expression (&exp);
293533965Sjdp
293633965Sjdp  if (exp.X_op == O_illegal)
293733965Sjdp    as_bad ("illegal expression; zero assumed");
293833965Sjdp  else if (exp.X_op == O_absent)
293933965Sjdp    as_bad ("missing expression; zero assumed");
294033965Sjdp  else if (exp.X_op == O_big)
294133965Sjdp    as_bad ("%s number invalid; zero assumed",
294233965Sjdp	    exp.X_add_number > 0 ? "bignum" : "floating point");
294333965Sjdp  else if (exp.X_op == O_subtract
294433965Sjdp	   && (S_GET_SEGMENT (exp.X_add_symbol)
294533965Sjdp	       == S_GET_SEGMENT (exp.X_op_symbol))
294633965Sjdp	   && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol))
294733965Sjdp	   && exp.X_add_symbol->sy_frag == exp.X_op_symbol->sy_frag)
294833965Sjdp    {
294933965Sjdp      exp.X_op = O_constant;
295033965Sjdp      exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol)
295133965Sjdp			  - S_GET_VALUE (exp.X_op_symbol));
295233965Sjdp    }
295333965Sjdp
295433965Sjdp  switch (exp.X_op)
295533965Sjdp    {
295633965Sjdp    case O_illegal:
295733965Sjdp    case O_absent:
295833965Sjdp    case O_big:
295933965Sjdp      exp.X_add_number = 0;
296033965Sjdp      /* Fall through.  */
296133965Sjdp    case O_constant:
296233965Sjdp      S_SET_SEGMENT (symbolP, absolute_section);
296333965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
296433965Sjdp      if (ext)
296533965Sjdp	S_SET_EXTERNAL (symbolP);
296633965Sjdp      else
296733965Sjdp	S_CLEAR_EXTERNAL (symbolP);
296833965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
296933965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
297033965Sjdp      symbolP->sy_frag = &zero_address_frag;
297133965Sjdp      break;
297233965Sjdp
297333965Sjdp    case O_register:
297433965Sjdp      S_SET_SEGMENT (symbolP, reg_section);
297533965Sjdp      S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
297633965Sjdp      symbolP->sy_frag = &zero_address_frag;
297733965Sjdp      break;
297833965Sjdp
297933965Sjdp    case O_symbol:
298033965Sjdp      if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section
298133965Sjdp	  || exp.X_add_number != 0)
298233965Sjdp	symbolP->sy_value = exp;
298333965Sjdp      else
298433965Sjdp	{
298533965Sjdp	  symbolS *s = exp.X_add_symbol;
298633965Sjdp
298733965Sjdp	  S_SET_SEGMENT (symbolP, S_GET_SEGMENT (s));
298833965Sjdp#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
298933965Sjdp	  if (ext)
299033965Sjdp	    S_SET_EXTERNAL (symbolP);
299133965Sjdp	  else
299233965Sjdp	    S_CLEAR_EXTERNAL (symbolP);
299333965Sjdp#endif /* OBJ_AOUT or OBJ_BOUT */
299433965Sjdp	  S_SET_VALUE (symbolP,
299533965Sjdp		       exp.X_add_number + S_GET_VALUE (s));
299633965Sjdp	  symbolP->sy_frag = s->sy_frag;
299733965Sjdp	  copy_symbol_attributes (symbolP, s);
299833965Sjdp	}
299933965Sjdp      break;
300033965Sjdp
300133965Sjdp    default:
300233965Sjdp      /* The value is some complex expression.
300333965Sjdp	 FIXME: Should we set the segment to anything?  */
300433965Sjdp      symbolP->sy_value = exp;
300533965Sjdp      break;
300633965Sjdp    }
300733965Sjdp}
300833965Sjdp
300933965Sjdp/*
301033965Sjdp *			cons()
301133965Sjdp *
301233965Sjdp * CONStruct more frag of .bytes, or .words etc.
301333965Sjdp * Should need_pass_2 be 1 then emit no frag(s).
301433965Sjdp * This understands EXPRESSIONS.
301533965Sjdp *
301633965Sjdp * Bug (?)
301733965Sjdp *
301833965Sjdp * This has a split personality. We use expression() to read the
301933965Sjdp * value. We can detect if the value won't fit in a byte or word.
302033965Sjdp * But we can't detect if expression() discarded significant digits
302133965Sjdp * in the case of a long. Not worth the crocks required to fix it.
302233965Sjdp */
302333965Sjdp
302433965Sjdp/* Select a parser for cons expressions.  */
302533965Sjdp
302633965Sjdp/* Some targets need to parse the expression in various fancy ways.
302733965Sjdp   You can define TC_PARSE_CONS_EXPRESSION to do whatever you like
302833965Sjdp   (for example, the HPPA does this).  Otherwise, you can define
302933965Sjdp   BITFIELD_CONS_EXPRESSIONS to permit bitfields to be specified, or
303033965Sjdp   REPEAT_CONS_EXPRESSIONS to permit repeat counts.  If none of these
303133965Sjdp   are defined, which is the normal case, then only simple expressions
303233965Sjdp   are permitted.  */
303333965Sjdp
303433965Sjdpstatic void
303533965Sjdpparse_mri_cons PARAMS ((expressionS *exp, unsigned int nbytes));
303633965Sjdp
303733965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION
303833965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS
303933965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES)
304033965Sjdpstatic void
304133965Sjdpparse_bitfield_cons PARAMS ((expressionS *exp, unsigned int nbytes));
304233965Sjdp#endif
304333965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
304433965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES)
304533965Sjdpstatic void
304633965Sjdpparse_repeat_cons PARAMS ((expressionS *exp, unsigned int nbytes));
304733965Sjdp#endif
304833965Sjdp
304933965Sjdp/* If we haven't gotten one yet, just call expression.  */
305033965Sjdp#ifndef TC_PARSE_CONS_EXPRESSION
305133965Sjdp#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP)
305233965Sjdp#endif
305333965Sjdp#endif
305433965Sjdp
305533965Sjdp/* worker to do .byte etc statements */
305633965Sjdp/* clobbers input_line_pointer, checks */
305733965Sjdp/* end-of-line. */
305833965Sjdpstatic void
305933965Sjdpcons_worker (nbytes, rva)
306033965Sjdp     register int nbytes;	/* 1=.byte, 2=.word, 4=.long */
306133965Sjdp     int rva;
306233965Sjdp{
306333965Sjdp  int c;
306433965Sjdp  expressionS exp;
306533965Sjdp  char *stop = NULL;
306633965Sjdp  char stopc;
306733965Sjdp
306833965Sjdp#ifdef md_flush_pending_output
306933965Sjdp  md_flush_pending_output ();
307033965Sjdp#endif
307133965Sjdp
307233965Sjdp  if (flag_mri)
307333965Sjdp    stop = mri_comment_field (&stopc);
307433965Sjdp
307533965Sjdp  if (is_it_end_of_statement ())
307633965Sjdp    {
307733965Sjdp      if (flag_mri)
307833965Sjdp	mri_comment_end (stop, stopc);
307933965Sjdp      demand_empty_rest_of_line ();
308033965Sjdp      return;
308133965Sjdp    }
308233965Sjdp
308333965Sjdp#ifdef md_cons_align
308433965Sjdp  md_cons_align (nbytes);
308533965Sjdp#endif
308633965Sjdp
308733965Sjdp  c = 0;
308833965Sjdp  do
308933965Sjdp    {
309033965Sjdp      if (flag_m68k_mri)
309133965Sjdp	parse_mri_cons (&exp, (unsigned int) nbytes);
309233965Sjdp      else
309333965Sjdp	TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
309433965Sjdp
309533965Sjdp      if (rva)
309633965Sjdp	{
309733965Sjdp	  if (exp.X_op == O_symbol)
309833965Sjdp	    exp.X_op = O_symbol_rva;
309933965Sjdp	  else
310033965Sjdp	    as_fatal ("rva without symbol");
310133965Sjdp	}
310233965Sjdp      emit_expr (&exp, (unsigned int) nbytes);
310333965Sjdp      ++c;
310433965Sjdp    }
310533965Sjdp  while (*input_line_pointer++ == ',');
310633965Sjdp
310733965Sjdp  /* In MRI mode, after an odd number of bytes, we must align to an
310833965Sjdp     even word boundary, unless the next instruction is a dc.b, ds.b
310933965Sjdp     or dcb.b.  */
311033965Sjdp  if (flag_mri && nbytes == 1 && (c & 1) != 0)
311133965Sjdp    mri_pending_align = 1;
311233965Sjdp
311333965Sjdp  input_line_pointer--;		/* Put terminator back into stream. */
311433965Sjdp
311533965Sjdp  if (flag_mri)
311633965Sjdp    mri_comment_end (stop, stopc);
311733965Sjdp
311833965Sjdp  demand_empty_rest_of_line ();
311933965Sjdp}
312033965Sjdp
312133965Sjdp
312233965Sjdpvoid
312333965Sjdpcons (size)
312433965Sjdp     int size;
312533965Sjdp{
312633965Sjdp  cons_worker (size, 0);
312733965Sjdp}
312833965Sjdp
312933965Sjdpvoid
313033965Sjdps_rva (size)
313133965Sjdp     int size;
313233965Sjdp{
313333965Sjdp  cons_worker (size, 1);
313433965Sjdp}
313533965Sjdp
313633965Sjdp
313733965Sjdp/* Put the contents of expression EXP into the object file using
313833965Sjdp   NBYTES bytes.  If need_pass_2 is 1, this does nothing.  */
313933965Sjdp
314033965Sjdpvoid
314133965Sjdpemit_expr (exp, nbytes)
314233965Sjdp     expressionS *exp;
314333965Sjdp     unsigned int nbytes;
314433965Sjdp{
314533965Sjdp  operatorT op;
314633965Sjdp  register char *p;
314733965Sjdp  valueT extra_digit = 0;
314833965Sjdp
314933965Sjdp  /* Don't do anything if we are going to make another pass.  */
315033965Sjdp  if (need_pass_2)
315133965Sjdp    return;
315233965Sjdp
315333965Sjdp  op = exp->X_op;
315433965Sjdp
315533965Sjdp  /* Allow `.word 0' in the absolute section.  */
315633965Sjdp  if (now_seg == absolute_section)
315733965Sjdp    {
315833965Sjdp      if (op != O_constant || exp->X_add_number != 0)
315933965Sjdp	as_bad ("attempt to store value in absolute section");
316033965Sjdp      abs_section_offset += nbytes;
316133965Sjdp      return;
316233965Sjdp    }
316333965Sjdp
316433965Sjdp  /* Handle a negative bignum.  */
316533965Sjdp  if (op == O_uminus
316633965Sjdp      && exp->X_add_number == 0
316733965Sjdp      && exp->X_add_symbol->sy_value.X_op == O_big
316833965Sjdp      && exp->X_add_symbol->sy_value.X_add_number > 0)
316933965Sjdp    {
317033965Sjdp      int i;
317133965Sjdp      unsigned long carry;
317233965Sjdp
317333965Sjdp      exp = &exp->X_add_symbol->sy_value;
317433965Sjdp
317533965Sjdp      /* Negate the bignum: one's complement each digit and add 1.  */
317633965Sjdp      carry = 1;
317733965Sjdp      for (i = 0; i < exp->X_add_number; i++)
317833965Sjdp	{
317933965Sjdp	  unsigned long next;
318033965Sjdp
318133965Sjdp	  next = (((~ (generic_bignum[i] & LITTLENUM_MASK))
318233965Sjdp		   & LITTLENUM_MASK)
318333965Sjdp		  + carry);
318433965Sjdp	  generic_bignum[i] = next & LITTLENUM_MASK;
318533965Sjdp	  carry = next >> LITTLENUM_NUMBER_OF_BITS;
318633965Sjdp	}
318733965Sjdp
318833965Sjdp      /* We can ignore any carry out, because it will be handled by
318933965Sjdp	 extra_digit if it is needed.  */
319033965Sjdp
319133965Sjdp      extra_digit = (valueT) -1;
319233965Sjdp      op = O_big;
319333965Sjdp    }
319433965Sjdp
319533965Sjdp  if (op == O_absent || op == O_illegal)
319633965Sjdp    {
319733965Sjdp      as_warn ("zero assumed for missing expression");
319833965Sjdp      exp->X_add_number = 0;
319933965Sjdp      op = O_constant;
320033965Sjdp    }
320133965Sjdp  else if (op == O_big && exp->X_add_number <= 0)
320233965Sjdp    {
320333965Sjdp      as_bad ("floating point number invalid; zero assumed");
320433965Sjdp      exp->X_add_number = 0;
320533965Sjdp      op = O_constant;
320633965Sjdp    }
320733965Sjdp  else if (op == O_register)
320833965Sjdp    {
320933965Sjdp      as_warn ("register value used as expression");
321033965Sjdp      op = O_constant;
321133965Sjdp    }
321233965Sjdp
321333965Sjdp  p = frag_more ((int) nbytes);
321433965Sjdp
321533965Sjdp#ifndef WORKING_DOT_WORD
321633965Sjdp  /* If we have the difference of two symbols in a word, save it on
321733965Sjdp     the broken_words list.  See the code in write.c.  */
321833965Sjdp  if (op == O_subtract && nbytes == 2)
321933965Sjdp    {
322033965Sjdp      struct broken_word *x;
322133965Sjdp
322233965Sjdp      x = (struct broken_word *) xmalloc (sizeof (struct broken_word));
322333965Sjdp      x->next_broken_word = broken_words;
322433965Sjdp      broken_words = x;
322533965Sjdp      x->frag = frag_now;
322633965Sjdp      x->word_goes_here = p;
322733965Sjdp      x->dispfrag = 0;
322833965Sjdp      x->add = exp->X_add_symbol;
322933965Sjdp      x->sub = exp->X_op_symbol;
323033965Sjdp      x->addnum = exp->X_add_number;
323133965Sjdp      x->added = 0;
323233965Sjdp      new_broken_words++;
323333965Sjdp      return;
323433965Sjdp    }
323533965Sjdp#endif
323633965Sjdp
323733965Sjdp  /* If we have an integer, but the number of bytes is too large to
323833965Sjdp     pass to md_number_to_chars, handle it as a bignum.  */
323933965Sjdp  if (op == O_constant && nbytes > sizeof (valueT))
324033965Sjdp    {
324133965Sjdp      valueT val;
324233965Sjdp      int gencnt;
324333965Sjdp
324433965Sjdp      if (! exp->X_unsigned && exp->X_add_number < 0)
324533965Sjdp	extra_digit = (valueT) -1;
324633965Sjdp      val = (valueT) exp->X_add_number;
324733965Sjdp      gencnt = 0;
324833965Sjdp      do
324933965Sjdp	{
325033965Sjdp	  generic_bignum[gencnt] = val & LITTLENUM_MASK;
325133965Sjdp	  val >>= LITTLENUM_NUMBER_OF_BITS;
325233965Sjdp	  ++gencnt;
325333965Sjdp	}
325433965Sjdp      while (val != 0);
325533965Sjdp      op = exp->X_op = O_big;
325633965Sjdp      exp->X_add_number = gencnt;
325733965Sjdp    }
325833965Sjdp
325933965Sjdp  if (op == O_constant)
326033965Sjdp    {
326133965Sjdp      register valueT get;
326233965Sjdp      register valueT use;
326333965Sjdp      register valueT mask;
326433965Sjdp      valueT hibit;
326533965Sjdp      register valueT unmask;
326633965Sjdp
326733965Sjdp      /* JF << of >= number of bits in the object is undefined.  In
326833965Sjdp	 particular SPARC (Sun 4) has problems */
326933965Sjdp      if (nbytes >= sizeof (valueT))
327033965Sjdp	{
327133965Sjdp	  mask = 0;
327233965Sjdp	  if (nbytes > sizeof (valueT))
327333965Sjdp	    hibit = 0;
327433965Sjdp	  else
327533965Sjdp	    hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
327633965Sjdp	}
327733965Sjdp      else
327833965Sjdp	{
327933965Sjdp	  /* Don't store these bits. */
328033965Sjdp	  mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes);
328133965Sjdp	  hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
328233965Sjdp	}
328333965Sjdp
328433965Sjdp      unmask = ~mask;		/* Do store these bits. */
328533965Sjdp
328633965Sjdp#ifdef NEVER
328733965Sjdp      "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
328833965Sjdp      mask = ~(unmask >> 1);	/* Includes sign bit now. */
328933965Sjdp#endif
329033965Sjdp
329133965Sjdp      get = exp->X_add_number;
329233965Sjdp      use = get & unmask;
329333965Sjdp      if ((get & mask) != 0
329433965Sjdp	  && ((get & mask) != mask
329533965Sjdp	      || (get & hibit) == 0))
329633965Sjdp	{		/* Leading bits contain both 0s & 1s. */
329733965Sjdp	  as_warn ("Value 0x%lx truncated to 0x%lx.",
329833965Sjdp		   (unsigned long) get, (unsigned long) use);
329933965Sjdp	}
330033965Sjdp      /* put bytes in right order. */
330133965Sjdp      md_number_to_chars (p, use, (int) nbytes);
330233965Sjdp    }
330333965Sjdp  else if (op == O_big)
330433965Sjdp    {
330533965Sjdp      int size;
330633965Sjdp      LITTLENUM_TYPE *nums;
330733965Sjdp
330833965Sjdp      know (nbytes % CHARS_PER_LITTLENUM == 0);
330933965Sjdp
331033965Sjdp      size = exp->X_add_number * CHARS_PER_LITTLENUM;
331133965Sjdp      if (nbytes < size)
331233965Sjdp	{
331333965Sjdp	  as_warn ("Bignum truncated to %d bytes", nbytes);
331433965Sjdp	  size = nbytes;
331533965Sjdp	}
331633965Sjdp
331733965Sjdp      if (target_big_endian)
331833965Sjdp	{
331933965Sjdp	  while (nbytes > size)
332033965Sjdp	    {
332133965Sjdp	      md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
332233965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
332333965Sjdp	      p += CHARS_PER_LITTLENUM;
332433965Sjdp	    }
332533965Sjdp
332633965Sjdp	  nums = generic_bignum + size / CHARS_PER_LITTLENUM;
332733965Sjdp	  while (size > 0)
332833965Sjdp	    {
332933965Sjdp	      --nums;
333033965Sjdp	      md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
333133965Sjdp	      size -= CHARS_PER_LITTLENUM;
333233965Sjdp	      p += CHARS_PER_LITTLENUM;
333333965Sjdp	    }
333433965Sjdp	}
333533965Sjdp      else
333633965Sjdp	{
333733965Sjdp	  nums = generic_bignum;
333833965Sjdp	  while (size > 0)
333933965Sjdp	    {
334033965Sjdp	      md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
334133965Sjdp	      ++nums;
334233965Sjdp	      size -= CHARS_PER_LITTLENUM;
334333965Sjdp	      p += CHARS_PER_LITTLENUM;
334433965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
334533965Sjdp	    }
334633965Sjdp
334733965Sjdp	  while (nbytes > 0)
334833965Sjdp	    {
334933965Sjdp	      md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
335033965Sjdp	      nbytes -= CHARS_PER_LITTLENUM;
335133965Sjdp	      p += CHARS_PER_LITTLENUM;
335233965Sjdp	    }
335333965Sjdp	}
335433965Sjdp    }
335533965Sjdp  else
335633965Sjdp    {
335733965Sjdp      memset (p, 0, nbytes);
335833965Sjdp
335933965Sjdp      /* Now we need to generate a fixS to record the symbol value.
336033965Sjdp	 This is easy for BFD.  For other targets it can be more
336133965Sjdp	 complex.  For very complex cases (currently, the HPPA and
336233965Sjdp	 NS32K), you can define TC_CONS_FIX_NEW to do whatever you
336333965Sjdp	 want.  For simpler cases, you can define TC_CONS_RELOC to be
336433965Sjdp	 the name of the reloc code that should be stored in the fixS.
336533965Sjdp	 If neither is defined, the code uses NO_RELOC if it is
336633965Sjdp	 defined, and otherwise uses 0.  */
336733965Sjdp
336833965Sjdp#ifdef BFD_ASSEMBLER
336933965Sjdp#ifdef TC_CONS_FIX_NEW
337033965Sjdp      TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
337133965Sjdp#else
337233965Sjdp      {
337333965Sjdp	bfd_reloc_code_real_type r;
337433965Sjdp
337533965Sjdp	switch (nbytes)
337633965Sjdp	  {
337733965Sjdp	  case 1:
337833965Sjdp	    r = BFD_RELOC_8;
337933965Sjdp	    break;
338033965Sjdp	  case 2:
338133965Sjdp	    r = BFD_RELOC_16;
338233965Sjdp	    break;
338333965Sjdp	  case 4:
338433965Sjdp	    r = BFD_RELOC_32;
338533965Sjdp	    break;
338633965Sjdp	  case 8:
338733965Sjdp	    r = BFD_RELOC_64;
338833965Sjdp	    break;
338933965Sjdp	  default:
339033965Sjdp	    as_bad ("unsupported BFD relocation size %u", nbytes);
339133965Sjdp	    r = BFD_RELOC_32;
339233965Sjdp	    break;
339333965Sjdp	  }
339433965Sjdp	fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp,
339533965Sjdp		     0, r);
339633965Sjdp      }
339733965Sjdp#endif
339833965Sjdp#else
339933965Sjdp#ifdef TC_CONS_FIX_NEW
340033965Sjdp      TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
340133965Sjdp#else
340233965Sjdp      /* Figure out which reloc number to use.  Use TC_CONS_RELOC if
340333965Sjdp	 it is defined, otherwise use NO_RELOC if it is defined,
340433965Sjdp	 otherwise use 0.  */
340533965Sjdp#ifndef TC_CONS_RELOC
340633965Sjdp#ifdef NO_RELOC
340733965Sjdp#define TC_CONS_RELOC NO_RELOC
340833965Sjdp#else
340933965Sjdp#define TC_CONS_RELOC 0
341033965Sjdp#endif
341133965Sjdp#endif
341233965Sjdp      fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0,
341333965Sjdp		   TC_CONS_RELOC);
341433965Sjdp#endif /* TC_CONS_FIX_NEW */
341533965Sjdp#endif /* BFD_ASSEMBLER */
341633965Sjdp    }
341733965Sjdp}
341833965Sjdp
341933965Sjdp#ifdef BITFIELD_CONS_EXPRESSIONS
342033965Sjdp
342133965Sjdp/* i960 assemblers, (eg, asm960), allow bitfields after ".byte" as
342233965Sjdp   w:x,y:z, where w and y are bitwidths and x and y are values.  They
342333965Sjdp   then pack them all together. We do a little better in that we allow
342433965Sjdp   them in words, longs, etc. and we'll pack them in target byte order
342533965Sjdp   for you.
342633965Sjdp
342733965Sjdp   The rules are: pack least significat bit first, if a field doesn't
342833965Sjdp   entirely fit, put it in the next unit.  Overflowing the bitfield is
342933965Sjdp   explicitly *not* even a warning.  The bitwidth should be considered
343033965Sjdp   a "mask".
343133965Sjdp
343233965Sjdp   To use this function the tc-XXX.h file should define
343333965Sjdp   BITFIELD_CONS_EXPRESSIONS.  */
343433965Sjdp
343533965Sjdpstatic void
343633965Sjdpparse_bitfield_cons (exp, nbytes)
343733965Sjdp     expressionS *exp;
343833965Sjdp     unsigned int nbytes;
343933965Sjdp{
344033965Sjdp  unsigned int bits_available = BITS_PER_CHAR * nbytes;
344133965Sjdp  char *hold = input_line_pointer;
344233965Sjdp
344333965Sjdp  (void) expression (exp);
344433965Sjdp
344533965Sjdp  if (*input_line_pointer == ':')
344633965Sjdp    {			/* bitfields */
344733965Sjdp      long value = 0;
344833965Sjdp
344933965Sjdp      for (;;)
345033965Sjdp	{
345133965Sjdp	  unsigned long width;
345233965Sjdp
345333965Sjdp	  if (*input_line_pointer != ':')
345433965Sjdp	    {
345533965Sjdp	      input_line_pointer = hold;
345633965Sjdp	      break;
345733965Sjdp	    }			/* next piece is not a bitfield */
345833965Sjdp
345933965Sjdp	  /* In the general case, we can't allow
346033965Sjdp	     full expressions with symbol
346133965Sjdp	     differences and such.  The relocation
346233965Sjdp	     entries for symbols not defined in this
346333965Sjdp	     assembly would require arbitrary field
346433965Sjdp	     widths, positions, and masks which most
346533965Sjdp	     of our current object formats don't
346633965Sjdp	     support.
346733965Sjdp
346833965Sjdp	     In the specific case where a symbol
346933965Sjdp	     *is* defined in this assembly, we
347033965Sjdp	     *could* build fixups and track it, but
347133965Sjdp	     this could lead to confusion for the
347233965Sjdp	     backends.  I'm lazy. I'll take any
347333965Sjdp	     SEG_ABSOLUTE. I think that means that
347433965Sjdp	     you can use a previous .set or
347533965Sjdp	     .equ type symbol.  xoxorich. */
347633965Sjdp
347733965Sjdp	  if (exp->X_op == O_absent)
347833965Sjdp	    {
347933965Sjdp	      as_warn ("using a bit field width of zero");
348033965Sjdp	      exp->X_add_number = 0;
348133965Sjdp	      exp->X_op = O_constant;
348233965Sjdp	    }			/* implied zero width bitfield */
348333965Sjdp
348433965Sjdp	  if (exp->X_op != O_constant)
348533965Sjdp	    {
348633965Sjdp	      *input_line_pointer = '\0';
348733965Sjdp	      as_bad ("field width \"%s\" too complex for a bitfield", hold);
348833965Sjdp	      *input_line_pointer = ':';
348933965Sjdp	      demand_empty_rest_of_line ();
349033965Sjdp	      return;
349133965Sjdp	    }			/* too complex */
349233965Sjdp
349333965Sjdp	  if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes))
349433965Sjdp	    {
349533965Sjdp	      as_warn ("field width %lu too big to fit in %d bytes: truncated to %d bits",
349633965Sjdp		       width, nbytes, (BITS_PER_CHAR * nbytes));
349733965Sjdp	      width = BITS_PER_CHAR * nbytes;
349833965Sjdp	    }			/* too big */
349933965Sjdp
350033965Sjdp	  if (width > bits_available)
350133965Sjdp	    {
350233965Sjdp	      /* FIXME-SOMEDAY: backing up and reparsing is wasteful.  */
350333965Sjdp	      input_line_pointer = hold;
350433965Sjdp	      exp->X_add_number = value;
350533965Sjdp	      break;
350633965Sjdp	    }			/* won't fit */
350733965Sjdp
350833965Sjdp	  hold = ++input_line_pointer; /* skip ':' */
350933965Sjdp
351033965Sjdp	  (void) expression (exp);
351133965Sjdp	  if (exp->X_op != O_constant)
351233965Sjdp	    {
351333965Sjdp	      char cache = *input_line_pointer;
351433965Sjdp
351533965Sjdp	      *input_line_pointer = '\0';
351633965Sjdp	      as_bad ("field value \"%s\" too complex for a bitfield", hold);
351733965Sjdp	      *input_line_pointer = cache;
351833965Sjdp	      demand_empty_rest_of_line ();
351933965Sjdp	      return;
352033965Sjdp	    }			/* too complex */
352133965Sjdp
352233965Sjdp	  value |= ((~(-1 << width) & exp->X_add_number)
352333965Sjdp		    << ((BITS_PER_CHAR * nbytes) - bits_available));
352433965Sjdp
352533965Sjdp	  if ((bits_available -= width) == 0
352633965Sjdp	      || is_it_end_of_statement ()
352733965Sjdp	      || *input_line_pointer != ',')
352833965Sjdp	    {
352933965Sjdp	      break;
353033965Sjdp	    }			/* all the bitfields we're gonna get */
353133965Sjdp
353233965Sjdp	  hold = ++input_line_pointer;
353333965Sjdp	  (void) expression (exp);
353433965Sjdp	}			/* forever loop */
353533965Sjdp
353633965Sjdp      exp->X_add_number = value;
353733965Sjdp      exp->X_op = O_constant;
353833965Sjdp      exp->X_unsigned = 1;
353933965Sjdp    }				/* if looks like a bitfield */
354033965Sjdp}				/* parse_bitfield_cons() */
354133965Sjdp
354233965Sjdp#endif /* BITFIELD_CONS_EXPRESSIONS */
354333965Sjdp
354433965Sjdp/* Handle an MRI style string expression.  */
354533965Sjdp
354633965Sjdpstatic void
354733965Sjdpparse_mri_cons (exp, nbytes)
354833965Sjdp     expressionS *exp;
354933965Sjdp     unsigned int nbytes;
355033965Sjdp{
355133965Sjdp  if (*input_line_pointer != '\''
355233965Sjdp      && (input_line_pointer[1] != '\''
355333965Sjdp	  || (*input_line_pointer != 'A'
355433965Sjdp	      && *input_line_pointer != 'E')))
355533965Sjdp    TC_PARSE_CONS_EXPRESSION (exp, nbytes);
355633965Sjdp  else
355733965Sjdp    {
355833965Sjdp      int scan = 0;
355933965Sjdp      unsigned int result = 0;
356033965Sjdp
356133965Sjdp      /* An MRI style string.  Cut into as many bytes as will fit into
356233965Sjdp	 a nbyte chunk, left justify if necessary, and separate with
356333965Sjdp	 commas so we can try again later.  */
356433965Sjdp      if (*input_line_pointer == 'A')
356533965Sjdp	++input_line_pointer;
356633965Sjdp      else if (*input_line_pointer == 'E')
356733965Sjdp	{
356833965Sjdp	  as_bad ("EBCDIC constants are not supported");
356933965Sjdp	  ++input_line_pointer;
357033965Sjdp	}
357133965Sjdp
357233965Sjdp      input_line_pointer++;
357333965Sjdp      for (scan = 0; scan < nbytes; scan++)
357433965Sjdp	{
357533965Sjdp	  if (*input_line_pointer == '\'')
357633965Sjdp	    {
357733965Sjdp	      if (input_line_pointer[1] == '\'')
357833965Sjdp		{
357933965Sjdp		  input_line_pointer++;
358033965Sjdp		}
358133965Sjdp	      else
358233965Sjdp		break;
358333965Sjdp	    }
358433965Sjdp	  result = (result << 8) | (*input_line_pointer++);
358533965Sjdp	}
358633965Sjdp
358733965Sjdp      /* Left justify */
358833965Sjdp      while (scan < nbytes)
358933965Sjdp	{
359033965Sjdp	  result <<= 8;
359133965Sjdp	  scan++;
359233965Sjdp	}
359333965Sjdp      /* Create correct expression */
359433965Sjdp      exp->X_op = O_constant;
359533965Sjdp      exp->X_add_number = result;
359633965Sjdp      /* Fake it so that we can read the next char too */
359733965Sjdp      if (input_line_pointer[0] != '\'' ||
359833965Sjdp	  (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\''))
359933965Sjdp	{
360033965Sjdp	  input_line_pointer -= 2;
360133965Sjdp	  input_line_pointer[0] = ',';
360233965Sjdp	  input_line_pointer[1] = '\'';
360333965Sjdp	}
360433965Sjdp      else
360533965Sjdp	input_line_pointer++;
360633965Sjdp    }
360733965Sjdp}
360833965Sjdp
360933965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
361033965Sjdp
361133965Sjdp/* Parse a repeat expression for cons.  This is used by the MIPS
361233965Sjdp   assembler.  The format is NUMBER:COUNT; NUMBER appears in the
361333965Sjdp   object file COUNT times.
361433965Sjdp
361533965Sjdp   To use this for a target, define REPEAT_CONS_EXPRESSIONS.  */
361633965Sjdp
361733965Sjdpstatic void
361833965Sjdpparse_repeat_cons (exp, nbytes)
361933965Sjdp     expressionS *exp;
362033965Sjdp     unsigned int nbytes;
362133965Sjdp{
362233965Sjdp  expressionS count;
362333965Sjdp  register int i;
362433965Sjdp
362533965Sjdp  expression (exp);
362633965Sjdp
362733965Sjdp  if (*input_line_pointer != ':')
362833965Sjdp    {
362933965Sjdp      /* No repeat count.  */
363033965Sjdp      return;
363133965Sjdp    }
363233965Sjdp
363333965Sjdp  ++input_line_pointer;
363433965Sjdp  expression (&count);
363533965Sjdp  if (count.X_op != O_constant
363633965Sjdp      || count.X_add_number <= 0)
363733965Sjdp    {
363833965Sjdp      as_warn ("Unresolvable or nonpositive repeat count; using 1");
363933965Sjdp      return;
364033965Sjdp    }
364133965Sjdp
364233965Sjdp  /* The cons function is going to output this expression once.  So we
364333965Sjdp     output it count - 1 times.  */
364433965Sjdp  for (i = count.X_add_number - 1; i > 0; i--)
364533965Sjdp    emit_expr (exp, nbytes);
364633965Sjdp}
364733965Sjdp
364833965Sjdp#endif /* REPEAT_CONS_EXPRESSIONS */
364933965Sjdp
365033965Sjdp/* Parse a floating point number represented as a hex constant.  This
365133965Sjdp   permits users to specify the exact bits they want in the floating
365233965Sjdp   point number.  */
365333965Sjdp
365433965Sjdpstatic int
365533965Sjdphex_float (float_type, bytes)
365633965Sjdp     int float_type;
365733965Sjdp     char *bytes;
365833965Sjdp{
365933965Sjdp  int length;
366033965Sjdp  int i;
366133965Sjdp
366233965Sjdp  switch (float_type)
366333965Sjdp    {
366433965Sjdp    case 'f':
366533965Sjdp    case 'F':
366633965Sjdp    case 's':
366733965Sjdp    case 'S':
366833965Sjdp      length = 4;
366933965Sjdp      break;
367033965Sjdp
367133965Sjdp    case 'd':
367233965Sjdp    case 'D':
367333965Sjdp    case 'r':
367433965Sjdp    case 'R':
367533965Sjdp      length = 8;
367633965Sjdp      break;
367733965Sjdp
367833965Sjdp    case 'x':
367933965Sjdp    case 'X':
368033965Sjdp      length = 12;
368133965Sjdp      break;
368233965Sjdp
368333965Sjdp    case 'p':
368433965Sjdp    case 'P':
368533965Sjdp      length = 12;
368633965Sjdp      break;
368733965Sjdp
368833965Sjdp    default:
368933965Sjdp      as_bad ("Unknown floating type type '%c'", float_type);
369033965Sjdp      return -1;
369133965Sjdp    }
369233965Sjdp
369333965Sjdp  /* It would be nice if we could go through expression to parse the
369433965Sjdp     hex constant, but if we get a bignum it's a pain to sort it into
369533965Sjdp     the buffer correctly.  */
369633965Sjdp  i = 0;
369733965Sjdp  while (hex_p (*input_line_pointer) || *input_line_pointer == '_')
369833965Sjdp    {
369933965Sjdp      int d;
370033965Sjdp
370133965Sjdp      /* The MRI assembler accepts arbitrary underscores strewn about
370233965Sjdp	 through the hex constant, so we ignore them as well. */
370333965Sjdp      if (*input_line_pointer == '_')
370433965Sjdp	{
370533965Sjdp	  ++input_line_pointer;
370633965Sjdp	  continue;
370733965Sjdp	}
370833965Sjdp
370933965Sjdp      if (i >= length)
371033965Sjdp	{
371133965Sjdp	  as_warn ("Floating point constant too large");
371233965Sjdp	  return -1;
371333965Sjdp	}
371433965Sjdp      d = hex_value (*input_line_pointer) << 4;
371533965Sjdp      ++input_line_pointer;
371633965Sjdp      while (*input_line_pointer == '_')
371733965Sjdp	++input_line_pointer;
371833965Sjdp      if (hex_p (*input_line_pointer))
371933965Sjdp	{
372033965Sjdp	  d += hex_value (*input_line_pointer);
372133965Sjdp	  ++input_line_pointer;
372233965Sjdp	}
372333965Sjdp      if (target_big_endian)
372433965Sjdp	bytes[i] = d;
372533965Sjdp      else
372633965Sjdp	bytes[length - i - 1] = d;
372733965Sjdp      ++i;
372833965Sjdp    }
372933965Sjdp
373033965Sjdp  if (i < length)
373133965Sjdp    {
373233965Sjdp      if (target_big_endian)
373333965Sjdp	memset (bytes + i, 0, length - i);
373433965Sjdp      else
373533965Sjdp	memset (bytes, 0, length - i);
373633965Sjdp    }
373733965Sjdp
373833965Sjdp  return length;
373933965Sjdp}
374033965Sjdp
374133965Sjdp/*
374233965Sjdp *			float_cons()
374333965Sjdp *
374433965Sjdp * CONStruct some more frag chars of .floats .ffloats etc.
374533965Sjdp * Makes 0 or more new frags.
374633965Sjdp * If need_pass_2 == 1, no frags are emitted.
374733965Sjdp * This understands only floating literals, not expressions. Sorry.
374833965Sjdp *
374933965Sjdp * A floating constant is defined by atof_generic(), except it is preceded
375033965Sjdp * by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its
375133965Sjdp * reading, I decided to be incompatible. This always tries to give you
375233965Sjdp * rounded bits to the precision of the pseudo-op. Former AS did premature
375333965Sjdp * truncatation, restored noisy bits instead of trailing 0s AND gave you
375433965Sjdp * a choice of 2 flavours of noise according to which of 2 floating-point
375533965Sjdp * scanners you directed AS to use.
375633965Sjdp *
375733965Sjdp * In:	input_line_pointer->whitespace before, or '0' of flonum.
375833965Sjdp *
375933965Sjdp */
376033965Sjdp
376133965Sjdpvoid
376233965Sjdpfloat_cons (float_type)
376333965Sjdp     /* Clobbers input_line-pointer, checks end-of-line. */
376433965Sjdp     register int float_type;	/* 'f':.ffloat ... 'F':.float ... */
376533965Sjdp{
376633965Sjdp  register char *p;
376733965Sjdp  int length;			/* Number of chars in an object. */
376833965Sjdp  register char *err;		/* Error from scanning floating literal. */
376933965Sjdp  char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
377033965Sjdp
377133965Sjdp  if (is_it_end_of_statement ())
377233965Sjdp    {
377333965Sjdp      demand_empty_rest_of_line ();
377433965Sjdp      return;
377533965Sjdp    }
377633965Sjdp
377733965Sjdp#ifdef md_flush_pending_output
377833965Sjdp  md_flush_pending_output ();
377933965Sjdp#endif
378033965Sjdp
378133965Sjdp  do
378233965Sjdp    {
378333965Sjdp      /* input_line_pointer->1st char of a flonum (we hope!). */
378433965Sjdp      SKIP_WHITESPACE ();
378533965Sjdp
378633965Sjdp      /* Skip any 0{letter} that may be present. Don't even check if the
378733965Sjdp       * letter is legal. Someone may invent a "z" format and this routine
378833965Sjdp       * has no use for such information. Lusers beware: you get
378933965Sjdp       * diagnostics if your input is ill-conditioned.
379033965Sjdp       */
379133965Sjdp      if (input_line_pointer[0] == '0' && isalpha (input_line_pointer[1]))
379233965Sjdp	input_line_pointer += 2;
379333965Sjdp
379433965Sjdp      /* Accept :xxxx, where the x's are hex digits, for a floating
379533965Sjdp         point with the exact digits specified.  */
379633965Sjdp      if (input_line_pointer[0] == ':')
379733965Sjdp	{
379833965Sjdp	  ++input_line_pointer;
379933965Sjdp	  length = hex_float (float_type, temp);
380033965Sjdp	  if (length < 0)
380133965Sjdp	    {
380233965Sjdp	      ignore_rest_of_line ();
380333965Sjdp	      return;
380433965Sjdp	    }
380533965Sjdp	}
380633965Sjdp      else
380733965Sjdp	{
380833965Sjdp	  err = md_atof (float_type, temp, &length);
380933965Sjdp	  know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
381033965Sjdp	  know (length > 0);
381133965Sjdp	  if (err)
381233965Sjdp	    {
381333965Sjdp	      as_bad ("Bad floating literal: %s", err);
381433965Sjdp	      ignore_rest_of_line ();
381533965Sjdp	      return;
381633965Sjdp	    }
381733965Sjdp	}
381833965Sjdp
381933965Sjdp      if (!need_pass_2)
382033965Sjdp	{
382133965Sjdp	  int count;
382233965Sjdp
382333965Sjdp	  count = 1;
382433965Sjdp
382533965Sjdp#ifdef REPEAT_CONS_EXPRESSIONS
382633965Sjdp	  if (*input_line_pointer == ':')
382733965Sjdp	    {
382833965Sjdp	      expressionS count_exp;
382933965Sjdp
383033965Sjdp	      ++input_line_pointer;
383133965Sjdp	      expression (&count_exp);
383233965Sjdp	      if (count_exp.X_op != O_constant
383333965Sjdp		  || count_exp.X_add_number <= 0)
383433965Sjdp		{
383533965Sjdp		  as_warn ("unresolvable or nonpositive repeat count; using 1");
383633965Sjdp		}
383733965Sjdp	      else
383833965Sjdp		count = count_exp.X_add_number;
383933965Sjdp	    }
384033965Sjdp#endif
384133965Sjdp
384233965Sjdp	  while (--count >= 0)
384333965Sjdp	    {
384433965Sjdp	      p = frag_more (length);
384533965Sjdp	      memcpy (p, temp, (unsigned int) length);
384633965Sjdp	    }
384733965Sjdp	}
384833965Sjdp      SKIP_WHITESPACE ();
384933965Sjdp    }
385033965Sjdp  while (*input_line_pointer++ == ',');
385133965Sjdp
385233965Sjdp  --input_line_pointer;		/* Put terminator back into stream.  */
385333965Sjdp  demand_empty_rest_of_line ();
385433965Sjdp}				/* float_cons() */
385533965Sjdp
385633965Sjdp/*
385733965Sjdp *			stringer()
385833965Sjdp *
385933965Sjdp * We read 0 or more ',' seperated, double-quoted strings.
386033965Sjdp *
386133965Sjdp * Caller should have checked need_pass_2 is FALSE because we don't check it.
386233965Sjdp */
386333965Sjdp
386433965Sjdp
386533965Sjdpvoid
386633965Sjdpstringer (append_zero)		/* Worker to do .ascii etc statements. */
386733965Sjdp     /* Checks end-of-line. */
386833965Sjdp     register int append_zero;	/* 0: don't append '\0', else 1 */
386933965Sjdp{
387033965Sjdp  register unsigned int c;
387133965Sjdp
387233965Sjdp#ifdef md_flush_pending_output
387333965Sjdp  md_flush_pending_output ();
387433965Sjdp#endif
387533965Sjdp
387633965Sjdp  /*
387733965Sjdp   * The following awkward logic is to parse ZERO or more strings,
387833965Sjdp   * comma seperated. Recall a string expression includes spaces
387933965Sjdp   * before the opening '\"' and spaces after the closing '\"'.
388033965Sjdp   * We fake a leading ',' if there is (supposed to be)
388133965Sjdp   * a 1st, expression. We keep demanding expressions for each
388233965Sjdp   * ','.
388333965Sjdp   */
388433965Sjdp  if (is_it_end_of_statement ())
388533965Sjdp    {
388633965Sjdp      c = 0;			/* Skip loop. */
388733965Sjdp      ++input_line_pointer;	/* Compensate for end of loop. */
388833965Sjdp    }
388933965Sjdp  else
389033965Sjdp    {
389133965Sjdp      c = ',';			/* Do loop. */
389233965Sjdp    }
389333965Sjdp  while (c == ',' || c == '<' || c == '"')
389433965Sjdp    {
389533965Sjdp      SKIP_WHITESPACE ();
389633965Sjdp      switch (*input_line_pointer)
389733965Sjdp	{
389833965Sjdp	case '\"':
389933965Sjdp	  ++input_line_pointer;	/*->1st char of string. */
390033965Sjdp	  while (is_a_char (c = next_char_of_string ()))
390133965Sjdp	    {
390233965Sjdp	      FRAG_APPEND_1_CHAR (c);
390333965Sjdp	    }
390433965Sjdp	  if (append_zero)
390533965Sjdp	    {
390633965Sjdp	      FRAG_APPEND_1_CHAR (0);
390733965Sjdp	    }
390833965Sjdp	  know (input_line_pointer[-1] == '\"');
390933965Sjdp	  break;
391033965Sjdp	case '<':
391133965Sjdp	  input_line_pointer++;
391233965Sjdp	  c = get_single_number ();
391333965Sjdp	  FRAG_APPEND_1_CHAR (c);
391433965Sjdp	  if (*input_line_pointer != '>')
391533965Sjdp	    {
391633965Sjdp	      as_bad ("Expected <nn>");
391733965Sjdp	    }
391833965Sjdp	  input_line_pointer++;
391933965Sjdp	  break;
392033965Sjdp	case ',':
392133965Sjdp	  input_line_pointer++;
392233965Sjdp	  break;
392333965Sjdp	}
392433965Sjdp      SKIP_WHITESPACE ();
392533965Sjdp      c = *input_line_pointer;
392633965Sjdp    }
392733965Sjdp
392833965Sjdp  demand_empty_rest_of_line ();
392933965Sjdp}				/* stringer() */
393033965Sjdp
393133965Sjdp/* FIXME-SOMEDAY: I had trouble here on characters with the
393233965Sjdp    high bits set.  We'll probably also have trouble with
393333965Sjdp    multibyte chars, wide chars, etc.  Also be careful about
393433965Sjdp    returning values bigger than 1 byte.  xoxorich. */
393533965Sjdp
393633965Sjdpunsigned int
393733965Sjdpnext_char_of_string ()
393833965Sjdp{
393933965Sjdp  register unsigned int c;
394033965Sjdp
394133965Sjdp  c = *input_line_pointer++ & CHAR_MASK;
394233965Sjdp  switch (c)
394333965Sjdp    {
394433965Sjdp    case '\"':
394533965Sjdp      c = NOT_A_CHAR;
394633965Sjdp      break;
394733965Sjdp
394833965Sjdp    case '\n':
394933965Sjdp      as_warn ("Unterminated string: Newline inserted.");
395033965Sjdp      bump_line_counters ();
395133965Sjdp      break;
395233965Sjdp
395333965Sjdp#ifndef NO_STRING_ESCAPES
395433965Sjdp    case '\\':
395533965Sjdp      switch (c = *input_line_pointer++)
395633965Sjdp	{
395733965Sjdp	case 'b':
395833965Sjdp	  c = '\b';
395933965Sjdp	  break;
396033965Sjdp
396133965Sjdp	case 'f':
396233965Sjdp	  c = '\f';
396333965Sjdp	  break;
396433965Sjdp
396533965Sjdp	case 'n':
396633965Sjdp	  c = '\n';
396733965Sjdp	  break;
396833965Sjdp
396933965Sjdp	case 'r':
397033965Sjdp	  c = '\r';
397133965Sjdp	  break;
397233965Sjdp
397333965Sjdp	case 't':
397433965Sjdp	  c = '\t';
397533965Sjdp	  break;
397633965Sjdp
397733965Sjdp	case 'v':
397833965Sjdp	  c = '\013';
397933965Sjdp	  break;
398033965Sjdp
398133965Sjdp	case '\\':
398233965Sjdp	case '"':
398333965Sjdp	  break;		/* As itself. */
398433965Sjdp
398533965Sjdp	case '0':
398633965Sjdp	case '1':
398733965Sjdp	case '2':
398833965Sjdp	case '3':
398933965Sjdp	case '4':
399033965Sjdp	case '5':
399133965Sjdp	case '6':
399233965Sjdp	case '7':
399333965Sjdp	case '8':
399433965Sjdp	case '9':
399533965Sjdp	  {
399633965Sjdp	    long number;
399733965Sjdp	    int i;
399833965Sjdp
399933965Sjdp	    for (i = 0, number = 0; isdigit (c) && i < 3; c = *input_line_pointer++, i++)
400033965Sjdp	      {
400133965Sjdp		number = number * 8 + c - '0';
400233965Sjdp	      }
400333965Sjdp	    c = number & 0xff;
400433965Sjdp	  }
400533965Sjdp	  --input_line_pointer;
400633965Sjdp	  break;
400733965Sjdp
400833965Sjdp	case 'x':
400933965Sjdp	case 'X':
401033965Sjdp	  {
401133965Sjdp	    long number;
401233965Sjdp
401333965Sjdp	    number = 0;
401433965Sjdp	    c = *input_line_pointer++;
401533965Sjdp	    while (isxdigit (c))
401633965Sjdp	      {
401733965Sjdp		if (isdigit (c))
401833965Sjdp		  number = number * 16 + c - '0';
401933965Sjdp		else if (isupper (c))
402033965Sjdp		  number = number * 16 + c - 'A' + 10;
402133965Sjdp		else
402233965Sjdp		  number = number * 16 + c - 'a' + 10;
402333965Sjdp		c = *input_line_pointer++;
402433965Sjdp	      }
402533965Sjdp	    c = number & 0xff;
402633965Sjdp	    --input_line_pointer;
402733965Sjdp	  }
402833965Sjdp	  break;
402933965Sjdp
403033965Sjdp	case '\n':
403133965Sjdp	  /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */
403233965Sjdp	  as_warn ("Unterminated string: Newline inserted.");
403333965Sjdp	  c = '\n';
403433965Sjdp	  bump_line_counters ();
403533965Sjdp	  break;
403633965Sjdp
403733965Sjdp	default:
403833965Sjdp
403933965Sjdp#ifdef ONLY_STANDARD_ESCAPES
404033965Sjdp	  as_bad ("Bad escaped character in string, '?' assumed");
404133965Sjdp	  c = '?';
404233965Sjdp#endif /* ONLY_STANDARD_ESCAPES */
404333965Sjdp
404433965Sjdp	  break;
404533965Sjdp	}			/* switch on escaped char */
404633965Sjdp      break;
404733965Sjdp#endif /* ! defined (NO_STRING_ESCAPES) */
404833965Sjdp
404933965Sjdp    default:
405033965Sjdp      break;
405133965Sjdp    }				/* switch on char */
405233965Sjdp  return (c);
405333965Sjdp}				/* next_char_of_string() */
405433965Sjdp
405533965Sjdpstatic segT
405633965Sjdpget_segmented_expression (expP)
405733965Sjdp     register expressionS *expP;
405833965Sjdp{
405933965Sjdp  register segT retval;
406033965Sjdp
406133965Sjdp  retval = expression (expP);
406233965Sjdp  if (expP->X_op == O_illegal
406333965Sjdp      || expP->X_op == O_absent
406433965Sjdp      || expP->X_op == O_big)
406533965Sjdp    {
406633965Sjdp      as_bad ("expected address expression; zero assumed");
406733965Sjdp      expP->X_op = O_constant;
406833965Sjdp      expP->X_add_number = 0;
406933965Sjdp      retval = absolute_section;
407033965Sjdp    }
407133965Sjdp  return retval;
407233965Sjdp}
407333965Sjdp
407433965Sjdpstatic segT
407533965Sjdpget_known_segmented_expression (expP)
407633965Sjdp     register expressionS *expP;
407733965Sjdp{
407833965Sjdp  register segT retval;
407933965Sjdp
408033965Sjdp  if ((retval = get_segmented_expression (expP)) == undefined_section)
408133965Sjdp    {
408233965Sjdp      /* There is no easy way to extract the undefined symbol from the
408333965Sjdp	 expression.  */
408433965Sjdp      if (expP->X_add_symbol != NULL
408533965Sjdp	  && S_GET_SEGMENT (expP->X_add_symbol) != expr_section)
408633965Sjdp	as_warn ("symbol \"%s\" undefined; zero assumed",
408733965Sjdp		 S_GET_NAME (expP->X_add_symbol));
408833965Sjdp      else
408933965Sjdp	as_warn ("some symbol undefined; zero assumed");
409033965Sjdp      retval = absolute_section;
409133965Sjdp      expP->X_op = O_constant;
409233965Sjdp      expP->X_add_number = 0;
409333965Sjdp    }
409433965Sjdp  know (retval == absolute_section || SEG_NORMAL (retval));
409533965Sjdp  return (retval);
409633965Sjdp}				/* get_known_segmented_expression() */
409733965Sjdp
409833965SjdpoffsetT
409933965Sjdpget_absolute_expression ()
410033965Sjdp{
410133965Sjdp  expressionS exp;
410233965Sjdp
410333965Sjdp  expression (&exp);
410433965Sjdp  if (exp.X_op != O_constant)
410533965Sjdp    {
410633965Sjdp      if (exp.X_op != O_absent)
410733965Sjdp	as_bad ("bad or irreducible absolute expression; zero assumed");
410833965Sjdp      exp.X_add_number = 0;
410933965Sjdp    }
411033965Sjdp  return exp.X_add_number;
411133965Sjdp}
411233965Sjdp
411333965Sjdpchar				/* return terminator */
411433965Sjdpget_absolute_expression_and_terminator (val_pointer)
411533965Sjdp     long *val_pointer;		/* return value of expression */
411633965Sjdp{
411733965Sjdp  /* FIXME: val_pointer should probably be offsetT *.  */
411833965Sjdp  *val_pointer = (long) get_absolute_expression ();
411933965Sjdp  return (*input_line_pointer++);
412033965Sjdp}
412133965Sjdp
412233965Sjdp/*
412333965Sjdp *			demand_copy_C_string()
412433965Sjdp *
412533965Sjdp * Like demand_copy_string, but return NULL if the string contains any '\0's.
412633965Sjdp * Give a warning if that happens.
412733965Sjdp */
412833965Sjdpchar *
412933965Sjdpdemand_copy_C_string (len_pointer)
413033965Sjdp     int *len_pointer;
413133965Sjdp{
413233965Sjdp  register char *s;
413333965Sjdp
413433965Sjdp  if ((s = demand_copy_string (len_pointer)) != 0)
413533965Sjdp    {
413633965Sjdp      register int len;
413733965Sjdp
413833965Sjdp      for (len = *len_pointer; len > 0; len--)
413933965Sjdp	{
414033965Sjdp	  if (*s == 0)
414133965Sjdp	    {
414233965Sjdp	      s = 0;
414333965Sjdp	      len = 1;
414433965Sjdp	      *len_pointer = 0;
414533965Sjdp	      as_bad ("This string may not contain \'\\0\'");
414633965Sjdp	    }
414733965Sjdp	}
414833965Sjdp    }
414933965Sjdp  return s;
415033965Sjdp}
415133965Sjdp
415233965Sjdp/*
415333965Sjdp *			demand_copy_string()
415433965Sjdp *
415533965Sjdp * Demand string, but return a safe (=private) copy of the string.
415633965Sjdp * Return NULL if we can't read a string here.
415733965Sjdp */
415833965Sjdpchar *
415933965Sjdpdemand_copy_string (lenP)
416033965Sjdp     int *lenP;
416133965Sjdp{
416233965Sjdp  register unsigned int c;
416333965Sjdp  register int len;
416433965Sjdp  char *retval;
416533965Sjdp
416633965Sjdp  len = 0;
416733965Sjdp  SKIP_WHITESPACE ();
416833965Sjdp  if (*input_line_pointer == '\"')
416933965Sjdp    {
417033965Sjdp      input_line_pointer++;	/* Skip opening quote. */
417133965Sjdp
417233965Sjdp      while (is_a_char (c = next_char_of_string ()))
417333965Sjdp	{
417433965Sjdp	  obstack_1grow (&notes, c);
417533965Sjdp	  len++;
417633965Sjdp	}
417733965Sjdp      /* JF this next line is so demand_copy_C_string will return a
417833965Sjdp	 null terminated string. */
417933965Sjdp      obstack_1grow (&notes, '\0');
418033965Sjdp      retval = obstack_finish (&notes);
418133965Sjdp    }
418233965Sjdp  else
418333965Sjdp    {
418433965Sjdp      as_warn ("Missing string");
418533965Sjdp      retval = NULL;
418633965Sjdp      ignore_rest_of_line ();
418733965Sjdp    }
418833965Sjdp  *lenP = len;
418933965Sjdp  return (retval);
419033965Sjdp}				/* demand_copy_string() */
419133965Sjdp
419233965Sjdp/*
419333965Sjdp *		is_it_end_of_statement()
419433965Sjdp *
419533965Sjdp * In:	Input_line_pointer->next character.
419633965Sjdp *
419733965Sjdp * Do:	Skip input_line_pointer over all whitespace.
419833965Sjdp *
419933965Sjdp * Out:	1 if input_line_pointer->end-of-line.
420033965Sjdp*/
420133965Sjdpint
420233965Sjdpis_it_end_of_statement ()
420333965Sjdp{
420433965Sjdp  SKIP_WHITESPACE ();
420533965Sjdp  return (is_end_of_line[(unsigned char) *input_line_pointer]);
420633965Sjdp}				/* is_it_end_of_statement() */
420733965Sjdp
420833965Sjdpvoid
420933965Sjdpequals (sym_name, reassign)
421033965Sjdp     char *sym_name;
421133965Sjdp     int reassign;
421233965Sjdp{
421333965Sjdp  register symbolS *symbolP;	/* symbol we are working with */
421433965Sjdp  char *stop;
421533965Sjdp  char stopc;
421633965Sjdp
421733965Sjdp  input_line_pointer++;
421833965Sjdp  if (*input_line_pointer == '=')
421933965Sjdp    input_line_pointer++;
422033965Sjdp
422133965Sjdp  while (*input_line_pointer == ' ' || *input_line_pointer == '\t')
422233965Sjdp    input_line_pointer++;
422333965Sjdp
422433965Sjdp  if (flag_mri)
422533965Sjdp    stop = mri_comment_field (&stopc);
422633965Sjdp
422733965Sjdp  if (sym_name[0] == '.' && sym_name[1] == '\0')
422833965Sjdp    {
422933965Sjdp      /* Turn '. = mumble' into a .org mumble */
423033965Sjdp      register segT segment;
423133965Sjdp      expressionS exp;
423233965Sjdp
423333965Sjdp      segment = get_known_segmented_expression (&exp);
423433965Sjdp      if (!need_pass_2)
423533965Sjdp	do_org (segment, &exp, 0);
423633965Sjdp    }
423733965Sjdp  else
423833965Sjdp    {
423933965Sjdp      symbolP = symbol_find_or_make (sym_name);
424033965Sjdp      /* Permit register names to be redefined.  */
424133965Sjdp      if (! reassign
424233965Sjdp	  && S_IS_DEFINED (symbolP)
424333965Sjdp	  && S_GET_SEGMENT (symbolP) != reg_section)
424433965Sjdp	as_bad ("symbol `%s' already defined", S_GET_NAME (symbolP));
424533965Sjdp      pseudo_set (symbolP);
424633965Sjdp    }
424733965Sjdp
424833965Sjdp  if (flag_mri)
424933965Sjdp    mri_comment_end (stop, stopc);
425033965Sjdp}				/* equals() */
425133965Sjdp
425233965Sjdp/* .include -- include a file at this point. */
425333965Sjdp
425433965Sjdp/* ARGSUSED */
425533965Sjdpvoid
425633965Sjdps_include (arg)
425733965Sjdp     int arg;
425833965Sjdp{
425933965Sjdp  char *newbuf;
426033965Sjdp  char *filename;
426133965Sjdp  int i;
426233965Sjdp  FILE *try;
426333965Sjdp  char *path;
426433965Sjdp
426533965Sjdp  if (! flag_m68k_mri)
426633965Sjdp    filename = demand_copy_string (&i);
426733965Sjdp  else
426833965Sjdp    {
426933965Sjdp      SKIP_WHITESPACE ();
427033965Sjdp      i = 0;
427133965Sjdp      while (! is_end_of_line[(unsigned char) *input_line_pointer]
427233965Sjdp	     && *input_line_pointer != ' '
427333965Sjdp	     && *input_line_pointer != '\t')
427433965Sjdp	{
427533965Sjdp	  obstack_1grow (&notes, *input_line_pointer);
427633965Sjdp	  ++input_line_pointer;
427733965Sjdp	  ++i;
427833965Sjdp	}
427933965Sjdp      obstack_1grow (&notes, '\0');
428033965Sjdp      filename = obstack_finish (&notes);
428133965Sjdp      while (! is_end_of_line[(unsigned char) *input_line_pointer])
428233965Sjdp	++input_line_pointer;
428333965Sjdp    }
428433965Sjdp  demand_empty_rest_of_line ();
428533965Sjdp  path = xmalloc ((unsigned long) i + include_dir_maxlen + 5 /* slop */ );
428633965Sjdp  for (i = 0; i < include_dir_count; i++)
428733965Sjdp    {
428833965Sjdp      strcpy (path, include_dirs[i]);
428933965Sjdp      strcat (path, "/");
429033965Sjdp      strcat (path, filename);
429133965Sjdp      if (0 != (try = fopen (path, "r")))
429233965Sjdp	{
429333965Sjdp	  fclose (try);
429433965Sjdp	  goto gotit;
429533965Sjdp	}
429633965Sjdp    }
429733965Sjdp  free (path);
429833965Sjdp  path = filename;
429933965Sjdpgotit:
430033965Sjdp  /* malloc Storage leak when file is found on path.  FIXME-SOMEDAY. */
430133965Sjdp  newbuf = input_scrub_include_file (path, input_line_pointer);
430233965Sjdp  buffer_limit = input_scrub_next_buffer (&input_line_pointer);
430333965Sjdp}				/* s_include() */
430433965Sjdp
430533965Sjdpvoid
430633965Sjdpadd_include_dir (path)
430733965Sjdp     char *path;
430833965Sjdp{
430933965Sjdp  int i;
431033965Sjdp
431133965Sjdp  if (include_dir_count == 0)
431233965Sjdp    {
431333965Sjdp      include_dirs = (char **) xmalloc (2 * sizeof (*include_dirs));
431433965Sjdp      include_dirs[0] = ".";	/* Current dir */
431533965Sjdp      include_dir_count = 2;
431633965Sjdp    }
431733965Sjdp  else
431833965Sjdp    {
431933965Sjdp      include_dir_count++;
432033965Sjdp      include_dirs = (char **) realloc (include_dirs,
432133965Sjdp				include_dir_count * sizeof (*include_dirs));
432233965Sjdp    }
432333965Sjdp
432433965Sjdp  include_dirs[include_dir_count - 1] = path;	/* New one */
432533965Sjdp
432633965Sjdp  i = strlen (path);
432733965Sjdp  if (i > include_dir_maxlen)
432833965Sjdp    include_dir_maxlen = i;
432933965Sjdp}				/* add_include_dir() */
433033965Sjdp
433133965Sjdpvoid
433233965Sjdps_ignore (arg)
433333965Sjdp     int arg;
433433965Sjdp{
433533965Sjdp  while (!is_end_of_line[(unsigned char) *input_line_pointer])
433633965Sjdp    {
433733965Sjdp      ++input_line_pointer;
433833965Sjdp    }
433933965Sjdp  ++input_line_pointer;
434033965Sjdp}
434133965Sjdp
434233965Sjdp
434333965Sjdpvoid
434433965Sjdpread_print_statistics (file)
434533965Sjdp     FILE *file;
434633965Sjdp{
434733965Sjdp  hash_print_statistics (file, "pseudo-op table", po_hash);
434833965Sjdp}
434933965Sjdp
435033965Sjdp/* end of read.c */
4351