Make sure to print a stack trace whenever an error signal is delivered
[oota-llvm.git] / utils / Burg / lex.c
1 char rcsid_lex[] = "$Id$";
2
3 #include <ctype.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include "b.h"
7 #include "fe.h"
8 #include "gram.tab.h"
9
10 static char buf[BUFSIZ];
11
12 static int yyline = 1;
13
14 typedef int (*ReadFn) ARGS((void));
15
16 static char *StrCopy ARGS((char *));
17 static int code_get ARGS((void));
18 static int simple_get ARGS((void));
19 static void ReadCharString ARGS((ReadFn, int));
20 static void ReadCodeBlock ARGS((void));
21 static void ReadOldComment ARGS((ReadFn));
22
23 static char *
24 StrCopy(s) char *s;
25 {
26         char *t = (char *)zalloc(strlen(s) + 1);
27         strcpy(t,s);
28         return t;
29 }
30
31 static int
32 simple_get()
33 {
34         int ch;
35         if ((ch = getchar()) == '\n') {
36                 yyline++;
37         }
38         return ch;
39 }
40
41 static int
42 code_get()
43 {
44         int ch;
45         if ((ch = getchar()) == '\n') {
46                 yyline++;
47         }
48         if (ch != EOF) {
49                 fputc(ch, outfile);
50         }
51         return ch;
52 }
53
54 void
55 yypurge()
56 {
57         while (code_get() != EOF) ;
58 }
59
60
61 static void
62 ReadCharString(rdfn, which) ReadFn rdfn; int which;
63 {
64         int ch;
65         int backslash = 0;
66         int firstline = yyline;
67
68         while ((ch = rdfn()) != EOF) {
69                 if (ch == which && !backslash) {
70                         return;
71                 }
72                 if (ch == '\\' && !backslash) {
73                         backslash = 1;
74                 } else {
75                         backslash = 0;
76                 }
77         }
78         yyerror1("Unexpected EOF in string on line ");
79         fprintf(stderr, "%d\n", firstline);
80         exit(1);
81 }
82
83 static void
84 ReadOldComment(rdfn) ReadFn rdfn;
85 {
86         /* will not work for comments delimiter in string */
87
88         int ch;
89         int starred = 0;
90         int firstline = yyline;
91
92         while ((ch = rdfn()) != EOF) {
93                 if (ch == '*') {
94                         starred = 1;
95                 } else if (ch == '/' && starred) {
96                         return;
97                 } else {
98                         starred = 0;
99                 }
100         }
101         yyerror1("Unexpected EOF in comment on line ");
102         fprintf(stderr, "%d\n", firstline);
103         exit(1);
104 }
105
106 static void
107 ReadCodeBlock()
108 {
109         int ch;
110         int firstline = yyline;
111
112         while ((ch = getchar()) != EOF) {
113                 if (ch == '%') {
114                         ch = getchar();
115                         if (ch != '}') {
116                                 yyerror("bad %%");
117                         }
118                         return;
119                 }
120                 fputc(ch, outfile);
121                 if (ch == '\n') {
122                         yyline++;
123                 }
124                 if (ch == '"' || ch == '\'') {
125                         ReadCharString(code_get, ch);
126                 } else if (ch == '/') {
127                         ch = getchar();
128                         if (ch == '*') {
129                                 fputc(ch, outfile);
130                                 ReadOldComment(code_get);
131                                 continue;
132                         } else {
133                                 ungetc(ch, stdin);
134                         }
135                 }
136         }
137         yyerror1("Unclosed block of C code started on line ");
138         fprintf(stderr, "%d\n", firstline);
139         exit(1);
140 }
141
142 static int done;
143 void
144 yyfinished()
145 {
146         done = 1;
147 }
148
149 int
150 yylex()
151 {
152         int ch;
153         char *ptr = buf;
154
155         if (done) return 0;
156         while ((ch = getchar()) != EOF) {
157                 switch (ch) {
158                 case ' ':
159                 case '\f':
160                 case '\t':
161                         continue;
162                 case '\n':
163                         yyline++;
164                         continue;
165                 case '(':
166                 case ')':
167                 case ',':
168                 case ':':
169                 case ';':
170                 case '=':
171                         return(ch);
172                 case '/':
173                         ch = getchar();
174                         if (ch == '*') {
175                                 ReadOldComment(simple_get);
176                                 continue;
177                         } else {
178                                 ungetc(ch, stdin);
179                                 yyerror("illegal char /");
180                                 continue;
181                         }
182                 case '%':
183                         ch = getchar();
184                         switch (ch) {
185                         case '%':
186                                 return (K_PPERCENT);
187                         case '{':
188                                 ReadCodeBlock();
189                                 continue;
190                         case 's':
191                         case 'g':
192                         case 't':
193                                 do {
194                                         if (ptr >= &buf[BUFSIZ]) {
195                                                 yyerror("ID too long");
196                                                 return(ERROR);
197                                         } else {
198                                                 *ptr++ = ch;
199                                         }
200                                         ch = getchar();
201                                 } while (isalpha(ch) || isdigit(ch) || ch == '_');
202                                 ungetc(ch, stdin);
203                                 *ptr = '\0';
204                                 if (!strcmp(buf, "term")) return K_TERM;
205                                 if (!strcmp(buf, "start")) return K_START;
206                                 if (!strcmp(buf, "gram")) return K_GRAM;
207                                 yyerror("illegal character after %%");
208                                 continue;
209                         default:
210                                 yyerror("illegal character after %%");
211                                 continue;
212                         }
213                 default:
214                         if (isalpha(ch) ) {
215                                 do {
216                                         if (ptr >= &buf[BUFSIZ]) {
217                                                 yyerror("ID too long");
218                                                 return(ERROR);
219                                         } else {
220                                                 *ptr++ = ch;
221                                         }
222                                         ch = getchar();
223                                 } while (isalpha(ch) || isdigit(ch) || ch == '_');
224                                 ungetc(ch, stdin);
225                                 *ptr = '\0';
226                                 yylval.y_string = StrCopy(buf);
227                                 return(ID);
228                         } 
229                         if (isdigit(ch)) {
230                                 int val=0;
231                                 do {
232                                         val *= 10;
233                                         val += (ch - '0');
234                                         ch = getchar();
235                                 } while (isdigit(ch));
236                                 ungetc(ch, stdin);
237                                 yylval.y_int = val;
238                                 return(INT);
239                         }
240                         yyerror1("illegal char ");
241                         fprintf(stderr, "(\\%03o)\n", ch);
242                         exit(1);
243                 }
244         }
245         return(0);
246 }
247
248 void yyerror1(const char *str)
249 {
250         fprintf(stderr, "line %d: %s", yyline, str);
251 }
252
253 void
254 yyerror(const char *str)
255 {
256         yyerror1(str);
257         fprintf(stderr, "\n");
258         exit(1);
259 }