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