xref: /openbsd-src/gnu/usr.bin/binutils-2.17/gas/app.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* This is the Assembler Pre-Processor
2*3d8817e4Smiod    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3*3d8817e4Smiod    1999, 2000, 2001, 2002, 2003
4*3d8817e4Smiod    Free Software Foundation, Inc.
5*3d8817e4Smiod 
6*3d8817e4Smiod    This file is part of GAS, the GNU Assembler.
7*3d8817e4Smiod 
8*3d8817e4Smiod    GAS is free software; you can redistribute it and/or modify
9*3d8817e4Smiod    it under the terms of the GNU General Public License as published by
10*3d8817e4Smiod    the Free Software Foundation; either version 2, or (at your option)
11*3d8817e4Smiod    any later version.
12*3d8817e4Smiod 
13*3d8817e4Smiod    GAS is distributed in the hope that it will be useful,
14*3d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
15*3d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*3d8817e4Smiod    GNU General Public License for more details.
17*3d8817e4Smiod 
18*3d8817e4Smiod    You should have received a copy of the GNU General Public License
19*3d8817e4Smiod    along with GAS; see the file COPYING.  If not, write to the Free
20*3d8817e4Smiod    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21*3d8817e4Smiod    02110-1301, USA.  */
22*3d8817e4Smiod 
23*3d8817e4Smiod /* Modified by Allen Wirfs-Brock, Instantiations Inc 2/90.  */
24*3d8817e4Smiod /* App, the assembler pre-processor.  This pre-processor strips out excess
25*3d8817e4Smiod    spaces, turns single-quoted characters into a decimal constant, and turns
26*3d8817e4Smiod    # <number> <filename> <garbage> into a .line <number>\n.file <filename>
27*3d8817e4Smiod    pair.  This needs better error-handling.  */
28*3d8817e4Smiod 
29*3d8817e4Smiod #include <stdio.h>
30*3d8817e4Smiod #include "as.h"			/* For BAD_CASE() only.  */
31*3d8817e4Smiod 
32*3d8817e4Smiod #if (__STDC__ != 1)
33*3d8817e4Smiod #ifndef const
34*3d8817e4Smiod #define const  /* empty */
35*3d8817e4Smiod #endif
36*3d8817e4Smiod #endif
37*3d8817e4Smiod 
38*3d8817e4Smiod #ifdef TC_M68K
39*3d8817e4Smiod /* Whether we are scrubbing in m68k MRI mode.  This is different from
40*3d8817e4Smiod    flag_m68k_mri, because the two flags will be affected by the .mri
41*3d8817e4Smiod    pseudo-op at different times.  */
42*3d8817e4Smiod static int scrub_m68k_mri;
43*3d8817e4Smiod 
44*3d8817e4Smiod /* The pseudo-op which switches in and out of MRI mode.  See the
45*3d8817e4Smiod    comment in do_scrub_chars.  */
46*3d8817e4Smiod static const char mri_pseudo[] = ".mri 0";
47*3d8817e4Smiod #else
48*3d8817e4Smiod #define scrub_m68k_mri 0
49*3d8817e4Smiod #endif
50*3d8817e4Smiod 
51*3d8817e4Smiod #if defined TC_ARM && defined OBJ_ELF
52*3d8817e4Smiod /* The pseudo-op for which we need to special-case `@' characters.
53*3d8817e4Smiod    See the comment in do_scrub_chars.  */
54*3d8817e4Smiod static const char   symver_pseudo[] = ".symver";
55*3d8817e4Smiod static const char * symver_state;
56*3d8817e4Smiod #endif
57*3d8817e4Smiod 
58*3d8817e4Smiod static char lex[256];
59*3d8817e4Smiod static const char symbol_chars[] =
60*3d8817e4Smiod "$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
61*3d8817e4Smiod 
62*3d8817e4Smiod #define LEX_IS_SYMBOL_COMPONENT		1
63*3d8817e4Smiod #define LEX_IS_WHITESPACE		2
64*3d8817e4Smiod #define LEX_IS_LINE_SEPARATOR		3
65*3d8817e4Smiod #define LEX_IS_COMMENT_START		4
66*3d8817e4Smiod #define LEX_IS_LINE_COMMENT_START	5
67*3d8817e4Smiod #define	LEX_IS_TWOCHAR_COMMENT_1ST	6
68*3d8817e4Smiod #define	LEX_IS_STRINGQUOTE		8
69*3d8817e4Smiod #define	LEX_IS_COLON			9
70*3d8817e4Smiod #define	LEX_IS_NEWLINE			10
71*3d8817e4Smiod #define	LEX_IS_ONECHAR_QUOTE		11
72*3d8817e4Smiod #ifdef TC_V850
73*3d8817e4Smiod #define LEX_IS_DOUBLEDASH_1ST		12
74*3d8817e4Smiod #endif
75*3d8817e4Smiod #ifdef TC_M32R
76*3d8817e4Smiod #define DOUBLEBAR_PARALLEL
77*3d8817e4Smiod #endif
78*3d8817e4Smiod #ifdef DOUBLEBAR_PARALLEL
79*3d8817e4Smiod #define LEX_IS_DOUBLEBAR_1ST		13
80*3d8817e4Smiod #endif
81*3d8817e4Smiod #define LEX_IS_PARALLEL_SEPARATOR	14
82*3d8817e4Smiod #define IS_SYMBOL_COMPONENT(c)		(lex[c] == LEX_IS_SYMBOL_COMPONENT)
83*3d8817e4Smiod #define IS_WHITESPACE(c)		(lex[c] == LEX_IS_WHITESPACE)
84*3d8817e4Smiod #define IS_LINE_SEPARATOR(c)		(lex[c] == LEX_IS_LINE_SEPARATOR)
85*3d8817e4Smiod #define IS_PARALLEL_SEPARATOR(c)	(lex[c] == LEX_IS_PARALLEL_SEPARATOR)
86*3d8817e4Smiod #define IS_COMMENT(c)			(lex[c] == LEX_IS_COMMENT_START)
87*3d8817e4Smiod #define IS_LINE_COMMENT(c)		(lex[c] == LEX_IS_LINE_COMMENT_START)
88*3d8817e4Smiod #define	IS_NEWLINE(c)			(lex[c] == LEX_IS_NEWLINE)
89*3d8817e4Smiod 
90*3d8817e4Smiod static int process_escape (int);
91*3d8817e4Smiod 
92*3d8817e4Smiod /* FIXME-soon: The entire lexer/parser thingy should be
93*3d8817e4Smiod    built statically at compile time rather than dynamically
94*3d8817e4Smiod    each and every time the assembler is run.  xoxorich.  */
95*3d8817e4Smiod 
96*3d8817e4Smiod void
do_scrub_begin(int m68k_mri ATTRIBUTE_UNUSED)97*3d8817e4Smiod do_scrub_begin (int m68k_mri ATTRIBUTE_UNUSED)
98*3d8817e4Smiod {
99*3d8817e4Smiod   const char *p;
100*3d8817e4Smiod   int c;
101*3d8817e4Smiod 
102*3d8817e4Smiod   lex[' '] = LEX_IS_WHITESPACE;
103*3d8817e4Smiod   lex['\t'] = LEX_IS_WHITESPACE;
104*3d8817e4Smiod   lex['\r'] = LEX_IS_WHITESPACE;
105*3d8817e4Smiod   lex['\n'] = LEX_IS_NEWLINE;
106*3d8817e4Smiod   lex[':'] = LEX_IS_COLON;
107*3d8817e4Smiod 
108*3d8817e4Smiod #ifdef TC_M68K
109*3d8817e4Smiod   scrub_m68k_mri = m68k_mri;
110*3d8817e4Smiod 
111*3d8817e4Smiod   if (! m68k_mri)
112*3d8817e4Smiod #endif
113*3d8817e4Smiod     {
114*3d8817e4Smiod       lex['"'] = LEX_IS_STRINGQUOTE;
115*3d8817e4Smiod 
116*3d8817e4Smiod #if ! defined (TC_HPPA) && ! defined (TC_I370)
117*3d8817e4Smiod       /* I370 uses single-quotes to delimit integer, float constants.  */
118*3d8817e4Smiod       lex['\''] = LEX_IS_ONECHAR_QUOTE;
119*3d8817e4Smiod #endif
120*3d8817e4Smiod 
121*3d8817e4Smiod #ifdef SINGLE_QUOTE_STRINGS
122*3d8817e4Smiod       lex['\''] = LEX_IS_STRINGQUOTE;
123*3d8817e4Smiod #endif
124*3d8817e4Smiod     }
125*3d8817e4Smiod 
126*3d8817e4Smiod   /* Note: if any other character can be LEX_IS_STRINGQUOTE, the loop
127*3d8817e4Smiod      in state 5 of do_scrub_chars must be changed.  */
128*3d8817e4Smiod 
129*3d8817e4Smiod   /* Note that these override the previous defaults, e.g. if ';' is a
130*3d8817e4Smiod      comment char, then it isn't a line separator.  */
131*3d8817e4Smiod   for (p = symbol_chars; *p; ++p)
132*3d8817e4Smiod     lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT;
133*3d8817e4Smiod 
134*3d8817e4Smiod   for (c = 128; c < 256; ++c)
135*3d8817e4Smiod     lex[c] = LEX_IS_SYMBOL_COMPONENT;
136*3d8817e4Smiod 
137*3d8817e4Smiod #ifdef tc_symbol_chars
138*3d8817e4Smiod   /* This macro permits the processor to specify all characters which
139*3d8817e4Smiod      may appears in an operand.  This will prevent the scrubber from
140*3d8817e4Smiod      discarding meaningful whitespace in certain cases.  The i386
141*3d8817e4Smiod      backend uses this to support prefixes, which can confuse the
142*3d8817e4Smiod      scrubber as to whether it is parsing operands or opcodes.  */
143*3d8817e4Smiod   for (p = tc_symbol_chars; *p; ++p)
144*3d8817e4Smiod     lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT;
145*3d8817e4Smiod #endif
146*3d8817e4Smiod 
147*3d8817e4Smiod   /* The m68k backend wants to be able to change comment_chars.  */
148*3d8817e4Smiod #ifndef tc_comment_chars
149*3d8817e4Smiod #define tc_comment_chars comment_chars
150*3d8817e4Smiod #endif
151*3d8817e4Smiod   for (p = tc_comment_chars; *p; p++)
152*3d8817e4Smiod     lex[(unsigned char) *p] = LEX_IS_COMMENT_START;
153*3d8817e4Smiod 
154*3d8817e4Smiod   for (p = line_comment_chars; *p; p++)
155*3d8817e4Smiod     lex[(unsigned char) *p] = LEX_IS_LINE_COMMENT_START;
156*3d8817e4Smiod 
157*3d8817e4Smiod   for (p = line_separator_chars; *p; p++)
158*3d8817e4Smiod     lex[(unsigned char) *p] = LEX_IS_LINE_SEPARATOR;
159*3d8817e4Smiod 
160*3d8817e4Smiod #ifdef tc_parallel_separator_chars
161*3d8817e4Smiod   /* This macro permits the processor to specify all characters which
162*3d8817e4Smiod      separate parallel insns on the same line.  */
163*3d8817e4Smiod   for (p = tc_parallel_separator_chars; *p; p++)
164*3d8817e4Smiod     lex[(unsigned char) *p] = LEX_IS_PARALLEL_SEPARATOR;
165*3d8817e4Smiod #endif
166*3d8817e4Smiod 
167*3d8817e4Smiod   /* Only allow slash-star comments if slash is not in use.
168*3d8817e4Smiod      FIXME: This isn't right.  We should always permit them.  */
169*3d8817e4Smiod   if (lex['/'] == 0)
170*3d8817e4Smiod     lex['/'] = LEX_IS_TWOCHAR_COMMENT_1ST;
171*3d8817e4Smiod 
172*3d8817e4Smiod #ifdef TC_M68K
173*3d8817e4Smiod   if (m68k_mri)
174*3d8817e4Smiod     {
175*3d8817e4Smiod       lex['\''] = LEX_IS_STRINGQUOTE;
176*3d8817e4Smiod       lex[';'] = LEX_IS_COMMENT_START;
177*3d8817e4Smiod       lex['*'] = LEX_IS_LINE_COMMENT_START;
178*3d8817e4Smiod       /* The MRI documentation says '!' is LEX_IS_COMMENT_START, but
179*3d8817e4Smiod 	 then it can't be used in an expression.  */
180*3d8817e4Smiod       lex['!'] = LEX_IS_LINE_COMMENT_START;
181*3d8817e4Smiod     }
182*3d8817e4Smiod #endif
183*3d8817e4Smiod 
184*3d8817e4Smiod #ifdef TC_V850
185*3d8817e4Smiod   lex['-'] = LEX_IS_DOUBLEDASH_1ST;
186*3d8817e4Smiod #endif
187*3d8817e4Smiod #ifdef DOUBLEBAR_PARALLEL
188*3d8817e4Smiod   lex['|'] = LEX_IS_DOUBLEBAR_1ST;
189*3d8817e4Smiod #endif
190*3d8817e4Smiod #ifdef TC_D30V
191*3d8817e4Smiod   /* Must do this is we want VLIW instruction with "->" or "<-".  */
192*3d8817e4Smiod   lex['-'] = LEX_IS_SYMBOL_COMPONENT;
193*3d8817e4Smiod #endif
194*3d8817e4Smiod }
195*3d8817e4Smiod 
196*3d8817e4Smiod /* Saved state of the scrubber.  */
197*3d8817e4Smiod static int state;
198*3d8817e4Smiod static int old_state;
199*3d8817e4Smiod static char *out_string;
200*3d8817e4Smiod static char out_buf[20];
201*3d8817e4Smiod static int add_newlines;
202*3d8817e4Smiod static char *saved_input;
203*3d8817e4Smiod static int saved_input_len;
204*3d8817e4Smiod static char input_buffer[32 * 1024];
205*3d8817e4Smiod static const char *mri_state;
206*3d8817e4Smiod static char mri_last_ch;
207*3d8817e4Smiod 
208*3d8817e4Smiod /* Data structure for saving the state of app across #include's.  Note that
209*3d8817e4Smiod    app is called asynchronously to the parsing of the .include's, so our
210*3d8817e4Smiod    state at the time .include is interpreted is completely unrelated.
211*3d8817e4Smiod    That's why we have to save it all.  */
212*3d8817e4Smiod 
213*3d8817e4Smiod struct app_save
214*3d8817e4Smiod {
215*3d8817e4Smiod   int          state;
216*3d8817e4Smiod   int          old_state;
217*3d8817e4Smiod   char *       out_string;
218*3d8817e4Smiod   char         out_buf[sizeof (out_buf)];
219*3d8817e4Smiod   int          add_newlines;
220*3d8817e4Smiod   char *       saved_input;
221*3d8817e4Smiod   int          saved_input_len;
222*3d8817e4Smiod #ifdef TC_M68K
223*3d8817e4Smiod   int          scrub_m68k_mri;
224*3d8817e4Smiod #endif
225*3d8817e4Smiod   const char * mri_state;
226*3d8817e4Smiod   char         mri_last_ch;
227*3d8817e4Smiod #if defined TC_ARM && defined OBJ_ELF
228*3d8817e4Smiod   const char * symver_state;
229*3d8817e4Smiod #endif
230*3d8817e4Smiod };
231*3d8817e4Smiod 
232*3d8817e4Smiod char *
app_push(void)233*3d8817e4Smiod app_push (void)
234*3d8817e4Smiod {
235*3d8817e4Smiod   register struct app_save *saved;
236*3d8817e4Smiod 
237*3d8817e4Smiod   saved = (struct app_save *) xmalloc (sizeof (*saved));
238*3d8817e4Smiod   saved->state = state;
239*3d8817e4Smiod   saved->old_state = old_state;
240*3d8817e4Smiod   saved->out_string = out_string;
241*3d8817e4Smiod   memcpy (saved->out_buf, out_buf, sizeof (out_buf));
242*3d8817e4Smiod   saved->add_newlines = add_newlines;
243*3d8817e4Smiod   if (saved_input == NULL)
244*3d8817e4Smiod     saved->saved_input = NULL;
245*3d8817e4Smiod   else
246*3d8817e4Smiod     {
247*3d8817e4Smiod       saved->saved_input = xmalloc (saved_input_len);
248*3d8817e4Smiod       memcpy (saved->saved_input, saved_input, saved_input_len);
249*3d8817e4Smiod       saved->saved_input_len = saved_input_len;
250*3d8817e4Smiod     }
251*3d8817e4Smiod #ifdef TC_M68K
252*3d8817e4Smiod   saved->scrub_m68k_mri = scrub_m68k_mri;
253*3d8817e4Smiod #endif
254*3d8817e4Smiod   saved->mri_state = mri_state;
255*3d8817e4Smiod   saved->mri_last_ch = mri_last_ch;
256*3d8817e4Smiod #if defined TC_ARM && defined OBJ_ELF
257*3d8817e4Smiod   saved->symver_state = symver_state;
258*3d8817e4Smiod #endif
259*3d8817e4Smiod 
260*3d8817e4Smiod   /* do_scrub_begin() is not useful, just wastes time.  */
261*3d8817e4Smiod 
262*3d8817e4Smiod   state = 0;
263*3d8817e4Smiod   saved_input = NULL;
264*3d8817e4Smiod 
265*3d8817e4Smiod   return (char *) saved;
266*3d8817e4Smiod }
267*3d8817e4Smiod 
268*3d8817e4Smiod void
app_pop(char * arg)269*3d8817e4Smiod app_pop (char *arg)
270*3d8817e4Smiod {
271*3d8817e4Smiod   register struct app_save *saved = (struct app_save *) arg;
272*3d8817e4Smiod 
273*3d8817e4Smiod   /* There is no do_scrub_end ().  */
274*3d8817e4Smiod   state = saved->state;
275*3d8817e4Smiod   old_state = saved->old_state;
276*3d8817e4Smiod   out_string = saved->out_string;
277*3d8817e4Smiod   memcpy (out_buf, saved->out_buf, sizeof (out_buf));
278*3d8817e4Smiod   add_newlines = saved->add_newlines;
279*3d8817e4Smiod   if (saved->saved_input == NULL)
280*3d8817e4Smiod     saved_input = NULL;
281*3d8817e4Smiod   else
282*3d8817e4Smiod     {
283*3d8817e4Smiod       assert (saved->saved_input_len <= (int) (sizeof input_buffer));
284*3d8817e4Smiod       memcpy (input_buffer, saved->saved_input, saved->saved_input_len);
285*3d8817e4Smiod       saved_input = input_buffer;
286*3d8817e4Smiod       saved_input_len = saved->saved_input_len;
287*3d8817e4Smiod       free (saved->saved_input);
288*3d8817e4Smiod     }
289*3d8817e4Smiod #ifdef TC_M68K
290*3d8817e4Smiod   scrub_m68k_mri = saved->scrub_m68k_mri;
291*3d8817e4Smiod #endif
292*3d8817e4Smiod   mri_state = saved->mri_state;
293*3d8817e4Smiod   mri_last_ch = saved->mri_last_ch;
294*3d8817e4Smiod #if defined TC_ARM && defined OBJ_ELF
295*3d8817e4Smiod   symver_state = saved->symver_state;
296*3d8817e4Smiod #endif
297*3d8817e4Smiod 
298*3d8817e4Smiod   free (arg);
299*3d8817e4Smiod }
300*3d8817e4Smiod 
301*3d8817e4Smiod /* @@ This assumes that \n &c are the same on host and target.  This is not
302*3d8817e4Smiod    necessarily true.  */
303*3d8817e4Smiod 
304*3d8817e4Smiod static int
process_escape(int ch)305*3d8817e4Smiod process_escape (int ch)
306*3d8817e4Smiod {
307*3d8817e4Smiod   switch (ch)
308*3d8817e4Smiod     {
309*3d8817e4Smiod     case 'b':
310*3d8817e4Smiod       return '\b';
311*3d8817e4Smiod     case 'f':
312*3d8817e4Smiod       return '\f';
313*3d8817e4Smiod     case 'n':
314*3d8817e4Smiod       return '\n';
315*3d8817e4Smiod     case 'r':
316*3d8817e4Smiod       return '\r';
317*3d8817e4Smiod     case 't':
318*3d8817e4Smiod       return '\t';
319*3d8817e4Smiod     case '\'':
320*3d8817e4Smiod       return '\'';
321*3d8817e4Smiod     case '"':
322*3d8817e4Smiod       return '\"';
323*3d8817e4Smiod     default:
324*3d8817e4Smiod       return ch;
325*3d8817e4Smiod     }
326*3d8817e4Smiod }
327*3d8817e4Smiod 
328*3d8817e4Smiod /* This function is called to process input characters.  The GET
329*3d8817e4Smiod    parameter is used to retrieve more input characters.  GET should
330*3d8817e4Smiod    set its parameter to point to a buffer, and return the length of
331*3d8817e4Smiod    the buffer; it should return 0 at end of file.  The scrubbed output
332*3d8817e4Smiod    characters are put into the buffer starting at TOSTART; the TOSTART
333*3d8817e4Smiod    buffer is TOLEN bytes in length.  The function returns the number
334*3d8817e4Smiod    of scrubbed characters put into TOSTART.  This will be TOLEN unless
335*3d8817e4Smiod    end of file was seen.  This function is arranged as a state
336*3d8817e4Smiod    machine, and saves its state so that it may return at any point.
337*3d8817e4Smiod    This is the way the old code used to work.  */
338*3d8817e4Smiod 
339*3d8817e4Smiod int
do_scrub_chars(int (* get)(char *,int),char * tostart,int tolen)340*3d8817e4Smiod do_scrub_chars (int (*get) (char *, int), char *tostart, int tolen)
341*3d8817e4Smiod {
342*3d8817e4Smiod   char *to = tostart;
343*3d8817e4Smiod   char *toend = tostart + tolen;
344*3d8817e4Smiod   char *from;
345*3d8817e4Smiod   char *fromend;
346*3d8817e4Smiod   int fromlen;
347*3d8817e4Smiod   register int ch, ch2 = 0;
348*3d8817e4Smiod   /* Character that started the string we're working on.  */
349*3d8817e4Smiod   static char quotechar;
350*3d8817e4Smiod 
351*3d8817e4Smiod   /*State 0: beginning of normal line
352*3d8817e4Smiod 	  1: After first whitespace on line (flush more white)
353*3d8817e4Smiod 	  2: After first non-white (opcode) on line (keep 1white)
354*3d8817e4Smiod 	  3: after second white on line (into operands) (flush white)
355*3d8817e4Smiod 	  4: after putting out a .line, put out digits
356*3d8817e4Smiod 	  5: parsing a string, then go to old-state
357*3d8817e4Smiod 	  6: putting out \ escape in a "d string.
358*3d8817e4Smiod 	  7: After putting out a .appfile, put out string.
359*3d8817e4Smiod 	  8: After putting out a .appfile string, flush until newline.
360*3d8817e4Smiod 	  9: After seeing symbol char in state 3 (keep 1white after symchar)
361*3d8817e4Smiod 	 10: After seeing whitespace in state 9 (keep white before symchar)
362*3d8817e4Smiod 	 11: After seeing a symbol character in state 0 (eg a label definition)
363*3d8817e4Smiod 	 -1: output string in out_string and go to the state in old_state
364*3d8817e4Smiod 	 -2: flush text until a '*' '/' is seen, then go to state old_state
365*3d8817e4Smiod #ifdef TC_V850
366*3d8817e4Smiod 	 12: After seeing a dash, looking for a second dash as a start
367*3d8817e4Smiod 	     of comment.
368*3d8817e4Smiod #endif
369*3d8817e4Smiod #ifdef DOUBLEBAR_PARALLEL
370*3d8817e4Smiod 	 13: After seeing a vertical bar, looking for a second
371*3d8817e4Smiod 	     vertical bar as a parallel expression separator.
372*3d8817e4Smiod #endif
373*3d8817e4Smiod #ifdef TC_IA64
374*3d8817e4Smiod 	 14: After seeing a `(' at state 0, looking for a `)' as
375*3d8817e4Smiod 	     predicate.
376*3d8817e4Smiod 	 15: After seeing a `(' at state 1, looking for a `)' as
377*3d8817e4Smiod 	     predicate.
378*3d8817e4Smiod #endif
379*3d8817e4Smiod #ifdef TC_Z80
380*3d8817e4Smiod 	 16: After seeing an 'a' or an 'A' at the start of a symbol
381*3d8817e4Smiod 	 17: After seeing an 'f' or an 'F' in state 16
382*3d8817e4Smiod #endif
383*3d8817e4Smiod 	  */
384*3d8817e4Smiod 
385*3d8817e4Smiod   /* I added states 9 and 10 because the MIPS ECOFF assembler uses
386*3d8817e4Smiod      constructs like ``.loc 1 20''.  This was turning into ``.loc
387*3d8817e4Smiod      120''.  States 9 and 10 ensure that a space is never dropped in
388*3d8817e4Smiod      between characters which could appear in an identifier.  Ian
389*3d8817e4Smiod      Taylor, ian@cygnus.com.
390*3d8817e4Smiod 
391*3d8817e4Smiod      I added state 11 so that something like "Lfoo add %r25,%r26,%r27" works
392*3d8817e4Smiod      correctly on the PA (and any other target where colons are optional).
393*3d8817e4Smiod      Jeff Law, law@cs.utah.edu.
394*3d8817e4Smiod 
395*3d8817e4Smiod      I added state 13 so that something like "cmp r1, r2 || trap #1" does not
396*3d8817e4Smiod      get squashed into "cmp r1,r2||trap#1", with the all important space
397*3d8817e4Smiod      between the 'trap' and the '#1' being eliminated.  nickc@cygnus.com  */
398*3d8817e4Smiod 
399*3d8817e4Smiod   /* This macro gets the next input character.  */
400*3d8817e4Smiod 
401*3d8817e4Smiod #define GET()							\
402*3d8817e4Smiod   (from < fromend						\
403*3d8817e4Smiod    ? * (unsigned char *) (from++)				\
404*3d8817e4Smiod    : (saved_input = NULL,					\
405*3d8817e4Smiod       fromlen = (*get) (input_buffer, sizeof input_buffer),	\
406*3d8817e4Smiod       from = input_buffer,					\
407*3d8817e4Smiod       fromend = from + fromlen,					\
408*3d8817e4Smiod       (fromlen == 0						\
409*3d8817e4Smiod        ? EOF							\
410*3d8817e4Smiod        : * (unsigned char *) (from++))))
411*3d8817e4Smiod 
412*3d8817e4Smiod   /* This macro pushes a character back on the input stream.  */
413*3d8817e4Smiod 
414*3d8817e4Smiod #define UNGET(uch) (*--from = (uch))
415*3d8817e4Smiod 
416*3d8817e4Smiod   /* This macro puts a character into the output buffer.  If this
417*3d8817e4Smiod      character fills the output buffer, this macro jumps to the label
418*3d8817e4Smiod      TOFULL.  We use this rather ugly approach because we need to
419*3d8817e4Smiod      handle two different termination conditions: EOF on the input
420*3d8817e4Smiod      stream, and a full output buffer.  It would be simpler if we
421*3d8817e4Smiod      always read in the entire input stream before processing it, but
422*3d8817e4Smiod      I don't want to make such a significant change to the assembler's
423*3d8817e4Smiod      memory usage.  */
424*3d8817e4Smiod 
425*3d8817e4Smiod #define PUT(pch)				\
426*3d8817e4Smiod   do						\
427*3d8817e4Smiod     {						\
428*3d8817e4Smiod       *to++ = (pch);				\
429*3d8817e4Smiod       if (to >= toend)				\
430*3d8817e4Smiod 	goto tofull;				\
431*3d8817e4Smiod     }						\
432*3d8817e4Smiod   while (0)
433*3d8817e4Smiod 
434*3d8817e4Smiod   if (saved_input != NULL)
435*3d8817e4Smiod     {
436*3d8817e4Smiod       from = saved_input;
437*3d8817e4Smiod       fromend = from + saved_input_len;
438*3d8817e4Smiod     }
439*3d8817e4Smiod   else
440*3d8817e4Smiod     {
441*3d8817e4Smiod       fromlen = (*get) (input_buffer, sizeof input_buffer);
442*3d8817e4Smiod       if (fromlen == 0)
443*3d8817e4Smiod 	return 0;
444*3d8817e4Smiod       from = input_buffer;
445*3d8817e4Smiod       fromend = from + fromlen;
446*3d8817e4Smiod     }
447*3d8817e4Smiod 
448*3d8817e4Smiod   while (1)
449*3d8817e4Smiod     {
450*3d8817e4Smiod       /* The cases in this switch end with continue, in order to
451*3d8817e4Smiod 	 branch back to the top of this while loop and generate the
452*3d8817e4Smiod 	 next output character in the appropriate state.  */
453*3d8817e4Smiod       switch (state)
454*3d8817e4Smiod 	{
455*3d8817e4Smiod 	case -1:
456*3d8817e4Smiod 	  ch = *out_string++;
457*3d8817e4Smiod 	  if (*out_string == '\0')
458*3d8817e4Smiod 	    {
459*3d8817e4Smiod 	      state = old_state;
460*3d8817e4Smiod 	      old_state = 3;
461*3d8817e4Smiod 	    }
462*3d8817e4Smiod 	  PUT (ch);
463*3d8817e4Smiod 	  continue;
464*3d8817e4Smiod 
465*3d8817e4Smiod 	case -2:
466*3d8817e4Smiod 	  for (;;)
467*3d8817e4Smiod 	    {
468*3d8817e4Smiod 	      do
469*3d8817e4Smiod 		{
470*3d8817e4Smiod 		  ch = GET ();
471*3d8817e4Smiod 
472*3d8817e4Smiod 		  if (ch == EOF)
473*3d8817e4Smiod 		    {
474*3d8817e4Smiod 		      as_warn (_("end of file in comment"));
475*3d8817e4Smiod 		      goto fromeof;
476*3d8817e4Smiod 		    }
477*3d8817e4Smiod 
478*3d8817e4Smiod 		  if (ch == '\n')
479*3d8817e4Smiod 		    PUT ('\n');
480*3d8817e4Smiod 		}
481*3d8817e4Smiod 	      while (ch != '*');
482*3d8817e4Smiod 
483*3d8817e4Smiod 	      while ((ch = GET ()) == '*')
484*3d8817e4Smiod 		;
485*3d8817e4Smiod 
486*3d8817e4Smiod 	      if (ch == EOF)
487*3d8817e4Smiod 		{
488*3d8817e4Smiod 		  as_warn (_("end of file in comment"));
489*3d8817e4Smiod 		  goto fromeof;
490*3d8817e4Smiod 		}
491*3d8817e4Smiod 
492*3d8817e4Smiod 	      if (ch == '/')
493*3d8817e4Smiod 		break;
494*3d8817e4Smiod 
495*3d8817e4Smiod 	      UNGET (ch);
496*3d8817e4Smiod 	    }
497*3d8817e4Smiod 
498*3d8817e4Smiod 	  state = old_state;
499*3d8817e4Smiod 	  UNGET (' ');
500*3d8817e4Smiod 	  continue;
501*3d8817e4Smiod 
502*3d8817e4Smiod 	case 4:
503*3d8817e4Smiod 	  ch = GET ();
504*3d8817e4Smiod 	  if (ch == EOF)
505*3d8817e4Smiod 	    goto fromeof;
506*3d8817e4Smiod 	  else if (ch >= '0' && ch <= '9')
507*3d8817e4Smiod 	    PUT (ch);
508*3d8817e4Smiod 	  else
509*3d8817e4Smiod 	    {
510*3d8817e4Smiod 	      while (ch != EOF && IS_WHITESPACE (ch))
511*3d8817e4Smiod 		ch = GET ();
512*3d8817e4Smiod 	      if (ch == '"')
513*3d8817e4Smiod 		{
514*3d8817e4Smiod 		  UNGET (ch);
515*3d8817e4Smiod 		  if (scrub_m68k_mri)
516*3d8817e4Smiod 		    out_string = "\n\tappfile ";
517*3d8817e4Smiod 		  else
518*3d8817e4Smiod 		    out_string = "\n\t.appfile ";
519*3d8817e4Smiod 		  old_state = 7;
520*3d8817e4Smiod 		  state = -1;
521*3d8817e4Smiod 		  PUT (*out_string++);
522*3d8817e4Smiod 		}
523*3d8817e4Smiod 	      else
524*3d8817e4Smiod 		{
525*3d8817e4Smiod 		  while (ch != EOF && ch != '\n')
526*3d8817e4Smiod 		    ch = GET ();
527*3d8817e4Smiod 		  state = 0;
528*3d8817e4Smiod 		  PUT (ch);
529*3d8817e4Smiod 		}
530*3d8817e4Smiod 	    }
531*3d8817e4Smiod 	  continue;
532*3d8817e4Smiod 
533*3d8817e4Smiod 	case 5:
534*3d8817e4Smiod 	  /* We are going to copy everything up to a quote character,
535*3d8817e4Smiod 	     with special handling for a backslash.  We try to
536*3d8817e4Smiod 	     optimize the copying in the simple case without using the
537*3d8817e4Smiod 	     GET and PUT macros.  */
538*3d8817e4Smiod 	  {
539*3d8817e4Smiod 	    char *s;
540*3d8817e4Smiod 	    int len;
541*3d8817e4Smiod 
542*3d8817e4Smiod 	    for (s = from; s < fromend; s++)
543*3d8817e4Smiod 	      {
544*3d8817e4Smiod 		ch = *s;
545*3d8817e4Smiod 		if (ch == '\\'
546*3d8817e4Smiod 		    || ch == quotechar
547*3d8817e4Smiod 		    || ch == '\n')
548*3d8817e4Smiod 		  break;
549*3d8817e4Smiod 	      }
550*3d8817e4Smiod 	    len = s - from;
551*3d8817e4Smiod 	    if (len > toend - to)
552*3d8817e4Smiod 	      len = toend - to;
553*3d8817e4Smiod 	    if (len > 0)
554*3d8817e4Smiod 	      {
555*3d8817e4Smiod 		memcpy (to, from, len);
556*3d8817e4Smiod 		to += len;
557*3d8817e4Smiod 		from += len;
558*3d8817e4Smiod 	      }
559*3d8817e4Smiod 	  }
560*3d8817e4Smiod 
561*3d8817e4Smiod 	  ch = GET ();
562*3d8817e4Smiod 	  if (ch == EOF)
563*3d8817e4Smiod 	    {
564*3d8817e4Smiod 	      as_warn (_("end of file in string; '%c' inserted"), quotechar);
565*3d8817e4Smiod 	      state = old_state;
566*3d8817e4Smiod 	      UNGET ('\n');
567*3d8817e4Smiod 	      PUT (quotechar);
568*3d8817e4Smiod 	    }
569*3d8817e4Smiod 	  else if (ch == quotechar)
570*3d8817e4Smiod 	    {
571*3d8817e4Smiod 	      state = old_state;
572*3d8817e4Smiod 	      PUT (ch);
573*3d8817e4Smiod 	    }
574*3d8817e4Smiod #ifndef NO_STRING_ESCAPES
575*3d8817e4Smiod 	  else if (ch == '\\')
576*3d8817e4Smiod 	    {
577*3d8817e4Smiod 	      state = 6;
578*3d8817e4Smiod 	      PUT (ch);
579*3d8817e4Smiod 	    }
580*3d8817e4Smiod #endif
581*3d8817e4Smiod 	  else if (scrub_m68k_mri && ch == '\n')
582*3d8817e4Smiod 	    {
583*3d8817e4Smiod 	      /* Just quietly terminate the string.  This permits lines like
584*3d8817e4Smiod 		   bne	label	loop if we haven't reach end yet.  */
585*3d8817e4Smiod 	      state = old_state;
586*3d8817e4Smiod 	      UNGET (ch);
587*3d8817e4Smiod 	      PUT ('\'');
588*3d8817e4Smiod 	    }
589*3d8817e4Smiod 	  else
590*3d8817e4Smiod 	    {
591*3d8817e4Smiod 	      PUT (ch);
592*3d8817e4Smiod 	    }
593*3d8817e4Smiod 	  continue;
594*3d8817e4Smiod 
595*3d8817e4Smiod 	case 6:
596*3d8817e4Smiod 	  state = 5;
597*3d8817e4Smiod 	  ch = GET ();
598*3d8817e4Smiod 	  switch (ch)
599*3d8817e4Smiod 	    {
600*3d8817e4Smiod 	      /* Handle strings broken across lines, by turning '\n' into
601*3d8817e4Smiod 		 '\\' and 'n'.  */
602*3d8817e4Smiod 	    case '\n':
603*3d8817e4Smiod 	      UNGET ('n');
604*3d8817e4Smiod 	      add_newlines++;
605*3d8817e4Smiod 	      PUT ('\\');
606*3d8817e4Smiod 	      continue;
607*3d8817e4Smiod 
608*3d8817e4Smiod 	    case EOF:
609*3d8817e4Smiod 	      as_warn (_("end of file in string; '%c' inserted"), quotechar);
610*3d8817e4Smiod 	      PUT (quotechar);
611*3d8817e4Smiod 	      continue;
612*3d8817e4Smiod 
613*3d8817e4Smiod 	    case '"':
614*3d8817e4Smiod 	    case '\\':
615*3d8817e4Smiod 	    case 'b':
616*3d8817e4Smiod 	    case 'f':
617*3d8817e4Smiod 	    case 'n':
618*3d8817e4Smiod 	    case 'r':
619*3d8817e4Smiod 	    case 't':
620*3d8817e4Smiod 	    case 'v':
621*3d8817e4Smiod 	    case 'x':
622*3d8817e4Smiod 	    case 'X':
623*3d8817e4Smiod 	    case '0':
624*3d8817e4Smiod 	    case '1':
625*3d8817e4Smiod 	    case '2':
626*3d8817e4Smiod 	    case '3':
627*3d8817e4Smiod 	    case '4':
628*3d8817e4Smiod 	    case '5':
629*3d8817e4Smiod 	    case '6':
630*3d8817e4Smiod 	    case '7':
631*3d8817e4Smiod 	      break;
632*3d8817e4Smiod 
633*3d8817e4Smiod 	    default:
634*3d8817e4Smiod #ifdef ONLY_STANDARD_ESCAPES
635*3d8817e4Smiod 	      as_warn (_("unknown escape '\\%c' in string; ignored"), ch);
636*3d8817e4Smiod #endif
637*3d8817e4Smiod 	      break;
638*3d8817e4Smiod 	    }
639*3d8817e4Smiod 	  PUT (ch);
640*3d8817e4Smiod 	  continue;
641*3d8817e4Smiod 
642*3d8817e4Smiod 	case 7:
643*3d8817e4Smiod 	  ch = GET ();
644*3d8817e4Smiod 	  quotechar = ch;
645*3d8817e4Smiod 	  state = 5;
646*3d8817e4Smiod 	  old_state = 8;
647*3d8817e4Smiod 	  PUT (ch);
648*3d8817e4Smiod 	  continue;
649*3d8817e4Smiod 
650*3d8817e4Smiod 	case 8:
651*3d8817e4Smiod 	  do
652*3d8817e4Smiod 	    ch = GET ();
653*3d8817e4Smiod 	  while (ch != '\n' && ch != EOF);
654*3d8817e4Smiod 	  if (ch == EOF)
655*3d8817e4Smiod 	    goto fromeof;
656*3d8817e4Smiod 	  state = 0;
657*3d8817e4Smiod 	  PUT (ch);
658*3d8817e4Smiod 	  continue;
659*3d8817e4Smiod 
660*3d8817e4Smiod #ifdef DOUBLEBAR_PARALLEL
661*3d8817e4Smiod 	case 13:
662*3d8817e4Smiod 	  ch = GET ();
663*3d8817e4Smiod 	  if (ch != '|')
664*3d8817e4Smiod 	    abort ();
665*3d8817e4Smiod 
666*3d8817e4Smiod 	  /* Reset back to state 1 and pretend that we are parsing a
667*3d8817e4Smiod 	     line from just after the first white space.  */
668*3d8817e4Smiod 	  state = 1;
669*3d8817e4Smiod 	  PUT ('|');
670*3d8817e4Smiod 	  continue;
671*3d8817e4Smiod #endif
672*3d8817e4Smiod #ifdef TC_Z80
673*3d8817e4Smiod 	case 16:
674*3d8817e4Smiod 	  /* We have seen an 'a' at the start of a symbol, look for an 'f'.  */
675*3d8817e4Smiod 	  ch = GET ();
676*3d8817e4Smiod 	  if (ch == 'f' || ch == 'F')
677*3d8817e4Smiod 	    {
678*3d8817e4Smiod 	      state = 17;
679*3d8817e4Smiod 	      PUT (ch);
680*3d8817e4Smiod 	    }
681*3d8817e4Smiod 	  else
682*3d8817e4Smiod 	    {
683*3d8817e4Smiod 	      state = 9;
684*3d8817e4Smiod 	      break;
685*3d8817e4Smiod 	    }
686*3d8817e4Smiod 	case 17:
687*3d8817e4Smiod 	  /* We have seen "af" at the start of a symbol,
688*3d8817e4Smiod 	     a ' here is a part of that symbol.  */
689*3d8817e4Smiod 	  ch = GET ();
690*3d8817e4Smiod 	  state = 9;
691*3d8817e4Smiod 	  if (ch == '\'')
692*3d8817e4Smiod 	    /* Change to avoid warning about unclosed string.  */
693*3d8817e4Smiod 	    PUT ('`');
694*3d8817e4Smiod 	  else
695*3d8817e4Smiod 	    UNGET (ch);
696*3d8817e4Smiod 	  break;
697*3d8817e4Smiod #endif
698*3d8817e4Smiod 	}
699*3d8817e4Smiod 
700*3d8817e4Smiod       /* OK, we are somewhere in states 0 through 4 or 9 through 11.  */
701*3d8817e4Smiod 
702*3d8817e4Smiod       /* flushchar: */
703*3d8817e4Smiod       ch = GET ();
704*3d8817e4Smiod 
705*3d8817e4Smiod #ifdef TC_IA64
706*3d8817e4Smiod       if (ch == '(' && (state == 0 || state == 1))
707*3d8817e4Smiod 	{
708*3d8817e4Smiod 	  state += 14;
709*3d8817e4Smiod 	  PUT (ch);
710*3d8817e4Smiod 	  continue;
711*3d8817e4Smiod 	}
712*3d8817e4Smiod       else if (state == 14 || state == 15)
713*3d8817e4Smiod 	{
714*3d8817e4Smiod 	  if (ch == ')')
715*3d8817e4Smiod 	    {
716*3d8817e4Smiod 	      state -= 14;
717*3d8817e4Smiod 	      PUT (ch);
718*3d8817e4Smiod 	      ch = GET ();
719*3d8817e4Smiod 	    }
720*3d8817e4Smiod 	  else
721*3d8817e4Smiod 	    {
722*3d8817e4Smiod 	      PUT (ch);
723*3d8817e4Smiod 	      continue;
724*3d8817e4Smiod 	    }
725*3d8817e4Smiod 	}
726*3d8817e4Smiod #endif
727*3d8817e4Smiod 
728*3d8817e4Smiod     recycle:
729*3d8817e4Smiod 
730*3d8817e4Smiod #if defined TC_ARM && defined OBJ_ELF
731*3d8817e4Smiod       /* We need to watch out for .symver directives.  See the comment later
732*3d8817e4Smiod 	 in this function.  */
733*3d8817e4Smiod       if (symver_state == NULL)
734*3d8817e4Smiod 	{
735*3d8817e4Smiod 	  if ((state == 0 || state == 1) && ch == symver_pseudo[0])
736*3d8817e4Smiod 	    symver_state = symver_pseudo + 1;
737*3d8817e4Smiod 	}
738*3d8817e4Smiod       else
739*3d8817e4Smiod 	{
740*3d8817e4Smiod 	  /* We advance to the next state if we find the right
741*3d8817e4Smiod 	     character.  */
742*3d8817e4Smiod 	  if (ch != '\0' && (*symver_state == ch))
743*3d8817e4Smiod 	    ++symver_state;
744*3d8817e4Smiod 	  else if (*symver_state != '\0')
745*3d8817e4Smiod 	    /* We did not get the expected character, or we didn't
746*3d8817e4Smiod 	       get a valid terminating character after seeing the
747*3d8817e4Smiod 	       entire pseudo-op, so we must go back to the beginning.  */
748*3d8817e4Smiod 	    symver_state = NULL;
749*3d8817e4Smiod 	  else
750*3d8817e4Smiod 	    {
751*3d8817e4Smiod 	      /* We've read the entire pseudo-op.  If this is the end
752*3d8817e4Smiod 		 of the line, go back to the beginning.  */
753*3d8817e4Smiod 	      if (IS_NEWLINE (ch))
754*3d8817e4Smiod 		symver_state = NULL;
755*3d8817e4Smiod 	    }
756*3d8817e4Smiod 	}
757*3d8817e4Smiod #endif /* TC_ARM && OBJ_ELF */
758*3d8817e4Smiod 
759*3d8817e4Smiod #ifdef TC_M68K
760*3d8817e4Smiod       /* We want to have pseudo-ops which control whether we are in
761*3d8817e4Smiod 	 MRI mode or not.  Unfortunately, since m68k MRI mode affects
762*3d8817e4Smiod 	 the scrubber, that means that we need a special purpose
763*3d8817e4Smiod 	 recognizer here.  */
764*3d8817e4Smiod       if (mri_state == NULL)
765*3d8817e4Smiod 	{
766*3d8817e4Smiod 	  if ((state == 0 || state == 1)
767*3d8817e4Smiod 	      && ch == mri_pseudo[0])
768*3d8817e4Smiod 	    mri_state = mri_pseudo + 1;
769*3d8817e4Smiod 	}
770*3d8817e4Smiod       else
771*3d8817e4Smiod 	{
772*3d8817e4Smiod 	  /* We advance to the next state if we find the right
773*3d8817e4Smiod 	     character, or if we need a space character and we get any
774*3d8817e4Smiod 	     whitespace character, or if we need a '0' and we get a
775*3d8817e4Smiod 	     '1' (this is so that we only need one state to handle
776*3d8817e4Smiod 	     ``.mri 0'' and ``.mri 1'').  */
777*3d8817e4Smiod 	  if (ch != '\0'
778*3d8817e4Smiod 	      && (*mri_state == ch
779*3d8817e4Smiod 		  || (*mri_state == ' '
780*3d8817e4Smiod 		      && lex[ch] == LEX_IS_WHITESPACE)
781*3d8817e4Smiod 		  || (*mri_state == '0'
782*3d8817e4Smiod 		      && ch == '1')))
783*3d8817e4Smiod 	    {
784*3d8817e4Smiod 	      mri_last_ch = ch;
785*3d8817e4Smiod 	      ++mri_state;
786*3d8817e4Smiod 	    }
787*3d8817e4Smiod 	  else if (*mri_state != '\0'
788*3d8817e4Smiod 		   || (lex[ch] != LEX_IS_WHITESPACE
789*3d8817e4Smiod 		       && lex[ch] != LEX_IS_NEWLINE))
790*3d8817e4Smiod 	    {
791*3d8817e4Smiod 	      /* We did not get the expected character, or we didn't
792*3d8817e4Smiod 		 get a valid terminating character after seeing the
793*3d8817e4Smiod 		 entire pseudo-op, so we must go back to the
794*3d8817e4Smiod 		 beginning.  */
795*3d8817e4Smiod 	      mri_state = NULL;
796*3d8817e4Smiod 	    }
797*3d8817e4Smiod 	  else
798*3d8817e4Smiod 	    {
799*3d8817e4Smiod 	      /* We've read the entire pseudo-op.  mips_last_ch is
800*3d8817e4Smiod 		 either '0' or '1' indicating whether to enter or
801*3d8817e4Smiod 		 leave MRI mode.  */
802*3d8817e4Smiod 	      do_scrub_begin (mri_last_ch == '1');
803*3d8817e4Smiod 	      mri_state = NULL;
804*3d8817e4Smiod 
805*3d8817e4Smiod 	      /* We continue handling the character as usual.  The
806*3d8817e4Smiod 		 main gas reader must also handle the .mri pseudo-op
807*3d8817e4Smiod 		 to control expression parsing and the like.  */
808*3d8817e4Smiod 	    }
809*3d8817e4Smiod 	}
810*3d8817e4Smiod #endif
811*3d8817e4Smiod 
812*3d8817e4Smiod       if (ch == EOF)
813*3d8817e4Smiod 	{
814*3d8817e4Smiod 	  if (state != 0)
815*3d8817e4Smiod 	    {
816*3d8817e4Smiod 	      as_warn (_("end of file not at end of a line; newline inserted"));
817*3d8817e4Smiod 	      state = 0;
818*3d8817e4Smiod 	      PUT ('\n');
819*3d8817e4Smiod 	    }
820*3d8817e4Smiod 	  goto fromeof;
821*3d8817e4Smiod 	}
822*3d8817e4Smiod 
823*3d8817e4Smiod       switch (lex[ch])
824*3d8817e4Smiod 	{
825*3d8817e4Smiod 	case LEX_IS_WHITESPACE:
826*3d8817e4Smiod 	  do
827*3d8817e4Smiod 	    {
828*3d8817e4Smiod 	      ch = GET ();
829*3d8817e4Smiod 	    }
830*3d8817e4Smiod 	  while (ch != EOF && IS_WHITESPACE (ch));
831*3d8817e4Smiod 	  if (ch == EOF)
832*3d8817e4Smiod 	    goto fromeof;
833*3d8817e4Smiod 
834*3d8817e4Smiod 	  if (state == 0)
835*3d8817e4Smiod 	    {
836*3d8817e4Smiod 	      /* Preserve a single whitespace character at the
837*3d8817e4Smiod 		 beginning of a line.  */
838*3d8817e4Smiod 	      state = 1;
839*3d8817e4Smiod 	      UNGET (ch);
840*3d8817e4Smiod 	      PUT (' ');
841*3d8817e4Smiod 	      break;
842*3d8817e4Smiod 	    }
843*3d8817e4Smiod 
844*3d8817e4Smiod #ifdef KEEP_WHITE_AROUND_COLON
845*3d8817e4Smiod 	  if (lex[ch] == LEX_IS_COLON)
846*3d8817e4Smiod 	    {
847*3d8817e4Smiod 	      /* Only keep this white if there's no white *after* the
848*3d8817e4Smiod 		 colon.  */
849*3d8817e4Smiod 	      ch2 = GET ();
850*3d8817e4Smiod 	      UNGET (ch2);
851*3d8817e4Smiod 	      if (!IS_WHITESPACE (ch2))
852*3d8817e4Smiod 		{
853*3d8817e4Smiod 		  state = 9;
854*3d8817e4Smiod 		  UNGET (ch);
855*3d8817e4Smiod 		  PUT (' ');
856*3d8817e4Smiod 		  break;
857*3d8817e4Smiod 		}
858*3d8817e4Smiod 	    }
859*3d8817e4Smiod #endif
860*3d8817e4Smiod 	  if (IS_COMMENT (ch)
861*3d8817e4Smiod 	      || ch == '/'
862*3d8817e4Smiod 	      || IS_LINE_SEPARATOR (ch)
863*3d8817e4Smiod 	      || IS_PARALLEL_SEPARATOR (ch))
864*3d8817e4Smiod 	    {
865*3d8817e4Smiod 	      if (scrub_m68k_mri)
866*3d8817e4Smiod 		{
867*3d8817e4Smiod 		  /* In MRI mode, we keep these spaces.  */
868*3d8817e4Smiod 		  UNGET (ch);
869*3d8817e4Smiod 		  PUT (' ');
870*3d8817e4Smiod 		  break;
871*3d8817e4Smiod 		}
872*3d8817e4Smiod 	      goto recycle;
873*3d8817e4Smiod 	    }
874*3d8817e4Smiod 
875*3d8817e4Smiod 	  /* If we're in state 2 or 11, we've seen a non-white
876*3d8817e4Smiod 	     character followed by whitespace.  If the next character
877*3d8817e4Smiod 	     is ':', this is whitespace after a label name which we
878*3d8817e4Smiod 	     normally must ignore.  In MRI mode, though, spaces are
879*3d8817e4Smiod 	     not permitted between the label and the colon.  */
880*3d8817e4Smiod 	  if ((state == 2 || state == 11)
881*3d8817e4Smiod 	      && lex[ch] == LEX_IS_COLON
882*3d8817e4Smiod 	      && ! scrub_m68k_mri)
883*3d8817e4Smiod 	    {
884*3d8817e4Smiod 	      state = 1;
885*3d8817e4Smiod 	      PUT (ch);
886*3d8817e4Smiod 	      break;
887*3d8817e4Smiod 	    }
888*3d8817e4Smiod 
889*3d8817e4Smiod 	  switch (state)
890*3d8817e4Smiod 	    {
891*3d8817e4Smiod 	    case 0:
892*3d8817e4Smiod 	      state++;
893*3d8817e4Smiod 	      goto recycle;	/* Punted leading sp */
894*3d8817e4Smiod 	    case 1:
895*3d8817e4Smiod 	      /* We can arrive here if we leave a leading whitespace
896*3d8817e4Smiod 		 character at the beginning of a line.  */
897*3d8817e4Smiod 	      goto recycle;
898*3d8817e4Smiod 	    case 2:
899*3d8817e4Smiod 	      state = 3;
900*3d8817e4Smiod 	      if (to + 1 < toend)
901*3d8817e4Smiod 		{
902*3d8817e4Smiod 		  /* Optimize common case by skipping UNGET/GET.  */
903*3d8817e4Smiod 		  PUT (' ');	/* Sp after opco */
904*3d8817e4Smiod 		  goto recycle;
905*3d8817e4Smiod 		}
906*3d8817e4Smiod 	      UNGET (ch);
907*3d8817e4Smiod 	      PUT (' ');
908*3d8817e4Smiod 	      break;
909*3d8817e4Smiod 	    case 3:
910*3d8817e4Smiod 	      if (scrub_m68k_mri)
911*3d8817e4Smiod 		{
912*3d8817e4Smiod 		  /* In MRI mode, we keep these spaces.  */
913*3d8817e4Smiod 		  UNGET (ch);
914*3d8817e4Smiod 		  PUT (' ');
915*3d8817e4Smiod 		  break;
916*3d8817e4Smiod 		}
917*3d8817e4Smiod 	      goto recycle;	/* Sp in operands */
918*3d8817e4Smiod 	    case 9:
919*3d8817e4Smiod 	    case 10:
920*3d8817e4Smiod 	      if (scrub_m68k_mri)
921*3d8817e4Smiod 		{
922*3d8817e4Smiod 		  /* In MRI mode, we keep these spaces.  */
923*3d8817e4Smiod 		  state = 3;
924*3d8817e4Smiod 		  UNGET (ch);
925*3d8817e4Smiod 		  PUT (' ');
926*3d8817e4Smiod 		  break;
927*3d8817e4Smiod 		}
928*3d8817e4Smiod 	      state = 10;	/* Sp after symbol char */
929*3d8817e4Smiod 	      goto recycle;
930*3d8817e4Smiod 	    case 11:
931*3d8817e4Smiod 	      if (LABELS_WITHOUT_COLONS || flag_m68k_mri)
932*3d8817e4Smiod 		state = 1;
933*3d8817e4Smiod 	      else
934*3d8817e4Smiod 		{
935*3d8817e4Smiod 		  /* We know that ch is not ':', since we tested that
936*3d8817e4Smiod 		     case above.  Therefore this is not a label, so it
937*3d8817e4Smiod 		     must be the opcode, and we've just seen the
938*3d8817e4Smiod 		     whitespace after it.  */
939*3d8817e4Smiod 		  state = 3;
940*3d8817e4Smiod 		}
941*3d8817e4Smiod 	      UNGET (ch);
942*3d8817e4Smiod 	      PUT (' ');	/* Sp after label definition.  */
943*3d8817e4Smiod 	      break;
944*3d8817e4Smiod 	    default:
945*3d8817e4Smiod 	      BAD_CASE (state);
946*3d8817e4Smiod 	    }
947*3d8817e4Smiod 	  break;
948*3d8817e4Smiod 
949*3d8817e4Smiod 	case LEX_IS_TWOCHAR_COMMENT_1ST:
950*3d8817e4Smiod 	  ch2 = GET ();
951*3d8817e4Smiod 	  if (ch2 == '*')
952*3d8817e4Smiod 	    {
953*3d8817e4Smiod 	      for (;;)
954*3d8817e4Smiod 		{
955*3d8817e4Smiod 		  do
956*3d8817e4Smiod 		    {
957*3d8817e4Smiod 		      ch2 = GET ();
958*3d8817e4Smiod 		      if (ch2 != EOF && IS_NEWLINE (ch2))
959*3d8817e4Smiod 			add_newlines++;
960*3d8817e4Smiod 		    }
961*3d8817e4Smiod 		  while (ch2 != EOF && ch2 != '*');
962*3d8817e4Smiod 
963*3d8817e4Smiod 		  while (ch2 == '*')
964*3d8817e4Smiod 		    ch2 = GET ();
965*3d8817e4Smiod 
966*3d8817e4Smiod 		  if (ch2 == EOF || ch2 == '/')
967*3d8817e4Smiod 		    break;
968*3d8817e4Smiod 
969*3d8817e4Smiod 		  /* This UNGET will ensure that we count newlines
970*3d8817e4Smiod 		     correctly.  */
971*3d8817e4Smiod 		  UNGET (ch2);
972*3d8817e4Smiod 		}
973*3d8817e4Smiod 
974*3d8817e4Smiod 	      if (ch2 == EOF)
975*3d8817e4Smiod 		as_warn (_("end of file in multiline comment"));
976*3d8817e4Smiod 
977*3d8817e4Smiod 	      ch = ' ';
978*3d8817e4Smiod 	      goto recycle;
979*3d8817e4Smiod 	    }
980*3d8817e4Smiod #ifdef DOUBLESLASH_LINE_COMMENTS
981*3d8817e4Smiod 	  else if (ch2 == '/')
982*3d8817e4Smiod 	    {
983*3d8817e4Smiod 	      do
984*3d8817e4Smiod 		{
985*3d8817e4Smiod 		  ch = GET ();
986*3d8817e4Smiod 		}
987*3d8817e4Smiod 	      while (ch != EOF && !IS_NEWLINE (ch));
988*3d8817e4Smiod 	      if (ch == EOF)
989*3d8817e4Smiod 		as_warn ("end of file in comment; newline inserted");
990*3d8817e4Smiod 	      state = 0;
991*3d8817e4Smiod 	      PUT ('\n');
992*3d8817e4Smiod 	      break;
993*3d8817e4Smiod 	    }
994*3d8817e4Smiod #endif
995*3d8817e4Smiod 	  else
996*3d8817e4Smiod 	    {
997*3d8817e4Smiod 	      if (ch2 != EOF)
998*3d8817e4Smiod 		UNGET (ch2);
999*3d8817e4Smiod 	      if (state == 9 || state == 10)
1000*3d8817e4Smiod 		state = 3;
1001*3d8817e4Smiod 	      PUT (ch);
1002*3d8817e4Smiod 	    }
1003*3d8817e4Smiod 	  break;
1004*3d8817e4Smiod 
1005*3d8817e4Smiod 	case LEX_IS_STRINGQUOTE:
1006*3d8817e4Smiod 	  quotechar = ch;
1007*3d8817e4Smiod 	  if (state == 10)
1008*3d8817e4Smiod 	    {
1009*3d8817e4Smiod 	      /* Preserve the whitespace in foo "bar".  */
1010*3d8817e4Smiod 	      UNGET (ch);
1011*3d8817e4Smiod 	      state = 3;
1012*3d8817e4Smiod 	      PUT (' ');
1013*3d8817e4Smiod 
1014*3d8817e4Smiod 	      /* PUT didn't jump out.  We could just break, but we
1015*3d8817e4Smiod 		 know what will happen, so optimize a bit.  */
1016*3d8817e4Smiod 	      ch = GET ();
1017*3d8817e4Smiod 	      old_state = 3;
1018*3d8817e4Smiod 	    }
1019*3d8817e4Smiod 	  else if (state == 9)
1020*3d8817e4Smiod 	    old_state = 3;
1021*3d8817e4Smiod 	  else
1022*3d8817e4Smiod 	    old_state = state;
1023*3d8817e4Smiod 	  state = 5;
1024*3d8817e4Smiod 	  PUT (ch);
1025*3d8817e4Smiod 	  break;
1026*3d8817e4Smiod 
1027*3d8817e4Smiod #ifndef IEEE_STYLE
1028*3d8817e4Smiod 	case LEX_IS_ONECHAR_QUOTE:
1029*3d8817e4Smiod 	  if (state == 10)
1030*3d8817e4Smiod 	    {
1031*3d8817e4Smiod 	      /* Preserve the whitespace in foo 'b'.  */
1032*3d8817e4Smiod 	      UNGET (ch);
1033*3d8817e4Smiod 	      state = 3;
1034*3d8817e4Smiod 	      PUT (' ');
1035*3d8817e4Smiod 	      break;
1036*3d8817e4Smiod 	    }
1037*3d8817e4Smiod 	  ch = GET ();
1038*3d8817e4Smiod 	  if (ch == EOF)
1039*3d8817e4Smiod 	    {
1040*3d8817e4Smiod 	      as_warn (_("end of file after a one-character quote; \\0 inserted"));
1041*3d8817e4Smiod 	      ch = 0;
1042*3d8817e4Smiod 	    }
1043*3d8817e4Smiod 	  if (ch == '\\')
1044*3d8817e4Smiod 	    {
1045*3d8817e4Smiod 	      ch = GET ();
1046*3d8817e4Smiod 	      if (ch == EOF)
1047*3d8817e4Smiod 		{
1048*3d8817e4Smiod 		  as_warn (_("end of file in escape character"));
1049*3d8817e4Smiod 		  ch = '\\';
1050*3d8817e4Smiod 		}
1051*3d8817e4Smiod 	      else
1052*3d8817e4Smiod 		ch = process_escape (ch);
1053*3d8817e4Smiod 	    }
1054*3d8817e4Smiod 	  sprintf (out_buf, "%d", (int) (unsigned char) ch);
1055*3d8817e4Smiod 
1056*3d8817e4Smiod 	  /* None of these 'x constants for us.  We want 'x'.  */
1057*3d8817e4Smiod 	  if ((ch = GET ()) != '\'')
1058*3d8817e4Smiod 	    {
1059*3d8817e4Smiod #ifdef REQUIRE_CHAR_CLOSE_QUOTE
1060*3d8817e4Smiod 	      as_warn (_("missing close quote; (assumed)"));
1061*3d8817e4Smiod #else
1062*3d8817e4Smiod 	      if (ch != EOF)
1063*3d8817e4Smiod 		UNGET (ch);
1064*3d8817e4Smiod #endif
1065*3d8817e4Smiod 	    }
1066*3d8817e4Smiod 	  if (strlen (out_buf) == 1)
1067*3d8817e4Smiod 	    {
1068*3d8817e4Smiod 	      PUT (out_buf[0]);
1069*3d8817e4Smiod 	      break;
1070*3d8817e4Smiod 	    }
1071*3d8817e4Smiod 	  if (state == 9)
1072*3d8817e4Smiod 	    old_state = 3;
1073*3d8817e4Smiod 	  else
1074*3d8817e4Smiod 	    old_state = state;
1075*3d8817e4Smiod 	  state = -1;
1076*3d8817e4Smiod 	  out_string = out_buf;
1077*3d8817e4Smiod 	  PUT (*out_string++);
1078*3d8817e4Smiod 	  break;
1079*3d8817e4Smiod #endif
1080*3d8817e4Smiod 
1081*3d8817e4Smiod 	case LEX_IS_COLON:
1082*3d8817e4Smiod #ifdef KEEP_WHITE_AROUND_COLON
1083*3d8817e4Smiod 	  state = 9;
1084*3d8817e4Smiod #else
1085*3d8817e4Smiod 	  if (state == 9 || state == 10)
1086*3d8817e4Smiod 	    state = 3;
1087*3d8817e4Smiod 	  else if (state != 3)
1088*3d8817e4Smiod 	    state = 1;
1089*3d8817e4Smiod #endif
1090*3d8817e4Smiod 	  PUT (ch);
1091*3d8817e4Smiod 	  break;
1092*3d8817e4Smiod 
1093*3d8817e4Smiod 	case LEX_IS_NEWLINE:
1094*3d8817e4Smiod 	  /* Roll out a bunch of newlines from inside comments, etc.  */
1095*3d8817e4Smiod 	  if (add_newlines)
1096*3d8817e4Smiod 	    {
1097*3d8817e4Smiod 	      --add_newlines;
1098*3d8817e4Smiod 	      UNGET (ch);
1099*3d8817e4Smiod 	    }
1100*3d8817e4Smiod 	  /* Fall through.  */
1101*3d8817e4Smiod 
1102*3d8817e4Smiod 	case LEX_IS_LINE_SEPARATOR:
1103*3d8817e4Smiod 	  state = 0;
1104*3d8817e4Smiod 	  PUT (ch);
1105*3d8817e4Smiod 	  break;
1106*3d8817e4Smiod 
1107*3d8817e4Smiod 	case LEX_IS_PARALLEL_SEPARATOR:
1108*3d8817e4Smiod 	  state = 1;
1109*3d8817e4Smiod 	  PUT (ch);
1110*3d8817e4Smiod 	  break;
1111*3d8817e4Smiod 
1112*3d8817e4Smiod #ifdef TC_V850
1113*3d8817e4Smiod 	case LEX_IS_DOUBLEDASH_1ST:
1114*3d8817e4Smiod 	  ch2 = GET ();
1115*3d8817e4Smiod 	  if (ch2 != '-')
1116*3d8817e4Smiod 	    {
1117*3d8817e4Smiod 	      UNGET (ch2);
1118*3d8817e4Smiod 	      goto de_fault;
1119*3d8817e4Smiod 	    }
1120*3d8817e4Smiod 	  /* Read and skip to end of line.  */
1121*3d8817e4Smiod 	  do
1122*3d8817e4Smiod 	    {
1123*3d8817e4Smiod 	      ch = GET ();
1124*3d8817e4Smiod 	    }
1125*3d8817e4Smiod 	  while (ch != EOF && ch != '\n');
1126*3d8817e4Smiod 
1127*3d8817e4Smiod 	  if (ch == EOF)
1128*3d8817e4Smiod 	    as_warn (_("end of file in comment; newline inserted"));
1129*3d8817e4Smiod 
1130*3d8817e4Smiod 	  state = 0;
1131*3d8817e4Smiod 	  PUT ('\n');
1132*3d8817e4Smiod 	  break;
1133*3d8817e4Smiod #endif
1134*3d8817e4Smiod #ifdef DOUBLEBAR_PARALLEL
1135*3d8817e4Smiod 	case LEX_IS_DOUBLEBAR_1ST:
1136*3d8817e4Smiod 	  ch2 = GET ();
1137*3d8817e4Smiod 	  UNGET (ch2);
1138*3d8817e4Smiod 	  if (ch2 != '|')
1139*3d8817e4Smiod 	    goto de_fault;
1140*3d8817e4Smiod 
1141*3d8817e4Smiod 	  /* Handle '||' in two states as invoking PUT twice might
1142*3d8817e4Smiod 	     result in the first one jumping out of this loop.  We'd
1143*3d8817e4Smiod 	     then lose track of the state and one '|' char.  */
1144*3d8817e4Smiod 	  state = 13;
1145*3d8817e4Smiod 	  PUT ('|');
1146*3d8817e4Smiod 	  break;
1147*3d8817e4Smiod #endif
1148*3d8817e4Smiod 	case LEX_IS_LINE_COMMENT_START:
1149*3d8817e4Smiod 	  /* FIXME-someday: The two character comment stuff was badly
1150*3d8817e4Smiod 	     thought out.  On i386, we want '/' as line comment start
1151*3d8817e4Smiod 	     AND we want C style comments.  hence this hack.  The
1152*3d8817e4Smiod 	     whole lexical process should be reworked.  xoxorich.  */
1153*3d8817e4Smiod 	  if (ch == '/')
1154*3d8817e4Smiod 	    {
1155*3d8817e4Smiod 	      ch2 = GET ();
1156*3d8817e4Smiod 	      if (ch2 == '*')
1157*3d8817e4Smiod 		{
1158*3d8817e4Smiod 		  old_state = 3;
1159*3d8817e4Smiod 		  state = -2;
1160*3d8817e4Smiod 		  break;
1161*3d8817e4Smiod 		}
1162*3d8817e4Smiod 	      else
1163*3d8817e4Smiod 		{
1164*3d8817e4Smiod 		  UNGET (ch2);
1165*3d8817e4Smiod 		}
1166*3d8817e4Smiod 	    }
1167*3d8817e4Smiod 
1168*3d8817e4Smiod 	  if (state == 0 || state == 1)	/* Only comment at start of line.  */
1169*3d8817e4Smiod 	    {
1170*3d8817e4Smiod 	      int startch;
1171*3d8817e4Smiod 
1172*3d8817e4Smiod 	      startch = ch;
1173*3d8817e4Smiod 
1174*3d8817e4Smiod 	      do
1175*3d8817e4Smiod 		{
1176*3d8817e4Smiod 		  ch = GET ();
1177*3d8817e4Smiod 		}
1178*3d8817e4Smiod 	      while (ch != EOF && IS_WHITESPACE (ch));
1179*3d8817e4Smiod 
1180*3d8817e4Smiod 	      if (ch == EOF)
1181*3d8817e4Smiod 		{
1182*3d8817e4Smiod 		  as_warn (_("end of file in comment; newline inserted"));
1183*3d8817e4Smiod 		  PUT ('\n');
1184*3d8817e4Smiod 		  break;
1185*3d8817e4Smiod 		}
1186*3d8817e4Smiod 
1187*3d8817e4Smiod 	      if (ch < '0' || ch > '9' || state != 0 || startch != '#')
1188*3d8817e4Smiod 		{
1189*3d8817e4Smiod 		  /* Not a cpp line.  */
1190*3d8817e4Smiod 		  while (ch != EOF && !IS_NEWLINE (ch))
1191*3d8817e4Smiod 		    ch = GET ();
1192*3d8817e4Smiod 		  if (ch == EOF)
1193*3d8817e4Smiod 		    as_warn (_("end of file in comment; newline inserted"));
1194*3d8817e4Smiod 		  state = 0;
1195*3d8817e4Smiod 		  PUT ('\n');
1196*3d8817e4Smiod 		  break;
1197*3d8817e4Smiod 		}
1198*3d8817e4Smiod 	      /* Looks like `# 123 "filename"' from cpp.  */
1199*3d8817e4Smiod 	      UNGET (ch);
1200*3d8817e4Smiod 	      old_state = 4;
1201*3d8817e4Smiod 	      state = -1;
1202*3d8817e4Smiod 	      if (scrub_m68k_mri)
1203*3d8817e4Smiod 		out_string = "\tappline ";
1204*3d8817e4Smiod 	      else
1205*3d8817e4Smiod 		out_string = "\t.appline ";
1206*3d8817e4Smiod 	      PUT (*out_string++);
1207*3d8817e4Smiod 	      break;
1208*3d8817e4Smiod 	    }
1209*3d8817e4Smiod 
1210*3d8817e4Smiod #ifdef TC_D10V
1211*3d8817e4Smiod 	  /* All insns end in a char for which LEX_IS_SYMBOL_COMPONENT is true.
1212*3d8817e4Smiod 	     Trap is the only short insn that has a first operand that is
1213*3d8817e4Smiod 	     neither register nor label.
1214*3d8817e4Smiod 	     We must prevent exef0f ||trap #1 to degenerate to exef0f ||trap#1 .
1215*3d8817e4Smiod 	     We can't make '#' LEX_IS_SYMBOL_COMPONENT because it is
1216*3d8817e4Smiod 	     already LEX_IS_LINE_COMMENT_START.  However, it is the
1217*3d8817e4Smiod 	     only character in line_comment_chars for d10v, hence we
1218*3d8817e4Smiod 	     can recognize it as such.  */
1219*3d8817e4Smiod 	  /* An alternative approach would be to reset the state to 1 when
1220*3d8817e4Smiod 	     we see '||', '<'- or '->', but that seems to be overkill.  */
1221*3d8817e4Smiod 	  if (state == 10)
1222*3d8817e4Smiod 	    PUT (' ');
1223*3d8817e4Smiod #endif
1224*3d8817e4Smiod 	  /* We have a line comment character which is not at the
1225*3d8817e4Smiod 	     start of a line.  If this is also a normal comment
1226*3d8817e4Smiod 	     character, fall through.  Otherwise treat it as a default
1227*3d8817e4Smiod 	     character.  */
1228*3d8817e4Smiod 	  if (strchr (tc_comment_chars, ch) == NULL
1229*3d8817e4Smiod 	      && (! scrub_m68k_mri
1230*3d8817e4Smiod 		  || (ch != '!' && ch != '*')))
1231*3d8817e4Smiod 	    goto de_fault;
1232*3d8817e4Smiod 	  if (scrub_m68k_mri
1233*3d8817e4Smiod 	      && (ch == '!' || ch == '*' || ch == '#')
1234*3d8817e4Smiod 	      && state != 1
1235*3d8817e4Smiod 	      && state != 10)
1236*3d8817e4Smiod 	    goto de_fault;
1237*3d8817e4Smiod 	  /* Fall through.  */
1238*3d8817e4Smiod 	case LEX_IS_COMMENT_START:
1239*3d8817e4Smiod #if defined TC_ARM && defined OBJ_ELF
1240*3d8817e4Smiod 	  /* On the ARM, `@' is the comment character.
1241*3d8817e4Smiod 	     Unfortunately this is also a special character in ELF .symver
1242*3d8817e4Smiod 	     directives (and .type, though we deal with those another way).
1243*3d8817e4Smiod 	     So we check if this line is such a directive, and treat
1244*3d8817e4Smiod 	     the character as default if so.  This is a hack.  */
1245*3d8817e4Smiod 	  if ((symver_state != NULL) && (*symver_state == 0))
1246*3d8817e4Smiod 	    goto de_fault;
1247*3d8817e4Smiod #endif
1248*3d8817e4Smiod #ifdef WARN_COMMENTS
1249*3d8817e4Smiod 	  if (!found_comment)
1250*3d8817e4Smiod 	    as_where (&found_comment_file, &found_comment);
1251*3d8817e4Smiod #endif
1252*3d8817e4Smiod 	  do
1253*3d8817e4Smiod 	    {
1254*3d8817e4Smiod 	      ch = GET ();
1255*3d8817e4Smiod 	    }
1256*3d8817e4Smiod 	  while (ch != EOF && !IS_NEWLINE (ch));
1257*3d8817e4Smiod 	  if (ch == EOF)
1258*3d8817e4Smiod 	    as_warn (_("end of file in comment; newline inserted"));
1259*3d8817e4Smiod 	  state = 0;
1260*3d8817e4Smiod 	  PUT ('\n');
1261*3d8817e4Smiod 	  break;
1262*3d8817e4Smiod 
1263*3d8817e4Smiod 	case LEX_IS_SYMBOL_COMPONENT:
1264*3d8817e4Smiod 	  if (state == 10)
1265*3d8817e4Smiod 	    {
1266*3d8817e4Smiod 	      /* This is a symbol character following another symbol
1267*3d8817e4Smiod 		 character, with whitespace in between.  We skipped
1268*3d8817e4Smiod 		 the whitespace earlier, so output it now.  */
1269*3d8817e4Smiod 	      UNGET (ch);
1270*3d8817e4Smiod 	      state = 3;
1271*3d8817e4Smiod 	      PUT (' ');
1272*3d8817e4Smiod 	      break;
1273*3d8817e4Smiod 	    }
1274*3d8817e4Smiod 
1275*3d8817e4Smiod #ifdef TC_Z80
1276*3d8817e4Smiod 	  /* "af'" is a symbol containing '\''.  */
1277*3d8817e4Smiod 	  if (state == 3 && (ch == 'a' || ch == 'A'))
1278*3d8817e4Smiod 	    {
1279*3d8817e4Smiod 	      state = 16;
1280*3d8817e4Smiod 	      PUT (ch);
1281*3d8817e4Smiod 	      ch = GET ();
1282*3d8817e4Smiod 	      if (ch == 'f' || ch == 'F')
1283*3d8817e4Smiod 		{
1284*3d8817e4Smiod 		  state = 17;
1285*3d8817e4Smiod 		  PUT (ch);
1286*3d8817e4Smiod 		  break;
1287*3d8817e4Smiod 		}
1288*3d8817e4Smiod 	      else
1289*3d8817e4Smiod 		{
1290*3d8817e4Smiod 		  state = 9;
1291*3d8817e4Smiod 		  if (!IS_SYMBOL_COMPONENT (ch))
1292*3d8817e4Smiod 		    {
1293*3d8817e4Smiod 		      UNGET (ch);
1294*3d8817e4Smiod 		      break;
1295*3d8817e4Smiod 		    }
1296*3d8817e4Smiod 		}
1297*3d8817e4Smiod 	    }
1298*3d8817e4Smiod #endif
1299*3d8817e4Smiod 	  if (state == 3)
1300*3d8817e4Smiod 	    state = 9;
1301*3d8817e4Smiod 
1302*3d8817e4Smiod 	  /* This is a common case.  Quickly copy CH and all the
1303*3d8817e4Smiod 	     following symbol component or normal characters.  */
1304*3d8817e4Smiod 	  if (to + 1 < toend
1305*3d8817e4Smiod 	      && mri_state == NULL
1306*3d8817e4Smiod #if defined TC_ARM && defined OBJ_ELF
1307*3d8817e4Smiod 	      && symver_state == NULL
1308*3d8817e4Smiod #endif
1309*3d8817e4Smiod 	      )
1310*3d8817e4Smiod 	    {
1311*3d8817e4Smiod 	      char *s;
1312*3d8817e4Smiod 	      int len;
1313*3d8817e4Smiod 
1314*3d8817e4Smiod 	      for (s = from; s < fromend; s++)
1315*3d8817e4Smiod 		{
1316*3d8817e4Smiod 		  int type;
1317*3d8817e4Smiod 
1318*3d8817e4Smiod 		  ch2 = *(unsigned char *) s;
1319*3d8817e4Smiod 		  type = lex[ch2];
1320*3d8817e4Smiod 		  if (type != 0
1321*3d8817e4Smiod 		      && type != LEX_IS_SYMBOL_COMPONENT)
1322*3d8817e4Smiod 		    break;
1323*3d8817e4Smiod 		}
1324*3d8817e4Smiod 
1325*3d8817e4Smiod 	      if (s > from)
1326*3d8817e4Smiod 		/* Handle the last character normally, for
1327*3d8817e4Smiod 		   simplicity.  */
1328*3d8817e4Smiod 		--s;
1329*3d8817e4Smiod 
1330*3d8817e4Smiod 	      len = s - from;
1331*3d8817e4Smiod 
1332*3d8817e4Smiod 	      if (len > (toend - to) - 1)
1333*3d8817e4Smiod 		len = (toend - to) - 1;
1334*3d8817e4Smiod 
1335*3d8817e4Smiod 	      if (len > 0)
1336*3d8817e4Smiod 		{
1337*3d8817e4Smiod 		  PUT (ch);
1338*3d8817e4Smiod 		  memcpy (to, from, len);
1339*3d8817e4Smiod 		  to += len;
1340*3d8817e4Smiod 		  from += len;
1341*3d8817e4Smiod 		  if (to >= toend)
1342*3d8817e4Smiod 		    goto tofull;
1343*3d8817e4Smiod 		  ch = GET ();
1344*3d8817e4Smiod 		}
1345*3d8817e4Smiod 	    }
1346*3d8817e4Smiod 
1347*3d8817e4Smiod 	  /* Fall through.  */
1348*3d8817e4Smiod 	default:
1349*3d8817e4Smiod 	de_fault:
1350*3d8817e4Smiod 	  /* Some relatively `normal' character.  */
1351*3d8817e4Smiod 	  if (state == 0)
1352*3d8817e4Smiod 	    {
1353*3d8817e4Smiod 	      state = 11;	/* Now seeing label definition.  */
1354*3d8817e4Smiod 	    }
1355*3d8817e4Smiod 	  else if (state == 1)
1356*3d8817e4Smiod 	    {
1357*3d8817e4Smiod 	      state = 2;	/* Ditto.  */
1358*3d8817e4Smiod 	    }
1359*3d8817e4Smiod 	  else if (state == 9)
1360*3d8817e4Smiod 	    {
1361*3d8817e4Smiod 	      if (!IS_SYMBOL_COMPONENT (ch))
1362*3d8817e4Smiod 		state = 3;
1363*3d8817e4Smiod 	    }
1364*3d8817e4Smiod 	  else if (state == 10)
1365*3d8817e4Smiod 	    {
1366*3d8817e4Smiod 	      if (ch == '\\')
1367*3d8817e4Smiod 		{
1368*3d8817e4Smiod 		  /* Special handling for backslash: a backslash may
1369*3d8817e4Smiod 		     be the beginning of a formal parameter (of a
1370*3d8817e4Smiod 		     macro) following another symbol character, with
1371*3d8817e4Smiod 		     whitespace in between.  If that is the case, we
1372*3d8817e4Smiod 		     output a space before the parameter.  Strictly
1373*3d8817e4Smiod 		     speaking, correct handling depends upon what the
1374*3d8817e4Smiod 		     macro parameter expands into; if the parameter
1375*3d8817e4Smiod 		     expands into something which does not start with
1376*3d8817e4Smiod 		     an operand character, then we don't want to keep
1377*3d8817e4Smiod 		     the space.  We don't have enough information to
1378*3d8817e4Smiod 		     make the right choice, so here we are making the
1379*3d8817e4Smiod 		     choice which is more likely to be correct.  */
1380*3d8817e4Smiod 		  PUT (' ');
1381*3d8817e4Smiod 		}
1382*3d8817e4Smiod 
1383*3d8817e4Smiod 	      state = 3;
1384*3d8817e4Smiod 	    }
1385*3d8817e4Smiod 	  PUT (ch);
1386*3d8817e4Smiod 	  break;
1387*3d8817e4Smiod 	}
1388*3d8817e4Smiod     }
1389*3d8817e4Smiod 
1390*3d8817e4Smiod   /*NOTREACHED*/
1391*3d8817e4Smiod 
1392*3d8817e4Smiod  fromeof:
1393*3d8817e4Smiod   /* We have reached the end of the input.  */
1394*3d8817e4Smiod   return to - tostart;
1395*3d8817e4Smiod 
1396*3d8817e4Smiod  tofull:
1397*3d8817e4Smiod   /* The output buffer is full.  Save any input we have not yet
1398*3d8817e4Smiod      processed.  */
1399*3d8817e4Smiod   if (fromend > from)
1400*3d8817e4Smiod     {
1401*3d8817e4Smiod       saved_input = from;
1402*3d8817e4Smiod       saved_input_len = fromend - from;
1403*3d8817e4Smiod     }
1404*3d8817e4Smiod   else
1405*3d8817e4Smiod     saved_input = NULL;
1406*3d8817e4Smiod 
1407*3d8817e4Smiod   return to - tostart;
1408*3d8817e4Smiod }
1409*3d8817e4Smiod 
1410