Fix UTIME_OMIT handling
[dragonfly.git] / usr.bin / window / scanner.c
blob2bea9f6156a2639dacf82bdb4d9ea61accfe16fe
1 /* @(#)scanner.c 8.1 (Berkeley) 6/6/93 */
2 /* $NetBSD: scanner.c,v 1.9 2003/08/07 11:17:29 agc Exp $ */
4 /*
5 * Copyright (c) 1983, 1993
6 * The Regents of the University of California. All rights reserved.
8 * This code is derived from software contributed to Berkeley by
9 * Edward Wang at The University of California, Berkeley.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
36 #include <stdlib.h>
38 #include "defs.h"
39 #include "token.h"
40 #include "context.h"
41 #include "window_string.h"
43 int s_getc(void);
44 int s_gettok1(void);
45 int s_ungetc(int);
47 int
48 s_getc(void)
50 int c;
52 switch (cx.x_type) {
53 case X_FILE:
54 c = getc(cx.x_fp);
55 if (cx.x_bol && c != EOF) {
56 cx.x_bol = 0;
57 cx.x_lineno++;
59 if (c == '\n')
60 cx.x_bol = 1;
61 return c;
62 case X_BUF:
63 if (*cx.x_bufp != 0)
64 return *cx.x_bufp++ & 0xff;
65 else
66 return EOF;
68 /*NOTREACHED*/
69 return(0); /* XXX: placate gcc */
72 int
73 s_ungetc(int c)
75 if (c == EOF)
76 return EOF;
77 switch (cx.x_type) {
78 case X_FILE:
79 cx.x_bol = 0;
80 return ungetc(c, cx.x_fp);
81 case X_BUF:
82 if (cx.x_bufp > cx.x_buf)
83 return *--cx.x_bufp = c;
84 else
85 return EOF;
87 /*NOTREACHED*/
88 return(0); /* XXX: placate gcc */
91 int
92 s_gettok(void)
94 char buf[100];
95 char *p = buf;
96 int c;
97 int state = 0;
99 loop:
100 c = s_getc();
101 switch (state) {
102 case 0:
103 switch (c) {
104 case ' ':
105 case '\t':
106 break;
107 case '\n':
108 case ';':
109 cx.x_token = T_EOL;
110 state = -1;
111 break;
112 case '#':
113 state = 1;
114 break;
115 case EOF:
116 cx.x_token = T_EOF;
117 state = -1;
118 break;
119 case 'a': case 'b': case 'c': case 'd': case 'e':
120 case 'f': case 'g': case 'h': case 'i': case 'j':
121 case 'k': case 'l': case 'm': case 'n': case 'o':
122 case 'p': case 'q': case 'r': case 's': case 't':
123 case 'u': case 'v': case 'w': case 'x': case 'y':
124 case 'z':
125 case 'A': case 'B': case 'C': case 'D': case 'E':
126 case 'F': case 'G': case 'H': case 'I': case 'J':
127 case 'K': case 'L': case 'M': case 'N': case 'O':
128 case 'P': case 'Q': case 'R': case 'S': case 'T':
129 case 'U': case 'V': case 'W': case 'X': case 'Y':
130 case 'Z':
131 case '_': case '.':
132 *p++ = c;
133 state = 2;
134 break;
135 case '"':
136 state = 3;
137 break;
138 case '\'':
139 state = 4;
140 break;
141 case '\\':
142 switch (c = s_gettok1()) {
143 case -1:
144 break;
145 case -2:
146 state = 0;
147 break;
148 default:
149 *p++ = c;
150 state = 2;
152 break;
153 case '0':
154 cx.x_val.v_num = 0;
155 state = 10;
156 break;
157 case '1': case '2': case '3': case '4':
158 case '5': case '6': case '7': case '8': case '9':
159 cx.x_val.v_num = c - '0';
160 state = 11;
161 break;
162 case '>':
163 state = 20;
164 break;
165 case '<':
166 state = 21;
167 break;
168 case '=':
169 state = 22;
170 break;
171 case '!':
172 state = 23;
173 break;
174 case '&':
175 state = 24;
176 break;
177 case '|':
178 state = 25;
179 break;
180 case '$':
181 state = 26;
182 break;
183 case '~':
184 cx.x_token = T_COMP;
185 state = -1;
186 break;
187 case '+':
188 cx.x_token = T_PLUS;
189 state = -1;
190 break;
191 case '-':
192 cx.x_token = T_MINUS;
193 state = -1;
194 break;
195 case '*':
196 cx.x_token = T_MUL;
197 state = -1;
198 break;
199 case '/':
200 cx.x_token = T_DIV;
201 state = -1;
202 break;
203 case '%':
204 cx.x_token = T_MOD;
205 state = -1;
206 break;
207 case '^':
208 cx.x_token = T_XOR;
209 state = -1;
210 break;
211 case '(':
212 cx.x_token = T_LP;
213 state = -1;
214 break;
215 case ')':
216 cx.x_token = T_RP;
217 state = -1;
218 break;
219 case ',':
220 cx.x_token = T_COMMA;
221 state = -1;
222 break;
223 case '?':
224 cx.x_token = T_QUEST;
225 state = -1;
226 break;
227 case ':':
228 cx.x_token = T_COLON;
229 state = -1;
230 break;
231 case '[':
232 cx.x_token = T_LB;
233 state = -1;
234 break;
235 case ']':
236 cx.x_token = T_RB;
237 state = -1;
238 break;
239 default:
240 cx.x_val.v_num = c;
241 cx.x_token = T_CHAR;
242 state = -1;
243 break;
245 break;
246 case 1: /* got # */
247 if (c == '\n' || c == EOF) {
248 (void) s_ungetc(c);
249 state = 0;
251 break;
252 case 2: /* unquoted string */
253 switch (c) {
254 case 'a': case 'b': case 'c': case 'd': case 'e':
255 case 'f': case 'g': case 'h': case 'i': case 'j':
256 case 'k': case 'l': case 'm': case 'n': case 'o':
257 case 'p': case 'q': case 'r': case 's': case 't':
258 case 'u': case 'v': case 'w': case 'x': case 'y':
259 case 'z':
260 case 'A': case 'B': case 'C': case 'D': case 'E':
261 case 'F': case 'G': case 'H': case 'I': case 'J':
262 case 'K': case 'L': case 'M': case 'N': case 'O':
263 case 'P': case 'Q': case 'R': case 'S': case 'T':
264 case 'U': case 'V': case 'W': case 'X': case 'Y':
265 case 'Z':
266 case '_': case '.':
267 case '0': case '1': case '2': case '3': case '4':
268 case '5': case '6': case '7': case '8': case '9':
269 if (p < buf + sizeof buf - 1)
270 *p++ = c;
271 break;
272 case '"':
273 state = 3;
274 break;
275 case '\'':
276 state = 4;
277 break;
278 case '\\':
279 switch (c = s_gettok1()) {
280 case -2:
281 (void) s_ungetc(' ');
282 case -1:
283 break;
284 default:
285 if (p < buf + sizeof buf - 1)
286 *p++ = c;
288 break;
289 default:
290 (void) s_ungetc(c);
291 /* FALLTHROUGH */
292 case EOF:
293 *p = 0;
294 cx.x_token = T_STR;
295 switch (*buf) {
296 case 'i':
297 if (buf[1] == 'f' && buf[2] == 0)
298 cx.x_token = T_IF;
299 break;
300 case 't':
301 if (buf[1] == 'h' && buf[2] == 'e'
302 && buf[3] == 'n' && buf[4] == 0)
303 cx.x_token = T_THEN;
304 break;
305 case 'e':
306 if (buf[1] == 'n' && buf[2] == 'd'
307 && buf[3] == 'i' && buf[4] == 'f'
308 && buf[5] == 0)
309 cx.x_token = T_ENDIF;
310 else {
311 if (buf[1] == 'l' && buf[2] == 's') {
312 if (buf[3] == 'i'
313 && buf[4] == 'f'
314 && buf[5] == 0)
315 cx.x_token = T_ELSIF;
316 else {
317 if (buf[3] == 'e'
318 && buf[4] == 0)
319 cx.x_token =
320 T_ELSE;
324 break;
326 if (cx.x_token == T_STR
327 && (cx.x_val.v_str = str_cpy(buf)) == 0) {
328 p_memerror();
329 cx.x_token = T_EOF;
331 state = -1;
332 break;
334 break;
335 case 3: /* " quoted string */
336 switch (c) {
337 case '\n':
338 (void) s_ungetc(c);
339 /* FALLTHROUGH */
340 case EOF:
341 case '"':
342 state = 2;
343 break;
344 case '\\':
345 switch (c = s_gettok1()) {
346 case -1:
347 case -2: /* newlines are invisible */
348 break;
349 default:
350 if (p < buf + sizeof buf - 1)
351 *p++ = c;
353 break;
354 default:
355 if (p < buf + sizeof buf - 1)
356 *p++ = c;
357 break;
359 break;
360 case 4: /* ' quoted string */
361 switch (c) {
362 case '\n':
363 (void) s_ungetc(c);
364 /* FALLTHROUGH */
365 case EOF:
366 case '\'':
367 state = 2;
368 break;
369 case '\\':
370 switch (c = s_gettok1()) {
371 case -1:
372 case -2: /* newlines are invisible */
373 break;
374 default:
375 if (p < buf + sizeof buf - 1)
376 *p++ = c;
378 break;
379 default:
380 if (p < buf + sizeof buf - 1)
381 *p++ = c;
382 break;
384 break;
385 case 10: /* got 0 */
386 switch (c) {
387 case 'x':
388 case 'X':
389 cx.x_val.v_num = 0;
390 state = 12;
391 break;
392 case '0': case '1': case '2': case '3': case '4':
393 case '5': case '6': case '7':
394 cx.x_val.v_num = c - '0';
395 state = 13;
396 break;
397 case '8': case '9':
398 cx.x_val.v_num = c - '0';
399 state = 11;
400 break;
401 default:
402 (void) s_ungetc(c);
403 state = -1;
404 cx.x_token = T_NUM;
406 break;
407 case 11: /* decimal number */
408 switch (c) {
409 case '0': case '1': case '2': case '3': case '4':
410 case '5': case '6': case '7': case '8': case '9':
411 cx.x_val.v_num = cx.x_val.v_num * 10 + c - '0';
412 break;
413 default:
414 (void) s_ungetc(c);
415 state = -1;
416 cx.x_token = T_NUM;
418 break;
419 case 12: /* hex number */
420 switch (c) {
421 case '0': case '1': case '2': case '3': case '4':
422 case '5': case '6': case '7': case '8': case '9':
423 cx.x_val.v_num = cx.x_val.v_num * 16 + c - '0';
424 break;
425 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
426 cx.x_val.v_num = cx.x_val.v_num * 16 + c - 'a' + 10;
427 break;
428 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
429 cx.x_val.v_num = cx.x_val.v_num * 16 + c - 'A' + 10;
430 break;
431 default:
432 (void) s_ungetc(c);
433 state = -1;
434 cx.x_token = T_NUM;
436 break;
437 case 13: /* octal number */
438 switch (c) {
439 case '0': case '1': case '2': case '3': case '4':
440 case '5': case '6': case '7':
441 cx.x_val.v_num = cx.x_val.v_num * 8 + c - '0';
442 break;
443 default:
444 (void) s_ungetc(c);
445 state = -1;
446 cx.x_token = T_NUM;
448 break;
449 case 20: /* got > */
450 switch (c) {
451 case '=':
452 cx.x_token = T_GE;
453 state = -1;
454 break;
455 case '>':
456 cx.x_token = T_RS;
457 state = -1;
458 break;
459 default:
460 (void) s_ungetc(c);
461 cx.x_token = T_GT;
462 state = -1;
464 break;
465 case 21: /* got < */
466 switch (c) {
467 case '=':
468 cx.x_token = T_LE;
469 state = -1;
470 break;
471 case '<':
472 cx.x_token = T_LS;
473 state = -1;
474 break;
475 default:
476 (void) s_ungetc(c);
477 cx.x_token = T_LT;
478 state = -1;
480 break;
481 case 22: /* got = */
482 switch (c) {
483 case '=':
484 cx.x_token = T_EQ;
485 state = -1;
486 break;
487 default:
488 (void) s_ungetc(c);
489 cx.x_token = T_ASSIGN;
490 state = -1;
492 break;
493 case 23: /* got ! */
494 switch (c) {
495 case '=':
496 cx.x_token = T_NE;
497 state = -1;
498 break;
499 default:
500 (void) s_ungetc(c);
501 cx.x_token = T_NOT;
502 state = -1;
504 break;
505 case 24: /* got & */
506 switch (c) {
507 case '&':
508 cx.x_token = T_ANDAND;
509 state = -1;
510 break;
511 default:
512 (void) s_ungetc(c);
513 cx.x_token = T_AND;
514 state = -1;
516 break;
517 case 25: /* got | */
518 switch (c) {
519 case '|':
520 cx.x_token = T_OROR;
521 state = -1;
522 break;
523 default:
524 (void) s_ungetc(c);
525 cx.x_token = T_OR;
526 state = -1;
528 break;
529 case 26: /* got $ */
530 switch (c) {
531 case '?':
532 cx.x_token = T_DQ;
533 state = -1;
534 break;
535 default:
536 (void) s_ungetc(c);
537 cx.x_token = T_DOLLAR;
538 state = -1;
540 break;
541 default:
542 abort();
544 if (state >= 0)
545 goto loop;
546 return cx.x_token;
550 s_gettok1(void)
552 int c;
553 int n;
555 c = s_getc(); /* got \ */
556 switch (c) {
557 case EOF:
558 return -1;
559 case '\n':
560 return -2;
561 case 'b':
562 return '\b';
563 case 'f':
564 return '\f';
565 case 'n':
566 return '\n';
567 case 'r':
568 return '\r';
569 case 't':
570 return '\t';
571 default:
572 return c;
573 case '0': case '1': case '2': case '3': case '4':
574 case '5': case '6': case '7':
575 break;
577 n = c - '0';
578 c = s_getc(); /* got \[0-7] */
579 if (c < '0' || c > '7') {
580 (void) s_ungetc(c);
581 return n;
583 n = n * 8 + c - '0';
584 c = s_getc(); /* got \[0-7][0-7] */
585 if (c < '0' || c > '7') {
586 (void) s_ungetc(c);
587 return n;
589 return n * 8 + c - '0';