1 /***********************************************************************
2 * lexicon.c - lexical scanner
3 *
4 * There is enough lookahead to enable use of '/' as both an arithmetic
5 * and units operator. Nested macro expansion is supported using a stack
6 * of input contexts (see definition of LexIn in file syntax.y).
7 ***********************************************************************
8 *
9 * Copyright (c) 1995-2002 Silicon Graphics, Inc. All Rights Reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 * for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <string.h>
29 #include <limits.h>
30 #include <math.h>
31
32 #include "dstruct.h"
33 #include "syntax.h"
34 #include "grammar.h"
35 #include "lexicon.h"
36 #include "pragmatics.h"
37
38
39 /***********************************************************************
40 * type definitions
41 ***********************************************************************/
42
43 /* for table of lexical items */
44 typedef struct {
45 char *key;
46 int token;
47 } LexEntry1;
48
49 /* for another table of lexical items */
50 typedef struct {
51 char *key;
52 int token;
53 int scale;
54 } LexEntry2;
55
56
57 /***********************************************************************
58 * constants
59 ***********************************************************************/
60
61 static LexEntry1 domtab[] = {
62 {"host", HOST_DOM},
63 {"inst", INST_DOM},
64 {"sample", TIME_DOM},
65 {NULL, 0}
66 };
67
68 static LexEntry1 quantab[] = {
69 {"sum", SUM_AGGR},
70 {"avg", AVG_AGGR},
71 {"max", MAX_AGGR},
72 {"min", MIN_AGGR},
73 {"count", COUNT_AGGR},
74 {"all", ALL_QUANT},
75 {"some", SOME_QUANT},
76 {"%", PCNT_QUANT},
77 {NULL, 0}
78 };
79
80 static LexEntry1 optab[] = {
81 {"true", TRU},
82 {"false", FALS},
83 {"rate", RATE},
84 {"shell", SHELL},
85 {"alarm", ALARM},
86 {"syslog", SYSLOG},
87 {"print", PRINT},
88 {"stomp", STOMP},
89 {"rising", RISE},
90 {"falling", FALL},
91 {"match_inst", MATCH},
92 {"nomatch_inst",NOMATCH},
93 {NULL, 0}
94 };
95
96 static LexEntry2 unitab[] = {
97 {"byte", SPACE_UNIT, PM_SPACE_BYTE},
98 {"Kbyte", SPACE_UNIT, PM_SPACE_KBYTE},
99 {"Mbyte", SPACE_UNIT, PM_SPACE_MBYTE},
100 {"Gbyte", SPACE_UNIT, PM_SPACE_GBYTE},
101 {"Tbyte", SPACE_UNIT, PM_SPACE_TBYTE},
102 {"nsec", TIME_UNIT, PM_TIME_NSEC},
103 {"usec", TIME_UNIT, PM_TIME_USEC},
104 {"msec", TIME_UNIT, PM_TIME_MSEC},
105 {"sec", TIME_UNIT, PM_TIME_SEC},
106 {"min", TIME_UNIT, PM_TIME_MIN},
107 {"hour", TIME_UNIT, PM_TIME_HOUR},
108 {"count", EVENT_UNIT, 0},
109 {"Kcount", EVENT_UNIT, 3},
110 {"Mcount", EVENT_UNIT, 6},
111 {"Gcount", EVENT_UNIT, 9},
112 {"Tcount", EVENT_UNIT, 12},
113 {"nanosec", TIME_UNIT, PM_TIME_NSEC},
114 {"nanosecond", TIME_UNIT, PM_TIME_NSEC},
115 {"microsec", TIME_UNIT, PM_TIME_USEC},
116 {"microsecond", TIME_UNIT, PM_TIME_USEC},
117 {"millisec", TIME_UNIT, PM_TIME_MSEC},
118 {"millisecond", TIME_UNIT, PM_TIME_MSEC},
119 {"second", TIME_UNIT, PM_TIME_SEC},
120 {"minute", TIME_UNIT, PM_TIME_MIN},
121 {NULL, 0, 0}
122 };
123
124
125
126 /***********************************************************************
127 * variables
128 ***********************************************************************/
129
130 LexIn *lin; /* current input context */
131 static char *token; /* current token buffer */
132
133
134
135 /***********************************************************************
136 * local functions
137 ***********************************************************************/
138
139 /* unwind input context */
140 static void
141 unwind(void)
142 {
143 LexIn *tmp;
144
145 if (lin->name) {
146 free(lin->name);
147 if (! lin->macro)
148 fclose(lin->stream);
149 }
150 tmp = lin;
151 lin = lin->prev;
152 free(tmp);
153 }
154
155
156 /* next input character */
157 static int
158 nextc(void)
159 {
160 int c = '\0';
161
162 if (lin) {
163 if (lin->lookin != lin->lookout) {
164 c = lin->look[lin->lookout++];
165 if (lin->lookout >= LEX_MAX + 2)
166 lin->lookout = 0;
167 }
168 else {
169 if (lin->macro)
170 c = *lin->macro++;
171 else {
172 c = getc(lin->stream);
173 if (c == EOF)
174 c = '\0';
175 }
176 if (c == '\0') {
177 unwind();
178 return nextc();
179 }
180 lin->cno++;
181 if (c == '\n') {
182 lin->lno++;
183 lin->cno = 0;
184 }
185 }
186 #if PCP_DEBUG && PCP_DESPERATE
187 if (pmDebug & DBG_TRACE_APPL0)
188 fprintf(stderr, "nextc() -> \'%c\'\n", c);
189 #endif
190 return c;
191 }
192 return EOF;
193 }
194
195
196 /* new file input context */
197 static int
198 inFile(char *name)
199 {
200 FILE *f;
201 LexIn *t;
202
203 t = (LexIn *) zalloc(sizeof(LexIn));
204
205 if (name == NULL)
206 f = stdin;
207 else {
208 if ((f = fopen(name, "r")) == NULL) {
209 fprintf(stderr, "%s: cannot open config file %s\n", pmProgname, name);
210 free(t);
211 return 0;
212 }
213 t->name = (char *) alloc(strlen(name) + 1);
214 strcpy(t->name, name);
215 }
216
217 t->stream = f;
218 t->lno = 1;
219 t->cno = 0;
220 t->prev = lin;
221 lin = t;
222 return 1;
223 }
224
225
226 /* dereference macro */
227 static int /* 0 -> error, 1 -> string, 2 -> truth, 3 -> number */
228 varDeref(char *name)
229 {
230 Symbol s;
231 Expr *x;
232 LexIn *t;
233
234 /* lookup macro name */
235 if ((s = symLookup(&vars, name)) == NULL) {
236 fprintf(stderr, "undefined macro name $%s\n", name);
237 return 0;
238 }
239 x = symValue(s);
240
241 /* string macro */
242 if (x->sem == SEM_CHAR) {
243 t = (LexIn *) zalloc(sizeof(LexIn));
244 t->prev = lin;
245 lin = t;
246 lin->name = (char *) alloc(strlen(name) + 1);
247 strcpy(lin->name, name);
248 lin->macro = (char *) x->ring;
249 lin->lno = 1;
250 lin->cno = 0;
251 return 1;
252 }
253
254 /* truth valued macro */
255 if (x->sem == SEM_TRUTH) {
256 yylval.x = x;
257 return 2;
258 }
259
260 /* constant numeric valued macro */
261 if (x->sem == SEM_NUMCONST) {
262 /*
263 * need to copy the Expr as the one returned here may be freed
264 * later after constant folding, and we need the real macro's
265 * value to be available for use in later rules
266 */
267 yylval.x = newExpr(NOP, NULL, NULL, -1, -1, -1, 1, SEM_NUMCONST);
268 yylval.x->smpls[0].ptr = x->smpls[0].ptr;
269 yylval.x->valid = 1;
270 return 3;
271 }
272
273 /* variable numeric valued macro */
274 if (x->sem == SEM_NUMVAR) {
275 yylval.x = x;
276 return 3;
277 }
278
279 fprintf(stderr, "varDeref(%s): internal botch sem=%d?\n", name, x->sem);
280 dumpExpr(x);
281 exit(1);
282 }
283
284
285 /* push character into lookahead queue */
286 static void
287 prevc(int c)
288 {
289 if (lin) {
290 lin->look[lin->lookin++] = c;
291 if (lin->lookin >= LEX_MAX + 2)
292 lin->lookin = 0;
293 }
294 }
295
296
297 /* push string into lookahead queue */
298 static void
299 prevs(char *s)
300 {
301 while (*s != '\0') {
302 lin->look[lin->lookin++] = *s++;
303 if (lin->lookin >= LEX_MAX + 2)
304 lin->lookin = 0;
305 }
306 }
307
308 /* get IDENT after '$' ... match rules for IDENT in main scanner */
309 static int
310 get_ident(char *namebuf)
311 {
312 int c;
313 int d = 0;
314 int i;
315 char *namebuf_start = namebuf;
316
317 c = nextc();
318 if (c == '\'') {
319 d = c;
320 c = nextc();
321 }
322 if (!isalpha(c)) {
323 fprintf(stderr, "macro name must begin with an alphabetic (not '%c')\n", c);
324 lexSync();
325 return 0;
326 }
327 i = 0;
328 do {
329 if (c == '\\') c = nextc();
330 *namebuf++ = c;
331 i++;
332 c = nextc();
333 } while (i < LEX_MAX && c != EOF &&
334 (isalpha(c) || isdigit(c) || c == '_' || (d && c != d)));
335
336 if (i == LEX_MAX) {
337 namebuf_start[20] = '\0';
338 fprintf(stderr, "macro name too long: $%s...\n", namebuf_start);
339 lexSync();
340 return 0;
341 }
342 if (c == EOF) {
343 *namebuf = '\0';
344 fprintf(stderr, "unexpected end of file in macro name: $%s\n", namebuf_start);
345 lexSync();
346 return 0;
347 }
348
349 if (!d)
350 prevc(c);
351
352 *namebuf = '\0';
353
354 #if PCP_DEBUG
355 if (pmDebug & DBG_TRACE_APPL0)
356 fprintf(stderr, "get_ident() -> macro name \"%s\"\n", namebuf_start);
357 #endif
358
359 return 1;
360 }
361
362
363 /***********************************************************************
364 * exported functions
365 ***********************************************************************/
366
367 /* initialize scan of new input stream */
368 int
369 lexInit(char *fname)
370 {
371 lin = NULL;
372 if (! inFile(fname))
373 return 0;
374 token = (char *) alloc(LEX_MAX + 1);
375 return 1;
376 }
377
378
379 /* finalize scan of input stream */
380 void
381 lexFinal(void)
382 {
383 free(token);
384 }
385
386
387 /* not end of input stream? */
388 int lexMore(void)
389 {
390 return (lin != NULL);
391 }
392
393
394 /* discard input to next ';' or EOF */
395 void
396 lexSync(void)
397 {
398 int c;
399
400 do
401 c = nextc();
402 while ((c != ';') && (c != EOF));
403 prevc(c);
404 }
405
406
407 /* scanner main function */
408 int
409 yylex(void)
410 {
411 int c, d; /* current character */
412 int esc = 0; /* for escape processing */
413 static int ahead = 0; /* lookahead token */
414 int behind = 0; /* lookbehind token */
415 LexEntry1 *lt1; /* scans through lexbuf1 */
416 LexEntry2 *lt2; /* scans through lexbuf2 */
417 char *p, *q;
418 int i;
419 char nbuf[LEX_MAX+1]; /* for getting macro name */
420
421 /* token from previous invocation */
422 if (ahead) {
423 c = ahead;
424 ahead = 0;
425 #if PCP_DEBUG
426 if (pmDebug & DBG_TRACE_APPL0)
427 fprintf(stderr, "yylex() -> TOKEN (ahead) \'%c\'\n", c);
428 #endif
429 return c;
430 }
431
432 /* scan token from input */
433 c = nextc();
434 while (c != EOF) {
435
436 /* skip blanks */
437 while (isspace(c))
438 c = nextc();
439
440 /* scan C style comment */
441 if (c == '/') {
442 if ((d = nextc()) != '*')
443 prevc(d);
444 else {
445 c = nextc();
446 while (c != EOF) {
447 d = nextc();
448 if ((c == '*') && (d == '/')) {
449 c = nextc();
450 break;
451 }
452 c = d;
453 }
454 continue;
455 }
456 }
457
458 /* scan C++ style comment */
459 if (c == '/') {
460 if ((d = nextc()) != '/')
461 prevc(d);
462 else {
463 do c = nextc();
464 while (( c != '\n') && (c != EOF));
465 continue;
466 }
467 }
468
469 /* scan alphanumeric */
470 if (isalpha(c) || (c == '\'') || (c == '%')) {
471 d = c;
472 if (d == '\'') c = nextc();
473 i = 0;
474 do {
475 if (c == '$') {
476 /* macro embedded in identifier */
477 int sts;
478 if (!get_ident(nbuf))
479 return EOF;
480 sts = varDeref(nbuf);
481 if (sts == 0) {
482 /* error reporting in varDeref() */
483 lexSync();
484 return EOF;
485 }
486 else if (sts != 1) {
487 synerr();
488 fprintf(stderr, "macro $%s not string valued as expected\n", nbuf);
489 lexSync();
490 return EOF;
491 }
492 c = nextc();
493 }
494 else {
495 if (c == '\\') c = nextc();
496 token[i++] = c;
497 c = nextc();
498 }
499 } while ((isalpha(c) || isdigit(c) ||
500 c == '.' || c == '_' || c == '\\' || c == '$' ||
501 (d == '\'' && c != d)) &&
502 (i < LEX_MAX));
503 token[i] = '\0';
504 if (d == '\'') c = nextc();
505
506 /* recognize units keyword */
507 if (d != '\'') {
508 lt2 = &unitab[0];
509 if (i > 0 && token[i-1] == 's')
510 i--;
511 do {
512 if (strlen(lt2->key) == i &&
513 strncmp(token, lt2->key, i) == 0) {
514
515 /* if looking ahead after '/', return UNIT_SLASH */
516 if (behind == '/') {
517 prevs(&token[0]);
518 prevc(c);
519 #if PCP_DEBUG
520 if (pmDebug & DBG_TRACE_APPL0)
521 fprintf(stderr, "yylex() -> OPERATOR \"/\"\n");
522 #endif
523 return UNIT_SLASH;
524 }
525 prevc(c);
526
527 yylval.u = noUnits;
528 switch (lt2->token) {
529 case SPACE_UNIT:
530 yylval.u.dimSpace = 1;
531 yylval.u.scaleSpace = lt2->scale;
532 break;
533 case TIME_UNIT:
534 yylval.u.dimTime = 1;
535 yylval.u.scaleTime = lt2->scale;
536 break;
537 case EVENT_UNIT:
538 yylval.u.dimCount = 1;
539 yylval.u.scaleCount = lt2->scale;
540 break;
541 }
542 #if PCP_DEBUG
543 if (pmDebug & DBG_TRACE_APPL0)
544 fprintf(stderr, "yylex() -> UNITS \"%s\"\n", pmUnitsStr(&yylval.u));
545 #endif
546 return lt2->token;
547 }
548 lt2++;
549 } while (lt2->key);
550 }
551
552 /* if looking ahead, return previous token */
553 if (behind) {
554 prevs(&token[0]);
555 prevc(c);
556 #if PCP_DEBUG
557 if (pmDebug & DBG_TRACE_APPL0)
558 fprintf(stderr, "yylex() -> TOKEN (behind) \'%c\'\n", behind);
559 #endif
560 return behind;
561 }
562 prevc(c);
563
564 /* recognize aggregation and quantification */
565 if (d != '\'') {
566 if ((p = strchr(token, '_')) != NULL) {
567 *p = '\0';
568 lt1 = &quantab[0];
569 do {
570 if (strcmp(&token[0], lt1->key) == 0) {
571 c = lt1->token;
572 q = p + 1;
573 lt1 = &domtab[0];
574 do {
575 if (strcmp(q, lt1->key) == 0) {
576 ahead = lt1->token;
577 #if PCP_DEBUG
578 if (pmDebug & DBG_TRACE_APPL0)
579 fprintf(stderr, "yylex() -> OPERATOR \"%s\'\n", token);
580 #endif
581 return c;
582 }
583 lt1++;
584 } while (lt1->key);
585 break;
586 }
587 lt1++;
588 } while (lt1->key);
589 *p = '_';
590 }
591
592 /* recognize other reserved word */
593 lt1 = &optab[0];
594 do {
595 if (strcmp(&token[0], lt1->key) == 0) {
596 #if PCP_DEBUG
597 if (pmDebug & DBG_TRACE_APPL0)
598 fprintf(stderr, "yylex() -> RESERVED-WORD \"%s\"\n", token);
599 #endif
600 return lt1->token;
601 }
602 lt1++;
603 } while (lt1->key);
604 }
605
606 /* recognize identifier */
607 yylval.s = (char *) alloc(strlen(&token[0]) + 1);
608 strcpy(yylval.s, &token[0]);
609 #if PCP_DEBUG
610 if (pmDebug & DBG_TRACE_APPL0)
611 fprintf(stderr, "yylex() -> IDENT \"%s\"\n", token);
612 #endif
613 return IDENT;
614 }
615
616 /* if looking ahead, return preceding token */
617 if (behind) {
618 prevc(c);
619 #if PCP_DEBUG
620 if (pmDebug & DBG_TRACE_APPL0)
621 fprintf(stderr, "yylex() -> TOKEN (behind) \'%c\'\n", behind);
622 #endif
623 return behind;
624 }
625
626 /* special case for .[0-9]... number without leading [0-9] */
627 if (c == '.') {
628 c = nextc();
629 if (isdigit(c)) {
630 /* note prevc() implements a FIFO, not a stack! */
631 prevc('.'); /* push back period */
632 prevc(c); /* push back digit */
633 c = '0'; /* start with fake leading zero */
634 }
635 else
636 prevc(c); /* not a digit after period, push back */
637 }
638
639 /* scan NUMBER */
640 if (isdigit(c)) {
641 int flote = 0;
642 i = 0;
643 do {
644 token[i++] = c;
645 c = nextc();
646 if ((flote == 0) && (c == '.') && (i < LEX_MAX)) {
647 c = nextc();
648 if (c == '.')
649 prevc(c); /* INTERVAL token */
650 else {
651 flote = 1;
652 token[i++] = '.';
653 }
654 }
655 if ((flote <= 1) && (i < LEX_MAX) && ((c == 'e') || (c == 'E'))) {
656 flote = 2;
657 token[i++] = c;
658 c = nextc();
659 }
660 if ((flote <= 2) && (c == '-') && (i < LEX_MAX)) {
661 flote = 3;
662 token[i++] = c;
663 c = nextc();
664 }
665 } while (isdigit(c) && (i < LEX_MAX));
666 prevc(c);
667 token[i] = '\0';
668 yylval.d = strtod(&token[0], NULL);
669 #if PCP_DEBUG
670 if (pmDebug & DBG_TRACE_APPL0)
671 fprintf(stderr, "yylex() -> NUMBER %g\n", yylval.d);
672 #endif
673 return NUMBER;
674 }
675
676 /* scan string */
677 if (c == '"') {
678 yylval.s = NULL;
679 i = 0;
680 c = nextc();
681 while ((c != '"') && (c != EOF) && (i < LEX_MAX)) {
682
683 /* escape character */
684 if (c == '\\') {
685 esc = 1;
686 c = nextc();
687 switch (c) {
688 case 'n':
689 c = '\n';
690 break;
691 case 't':
692 c = '\t';
693 break;
694 case 'v':
695 c = '\v';
696 break;
697 case 'b':
698 c = '\b';
699 break;
700 case 'r':
701 c = '\r';
702 break;
703 case 'f':
704 c = '\f';
705 break;
706 case 'a':
707 c = '\a';
708 break;
709 }
710 }
711 else
712 esc = 0;
713
714 /* macro embedded in string */
715 if (c == '$' && !esc) {
716 int sts;
717 if (!get_ident(nbuf))
718 return EOF;
719 sts = varDeref(nbuf);
720 if (sts == 0) {
721 /* error reporting in varDeref() */
722 lexSync();
723 return EOF;
724 }
725 else if (sts != 1) {
726 synerr();
727 fprintf(stderr, "macro $%s not string valued as expected\n", nbuf);
728 lexSync();
729 return EOF;
730 }
731 c = nextc();
732 }
733
734 /* add character to string */
735 yylval.s = (char *) ralloc(yylval.s, i+2);
736 yylval.s[i++] = c;
737 c = nextc();
738 }
739 if (i == 0) {
740 /* special case for null string */
741 yylval.s = (char *) ralloc(yylval.s, 1);
742 }
743 yylval.s[i++] = '\0';
744 #if PCP_DEBUG
745 if (pmDebug & DBG_TRACE_APPL0)
746 fprintf(stderr, "yylex() -> STRING \"%s\"\n", yylval.s);
747 #endif
748 return STRING;
749 }
750
751 /* scan operator */
752 switch (c) {
753 case ';':
754 do
755 d = nextc();
756 while (isspace(d));
757 if (d == '.') {
758 while (lin)
759 unwind();
760 }
761 else
762 prevc(d);
763 #if PCP_DEBUG
764 if (pmDebug & DBG_TRACE_APPL0)
765 fprintf(stderr, "yylex() -> END-OF-RULE\n");
766 #endif
767 return EOF;
768
|
Event unterminated_case: |
This case (value 36) is not terminated by a 'break' statement. |
| Also see events: |
[fallthrough] |
769 case '$':
770 if (!get_ident(nbuf))
771 return EOF;
772 switch (varDeref(nbuf)) {
773 case 0:
774 lexSync();
775 return EOF;
776 case 1:
777 c = nextc();
778 continue;
779 case 2:
780 #if PCP_DEBUG
781 if (pmDebug & DBG_TRACE_APPL0)
782 fprintf(stderr, "yylex() -> (boolean) macro $%s\n", nbuf);
783 #endif
784 return VAR;
785 case 3:
786 #if PCP_DEBUG
787 if (pmDebug & DBG_TRACE_APPL0)
788 fprintf(stderr, "yylex() -> (numeric) macro $%s\n", nbuf);
789 #endif
790 return VAR;
791 }
|
Event fallthrough: |
The above case falls through to this one. |
| Also see events: |
[unterminated_case] |
792 case '/':
793 behind = c;
794 c = nextc();
795 continue;
796 case '-':
797 if ((d = nextc()) == '>') {
798 #if PCP_DEBUG
799 if (pmDebug & DBG_TRACE_APPL0)
800 fprintf(stderr, "yylex() -> OPERATOR \"->\"\n");
801 #endif
802 return ARROW;
803 }
804 prevc(d);
805 break;
806 case '=':
807 if ((d = nextc()) == '=') {
808 #if PCP_DEBUG
809 if (pmDebug & DBG_TRACE_APPL0)
810 fprintf(stderr, "yylex() -> OPERATOR \"==\"\n");
811 #endif
812 return EQ_REL;
813 }
814 prevc(d);
815 break;
816 case '!':
817 if ((d = nextc()) == '=') {
818 #if PCP_DEBUG
819 if (pmDebug & DBG_TRACE_APPL0)
820 fprintf(stderr, "yylex() -> OPERATOR \"!=\"\n");
821 #endif
822 return NEQ_REL;
823 }
824 prevc(d);
825 #if PCP_DEBUG
826 if (pmDebug & DBG_TRACE_APPL0)
827 fprintf(stderr, "yylex() -> OPERATOR \"!\"\n");
828 #endif
829 return NOT;
830 case '<':
831 if ((d = nextc()) == '=') {
832 #if PCP_DEBUG
833 if (pmDebug & DBG_TRACE_APPL0)
834 fprintf(stderr, "yylex() -> OPERATOR \"<=\"\n");
835 #endif
836 return LEQ_REL;
837 }
838 prevc(d);
839 break;
840 case '>':
841 if ((d = nextc()) == '=') {
842 #if PCP_DEBUG
843 if (pmDebug & DBG_TRACE_APPL0)
844 fprintf(stderr, "yylex() -> OPERATOR \">=\"\n");
845 #endif
846 return GEQ_REL;
847 }
848 prevc(d);
849 break;
850 case '&':
851 if ((d = nextc()) == '&') {
852 #if PCP_DEBUG
853 if (pmDebug & DBG_TRACE_APPL0)
854 fprintf(stderr, "yylex() -> OPERATOR \"&&\"\n");
855 #endif
856 return AND;
857 }
858 prevc(d);
859 #if PCP_DEBUG
860 if (pmDebug & DBG_TRACE_APPL0)
861 fprintf(stderr, "yylex() -> OPERATOR \"&\"\n");
862 #endif
863 return SEQ;
864 case '|':
865 if ((d = nextc()) == '|') {
866 #if PCP_DEBUG
867 if (pmDebug & DBG_TRACE_APPL0)
868 fprintf(stderr, "yylex() -> OPERATOR \"||\"\n");
869 #endif
870 return OR;
871 }
872 prevc(d);
873 #if PCP_DEBUG
874 if (pmDebug & DBG_TRACE_APPL0)
875 fprintf(stderr, "yylex() -> OPERATOR \"|\"\n");
876 #endif
877 return ALT;
878 case '.':
879 if ((d = nextc()) == '.') {
880 #if PCP_DEBUG
881 if (pmDebug & DBG_TRACE_APPL0)
882 fprintf(stderr, "yylex() -> OPERATOR \"..\"\n");
883 #endif
884 return INTERVAL;
885 }
886 prevc(d);
887 break;
888
889 }
890 #if PCP_DEBUG
891 if (pmDebug & DBG_TRACE_APPL0) {
892 if (c == EOF)
893 fprintf(stderr, "yylex() -> EOF\n");
894 else
895 fprintf(stderr, "yylex() -> TOKEN \'%c\' (0x%x)\n", c, c & 0xff);
896 }
897 #endif
898 return c;
899 }
900
901 #if PCP_DEBUG
902 if (pmDebug & DBG_TRACE_APPL0)
903 fprintf(stderr, "yylex() -> EOF\n");
904 #endif
905 return EOF;
906 }
907
908
909