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