a56: Makefile: add hardening stuff to CFLAGS
[linux-libre-firmware.git] / a56 / lex.c
1 /*******************************************************
2  *
3  *  a56 - a DSP56001 assembler
4  *
5  *  Written by Quinn C. Jensen
6  *  July 1990
7  *
8  *******************************************************\
9
10 /*
11  * Copyright (C) 1990-1998 Quinn C. Jensen
12  *
13  * Permission to use, copy, modify, distribute, and sell this
14  * software and its documentation for any purpose is hereby granted
15  * without fee, provided that the above copyright notice appear in
16  * all copies and that both that copyright notice and this permission
17  * notice appear in supporting documentation.  The author makes no
18  * representations about the suitability of this software for any
19  * purpose. It is provided "as is" without express or implied
20  * warranty.
21  */
22
23 /*
24  *  lex.c - lexical analyzer envelope.  lexyy.c, included below,
25  *  is the LEX-generated code.
26  *
27  */
28
29 #include "a56.h"
30 #include "gram.h"
31
32 int ldebug = 0;
33 #ifdef LDEBUG
34 #define RET(val) \
35         {\
36                 if(ldebug) {\
37                         printf("[%s]", tok_print(val));\
38                         fflush(stdout);\
39                 }\
40                 return val;\
41         }
42 #else
43 #define RET(val) {return val;}
44 #endif
45
46 extern YYSTYPE yyval;
47
48 double atof();
49
50 /**************** yylex - returns next token *****************************/
51
52 #define MAX_TOK 1024
53 char tok[MAX_TOK];
54
55 yylex()
56 {
57         int ltok = next_tok();
58         int itok;
59
60         switch(ltok) {
61         case EOF:
62                 if(yywrap() == 1)
63                         return 0;
64                 else
65                         return yylex();
66                 break;
67         case SYM:
68                 if(itok = is_keyword(tok)) {
69                         RET(itok);
70                 } else {
71                         yylval.sval = strsave(tok);
72                         RET(SYM);
73                 }
74                 break;
75         case CHEX:
76                 yylval.n.type = INT;
77                 yylval.n.seg = ANY;
78                 yylval.n.val.i = strtol(tok, 0, 16);
79                 RET(CHEX);
80                 break;
81         case CDEC:
82                 yylval.n.type= INT;
83                 yylval.n.seg = ANY;
84                 yylval.n.val.i = atoi(tok);
85                 RET(CDEC);
86                 break;
87         case FRAC:
88                 yylval.n.type = FLT;
89                 yylval.n.seg = ANY;
90                 yylval.n.val.f = atof(tok);
91                 RET(FRAC);
92         case CHAR:
93                 yylval.cval = *tok;
94                 RET(CHAR);
95         case STRING:
96                 yylval.sval = (char *)fixstring(tok);
97                 yylval.sval = strsave(yylval.sval);
98                 RET(STRING);
99         default:
100                 RET(ltok);
101         }
102 }
103
104 is_keyword(tok)
105 char *tok;
106 {
107         int kval = kparse(tok);
108         if(kval > 0)
109                 return kval;
110
111         return 0;
112 }
113
114 struct ascii_tab {
115         char *str;
116         int flags;
117 } ascii_tab[];
118 #define IS_NONE         0x0000
119 #define IS_NUM          0x0001
120 #define IS_ALPHA        0x0002
121 #define IS_HEX          0x0004
122 #define IS_WHITE        0x0008
123
124 extern FILE *yyin;
125
126 int next_tok()
127 {
128         char *tp = tok;
129         enum {S_TOP, S_HEXNUM, S_NUM, S_ALNUM, S_CHAR, S_ESC_CHAR, S_COMMENT,
130                 S_SQ_STRING, S_DQ_STRING, S_SHL, S_SHR} state = S_TOP;
131         static int unget = 0;
132         BOOL dot_seen = FALSE;
133
134         for(;;) {
135                 int c = unget ? unget : lgetc(yyin);
136                 int flags;
137                 unget = 0;
138                 flags = ascii_tab[c & 0x7F].flags;
139                 if(tp > tok + MAX_TOK - 2) return LEXBAD;
140                 switch(state) {
141                 case S_TOP:
142                         if(c == EOF) {
143                                 return EOF;
144                         } else if(flags & IS_WHITE) {
145                                 /* ignore */ ;
146                         } else if(flags & IS_ALPHA) {
147                                 *tp++ = c;
148                                 state = S_ALNUM;
149                         } else if((flags & IS_NUM) || c == '.') {
150                                 unget = c;
151                                 state = S_NUM;
152                         } else {
153                                 switch(c) {
154                                 case '$': state = S_HEXNUM; break;
155                                 case '"': state = S_DQ_STRING; break;
156                                 case '\'': state = S_CHAR; break;
157                                 case '>': state = S_SHR; break;
158                                 case '<': state = S_SHL; break;
159                                 case ';': state = S_COMMENT; break;
160                                 case '\n': return EOL;
161                                 case '@': return EOS;
162                                 default: return c;
163                                 }
164                         }
165                         break;
166                 case S_COMMENT:
167                         if(c == EOF) {
168                                 unget = EOF;
169                                 *tp = '\0';
170                                 return EOL;
171                         } else if(c == '\n') {
172                                 return EOL;
173                         }
174                         break;
175                 case S_SHR:
176                         if(c == EOF) {
177                                 unget = EOF;
178                                 *tp = '\0';
179                                 return '>';
180                         } else if(c == '>') {
181                                 return SHR;
182                         } else {
183                                 unget = c;
184                                 return '>';
185                         }
186                         break;
187                 case S_SHL:
188                         if(c == EOF) {
189                                 unget = EOF;
190                                 *tp = '\0';
191                                 return '<';
192                         } else if(c == '<') {
193                                 return SHL;
194                         } else {
195                                 unget = c;
196                                 return '<';
197                         }
198                         break;
199                 case S_HEXNUM:
200                         if(c == EOF) {
201                                 unget = EOF;
202                                 *tp = '\0';
203                                 return CHEX;
204                         } else if(flags & IS_HEX) {
205                                 *tp++ = c;
206                                 break;
207                         } else {
208                                 unget = c;
209                                 *tp = '\0';
210                                 return CHEX;
211                         }
212                         break;
213                 case S_ALNUM:
214                         if(c == EOF) {
215                                 unget = EOF;
216                                 *tp = '\0';
217                                 return SYM;
218                         } else if(c == ':') {
219                                 *tp++ = c;
220                                 *tp = '\0';
221                                 return SYM;
222                                 break;
223                         } else if(flags & (IS_ALPHA|IS_NUM)) {
224                                 *tp++ = c;
225                                 break;
226                         } else {
227                                 unget = c;
228                                 *tp = '\0';
229                                 return SYM;
230                         }
231                         break;
232                 case S_NUM:
233                         if(c == EOF) {
234                                 unget = EOF;
235                                 *tp = '\0';
236                                 return dot_seen ? FRAC : CDEC;
237                         } else if((flags & IS_NUM) || (c == '.' && NOT dot_seen)) {
238                                 *tp++ = c;
239                                 if(c == '.') dot_seen = TRUE;
240                                 break;
241                         } else {
242                                 unget = c;
243                                 *tp = '\0';
244                                 return dot_seen ? FRAC : CDEC;
245                         }
246                         break;
247                 case S_CHAR:
248                         if(c == EOF) {
249                                 unget = EOF;
250                                 *tp = '\0';
251                                 return CHAR;
252                         } else if(c == '\\') {
253                                 state = S_ESC_CHAR;
254                         } else if(c == '\'') {
255                                 *tp = '\0';
256                                 return CHAR;
257                         } else {
258                                 *tp++ = c;
259                                 if(tp > tok + 1)
260                                         state = S_SQ_STRING;
261                         }
262                         break;
263                 case S_ESC_CHAR:
264                         if(c == EOF) {
265                                 unget = EOF;
266                                 *tp = '\0';
267                                 return CHAR;
268                         }
269                         switch(c) {
270                         case 'b': *tp = '\b'; break;
271                         case 'f': *tp = '\f'; break;
272                         case 'n': *tp = '\n'; break;
273                         case 'r': *tp = '\r'; break;
274                         case 't': *tp = '\t'; break;
275                         case '\\': *tp = '\\'; break;
276                         case '\'':
277                                 *tp = '\0';
278                                 return CHAR;
279                                 break;
280                         default:
281                                 *tp++ = c;
282                                 state = S_SQ_STRING;
283                                 break;
284                         }
285                         break;
286                 case S_SQ_STRING:
287                         if(c == EOF) {
288                                 unget = EOF;
289                                 *tp = '\0';
290                                 return STRING;
291                         } else if(c == '\'') {
292                                 *tp = '\0';
293                                 return STRING;
294                         } else {
295                                 *tp++ = c;
296                         }
297                         break;
298                 case S_DQ_STRING:
299                         if(c == EOF) {
300                                 unget = EOF;
301                                 *tp = '\0';
302                                 return STRING;
303                         } else if(c == '"') {
304                                 *tp = '\0';
305                                 return STRING;
306                         } else {
307                                 *tp++ = c;
308                         }
309                         break;
310                 } /* switch(state) */
311         } /* for(;;) */
312 }
313
314 struct ascii_tab ascii_tab[] = {
315         {"\\z00",       IS_NONE                                 /* 0x00 */},
316         {"\\z01",       IS_NONE                                 /* 0x01 */},
317         {"\\z02",       IS_NONE                                 /* 0x02 */},
318         {"\\z03",       IS_NONE                                 /* 0x03 */},
319         {"\\z04",       IS_NONE                                 /* 0x04 */},
320         {"\\z05",       IS_NONE                                 /* 0x05 */},
321         {"\\z06",       IS_NONE                                 /* 0x06 */},
322         {"\\z07",       IS_NONE                                 /* 0x07 */},
323         {"\\b",         IS_NONE                                 /* 0x08 */},
324         {"\\t",         IS_NONE|IS_WHITE                /* 0x09 */},
325         {"\\n",         IS_NONE                                 /* 0x0A */},
326         {"\\z0B",       IS_NONE                                 /* 0x0B */},
327         {"\\z0C",       IS_NONE                                 /* 0x0C */},
328         {"\\r",         IS_NONE                                 /* 0x0D */},
329         {"\\z0E",       IS_NONE                                 /* 0x0E */},
330         {"\\z0F",       IS_NONE                                 /* 0x0F */},
331         {"\\z10",       IS_NONE                                 /* 0x10 */},
332         {"\\z11",       IS_NONE                                 /* 0x11 */},
333         {"\\z12",       IS_NONE                                 /* 0x12 */},
334         {"\\z13",       IS_NONE                                 /* 0x13 */},
335         {"\\z14",       IS_NONE                                 /* 0x14 */},
336         {"\\z15",       IS_NONE                                 /* 0x15 */},
337         {"\\z16",       IS_NONE                                 /* 0x16 */},
338         {"\\z17",       IS_NONE                                 /* 0x17 */},
339         {"\\z18",       IS_NONE                                 /* 0x18 */},
340         {"\\z19",       IS_NONE                                 /* 0x19 */},
341         {"\\z1A",       IS_NONE                                 /* 0x1A */},
342         {"\\z1B",       IS_NONE                                 /* 0x1B */},
343         {"\\z1C",       IS_NONE                                 /* 0x1C */},
344         {"\\z1D",       IS_NONE                                 /* 0x1D */},
345         {"\\z1E",       IS_NONE                                 /* 0x1E */},
346         {"\\z1F",       IS_NONE                                 /* 0x1F */},
347         {" ",           IS_NONE|IS_WHITE                /* 0x20 */},
348         {"!",           IS_NONE                                 /* 0x21 */},
349         {"\"",          IS_NONE                                 /* 0x22 */},
350         {"#",           IS_NONE                                 /* 0x23 */},
351         {"$",           IS_NONE                                 /* 0x24 */},
352         {"%",           IS_NONE                                 /* 0x25 */},
353         {"&",           IS_NONE                                 /* 0x26 */},
354         {"'",           IS_NONE                                 /* 0x27 */},
355         {"(",           IS_NONE                                 /* 0x28 */},
356         {")",           IS_NONE                                 /* 0x29 */},
357         {"*",           IS_NONE                                 /* 0x2A */},
358         {"+",           IS_NONE                                 /* 0x2B */},
359         {",",           IS_NONE                                 /* 0x2C */},
360         {"-",           IS_NONE                                 /* 0x2D */},
361         {".",           IS_NONE                                 /* 0x2E */},
362         {"/",           IS_NONE                                 /* 0x2F */},
363         {"0",           IS_NONE|IS_NUM|IS_HEX   /* 0x30 */},
364         {"1",           IS_NONE|IS_NUM|IS_HEX   /* 0x31 */},
365         {"2",           IS_NONE|IS_NUM|IS_HEX   /* 0x32 */},
366         {"3",           IS_NONE|IS_NUM|IS_HEX   /* 0x33 */},
367         {"4",           IS_NONE|IS_NUM|IS_HEX   /* 0x34 */},
368         {"5",           IS_NONE|IS_NUM|IS_HEX   /* 0x35 */},
369         {"6",           IS_NONE|IS_NUM|IS_HEX   /* 0x36 */},
370         {"7",           IS_NONE|IS_NUM|IS_HEX   /* 0x37 */},
371         {"8",           IS_NONE|IS_NUM|IS_HEX   /* 0x38 */},
372         {"9",           IS_NONE|IS_NUM|IS_HEX   /* 0x39 */},
373         {":",           IS_NONE                                 /* 0x3A */},
374         {";",           IS_NONE                                 /* 0x3B */},
375         {"<",           IS_NONE                                 /* 0x3C */},
376         {"=",           IS_NONE                                 /* 0x3D */},
377         {">",           IS_NONE                                 /* 0x3E */},
378         {"?",           IS_NONE                                 /* 0x3F */},
379         {"@",           IS_NONE                                 /* 0x40 */},
380         {"A",           IS_NONE|IS_ALPHA|IS_HEX /* 0x41 */},
381         {"B",           IS_NONE|IS_ALPHA|IS_HEX /* 0x42 */},
382         {"C",           IS_NONE|IS_ALPHA|IS_HEX /* 0x43 */},
383         {"D",           IS_NONE|IS_ALPHA|IS_HEX /* 0x44 */},
384         {"E",           IS_NONE|IS_ALPHA|IS_HEX /* 0x45 */},
385         {"F",           IS_NONE|IS_ALPHA|IS_HEX /* 0x46 */},
386         {"G",           IS_NONE|IS_ALPHA                /* 0x47 */},
387         {"H",           IS_NONE|IS_ALPHA                /* 0x48 */},
388         {"I",           IS_NONE|IS_ALPHA                /* 0x49 */},
389         {"J",           IS_NONE|IS_ALPHA                /* 0x4A */},
390         {"K",           IS_NONE|IS_ALPHA                /* 0x4B */},
391         {"L",           IS_NONE|IS_ALPHA                /* 0x4C */},
392         {"M",           IS_NONE|IS_ALPHA                /* 0x4D */},
393         {"N",           IS_NONE|IS_ALPHA                /* 0x4E */},
394         {"O",           IS_NONE|IS_ALPHA                /* 0x4F */},
395         {"P",           IS_NONE|IS_ALPHA                /* 0x50 */},
396         {"Q",           IS_NONE|IS_ALPHA                /* 0x51 */},
397         {"R",           IS_NONE|IS_ALPHA                /* 0x52 */},
398         {"S",           IS_NONE|IS_ALPHA                /* 0x53 */},
399         {"T",           IS_NONE|IS_ALPHA                /* 0x54 */},
400         {"U",           IS_NONE|IS_ALPHA                /* 0x55 */},
401         {"V",           IS_NONE|IS_ALPHA                /* 0x56 */},
402         {"W",           IS_NONE|IS_ALPHA                /* 0x57 */},
403         {"X",           IS_NONE|IS_ALPHA                /* 0x58 */},
404         {"Y",           IS_NONE|IS_ALPHA                /* 0x59 */},
405         {"Z",           IS_NONE|IS_ALPHA                /* 0x5A */},
406         {"[",           IS_NONE                                 /* 0x5B */},
407         {"\\",          IS_NONE                                 /* 0x5C */},
408         {"]",           IS_NONE                                 /* 0x5D */},
409         {"^",           IS_NONE                                 /* 0x5E */},
410         {"_",           IS_NONE|IS_ALPHA                /* 0x5F */},
411         {"`",           IS_NONE                                 /* 0x60 */},
412         {"a",           IS_NONE|IS_ALPHA|IS_HEX /* 0x61 */},
413         {"b",           IS_NONE|IS_ALPHA|IS_HEX /* 0x62 */},
414         {"c",           IS_NONE|IS_ALPHA|IS_HEX /* 0x63 */},
415         {"d",           IS_NONE|IS_ALPHA|IS_HEX /* 0x64 */},
416         {"e",           IS_NONE|IS_ALPHA|IS_HEX /* 0x65 */},
417         {"f",           IS_NONE|IS_ALPHA|IS_HEX /* 0x66 */},
418         {"g",           IS_NONE|IS_ALPHA                /* 0x67 */},
419         {"h",           IS_NONE|IS_ALPHA                /* 0x68 */},
420         {"i",           IS_NONE|IS_ALPHA                /* 0x69 */},
421         {"j",           IS_NONE|IS_ALPHA                /* 0x6A */},
422         {"k",           IS_NONE|IS_ALPHA                /* 0x6B */},
423         {"l",           IS_NONE|IS_ALPHA                /* 0x6C */},
424         {"m",           IS_NONE|IS_ALPHA                /* 0x6D */},
425         {"n",           IS_NONE|IS_ALPHA                /* 0x6E */},
426         {"o",           IS_NONE|IS_ALPHA                /* 0x6F */},
427         {"p",           IS_NONE|IS_ALPHA                /* 0x70 */},
428         {"q",           IS_NONE|IS_ALPHA                /* 0x71 */},
429         {"r",           IS_NONE|IS_ALPHA                /* 0x72 */},
430         {"s",           IS_NONE|IS_ALPHA                /* 0x73 */},
431         {"t",           IS_NONE|IS_ALPHA                /* 0x74 */},
432         {"u",           IS_NONE|IS_ALPHA                /* 0x75 */},
433         {"v",           IS_NONE|IS_ALPHA                /* 0x76 */},
434         {"w",           IS_NONE|IS_ALPHA                /* 0x77 */},
435         {"x",           IS_NONE|IS_ALPHA                /* 0x78 */},
436         {"y",           IS_NONE|IS_ALPHA                /* 0x79 */},
437         {"z",           IS_NONE|IS_ALPHA                /* 0x7A */},
438         {"{",           IS_NONE                                 /* 0x7B */},
439         {"|",           IS_NONE                                 /* 0x7C */},
440         {"}",           IS_NONE                                 /* 0x7D */},
441         {"~",           IS_NONE                                 /* 0x7E */},
442         {"\\z7F",       IS_NONE                                 /* 0x7F */},
443 };
444
445
446 /**************** lgetc - returns next character *************************/
447
448 #define INLINE 1024
449
450 char line_buf[INLINE];
451 char *cur_line = line_buf;              /* points to current line buffer */
452 char *clp = NULL;                               /* where we're at in cur_line */
453
454 lgetc(fp)
455 FILE *fp;
456 {
457         int c;
458
459         if(clp == NULL) {
460                 if(fgets(cur_line, INLINE, fp) == NULL) {
461                         c = EOF;
462                 } else {
463                         clp = cur_line;
464                         c = *clp++;
465                 }
466         } else {
467                 c = *clp++;
468         }
469
470         switch(c) {
471         case EOF:
472                 /* at EOF: all done */
473                 if(ldebug)
474                         printf("<eof>\n");
475                 return EOF;
476                 break;
477         case '\0':
478                 c = '\n';
479         case '\n':
480                 clp = NULL;
481                 break;
482         default:
483                 break;
484         }
485
486         if(ldebug)
487                 printf(c < ' ' ? "<\\z%02X>%s" : "<%c>", c, c == '\n' ? "\n" : "");
488
489         return c;
490 }