BSD 4_3_Net_2 development
[unix-history] / usr / src / usr.bin / gas / app.c
CommitLineData
515eb9d8
C
1/* This is the Assembler Pre-Processor
2 Copyright (C) 1987 Free Software Foundation, Inc.
3
4This file is part of GAS, the GNU Assembler.
5
6GAS is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GAS is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GAS; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20/* App, the assembler pre-processor. This pre-processor strips out excess
21 spaces, turns single-quoted characters into a decimal constant, and turns
22 # <number> <filename> <garbage> into a .line <number>;.file <filename> pair.
23 This needs better error-handling.
24 */
25#include <stdio.h>
26#ifdef USG
27#define bzero(s,n) memset(s,0,n)
28#endif
29#if !defined(__STDC__) && !defined(const)
30#define const /* Nothing */
31#endif
32
33static char lex [256];
34static const char symbol_chars[] =
35 "$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
36
37extern const char comment_chars[];
38extern const char line_comment_chars[];
39
40#define LEX_IS_SYMBOL_COMPONENT (1)
41#define LEX_IS_WHITESPACE (2)
42#define LEX_IS_LINE_SEPERATOR (4)
43#define LEX_IS_COMMENT_START (8) /* JF added these two */
44#define LEX_IS_LINE_COMMENT_START (16)
45#define IS_SYMBOL_COMPONENT(c) (lex [c] & LEX_IS_SYMBOL_COMPONENT)
46#define IS_WHITESPACE(c) (lex [c] & LEX_IS_WHITESPACE)
47#define IS_LINE_SEPERATOR(c) (lex [c] & LEX_IS_LINE_SEPERATOR)
48#define IS_COMMENT(c) (lex [c] & LEX_IS_COMMENT_START)
49#define IS_LINE_COMMENT(c) (lex [c] & LEX_IS_LINE_COMMENT_START)
50
51void
52do_scrub_begin()
53{
54 const char *p;
55
56 bzero (lex, sizeof(lex)); /* Trust NOBODY! */
57 lex [' '] |= LEX_IS_WHITESPACE;
58 lex ['\t'] |= LEX_IS_WHITESPACE;
59 for (p =symbol_chars;*p;++p)
60 lex [*p] |= LEX_IS_SYMBOL_COMPONENT;
61 lex ['\n'] |= LEX_IS_LINE_SEPERATOR;
62#ifdef DONTDEF
63 lex [':'] |= LEX_IS_LINE_SEPERATOR;
64#endif
65 lex [';'] |= LEX_IS_LINE_SEPERATOR;
66 for (p=comment_chars;*p;p++)
67 lex[*p] |= LEX_IS_COMMENT_START;
68 for (p=line_comment_chars;*p;p++)
69 lex[*p] |= LEX_IS_LINE_COMMENT_START;
70}
71
72FILE *scrub_file;
73
74int
75scrub_from_file()
76{
77 return getc(scrub_file);
78}
79
80void
81scrub_to_file(ch)
82int ch;
83{
84 ungetc(ch,scrub_file);
85}
86
87char *scrub_string;
88char *scrub_last_string;
89
90int
91scrub_from_string()
92{
93 return scrub_string == scrub_last_string ? EOF : *scrub_string++;
94}
95
96void
97scrub_to_string(ch)
98int ch;
99{
100 *--scrub_string=ch;
101}
102
103int
104do_scrub_next_char(get,unget)
105int (*get)();
106void (*unget)();
107/* FILE *fp; */
108{
109 /* State 0: beginning of normal line
110 1: After first whitespace on normal line (flush more white)
111 2: After first non-white on normal line (keep 1white)
112 3: after second white on normal line (flush white)
113 4: after putting out a .line, put out digits
114 5: parsing a string, then go to old-state
115 6: putting out \ escape in a "d string.
116 7: After putting out a .file, put out string.
117 8: After putting out a .file string, flush until newline.
118 -1: output string in out_string and go to the state in old_state
119 -2: flush text until a '*' '/' is seen, then go to state old_state
120 */
121
122 static state;
123 static old_state;
124 static char *out_string;
125 static char out_buf[20];
126 static add_newlines;
127 int ch;
128
129 if(state==-1) {
130 ch= *out_string++;
131 if(*out_string==0) {
132 state=old_state;
133 old_state=3;
134 }
135 return ch;
136 }
137 if(state==-2) {
138 for(;;) {
139 do ch=(*get)();
140 while(ch!=EOF && ch!='\n' && ch!='*');
141 if(ch=='\n' || ch==EOF)
142 return ch;
143 ch=(*get)();
144 if(ch==EOF || ch=='/')
145 break;
146 (*unget)(ch);
147 }
148 state=old_state;
149 return ' ';
150 }
151 if(state==4) {
152 ch=(*get)();
153 if(ch==EOF || (ch>='0' && ch<='9'))
154 return ch;
155 else {
156 while(ch!=EOF && IS_WHITESPACE(ch))
157 ch=(*get)();
158 if(ch=='"') {
159 (*unget)(ch);
160 out_string="; .file ";
161 old_state=7;
162 state= -1;
163 return *out_string++;
164 } else {
165 while(ch!=EOF && ch!='\n')
166 ch=(*get)();
167 return ch;
168 }
169 }
170 }
171 if(state==5) {
172 ch=(*get)();
173 if(ch=='"') {
174 state=old_state;
175 return '"';
176 } else if(ch=='\\') {
177 state=6;
178 return ch;
179 } else if(ch==EOF) {
180 as_warn("End of file in string: inserted '\"'");
181 state=old_state;
182 (*unget)('\n');
183 return '"';
184 } else {
185 return ch;
186 }
187 }
188 if(state==6) {
189 state=5;
190 ch=(*get)();
191 switch(ch) {
192 /* This is neet. Turn "string
193 more string" into "string\n more string"
194 */
195 case '\n':
196 (*unget)('n');
197 add_newlines++;
198 return '\\';
199
200 case '"':
201 case '\\':
202 case 'b':
203 case 'f':
204 case 'n':
205 case 'r':
206 case 't':
207 case '0':
208 case '1':
209 case '2':
210 case '3':
211 case '4':
212 case '5':
213 case '6':
214 case '7':
215 break;
216 default:
217 as_warn("Unknown escape '\\%c' in string: Ignored",ch);
218 break;
219
220 case EOF:
221 as_warn("End of file in string: '\"' inserted");
222 return '"';
223 }
224 return ch;
225 }
226
227 if(state==7) {
228 ch=(*get)();
229 state=5;
230 old_state=8;
231 return ch;
232 }
233
234 if(state==8) {
235 do ch= (*get)();
236 while(ch!='\n');
237 state=0;
238 return ch;
239 }
240
241 flushchar:
242 ch=(*get)();
243 switch(ch) {
244 case ' ':
245 case '\t':
246 do ch=(*get)();
247 while(ch!=EOF && IS_WHITESPACE(ch));
248 if(ch==EOF)
249 return ch;
250 if(IS_COMMENT(ch) || (state==0 && IS_LINE_COMMENT(ch)) || ch=='/' || IS_LINE_SEPERATOR(ch)) {
251 (*unget)(ch);
252 goto flushchar;
253 }
254 (*unget)(ch);
255 if(state==0 || state==2) {
256 state++;
257 return ' ';
258 } else goto flushchar;
259
260 case '/':
261 ch=(*get)();
262 if(ch=='*') {
263 for(;;) {
264 do {
265 ch=(*get)();
266 if(ch=='\n')
267 add_newlines++;
268 } while(ch!=EOF && ch!='*');
269 ch=(*get)();
270 if(ch==EOF || ch=='/')
271 break;
272 (*unget)(ch);
273 }
274 if(ch==EOF)
275 as_warn("End of file in '/' '*' string: */ inserted");
276
277 (*unget)(' ');
278 goto flushchar;
279 } else {
280 if(IS_COMMENT('/') || (state==0 && IS_LINE_COMMENT('/'))) {
281 (*unget)(ch);
282 ch='/';
283 goto deal_misc;
284 }
285 if(ch!=EOF)
286 (*unget)(ch);
287 return '/';
288 }
289 break;
290
291 case '"':
292 old_state=state;
293 state=5;
294 return '"';
295 break;
296
297 case '\'':
298 ch=(*get)();
299 if(ch==EOF) {
300 as_warn("End-of-file after a ': \000 inserted");
301 ch=0;
302 }
303 sprintf(out_buf,"(%d)",ch&0xff);
304 old_state=state;
305 state= -1;
306 out_string=out_buf;
307 return *out_string++;
308
309 case ':':
310 if(state!=3)
311 state=0;
312 return ch;
313
314 case '\n':
315 if(add_newlines) {
316 --add_newlines;
317 (*unget)(ch);
318 }
319 case ';':
320 state=0;
321 return ch;
322
323 default:
324 deal_misc:
325 if(state==0 && IS_LINE_COMMENT(ch)) {
326 do ch=(*get)();
327 while(ch!=EOF && IS_WHITESPACE(ch));
328 if(ch==EOF) {
329 as_warn("EOF in comment: Newline inserted");
330 return '\n';
331 }
332 if(ch<'0' || ch>'9') {
333 while(ch!=EOF && ch!='\n')
334 ch=(*get)();
335 if(ch==EOF)
336 as_warn("EOF in Comment: Newline inserted");
337 state=0;
338 return '\n';
339 }
340 (*unget)(ch);
341 old_state=4;
342 state= -1;
343 out_string=".line ";
344 return *out_string++;
345
346 } else if(IS_COMMENT(ch)) {
347 do ch=(*get)();
348 while(ch!=EOF && ch!='\n');
349 if(ch==EOF)
350 as_warn("EOF in comment: Newline inserted");
351 state=0;
352 return '\n';
353
354 } else if(state==0) {
355 state=2;
356 return ch;
357 } else if(state==1) {
358 state=2;
359 return ch;
360 } else {
361 return ch;
362
363 }
364 case EOF:
365 if(state==0)
366 return ch;
367 as_warn("End-of-File not at end of a line");
368 }
369 return -1;
370}
371
372#ifdef TEST
373
374char comment_chars[] = "|";
375char line_comment_chars[] = "#";
376
377main()
378{
379 int ch;
380
381 app_begin();
382 while((ch=do_scrub_next_char(stdin))!=EOF)
383 putc(ch,stdout);
384}
385
386as_warn(str)
387char *str;
388{
389 fputs(str,stderr);
390 putc('\n',stderr);
391}
392#endif