Move the sources to trunk
[opencv] / apps / Hawk / CVEiCL / EiC / src / lexer.c
1 /* lexer.c
2  *
3  *      (C) Copyright Apr 15 1995, Edmond J. Breen.
4  *                 ALL RIGHTS RESERVED.
5  * This code may be copied for personal, non-profit use only.
6  *
7  *
8  * History:
9  *           First written V1.0 1984 (E.J.B)
10  *           Revised       V1.2 1994 (E.J.B)
11  *           Revised       V2.0 1995 (E.J.B)
12  *
13  */
14  
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <limits.h>
18 #include <string.h>
19 #include <math.h>
20 #include <float.h>
21
22 #include "global.h"
23 #include "xalloc.h"
24 #include "error.h"
25 #include "symbol.h"
26 #include "lexer.h"
27 #include "preproc.h"
28
29 static void retract(char c);
30 static int fail(int ival, int c);
31 static int charliteral(int c);
32 static void EiC_stringliteral(void);
33 static void success(int ival);
34
35 char nextchar(void);
36 char *nextproline(void);
37 void retract(char c);
38 int fail(int ival, int c);
39 int charliteral(int c);
40 void stringliteral(void);
41 void success(int ival);
42
43
44 #define NEWLINE(ch)  (ch  == '\n' ? TRUE: FALSE)
45 #define LETTER(ch)   ((ch >=  'a'  && ch   <=  'z') ? TRUE :\
46                                  ((ch >=  'A'  && ch   <=  'Z') ? TRUE :\
47                                  ((ch ==  '_'   || ch   ==  '$')? TRUE : FALSE)))
48
49 #define DIGIT(ch)   ((ch  >=  '0'   && ch   <= '9') ? TRUE : FALSE)
50 #define WHITE(ch)   ((ch  == ' '    || ch   == '\t')? TRUE : FALSE)
51
52
53
54 keyword_t cwords[] =
55 {
56     {"__eiclongjmp",eiclongjmpsym,},
57     {"__eicsetjmp",eicsetjmpsym,},
58
59   {"auto", autosym,},
60   {"break", breaksym,},
61   {"case", casesym,},
62   {"char", charsym,},
63   {"const", constsym,},
64   {"continue", continuesym,},
65   {"default", defaultsym,},
66   {"do", dosym,},
67   {"double", doublesym,},
68   {"else", elsesym,},
69   {"enum", enumsym,},
70   {"extern", externsym,},
71   {"float", floatsym,},
72   {"for", forsym,},
73   {"goto",gotosym,},
74   {"if", ifsym,},
75   {"int", intsym,},
76   {"long", longsym,},
77   {"register", registersym,},
78   {"return", returnsym,},
79   {"safe", safesym,},
80   {"short", shortsym,},
81   {"signed", signedsym,},
82   {"sizeof", sizeofsym,},
83   {"static", staticsym,},
84   {"struct", structsym,},
85   {"switch", switchsym,},
86   {"typedef", typedefsym,},
87   {"union", unionsym,},
88   {"unsafe", unsafesym,},
89   {"unsigned", unsignedsym,},
90   {"void", voidsym,},
91   {"volatile", volatilesym,},
92   {"while", whilesym,},
93 };
94
95
96
97 #define NOTOKEN 0
98
99 char EiC_LEXEM[BSIZE+1];
100 static token_t TOK;
101 token_t *token = &TOK;
102
103 #ifdef ILOOKAHEAD
104
105 token_t EiC_TokenArray[MAX_TOKENS];
106 int EiC_TokenI = 0, EiC_TokenP = 0, EiC_TokenR=0;
107
108 #else
109
110 unsigned short STOKEN;
111
112 #endif
113
114
115
116
117 unsigned lex_lineno, lex_lineprev, lex_linepos, lex_linelen, lex_curpos = 0,
118  lex_lastpos;
119 char *lex_buff;
120
121 static int state = 0;
122 static unsigned long lexival;
123 static double lexfval;
124 static char Lseen,  /* long seen */
125             Fseen,  /* floating point seen */
126             Useen,  /* Unsigned specifier seen */
127             Hseen;  /* Hex or Octal value seen */
128
129 #define getoct(x)  (((x)>='0'&&(x)<='7')? (x)-'0':-1)
130
131
132 static int gethex(int c)
133 {
134     if (c >= '0' && c <= '9')
135         return c - '0';
136     if (c >= 'a' && c <= 'f')
137         return c - 'a' + 10;
138     if (c >= 'A' && c <= 'F')
139         return c - 'A' + 10;
140     return -1;
141 }
142
143
144 void EiC_initlex(char *str)
145 {
146     lex_buff = str;
147     lex_curpos = 0;
148     lex_lineprev = 0;
149     lex_lineno = 1;
150
151 #ifdef ILOOKAHEAD
152     EiC_TokenR = EiC_TokenP = EiC_TokenI = 0;
153     
154 #else
155
156     STOKEN = NOTOKEN;
157 #endif
158     
159 }
160
161 char EiC_nextchar()
162 {
163     char *EiC_nextproline();
164     if (lex_buff[lex_curpos] == EOF) {
165         return 0;
166     }
167     else if (lex_buff[lex_curpos] == '\0') {
168       
169         if (lex_curpos != lex_lastpos)
170             return 0;
171
172         lex_buff = EiC_nextproline();
173         lex_lastpos = lex_curpos = 0;
174         lex_lineprev = 0;
175         lex_lineno = 1;
176     }
177     if (lex_lineprev != lex_lineno) {
178         lex_linepos = lex_curpos;
179         lex_lineprev = lex_lineno;
180     }
181     return (lex_buff[lex_curpos++]);
182 }
183
184 static void checkExt(int c)
185 {                               /* check for unsigned and long suffix */
186     Lseen = Useen = Fseen = 0;
187     if (c == 'f' || c == 'F')
188         Fseen = 1;
189     else if (c == 'u' || c == 'U') {
190         Useen = 1;
191         if ((c = EiC_nextchar()) == 'l' || c == 'L')
192             Lseen = 1;
193         else
194             retract(c);
195     } else if (c == 'l' || c == 'L')
196         Lseen = 1;
197     else
198         retract(c);
199 }
200
201 static void retract(char c)
202 {
203     if (c != '\0') {
204         lex_curpos--;
205         if (lex_curpos < lex_lastpos)
206             lex_lastpos = lex_curpos;
207     }
208 }
209
210
211 static int fail(int ival, int c)
212 {
213     retract(c);
214     switch (ival) {
215       case RELOP: return (10);
216       case ID:    return (20);
217       case FLOAT:
218       case INT: return (100);
219     }
220     return 0;
221 }
222
223 static void setfloatval(void)
224 {
225
226     if (Lseen || lexfval > FLT_MAX  || !Fseen ) {
227         token->Val.dval = lexfval;
228         token->Tok = DOUBLE;
229     } else {
230         /* mandatory conversion to float */
231         float f = lexfval;
232         token->Val.dval = f;
233         token->Tok = FLOAT;
234     }
235
236 }
237
238 static void setintval(void)
239 {
240     if (Fseen) {
241         lexfval = lexival;
242         setfloatval();
243         return;
244     }
245     if (Useen) {
246         if (Lseen || lexival > UINT_MAX) {
247             token->Tok = ULONG;
248             token->Val.ulval = lexival;
249         } else {
250             token->Tok = UINT;
251             token->Val.uival = (unsigned) lexival;
252         }
253     } else if (Lseen || lexival > UINT_MAX) {
254         if (lexival > ULONG_MAX) {
255             token->Tok = ULONG;
256             token->Val.ulval = lexival;
257         } else if (lexival >= ULONG_MAX) {
258             token->Tok = ULONG;
259             token->Val.ulval = lexival;
260         } else {
261             token->Val.lval = lexival;
262             token->Tok = LONG;
263         }
264     } else {
265         if (lexival <= INT_MAX) {
266             token->Val.ival = (int) lexival;
267             token->Tok = INT;
268         } else if(Hseen && lexival <= UINT_MAX) {
269             token->Tok = UINT;
270             token->Val.uival = (unsigned) lexival;
271         } else if(lexival <= LONG_MAX) {            
272             token->Val.lval = (long) lexival;
273             token->Tok = LONG;
274         } else {
275            token->Tok = ULONG;
276            token->Val.ulval = lexival;
277        }
278     }
279 }
280
281 static void success(int ival)
282 {
283     int i, size;
284
285     size = (int) (lex_curpos - lex_lastpos);
286     memcpy(EiC_LEXEM, &lex_buff[lex_lastpos], size);
287     EiC_LEXEM[size] = '\0';
288     if (Lseen) size--;
289     if (Useen) size--;
290     if (Fseen) size--;
291
292     Hseen = 0;
293     switch (ival) {
294         case ID:
295             if ((token->Tok = EiC_iskeyword(cwords, EiC_LEXEM,
296                                         sizeof(cwords) / sizeof(keyword_t))) == 0) {
297                 token->Tok = ID;
298                 /* search for id in various name spaces */
299                 if ((token->Val.sym = EiC_lookup(EiC_work_tab, EiC_LEXEM)) == NULL)
300                     token->Val.sym = EiC_insertLUT(EiC_work_tab, EiC_LEXEM, ID);
301                 if (token->Val.sym)
302                     if (token->Val.sym->sclass == c_typedef)
303                         token->Tok = TYPENAME;
304             }
305             break;
306         case OCTAL:
307             if (Fseen)
308                 EiC_error("Declaration syntax error");
309             for (lexival = 0, i = 0; i < size; i++)
310                 lexival = lexival * 8 + getoct(EiC_LEXEM[i]);
311             Hseen = 1;
312             setintval();
313             break;
314         case HEX:
315             for (lexival = 0, i = 2; i < size; i++)
316                 lexival = lexival * 16 + gethex(EiC_LEXEM[i]);
317             Hseen = 1;
318             setintval();
319             break;
320         case INT:
321             for (lexival = 0, i = 0; i < size; i++)
322                 lexival = lexival * 10 + EiC_LEXEM[i] - '0';
323             setintval();
324             break;
325         case FLOAT:
326             if (Useen)
327                 EiC_error("Declaration syntax error");
328             lexfval = atof(EiC_LEXEM);
329             setfloatval();
330             break;
331         case RELOP:
332         case MISC:
333             break;
334     }
335 }
336
337
338 static int WASLITERAL;
339 static int charliteral(int c)
340 {
341     if (c == '\\') {
342         switch ((c = EiC_nextchar())) {
343         case 'n': c = '\n'; break;     /* newline */
344         case 't': c = '\t'; break;     /* tabspace */
345         case 'v': c = '\v'; break;     /* vertical tab */
346         case 'b': c = '\b'; break;     /* backspace */
347         case 'r': c = '\r'; break;     /* carriage return */
348         case 'f': c = '\f'; break;     /* formfeed */
349         case 'a': c = '\a'; break;     /* bell */
350         case '\\': c = '\\'; break;    /* backslash */
351         case '\'': c = '\''; break;    /* single quote */
352         case '"': c = '\"'; break;     /* double quote */
353         case '?': c = '\?'; break;     /* question mark */
354         case 'x':                      /* string of hex characters */
355         case 'X':{
356             int i, val = 0;
357             while ((i = gethex((c = EiC_nextchar()))) > -1) {
358                 val = val * 16 + i;
359             }
360             retract(c);
361             if (val > 255)
362                 EiC_error("Illegal character hex value");
363             c = val;
364         }
365         break;
366         default:
367             if (getoct(c) > -1) {               /* octal characters */
368                 int i, val = 0;
369                 while ((i = getoct(c)) > -1) {
370                     val = val * 8 + i;
371                     c = EiC_nextchar();
372                 }
373                 retract(c);
374                 if (val > 255)
375                     EiC_error("Illegal character octal value");
376                 c = val;
377             } else
378                 EiC_error("Illegal character escape sequence `\\%c'", c);
379             break;
380         }
381         WASLITERAL = 1;
382     } else
383         WASLITERAL = 0;
384     return ((signed char )c);
385 }
386
387 static void EiC_stringliteral(void)
388 {
389     unsigned size, lastsize = 0, c;
390     char *p=NULL;
391     lex_lastpos = lex_curpos;
392     do {
393
394         for (size = 0; ((c = charliteral(EiC_nextchar())) != '\0' || WASLITERAL) &&
395              !(c == '"' && !WASLITERAL)  && size < BSIZE; size++) 
396             EiC_LEXEM[size] = c;
397     
398
399         if (lastsize)
400             p = (char *) xrealloc(p, lastsize + size + 1);
401         else
402             p = (char *) xcalloc(size + 1, sizeof(char));
403
404         memcpy(&p[lastsize], EiC_LEXEM, size);
405         lastsize += size;
406
407         if(c != '"' && size == BSIZE) {
408             p[lastsize++] = c;
409             continue;
410         }
411         
412         if (c != '"')
413             EiC_error("String literal error");
414
415         do {
416             c = EiC_nextchar();
417             if (c == '\n')
418                 lex_lastpos++, lex_lineno++;
419         } while (WHITE(c) || c == '\n');
420
421         lex_lastpos = lex_curpos;
422         if (!c)
423             do
424                 c = EiC_nextchar();
425             while (WHITE(c));
426     } while (c == '"' || size == BSIZE);
427     retract(c);
428     p[lastsize] = '\0';
429     token->Val.p.sp = token->Val.p.p = p;
430     token->Val.p.ep = p + lastsize + 1;
431 }
432
433 extern int EiC_lexan(void)
434 {
435     int t=0, loop; char c=0, EiC_nextchar();
436
437 #ifdef ILOOKAHEAD
438
439     token = &EiC_TokenArray[EiC_TokenP];
440
441     if(EiC_TokenR > 0) {
442         EiC_TokenR--;
443         EiC_TokenI++;
444         EiC_TokenP=(EiC_TokenP+1)%MAX_TOKENS;
445         return token->Tok;
446     }
447
448
449 #else
450
451     if (STOKEN != NOTOKEN) {
452         STOKEN = NOTOKEN;
453         return token->Tok;
454     }
455
456 #endif
457     
458     loop  = 1;
459     state = 0;
460     while (loop) {
461         switch (state) {
462           case 0: lex_lastpos = lex_curpos; c = EiC_nextchar();
463             state = (WHITE(c) ? 0 :
464                     (c == '\n' ? lex_lineno++, 0 :
465                     (c == '<' ? t = LT, 1 :
466                     (c == '>' ? t = GT, 2 :
467                     (c == '+' ? t = '+', 3 :
468                     (c == '-' ? t = '-', 4 :
469                     (c == '|' ? t = BOR, 5 :
470                     (c == '&' ? t = AND, 6 :
471                     (c == '\''? 7 :
472                     (c == '"' ? 8 :
473                     (c == '.' ? 9 :  
474                     (c == '/' ? t = '/', c = EiC_nextchar(), 50 :
475                     (c == '%' ? t = '%', c = EiC_nextchar(), 50 :
476                     (c == '*' ? t = '*', c = EiC_nextchar(), 50 :
477                     (c == '=' ? t = ASS, c = EiC_nextchar(), 50 :
478                     (c == '!' ? t = NOT, c = EiC_nextchar(), 50 :
479                     (c == '^' ? t = XOR, c = EiC_nextchar(), 50 :
480                      fail(RELOP, c))))))))))))))))));
481             break;
482           case 1: /* get <,  <= and << */
483             if ((c = EiC_nextchar()) == '<') t = LSHT;
484             else state = 50;
485             break;
486           case 2: /* get >, >= and >> */
487             if ((c = EiC_nextchar()) == '>') t = RSHT;
488             else state = 50;
489             break;
490           case 3: c = EiC_nextchar();                         /* get +, += or ++ */
491             if (c == '+') t = INC, state = 60;
492             else state = 50;
493             break;
494           case 4: c = EiC_nextchar();                            /* get -, -= -- */
495             state = 60;
496             if (c == '-') t = DEC;
497             else if (c == '>') t = RARROW;
498             else state = 50;
499             break;
500           case 5: c = EiC_nextchar();                         /* get |, |= or || */
501             if (c == '|') t = LOR, state = 60;
502             else state = 50;
503             break;
504           case 6: c = EiC_nextchar();                         /* get &, &= or && */
505             if (c == '&') t = LAND, state = 60;
506             else state = 50;
507             break;
508           case 7:token->Val.ival = charliteral(EiC_nextchar()); /* char_constants */
509             t = CHAR;
510             if (EiC_nextchar() != '\'')
511                 EiC_error("Missing single quote '");
512             state = 60;
513             break;
514           case 8: EiC_stringliteral();                        /* string literals */
515             token->Tok = STR;
516             /*return STR;*/ loop = 0; break;
517           case 9: c = EiC_nextchar();
518             t = '.';
519             if(DIGIT(c)) 
520                 state = 22;
521             else
522                 state = 60;
523             retract(c);
524             break;
525           case 10: c = EiC_nextchar();              /* identifiers and  keywords */
526             state = (LETTER(c) ? 11 :
527                     (c == '_' ? 11 : fail(ID, c)));
528             break;
529           case 11: c = EiC_nextchar();
530             state = (LETTER(c) ? 11 :
531                     (DIGIT(c) ? 11 :
532                     (c == '_' ? 11 : 12)));
533             break;
534           case 12: retract(c); success(ID); /*return (token->Tok);*/ loop = 0; break;
535
536           case 20: c = EiC_nextchar();                     /* integers and reals */
537             state = (c == '0' ? 30 :
538                     (DIGIT(c) ? 21 : fail(INT, c)));
539             break;
540           case 21: c = EiC_nextchar();
541             state = (DIGIT(c) ? 21 :
542                     (c == '.' ? 22 :
543                     (c == 'e' ? 23 :
544                     (c == 'E' ? 23 : 25))));
545             break;
546           case 22: c = EiC_nextchar();
547             state = (DIGIT(c) ? 22 :
548                     (c == 'e' ? 23 :
549                     (c == 'E' ? 23 : 26)));
550             break;
551           case 23: c = EiC_nextchar();
552             state = (c == '+' ? 24 :
553                     (c == '-' ? 24 :
554                     (DIGIT(c) ? 24 : fail(FLOAT, c) /* ??? */ )));
555             break;
556           case 24: c = EiC_nextchar();
557             state = (DIGIT(c) ? 24 : 26);
558             break;
559           case 25: checkExt(c); success(INT); /*return (token->Tok);*/ loop = 0; break;
560           case 26: checkExt(c); success(FLOAT); /*return (token->Tok);*/ loop = 0; break;
561           case 27: checkExt(c); success(HEX);   /*return (token->Tok);*/ loop = 0; break;
562           case 28: checkExt(c); success(OCTAL); /*return (token->Tok);*/ loop = 0; break;
563           case 30:                        /* check for octal and hex numbers */
564             if ((c = EiC_nextchar()) == 'x' || c == 'X') {
565                 while (gethex((c = EiC_nextchar())) > -1);
566                 state = 27;
567                 break;
568             }
569             if (c != '.' && c != 'e' && c != 'E') {
570                 while (getoct(c) > -1)
571                     c = EiC_nextchar();
572                 state = 28;
573                 break;
574             }
575             retract(c); state = 21; break;
576           case 50:                                      /* mix with equal's  */
577             if (c == '=')
578                 switch (t) {
579                   case '+': t = ADDEQ;  break;          /* += */
580                   case '-': t = SUBEQ;  break;          /* -= */
581                   case '/': t = DIVEQ;  break;          /* /= */
582                   case '*': t = MULEQ;  break;          /* *= */
583                   case '%': t = MODEQ;  break;          /* %= */
584                   case ASS: t = EQ;     break;          /* == */
585                   case GT:  t = GE;     break;          /* >= */
586                   case LT:  t = LE;     break;          /* <= */
587                   case NOT: t = NE;     break;          /* != */
588                   case RSHT:t = RSHTEQ; break;          /* >>= */
589                   case LSHT:t = LSHTEQ; break;          /* <<= */
590                   case AND: t = ANDEQ;  break;          /* &= */
591                   case BOR: t = BOREQ;  break;          /* |= */
592                   case XOR: t = XOREQ;  break;          /* ^= */
593                   default: retract(c);
594             } else retract(c);
595             state = 60;
596             break;
597           case 60: success(MISC); token->Tok = t; /*return (token->Tok);*/ loop = 0; break;
598           case 100: token->Tok = EiC_nextchar(); /*return (token->Tok);*/ loop = 0; break;
599         }
600     }
601
602 #ifdef ILOOKAHEAD
603
604     if(EiC_TokenI<MAX_TOKENS)
605         EiC_TokenI++;
606
607     EiC_TokenP = (EiC_TokenP +1)%MAX_TOKENS;
608
609 #endif
610
611     return token->Tok;
612
613
614 }
615
616
617
618