lex.c revision 1.7 1 1.1 christos /****************************************************************
2 1.1 christos Copyright (C) Lucent Technologies 1997
3 1.1 christos All Rights Reserved
4 1.1 christos
5 1.1 christos Permission to use, copy, modify, and distribute this software and
6 1.1 christos its documentation for any purpose and without fee is hereby
7 1.1 christos granted, provided that the above copyright notice appear in all
8 1.1 christos copies and that both that the copyright notice and this
9 1.1 christos permission notice and warranty disclaimer appear in supporting
10 1.1 christos documentation, and that the name Lucent Technologies or any of
11 1.1 christos its entities not be used in advertising or publicity pertaining
12 1.1 christos to distribution of the software without specific, written prior
13 1.1 christos permission.
14 1.1 christos
15 1.1 christos LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 1.1 christos INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17 1.1 christos IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18 1.1 christos SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 1.1 christos WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20 1.1 christos IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 1.1 christos ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22 1.1 christos THIS SOFTWARE.
23 1.1 christos ****************************************************************/
24 1.1 christos
25 1.2 christos #if HAVE_NBTOOL_CONFIG_H
26 1.2 christos #include "nbtool_config.h"
27 1.2 christos #endif
28 1.2 christos
29 1.1 christos #include <stdio.h>
30 1.1 christos #include <stdlib.h>
31 1.1 christos #include <string.h>
32 1.1 christos #include <ctype.h>
33 1.1 christos #include "awk.h"
34 1.2 christos #include "awkgram.h"
35 1.1 christos
36 1.1 christos extern YYSTYPE yylval;
37 1.1 christos extern int infunc;
38 1.1 christos
39 1.1 christos int lineno = 1;
40 1.1 christos int bracecnt = 0;
41 1.1 christos int brackcnt = 0;
42 1.1 christos int parencnt = 0;
43 1.1 christos
44 1.1 christos typedef struct Keyword {
45 1.1 christos const char *word;
46 1.1 christos int sub;
47 1.1 christos int type;
48 1.1 christos } Keyword;
49 1.1 christos
50 1.6 christos const Keyword keywords[] = { /* keep sorted: binary searched */
51 1.1 christos { "BEGIN", XBEGIN, XBEGIN },
52 1.1 christos { "END", XEND, XEND },
53 1.1 christos { "NF", VARNF, VARNF },
54 1.6 christos { "and", FAND, BLTIN },
55 1.1 christos { "atan2", FATAN, BLTIN },
56 1.1 christos { "break", BREAK, BREAK },
57 1.1 christos { "close", CLOSE, CLOSE },
58 1.6 christos { "compl", FCOMPL, BLTIN },
59 1.1 christos { "continue", CONTINUE, CONTINUE },
60 1.1 christos { "cos", FCOS, BLTIN },
61 1.1 christos { "delete", DELETE, DELETE },
62 1.1 christos { "do", DO, DO },
63 1.1 christos { "else", ELSE, ELSE },
64 1.1 christos { "exit", EXIT, EXIT },
65 1.1 christos { "exp", FEXP, BLTIN },
66 1.1 christos { "fflush", FFLUSH, BLTIN },
67 1.1 christos { "for", FOR, FOR },
68 1.1 christos { "func", FUNC, FUNC },
69 1.1 christos { "function", FUNC, FUNC },
70 1.2 christos { "gensub", GENSUB, GENSUB },
71 1.1 christos { "getline", GETLINE, GETLINE },
72 1.1 christos { "gsub", GSUB, GSUB },
73 1.1 christos { "if", IF, IF },
74 1.1 christos { "in", IN, IN },
75 1.1 christos { "index", INDEX, INDEX },
76 1.1 christos { "int", FINT, BLTIN },
77 1.1 christos { "length", FLENGTH, BLTIN },
78 1.1 christos { "log", FLOG, BLTIN },
79 1.6 christos { "lshift", FLSHIFT, BLTIN },
80 1.1 christos { "match", MATCHFCN, MATCHFCN },
81 1.1 christos { "next", NEXT, NEXT },
82 1.1 christos { "nextfile", NEXTFILE, NEXTFILE },
83 1.6 christos { "or", FFOR, BLTIN },
84 1.1 christos { "print", PRINT, PRINT },
85 1.1 christos { "printf", PRINTF, PRINTF },
86 1.1 christos { "rand", FRAND, BLTIN },
87 1.1 christos { "return", RETURN, RETURN },
88 1.6 christos { "rshift", FRSHIFT, BLTIN },
89 1.1 christos { "sin", FSIN, BLTIN },
90 1.1 christos { "split", SPLIT, SPLIT },
91 1.1 christos { "sprintf", SPRINTF, SPRINTF },
92 1.1 christos { "sqrt", FSQRT, BLTIN },
93 1.1 christos { "srand", FSRAND, BLTIN },
94 1.2 christos { "strftime", FSTRFTIME, BLTIN },
95 1.1 christos { "sub", SUB, SUB },
96 1.1 christos { "substr", SUBSTR, SUBSTR },
97 1.1 christos { "system", FSYSTEM, BLTIN },
98 1.2 christos { "systime", FSYSTIME, BLTIN },
99 1.1 christos { "tolower", FTOLOWER, BLTIN },
100 1.1 christos { "toupper", FTOUPPER, BLTIN },
101 1.1 christos { "while", WHILE, WHILE },
102 1.6 christos { "xor", FXOR, BLTIN },
103 1.1 christos };
104 1.1 christos
105 1.1 christos #define RET(x) { if(dbg)printf("lex %s\n", tokname(x)); return(x); }
106 1.1 christos
107 1.6 christos static int peek(void)
108 1.1 christos {
109 1.1 christos int c = input();
110 1.1 christos unput(c);
111 1.1 christos return c;
112 1.1 christos }
113 1.1 christos
114 1.6 christos static int gettok(char **pbuf, int *psz) /* get next input token */
115 1.1 christos {
116 1.1 christos int c, retc;
117 1.6 christos char *buf = *pbuf;
118 1.1 christos int sz = *psz;
119 1.6 christos char *bp = buf;
120 1.1 christos
121 1.1 christos c = input();
122 1.1 christos if (c == 0)
123 1.1 christos return 0;
124 1.1 christos buf[0] = c;
125 1.1 christos buf[1] = 0;
126 1.1 christos if (!isalnum(c) && c != '.' && c != '_')
127 1.1 christos return c;
128 1.1 christos
129 1.1 christos *bp++ = c;
130 1.1 christos if (isalpha(c) || c == '_') { /* it's a varname */
131 1.1 christos for ( ; (c = input()) != 0; ) {
132 1.1 christos if (bp-buf >= sz)
133 1.1 christos if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok"))
134 1.1 christos FATAL( "out of space for name %.10s...", buf );
135 1.1 christos if (isalnum(c) || c == '_')
136 1.1 christos *bp++ = c;
137 1.1 christos else {
138 1.1 christos *bp = 0;
139 1.1 christos unput(c);
140 1.1 christos break;
141 1.1 christos }
142 1.1 christos }
143 1.1 christos *bp = 0;
144 1.1 christos retc = 'a'; /* alphanumeric */
145 1.1 christos } else { /* maybe it's a number, but could be . */
146 1.1 christos char *rem;
147 1.1 christos /* read input until can't be a number */
148 1.1 christos for ( ; (c = input()) != 0; ) {
149 1.1 christos if (bp-buf >= sz)
150 1.1 christos if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok"))
151 1.1 christos FATAL( "out of space for number %.10s...", buf );
152 1.5 christos if (isdigit(c) || c == 'e' || c == 'E'
153 1.1 christos || c == '.' || c == '+' || c == '-')
154 1.1 christos *bp++ = c;
155 1.1 christos else {
156 1.1 christos unput(c);
157 1.1 christos break;
158 1.1 christos }
159 1.1 christos }
160 1.1 christos *bp = 0;
161 1.1 christos strtod(buf, &rem); /* parse the number */
162 1.6 christos if (rem == buf) { /* it wasn't a valid number at all */
163 1.1 christos buf[1] = 0; /* return one character as token */
164 1.1 christos retc = buf[0]; /* character is its own type */
165 1.1 christos unputstr(rem+1); /* put rest back for later */
166 1.1 christos } else { /* some prefix was a number */
167 1.1 christos unputstr(rem); /* put rest back for later */
168 1.1 christos rem[0] = 0; /* truncate buf after number part */
169 1.1 christos retc = '0'; /* type is number */
170 1.1 christos }
171 1.1 christos }
172 1.1 christos *pbuf = buf;
173 1.1 christos *psz = sz;
174 1.1 christos return retc;
175 1.1 christos }
176 1.1 christos
177 1.1 christos int word(char *);
178 1.1 christos int string(void);
179 1.1 christos int regexpr(void);
180 1.6 christos bool sc = false; /* true => return a } right now */
181 1.6 christos bool reg = false; /* true => return a REGEXPR now */
182 1.1 christos
183 1.1 christos int yylex(void)
184 1.1 christos {
185 1.1 christos int c;
186 1.6 christos static char *buf = NULL;
187 1.1 christos static int bufsize = 5; /* BUG: setting this small causes core dump! */
188 1.1 christos
189 1.6 christos if (buf == NULL && (buf = malloc(bufsize)) == NULL)
190 1.1 christos FATAL( "out of space in yylex" );
191 1.1 christos if (sc) {
192 1.6 christos sc = false;
193 1.1 christos RET('}');
194 1.1 christos }
195 1.1 christos if (reg) {
196 1.6 christos reg = false;
197 1.1 christos return regexpr();
198 1.1 christos }
199 1.1 christos for (;;) {
200 1.1 christos c = gettok(&buf, &bufsize);
201 1.1 christos if (c == 0)
202 1.1 christos return 0;
203 1.1 christos if (isalpha(c) || c == '_')
204 1.1 christos return word(buf);
205 1.1 christos if (isdigit(c)) {
206 1.6 christos char *cp = tostring(buf);
207 1.6 christos yylval.cp = setsymtab(buf, cp, atof(buf), CON|NUM, symtab);
208 1.6 christos free(cp);
209 1.1 christos /* should this also have STR set? */
210 1.1 christos RET(NUMBER);
211 1.1 christos }
212 1.5 christos
213 1.1 christos yylval.i = c;
214 1.1 christos switch (c) {
215 1.1 christos case '\n': /* {EOL} */
216 1.6 christos lineno++;
217 1.1 christos RET(NL);
218 1.1 christos case '\r': /* assume \n is coming */
219 1.1 christos case ' ': /* {WS}+ */
220 1.1 christos case '\t':
221 1.1 christos break;
222 1.1 christos case '#': /* #.* strip comments */
223 1.1 christos while ((c = input()) != '\n' && c != 0)
224 1.1 christos ;
225 1.1 christos unput(c);
226 1.6 christos /*
227 1.6 christos * Next line is a hack, itcompensates for
228 1.6 christos * unput's treatment of \n.
229 1.6 christos */
230 1.6 christos lineno++;
231 1.1 christos break;
232 1.1 christos case ';':
233 1.1 christos RET(';');
234 1.1 christos case '\\':
235 1.1 christos if (peek() == '\n') {
236 1.1 christos input();
237 1.6 christos lineno++;
238 1.1 christos } else if (peek() == '\r') {
239 1.1 christos input(); input(); /* \n */
240 1.1 christos lineno++;
241 1.1 christos } else {
242 1.1 christos RET(c);
243 1.1 christos }
244 1.1 christos break;
245 1.1 christos case '&':
246 1.1 christos if (peek() == '&') {
247 1.1 christos input(); RET(AND);
248 1.5 christos } else
249 1.1 christos RET('&');
250 1.1 christos case '|':
251 1.1 christos if (peek() == '|') {
252 1.1 christos input(); RET(BOR);
253 1.1 christos } else
254 1.1 christos RET('|');
255 1.1 christos case '!':
256 1.1 christos if (peek() == '=') {
257 1.1 christos input(); yylval.i = NE; RET(NE);
258 1.1 christos } else if (peek() == '~') {
259 1.1 christos input(); yylval.i = NOTMATCH; RET(MATCHOP);
260 1.1 christos } else
261 1.1 christos RET(NOT);
262 1.1 christos case '~':
263 1.1 christos yylval.i = MATCH;
264 1.1 christos RET(MATCHOP);
265 1.1 christos case '<':
266 1.1 christos if (peek() == '=') {
267 1.1 christos input(); yylval.i = LE; RET(LE);
268 1.1 christos } else {
269 1.1 christos yylval.i = LT; RET(LT);
270 1.1 christos }
271 1.1 christos case '=':
272 1.1 christos if (peek() == '=') {
273 1.1 christos input(); yylval.i = EQ; RET(EQ);
274 1.1 christos } else {
275 1.1 christos yylval.i = ASSIGN; RET(ASGNOP);
276 1.1 christos }
277 1.1 christos case '>':
278 1.1 christos if (peek() == '=') {
279 1.1 christos input(); yylval.i = GE; RET(GE);
280 1.1 christos } else if (peek() == '>') {
281 1.1 christos input(); yylval.i = APPEND; RET(APPEND);
282 1.1 christos } else {
283 1.1 christos yylval.i = GT; RET(GT);
284 1.1 christos }
285 1.1 christos case '+':
286 1.1 christos if (peek() == '+') {
287 1.1 christos input(); yylval.i = INCR; RET(INCR);
288 1.1 christos } else if (peek() == '=') {
289 1.1 christos input(); yylval.i = ADDEQ; RET(ASGNOP);
290 1.1 christos } else
291 1.1 christos RET('+');
292 1.1 christos case '-':
293 1.1 christos if (peek() == '-') {
294 1.1 christos input(); yylval.i = DECR; RET(DECR);
295 1.1 christos } else if (peek() == '=') {
296 1.1 christos input(); yylval.i = SUBEQ; RET(ASGNOP);
297 1.1 christos } else
298 1.1 christos RET('-');
299 1.1 christos case '*':
300 1.1 christos if (peek() == '=') { /* *= */
301 1.1 christos input(); yylval.i = MULTEQ; RET(ASGNOP);
302 1.1 christos } else if (peek() == '*') { /* ** or **= */
303 1.1 christos input(); /* eat 2nd * */
304 1.1 christos if (peek() == '=') {
305 1.1 christos input(); yylval.i = POWEQ; RET(ASGNOP);
306 1.1 christos } else {
307 1.1 christos RET(POWER);
308 1.1 christos }
309 1.1 christos } else
310 1.1 christos RET('*');
311 1.1 christos case '/':
312 1.1 christos RET('/');
313 1.1 christos case '%':
314 1.1 christos if (peek() == '=') {
315 1.1 christos input(); yylval.i = MODEQ; RET(ASGNOP);
316 1.1 christos } else
317 1.1 christos RET('%');
318 1.1 christos case '^':
319 1.1 christos if (peek() == '=') {
320 1.1 christos input(); yylval.i = POWEQ; RET(ASGNOP);
321 1.1 christos } else
322 1.1 christos RET(POWER);
323 1.1 christos
324 1.1 christos case '$':
325 1.1 christos /* BUG: awkward, if not wrong */
326 1.1 christos c = gettok(&buf, &bufsize);
327 1.1 christos if (isalpha(c)) {
328 1.1 christos if (strcmp(buf, "NF") == 0) { /* very special */
329 1.1 christos unputstr("(NF)");
330 1.1 christos RET(INDIRECT);
331 1.1 christos }
332 1.1 christos c = peek();
333 1.1 christos if (c == '(' || c == '[' || (infunc && isarg(buf) >= 0)) {
334 1.1 christos unputstr(buf);
335 1.1 christos RET(INDIRECT);
336 1.1 christos }
337 1.1 christos yylval.cp = setsymtab(buf, "", 0.0, STR|NUM, symtab);
338 1.1 christos RET(IVAR);
339 1.1 christos } else if (c == 0) { /* */
340 1.1 christos SYNTAX( "unexpected end of input after $" );
341 1.1 christos RET(';');
342 1.1 christos } else {
343 1.1 christos unputstr(buf);
344 1.1 christos RET(INDIRECT);
345 1.1 christos }
346 1.5 christos
347 1.1 christos case '}':
348 1.1 christos if (--bracecnt < 0)
349 1.1 christos SYNTAX( "extra }" );
350 1.6 christos sc = true;
351 1.1 christos RET(';');
352 1.1 christos case ']':
353 1.1 christos if (--brackcnt < 0)
354 1.1 christos SYNTAX( "extra ]" );
355 1.1 christos RET(']');
356 1.1 christos case ')':
357 1.1 christos if (--parencnt < 0)
358 1.1 christos SYNTAX( "extra )" );
359 1.1 christos RET(')');
360 1.1 christos case '{':
361 1.1 christos bracecnt++;
362 1.1 christos RET('{');
363 1.1 christos case '[':
364 1.1 christos brackcnt++;
365 1.1 christos RET('[');
366 1.1 christos case '(':
367 1.1 christos parencnt++;
368 1.1 christos RET('(');
369 1.5 christos
370 1.1 christos case '"':
371 1.1 christos return string(); /* BUG: should be like tran.c ? */
372 1.5 christos
373 1.1 christos default:
374 1.1 christos RET(c);
375 1.1 christos }
376 1.1 christos }
377 1.1 christos }
378 1.1 christos
379 1.1 christos int string(void)
380 1.1 christos {
381 1.1 christos int c, n;
382 1.6 christos char *s, *bp;
383 1.6 christos static char *buf = NULL;
384 1.1 christos static int bufsz = 500;
385 1.1 christos
386 1.6 christos if (buf == NULL && (buf = malloc(bufsz)) == NULL)
387 1.1 christos FATAL("out of space for strings");
388 1.1 christos for (bp = buf; (c = input()) != '"'; ) {
389 1.1 christos if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, "string"))
390 1.1 christos FATAL("out of space for string %.10s...", buf);
391 1.1 christos switch (c) {
392 1.1 christos case '\n':
393 1.1 christos case '\r':
394 1.1 christos case 0:
395 1.6 christos *bp = '\0';
396 1.1 christos SYNTAX( "non-terminated string %.10s...", buf );
397 1.1 christos if (c == 0) /* hopeless */
398 1.1 christos FATAL( "giving up" );
399 1.6 christos lineno++;
400 1.1 christos break;
401 1.1 christos case '\\':
402 1.1 christos c = input();
403 1.1 christos switch (c) {
404 1.7 christos case '\n': break;
405 1.1 christos case '"': *bp++ = '"'; break;
406 1.5 christos case 'n': *bp++ = '\n'; break;
407 1.1 christos case 't': *bp++ = '\t'; break;
408 1.1 christos case 'f': *bp++ = '\f'; break;
409 1.1 christos case 'r': *bp++ = '\r'; break;
410 1.1 christos case 'b': *bp++ = '\b'; break;
411 1.1 christos case 'v': *bp++ = '\v'; break;
412 1.6 christos case 'a': *bp++ = '\a'; break;
413 1.1 christos case '\\': *bp++ = '\\'; break;
414 1.1 christos
415 1.1 christos case '0': case '1': case '2': /* octal: \d \dd \ddd */
416 1.1 christos case '3': case '4': case '5': case '6': case '7':
417 1.1 christos n = c - '0';
418 1.1 christos if ((c = peek()) >= '0' && c < '8') {
419 1.1 christos n = 8 * n + input() - '0';
420 1.1 christos if ((c = peek()) >= '0' && c < '8')
421 1.1 christos n = 8 * n + input() - '0';
422 1.1 christos }
423 1.1 christos *bp++ = n;
424 1.1 christos break;
425 1.1 christos
426 1.1 christos case 'x': /* hex \x0-9a-fA-F + */
427 1.1 christos { char xbuf[100], *px;
428 1.1 christos for (px = xbuf; (c = input()) != 0 && px-xbuf < 100-2; ) {
429 1.1 christos if (isdigit(c)
430 1.1 christos || (c >= 'a' && c <= 'f')
431 1.1 christos || (c >= 'A' && c <= 'F'))
432 1.1 christos *px++ = c;
433 1.1 christos else
434 1.1 christos break;
435 1.1 christos }
436 1.1 christos *px = 0;
437 1.1 christos unput(c);
438 1.6 christos sscanf(xbuf, "%x", (unsigned int *) &n);
439 1.1 christos *bp++ = n;
440 1.1 christos break;
441 1.1 christos }
442 1.1 christos
443 1.2 christos default:
444 1.1 christos *bp++ = c;
445 1.1 christos break;
446 1.1 christos }
447 1.1 christos break;
448 1.1 christos default:
449 1.1 christos *bp++ = c;
450 1.1 christos break;
451 1.1 christos }
452 1.1 christos }
453 1.5 christos *bp = 0;
454 1.1 christos s = tostring(buf);
455 1.6 christos *bp++ = ' '; *bp++ = '\0';
456 1.1 christos yylval.cp = setsymtab(buf, s, 0.0, CON|STR|DONTFREE, symtab);
457 1.6 christos free(s);
458 1.1 christos RET(STRING);
459 1.1 christos }
460 1.1 christos
461 1.1 christos
462 1.6 christos static int binsearch(char *w, const Keyword *kp, int n)
463 1.1 christos {
464 1.1 christos int cond, low, mid, high;
465 1.1 christos
466 1.1 christos low = 0;
467 1.1 christos high = n - 1;
468 1.1 christos while (low <= high) {
469 1.1 christos mid = (low + high) / 2;
470 1.1 christos if ((cond = strcmp(w, kp[mid].word)) < 0)
471 1.1 christos high = mid - 1;
472 1.1 christos else if (cond > 0)
473 1.1 christos low = mid + 1;
474 1.1 christos else
475 1.1 christos return mid;
476 1.1 christos }
477 1.1 christos return -1;
478 1.1 christos }
479 1.1 christos
480 1.5 christos int word(char *w)
481 1.1 christos {
482 1.2 christos const Keyword *kp;
483 1.1 christos int c, n;
484 1.1 christos
485 1.1 christos n = binsearch(w, keywords, sizeof(keywords)/sizeof(keywords[0]));
486 1.1 christos if (n != -1) { /* found in table */
487 1.4 kamil kp = keywords + n;
488 1.1 christos yylval.i = kp->sub;
489 1.1 christos switch (kp->type) { /* special handling */
490 1.1 christos case BLTIN:
491 1.1 christos if (kp->sub == FSYSTEM && safe)
492 1.1 christos SYNTAX( "system is unsafe" );
493 1.1 christos RET(kp->type);
494 1.1 christos case FUNC:
495 1.1 christos if (infunc)
496 1.1 christos SYNTAX( "illegal nested function" );
497 1.1 christos RET(kp->type);
498 1.1 christos case RETURN:
499 1.1 christos if (!infunc)
500 1.1 christos SYNTAX( "return not in function" );
501 1.1 christos RET(kp->type);
502 1.1 christos case VARNF:
503 1.1 christos yylval.cp = setsymtab("NF", "", 0.0, NUM, symtab);
504 1.1 christos RET(VARNF);
505 1.1 christos default:
506 1.1 christos RET(kp->type);
507 1.1 christos }
508 1.1 christos }
509 1.1 christos c = peek(); /* look for '(' */
510 1.1 christos if (c != '(' && infunc && (n=isarg(w)) >= 0) {
511 1.1 christos yylval.i = n;
512 1.1 christos RET(ARG);
513 1.1 christos } else {
514 1.1 christos yylval.cp = setsymtab(w, "", 0.0, STR|NUM|DONTFREE, symtab);
515 1.1 christos if (c == '(') {
516 1.1 christos RET(CALL);
517 1.1 christos } else {
518 1.1 christos RET(VAR);
519 1.1 christos }
520 1.1 christos }
521 1.1 christos }
522 1.1 christos
523 1.1 christos void startreg(void) /* next call to yylex will return a regular expression */
524 1.1 christos {
525 1.6 christos reg = true;
526 1.1 christos }
527 1.1 christos
528 1.1 christos int regexpr(void)
529 1.1 christos {
530 1.1 christos int c;
531 1.6 christos static char *buf = NULL;
532 1.1 christos static int bufsz = 500;
533 1.6 christos char *bp;
534 1.1 christos
535 1.6 christos if (buf == NULL && (buf = malloc(bufsz)) == NULL)
536 1.1 christos FATAL("out of space for rex expr");
537 1.1 christos bp = buf;
538 1.1 christos for ( ; (c = input()) != '/' && c != 0; ) {
539 1.1 christos if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, "regexpr"))
540 1.1 christos FATAL("out of space for reg expr %.10s...", buf);
541 1.1 christos if (c == '\n') {
542 1.6 christos *bp = '\0';
543 1.5 christos SYNTAX( "newline in regular expression %.10s...", buf );
544 1.1 christos unput('\n');
545 1.1 christos break;
546 1.1 christos } else if (c == '\\') {
547 1.5 christos *bp++ = '\\';
548 1.1 christos *bp++ = input();
549 1.1 christos } else {
550 1.1 christos *bp++ = c;
551 1.1 christos }
552 1.1 christos }
553 1.1 christos *bp = 0;
554 1.1 christos if (c == 0)
555 1.1 christos SYNTAX("non-terminated regular expression %.10s...", buf);
556 1.1 christos yylval.s = tostring(buf);
557 1.1 christos unput('/');
558 1.1 christos RET(REGEXPR);
559 1.1 christos }
560 1.1 christos
561 1.1 christos /* low-level lexical stuff, sort of inherited from lex */
562 1.1 christos
563 1.1 christos char ebuf[300];
564 1.1 christos char *ep = ebuf;
565 1.1 christos char yysbuf[100]; /* pushback buffer */
566 1.1 christos char *yysptr = yysbuf;
567 1.6 christos FILE *yyin = NULL;
568 1.1 christos
569 1.1 christos int input(void) /* get next lexical input character */
570 1.1 christos {
571 1.1 christos int c;
572 1.1 christos extern char *lexprog;
573 1.1 christos
574 1.1 christos if (yysptr > yysbuf)
575 1.1 christos c = (uschar)*--yysptr;
576 1.1 christos else if (lexprog != NULL) { /* awk '...' */
577 1.1 christos if ((c = (uschar)*lexprog) != 0)
578 1.1 christos lexprog++;
579 1.1 christos } else /* awk -f ... */
580 1.1 christos c = pgetc();
581 1.6 christos if (c == EOF)
582 1.1 christos c = 0;
583 1.1 christos if (ep >= ebuf + sizeof ebuf)
584 1.1 christos ep = ebuf;
585 1.6 christos *ep = c;
586 1.6 christos if (c != 0) {
587 1.6 christos ep++;
588 1.6 christos }
589 1.6 christos return (c);
590 1.1 christos }
591 1.1 christos
592 1.1 christos void unput(int c) /* put lexical character back on input */
593 1.1 christos {
594 1.6 christos if (c == '\n')
595 1.1 christos lineno--;
596 1.1 christos if (yysptr >= yysbuf + sizeof(yysbuf))
597 1.1 christos FATAL("pushed back too much: %.20s...", yysbuf);
598 1.1 christos *yysptr++ = c;
599 1.1 christos if (--ep < ebuf)
600 1.1 christos ep = ebuf + sizeof(ebuf) - 1;
601 1.1 christos }
602 1.1 christos
603 1.1 christos void unputstr(const char *s) /* put a string back on input */
604 1.1 christos {
605 1.1 christos int i;
606 1.1 christos
607 1.1 christos for (i = strlen(s)-1; i >= 0; i--)
608 1.1 christos unput(s[i]);
609 1.1 christos }
610