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