Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/sys/src/cmd/spin/spinlex.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/***** spin: spinlex.c *****/
2
 
3
/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
4
/* All Rights Reserved.  This software is for educational purposes only.  */
5
/* No guarantee whatsoever is expressed or implied by the distribution of */
6
/* this code.  Permission is given to distribute this code provided that  */
7
/* this introductory message is not removed and no monies are exchanged.  */
8
/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
9
/*             http://spinroot.com/                                       */
10
/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
11
 
12
#include <stdlib.h>
13
#include "spin.h"
14
#include "y.tab.h"
15
 
16
#define MAXINL	16	/* max recursion depth inline fcts */
17
#define MAXPAR	32	/* max params to an inline call */
18
#define MAXLEN	512	/* max len of an actual parameter text */
19
 
20
typedef struct IType {
21
	Symbol *nm;		/* name of the type */
22
	Lextok *cn;		/* contents */
23
	Lextok *params;		/* formal pars if any */
24
	char   **anms;		/* literal text for actual pars */
25
	char   *prec;		/* precondition for c_code or c_expr */
26
	int    uiid;		/* unique inline id */
27
	int    dln, cln;	/* def and call linenr */
28
	Symbol *dfn, *cfn;	/* def and call filename */
29
	struct IType *nxt;	/* linked list */
30
} IType;
31
 
32
typedef struct C_Added {
33
	Symbol *s;
34
	Symbol *t;
35
	Symbol *ival;
36
	struct C_Added *nxt;
37
} C_Added;
38
 
39
extern RunList	*X;
40
extern ProcList	*rdy;
41
extern Symbol	*Fname, *oFname;
42
extern Symbol	*context, *owner;
43
extern YYSTYPE	yylval;
44
extern short	has_last, has_code;
45
extern int	verbose, IArgs, hastrack, separate, ltl_mode;
46
 
47
short	has_stack = 0;
48
int	lineno  = 1;
49
int	scope_seq[128], scope_level = 0;
50
char	CurScope[MAXSCOPESZ];
51
char	yytext[2048];
52
FILE	*yyin, *yyout;
53
 
54
static C_Added	*c_added, *c_tracked;
55
static IType	*Inline_stub[MAXINL];
56
static char	*ReDiRect;
57
static char	*Inliner[MAXINL], IArg_cont[MAXPAR][MAXLEN];
58
static unsigned char	in_comment=0;
59
static int	IArgno = 0, Inlining = -1;
60
static int	check_name(char *);
61
 
62
#if 1
63
#define Token(y)	{ if (in_comment) goto again; \
64
			yylval = nn(ZN,0,ZN,ZN); return y; }
65
 
66
#define ValToken(x, y)	{ if (in_comment) goto again; \
67
			yylval = nn(ZN,0,ZN,ZN); yylval->val = x; return y; }
68
 
69
#define SymToken(x, y)	{ if (in_comment) goto again; \
70
			yylval = nn(ZN,0,ZN,ZN); yylval->sym = x; return y; }
71
#else
72
#define Token(y)	{ yylval = nn(ZN,0,ZN,ZN); \
73
			if (!in_comment) return y; else goto again; }
74
 
75
#define ValToken(x, y)	{ yylval = nn(ZN,0,ZN,ZN); yylval->val = x; \
76
			if (!in_comment) return y; else goto again; }
77
 
78
#define SymToken(x, y)	{ yylval = nn(ZN,0,ZN,ZN); yylval->sym = x; \
79
			if (!in_comment) return y; else goto again; }
80
#endif
81
 
82
static int	getinline(void);
83
static void	uninline(void);
84
 
85
#if 1
86
#define Getchar()	((Inlining<0)?getc(yyin):getinline())
87
#define Ungetch(c)	{if (Inlining<0) ungetc(c,yyin); else uninline();}
88
 
89
#else
90
 
91
static int
92
Getchar(void)
93
{	int c;
94
 
95
	if (Inlining<0)
96
		c = getc(yyin);
97
	else
98
		c = getinline();
99
	if (0)
100
	{	printf("<%c:%d>[%d] ", c, c, Inlining);
101
	} else
102
	{	printf("%c", c);
103
	}
104
	return c;
105
}
106
 
107
static void
108
Ungetch(int c)
109
{
110
	if (Inlining<0)
111
		ungetc(c,yyin);
112
	else
113
		uninline();
114
	if (0)
115
	{	printf("<bs>");
116
	}
117
}
118
#endif
119
 
120
static int
121
notdollar(int c)
122
{	return (c != '$' && c != '\n');
123
}
124
 
125
static int
126
notquote(int c)
127
{	return (c != '\"' && c != '\n');
128
}
129
 
130
int
131
isalnum_(int c)
132
{	return (isalnum(c) || c == '_');
133
}
134
 
135
static int
136
isalpha_(int c)
137
{	return isalpha(c);	/* could be macro */
138
}
139
 
140
static int
141
isdigit_(int c)
142
{	return isdigit(c);	/* could be macro */
143
}
144
 
145
static void
146
getword(int first, int (*tst)(int))
147
{	int i=0, c;
148
 
149
	yytext[i++]= (char) first;
150
	while (tst(c = Getchar()))
151
	{	yytext[i++] = (char) c;
152
		if (c == '\\')
153
		{	c = Getchar();
154
			yytext[i++] = (char) c;	/* no tst */
155
	}	}
156
	yytext[i] = '\0';
157
	Ungetch(c);
158
}
159
 
160
static int
161
follow(int tok, int ifyes, int ifno)
162
{	int c;
163
 
164
	if ((c = Getchar()) == tok)
165
		return ifyes;
166
	Ungetch(c);
167
 
168
	return ifno;
169
}
170
 
171
static IType *seqnames;
172
 
173
static void
174
def_inline(Symbol *s, int ln, char *ptr, char *prc, Lextok *nms)
175
{	IType *tmp;
176
	int  cnt = 0;
177
	char *nw = (char *) emalloc(strlen(ptr)+1);
178
	strcpy(nw, ptr);
179
 
180
	for (tmp = seqnames; tmp; cnt++, tmp = tmp->nxt)
181
		if (!strcmp(s->name, tmp->nm->name))
182
		{	non_fatal("procedure name %s redefined",
183
				tmp->nm->name);
184
			tmp->cn = (Lextok *) nw;
185
			tmp->params = nms;
186
			tmp->dln = ln;
187
			tmp->dfn = Fname;
188
			return;
189
		}
190
	tmp = (IType *) emalloc(sizeof(IType));
191
	tmp->nm = s;
192
	tmp->cn = (Lextok *) nw;
193
	tmp->params = nms;
194
	if (strlen(prc) > 0)
195
	{	tmp->prec = (char *) emalloc(strlen(prc)+1);
196
		strcpy(tmp->prec, prc);
197
	}
198
	tmp->dln = ln;
199
	tmp->dfn = Fname;
200
	tmp->uiid = cnt+1;	/* so that 0 means: not an inline */
201
	tmp->nxt = seqnames;
202
	seqnames = tmp;
203
}
204
 
205
void
206
gencodetable(FILE *fd)
207
{	IType *tmp;
208
	char *q;
209
	int cnt;
210
 
211
	if (separate == 2) return;
212
 
213
	fprintf(fd, "struct {\n");
214
	fprintf(fd, "	char *c; char *t;\n");
215
	fprintf(fd, "} code_lookup[] = {\n");
216
 
217
	if (has_code)
218
	for (tmp = seqnames; tmp; tmp = tmp->nxt)
219
		if (tmp->nm->type == CODE_FRAG
220
		||  tmp->nm->type == CODE_DECL)
221
		{	fprintf(fd, "\t{ \"%s\", ",
222
				tmp->nm->name);
223
			q = (char *) tmp->cn;
224
 
225
			while (*q == '\n' || *q == '\r' || *q == '\\')
226
				q++;
227
 
228
			fprintf(fd, "\"");
229
			cnt = 0;
230
			while (*q && cnt < 1024) /* pangen1.h allows 2048 */
231
			{	switch (*q) {
232
				case '"':
233
					fprintf(fd, "\\\"");
234
					break;
235
				case '%':
236
					fprintf(fd, "%%");
237
					break;
238
				case '\n':
239
					fprintf(fd, "\\n");
240
					break;
241
				default:
242
					putc(*q, fd);
243
					break;
244
				}
245
				q++; cnt++;
246
			}
247
			if (*q) fprintf(fd, "...");
248
			fprintf(fd, "\"");
249
			fprintf(fd, " },\n");
250
		}
251
 
252
	fprintf(fd, "	{ (char *) 0, \"\" }\n");
253
	fprintf(fd, "};\n");
254
}
255
 
256
static int
257
iseqname(char *t)
258
{	IType *tmp;
259
 
260
	for (tmp = seqnames; tmp; tmp = tmp->nxt)
261
	{	if (!strcmp(t, tmp->nm->name))
262
			return 1;
263
	}
264
	return 0;
265
}
266
 
267
static int
268
getinline(void)
269
{	int c;
270
 
271
	if (ReDiRect)
272
	{	c = *ReDiRect++;
273
		if (c == '\0')
274
		{	ReDiRect = (char *) 0;
275
			c = *Inliner[Inlining]++;
276
		}
277
	} else
278
		c = *Inliner[Inlining]++;
279
 
280
	if (c == '\0')
281
	{	lineno = Inline_stub[Inlining]->cln;
282
		Fname  = Inline_stub[Inlining]->cfn;
283
		Inlining--;
284
#if 0
285
		if (verbose&32)
286
		printf("spin: %s:%d, done inlining %s\n",
287
			Fname, lineno, Inline_stub[Inlining+1]->nm->name);
288
#endif
289
		return Getchar();
290
	}
291
	return c;
292
}
293
 
294
static void
295
uninline(void)
296
{
297
	if (ReDiRect)
298
		ReDiRect--;
299
	else
300
		Inliner[Inlining]--;
301
}
302
 
303
int
304
is_inline(void)
305
{
306
	if (Inlining < 0)
307
		return 0;	/* i.e., not an inline */
308
	if (Inline_stub[Inlining] == NULL)
309
		fatal("unexpected, inline_stub not set", 0);
310
	return Inline_stub[Inlining]->uiid;
311
}
312
 
313
IType *
314
find_inline(char *s)
315
{	IType *tmp;
316
 
317
	for (tmp = seqnames; tmp; tmp = tmp->nxt)
318
		if (!strcmp(s, tmp->nm->name))
319
			break;
320
	if (!tmp)
321
		fatal("cannot happen, missing inline def %s", s);
322
 
323
	return tmp;
324
}
325
 
326
void
327
c_state(Symbol *s, Symbol *t, Symbol *ival)	/* name, scope, ival */
328
{	C_Added *r;
329
 
330
	r = (C_Added *) emalloc(sizeof(C_Added));
331
	r->s = s;	/* pointer to a data object */
332
	r->t = t;	/* size of object, or "global", or "local proctype_name"  */
333
	r->ival = ival;
334
	r->nxt = c_added;
335
	c_added = r;
336
}
337
 
338
void
339
c_track(Symbol *s, Symbol *t, Symbol *stackonly)	/* name, size */
340
{	C_Added *r;
341
 
342
	r = (C_Added *) emalloc(sizeof(C_Added));
343
	r->s = s;
344
	r->t = t;
345
	r->ival = stackonly;	/* abuse of name */
346
	r->nxt = c_tracked;
347
	c_tracked = r;
348
 
349
	if (stackonly != ZS)
350
	{	if (strcmp(stackonly->name, "\"Matched\"") == 0)
351
			r->ival = ZS;	/* the default */
352
		else if (strcmp(stackonly->name, "\"UnMatched\"") != 0
353
		     &&  strcmp(stackonly->name, "\"unMatched\"") != 0
354
		     &&  strcmp(stackonly->name, "\"StackOnly\"") != 0)
355
			non_fatal("expecting '[Un]Matched', saw %s", stackonly->name);
356
		else
357
			has_stack = 1;	/* unmatched stack */
358
	}
359
}
360
 
361
char *
362
jump_etc(char *op)
363
{	char *p = op;
364
 
365
	/* kludgy - try to get the type separated from the name */
366
 
367
	while (*p == ' ' || *p == '\t')
368
		p++;	/* initial white space */
369
	while (*p != ' ' && *p != '\t')
370
		p++;	/* type name */
371
	while (*p == ' ' || *p == '\t')
372
		p++;	/* white space */
373
	while (*p == '*')
374
		p++;	/* decorations */
375
	while (*p == ' ' || *p == '\t')
376
		p++;	/* white space */
377
 
378
	if (*p == '\0')
379
		fatal("c_state format (%s)", op);
380
 
381
	if (strchr(p, '[')
382
	&&  !strchr(p, '{'))
383
	{	non_fatal("array initialization error, c_state (%s)", p);
384
		return (char *) 0;
385
	}
386
 
387
	return p;
388
}
389
 
390
void
391
c_add_globinit(FILE *fd)
392
{	C_Added *r;
393
	char *p, *q;
394
 
395
	fprintf(fd, "void\nglobinit(void)\n{\n");
396
	for (r = c_added; r; r = r->nxt)
397
	{	if (r->ival == ZS)
398
			continue;
399
 
400
		if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0)
401
		{	for (q = r->ival->name; *q; q++)
402
			{	if (*q == '\"')
403
					*q = ' ';
404
				if (*q == '\\')
405
					*q++ = ' '; /* skip over the next */
406
			}
407
			p = jump_etc(r->s->name);	/* e.g., "int **q" */
408
			if (p)
409
			fprintf(fd, "	now.%s = %s;\n", p, r->ival->name);
410
 
411
		} else
412
		if (strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0)
413
		{	for (q = r->ival->name; *q; q++)
414
			{	if (*q == '\"')
415
					*q = ' ';
416
				if (*q == '\\')
417
					*q++ = ' '; /* skip over the next */
418
			}
419
			p = jump_etc(r->s->name);	/* e.g., "int **q" */
420
			if (p)
421
			fprintf(fd, "	%s = %s;\n", p, r->ival->name);	/* no now. prefix */
422
 
423
	}	}
424
	fprintf(fd, "}\n");
425
}
426
 
427
void
428
c_add_locinit(FILE *fd, int tpnr, char *pnm)
429
{	C_Added *r;
430
	char *p, *q, *s;
431
	int frst = 1;
432
 
433
	fprintf(fd, "void\nlocinit%d(int h)\n{\n", tpnr);
434
	for (r = c_added; r; r = r->nxt)
435
		if (r->ival != ZS
436
		&&  strncmp(r->t->name, " Local", strlen(" Local")) == 0)
437
		{	for (q = r->ival->name; *q; q++)
438
				if (*q == '\"')
439
					*q = ' ';
440
 
441
			p = jump_etc(r->s->name);	/* e.g., "int **q" */
442
 
443
			q = r->t->name + strlen(" Local");
444
			while (*q == ' ' || *q == '\t')
445
				q++;			/* process name */
446
 
447
			s = (char *) emalloc(strlen(q)+1);
448
			strcpy(s, q);
449
 
450
			q = &s[strlen(s)-1];
451
			while (*q == ' ' || *q == '\t')
452
				*q-- = '\0';
453
 
454
			if (strcmp(pnm, s) != 0)
455
				continue;
456
 
457
			if (frst)
458
			{	fprintf(fd, "\tuchar *this = pptr(h);\n");
459
				frst = 0;
460
			}
461
 
462
			if (p)
463
			fprintf(fd, "		((P%d *)this)->%s = %s;\n",
464
				tpnr, p, r->ival->name);
465
 
466
		}
467
	fprintf(fd, "}\n");
468
}
469
 
470
/* tracking:
471
	1. for non-global and non-local c_state decls: add up all the sizes in c_added
472
	2. add a global char array of that size into now
473
	3. generate a routine that memcpy's the required values into that array
474
	4. generate a call to that routine
475
 */
476
 
477
void
478
c_preview(void)
479
{	C_Added *r;
480
 
481
	hastrack = 0;
482
	if (c_tracked)
483
		hastrack = 1;
484
	else
485
	for (r = c_added; r; r = r->nxt)
486
		if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0
487
		&&  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0
488
		&&  strncmp(r->t->name, " Local",  strlen(" Local"))  != 0)
489
		{	hastrack = 1;	/* c_state variant now obsolete */
490
			break;
491
		}
492
}
493
 
494
int
495
c_add_sv(FILE *fd)	/* 1+2 -- called in pangen1.c */
496
{	C_Added *r;
497
	int cnt = 0;
498
 
499
	if (!c_added && !c_tracked) return 0;
500
 
501
	for (r = c_added; r; r = r->nxt)	/* pickup global decls */
502
		if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0)
503
			fprintf(fd, "	%s;\n", r->s->name);
504
 
505
	for (r = c_added; r; r = r->nxt)
506
		if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0
507
		&&  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0
508
		&&  strncmp(r->t->name, " Local",  strlen(" Local"))  != 0)
509
		{	cnt++;	/* obsolete use */
510
		}
511
 
512
	for (r = c_tracked; r; r = r->nxt)
513
		cnt++;		/* preferred use */
514
 
515
	if (cnt == 0) return 0;
516
 
517
	cnt = 0;
518
	fprintf(fd, "	uchar c_state[");
519
	for (r = c_added; r; r = r->nxt)
520
		if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0
521
		&&  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0
522
		&&  strncmp(r->t->name, " Local",  strlen(" Local"))  != 0)
523
		{	fprintf(fd, "%ssizeof(%s)",
524
				(cnt==0)?"":"+", r->t->name);
525
			cnt++;
526
		}
527
 
528
	for (r = c_tracked; r; r = r->nxt)
529
	{	if (r->ival != ZS) continue;
530
 
531
		fprintf(fd, "%s%s",
532
			(cnt==0)?"":"+", r->t->name);
533
		cnt++;
534
	}
535
 
536
	if (cnt == 0) fprintf(fd, "4");	/* now redundant */
537
	fprintf(fd, "];\n");
538
	return 1;
539
}
540
 
541
void
542
c_stack_size(FILE *fd)
543
{	C_Added *r;
544
	int cnt = 0;
545
 
546
	for (r = c_tracked; r; r = r->nxt)
547
		if (r->ival != ZS)
548
		{	fprintf(fd, "%s%s",
549
				(cnt==0)?"":"+", r->t->name);
550
			cnt++;
551
		}
552
	if (cnt == 0)
553
	{	fprintf(fd, "WS");
554
	}
555
}
556
 
557
void
558
c_add_stack(FILE *fd)
559
{	C_Added *r;
560
	int cnt = 0;
561
 
562
	if ((!c_added && !c_tracked) || !has_stack)
563
	{	return;
564
	}
565
 
566
	for (r = c_tracked; r; r = r->nxt)
567
		if (r->ival != ZS)
568
		{	cnt++;
569
		}
570
 
571
	if (cnt > 0)
572
	{	fprintf(fd, "	uchar c_stack[StackSize];\n");
573
	}
574
}
575
 
576
void
577
c_add_hidden(FILE *fd)
578
{	C_Added *r;
579
 
580
	for (r = c_added; r; r = r->nxt)	/* pickup hidden decls */
581
		if (strncmp(r->t->name, "\"Hidden\"", strlen("\"Hidden\"")) == 0)
582
		{	r->s->name[strlen(r->s->name)-1] = ' ';
583
			fprintf(fd, "%s;	/* Hidden */\n", &r->s->name[1]);
584
			r->s->name[strlen(r->s->name)-1] = '"';
585
		}
586
	/* called before c_add_def - quotes are still there */
587
}
588
 
589
void
590
c_add_loc(FILE *fd, char *s)	/* state vector entries for proctype s */
591
{	C_Added *r;
592
	static char buf[1024];
593
	char *p;
594
 
595
	if (!c_added) return;
596
 
597
	strcpy(buf, s);
598
	strcat(buf, " ");
599
	for (r = c_added; r; r = r->nxt)	/* pickup local decls */
600
		if (strncmp(r->t->name, " Local", strlen(" Local")) == 0)
601
		{	p = r->t->name + strlen(" Local");
602
			while (*p == ' ' || *p == '\t')
603
				p++;
604
			if (strcmp(p, buf) == 0)
605
				fprintf(fd, "	%s;\n", r->s->name);
606
		}
607
}
608
void
609
c_add_def(FILE *fd)	/* 3 - called in plunk_c_fcts() */
610
{	C_Added *r;
611
 
612
	fprintf(fd, "#if defined(C_States) && defined(HAS_TRACK)\n");
613
	for (r = c_added; r; r = r->nxt)
614
	{	r->s->name[strlen(r->s->name)-1] = ' ';
615
		r->s->name[0] = ' '; /* remove the "s */
616
 
617
		r->t->name[strlen(r->t->name)-1] = ' ';
618
		r->t->name[0] = ' ';
619
 
620
		if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0
621
		||  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0
622
		||  strncmp(r->t->name, " Local",  strlen(" Local"))  == 0)
623
			continue;
624
 
625
		if (strchr(r->s->name, '&'))
626
			fatal("dereferencing state object: %s", r->s->name);
627
 
628
		fprintf(fd, "extern %s %s;\n", r->t->name, r->s->name);
629
	}
630
	for (r = c_tracked; r; r = r->nxt)
631
	{	r->s->name[strlen(r->s->name)-1] = ' ';
632
		r->s->name[0] = ' '; /* remove " */
633
 
634
		r->t->name[strlen(r->t->name)-1] = ' ';
635
		r->t->name[0] = ' ';
636
	}
637
 
638
	if (separate == 2)
639
	{	fprintf(fd, "#endif\n");
640
		return;
641
	}
642
 
643
	if (has_stack)
644
	{	fprintf(fd, "int cpu_printf(const char *, ...);\n");
645
		fprintf(fd, "void\nc_stack(uchar *p_t_r)\n{\n");
646
		fprintf(fd, "#ifdef VERBOSE\n");
647
		fprintf(fd, "	cpu_printf(\"c_stack %%u\\n\", p_t_r);\n");
648
		fprintf(fd, "#endif\n");
649
		for (r = c_tracked; r; r = r->nxt)
650
		{	if (r->ival == ZS) continue;
651
 
652
			fprintf(fd, "\tif(%s)\n", r->s->name);
653
			fprintf(fd, "\t\tmemcpy(p_t_r, %s, %s);\n",
654
				r->s->name, r->t->name);
655
			fprintf(fd, "\telse\n");
656
			fprintf(fd, "\t\tmemset(p_t_r, 0, %s);\n",
657
				r->t->name);
658
			fprintf(fd, "\tp_t_r += %s;\n", r->t->name);
659
		}
660
		fprintf(fd, "}\n\n");
661
	}
662
 
663
	fprintf(fd, "void\nc_update(uchar *p_t_r)\n{\n");
664
	fprintf(fd, "#ifdef VERBOSE\n");
665
	fprintf(fd, "	printf(\"c_update %%u\\n\", p_t_r);\n");
666
	fprintf(fd, "#endif\n");
667
	for (r = c_added; r; r = r->nxt)
668
	{	if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0
669
		||  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0
670
		||  strncmp(r->t->name, " Local",  strlen(" Local"))  == 0)
671
			continue;
672
 
673
		fprintf(fd, "\tmemcpy(p_t_r, &%s, sizeof(%s));\n",
674
			r->s->name, r->t->name);
675
		fprintf(fd, "\tp_t_r += sizeof(%s);\n", r->t->name);
676
	}
677
 
678
	for (r = c_tracked; r; r = r->nxt)
679
	{	if (r->ival) continue;
680
 
681
		fprintf(fd, "\tif(%s)\n", r->s->name);
682
		fprintf(fd, "\t\tmemcpy(p_t_r, %s, %s);\n",
683
			r->s->name, r->t->name);
684
		fprintf(fd, "\telse\n");
685
		fprintf(fd, "\t\tmemset(p_t_r, 0, %s);\n",
686
			r->t->name);
687
		fprintf(fd, "\tp_t_r += %s;\n", r->t->name);
688
	}
689
 
690
	fprintf(fd, "}\n");
691
 
692
	if (has_stack)
693
	{	fprintf(fd, "void\nc_unstack(uchar *p_t_r)\n{\n");
694
		fprintf(fd, "#ifdef VERBOSE\n");
695
		fprintf(fd, "	cpu_printf(\"c_unstack %%u\\n\", p_t_r);\n");
696
		fprintf(fd, "#endif\n");
697
		for (r = c_tracked; r; r = r->nxt)
698
		{	if (r->ival == ZS) continue;
699
 
700
			fprintf(fd, "\tif(%s)\n", r->s->name);
701
			fprintf(fd, "\t\tmemcpy(%s, p_t_r, %s);\n",
702
				r->s->name, r->t->name);
703
			fprintf(fd, "\tp_t_r += %s;\n", r->t->name);
704
		}
705
		fprintf(fd, "}\n");
706
	}
707
 
708
	fprintf(fd, "void\nc_revert(uchar *p_t_r)\n{\n");
709
	fprintf(fd, "#ifdef VERBOSE\n");
710
	fprintf(fd, "	printf(\"c_revert %%u\\n\", p_t_r);\n");
711
	fprintf(fd, "#endif\n");
712
	for (r = c_added; r; r = r->nxt)
713
	{	if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0
714
		||  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0
715
		||  strncmp(r->t->name, " Local",  strlen(" Local"))  == 0)
716
			continue;
717
 
718
		fprintf(fd, "\tmemcpy(&%s, p_t_r, sizeof(%s));\n",
719
			r->s->name, r->t->name);
720
		fprintf(fd, "\tp_t_r += sizeof(%s);\n", r->t->name);
721
	}
722
	for (r = c_tracked; r; r = r->nxt)
723
	{	if (r->ival != ZS) continue;
724
 
725
		fprintf(fd, "\tif(%s)\n", r->s->name);
726
		fprintf(fd, "\t\tmemcpy(%s, p_t_r, %s);\n",
727
			r->s->name, r->t->name);
728
		fprintf(fd, "\tp_t_r += %s;\n", r->t->name);
729
	}
730
 
731
	fprintf(fd, "}\n");
732
	fprintf(fd, "#endif\n");
733
}
734
 
735
void
736
plunk_reverse(FILE *fd, IType *p, int matchthis)
737
{	char *y, *z;
738
 
739
	if (!p) return;
740
	plunk_reverse(fd, p->nxt, matchthis);
741
 
742
	if (!p->nm->context
743
	&&   p->nm->type == matchthis)
744
	{	fprintf(fd, "\n/* start of %s */\n", p->nm->name);
745
		z = (char *) p->cn;
746
		while (*z == '\n' || *z == '\r' || *z == '\\')
747
			z++;
748
		/* e.g.: \#include "..." */
749
 
750
		y = z;
751
		while ((y = strstr(y, "\\#")) != NULL)
752
		{	*y = '\n'; y++;
753
		}
754
 
755
		fprintf(fd, "%s\n", z);
756
		fprintf(fd, "\n/* end of %s */\n", p->nm->name);
757
	}
758
}
759
 
760
void
761
plunk_c_decls(FILE *fd)
762
{
763
	plunk_reverse(fd, seqnames, CODE_DECL);
764
}
765
 
766
void
767
plunk_c_fcts(FILE *fd)
768
{
769
	if (separate == 2 && hastrack)
770
	{	c_add_def(fd);
771
		return;
772
	}
773
 
774
	c_add_hidden(fd);
775
	plunk_reverse(fd, seqnames, CODE_FRAG);
776
 
777
	if (c_added || c_tracked)	/* enables calls to c_revert and c_update */
778
		fprintf(fd, "#define C_States	1\n");
779
	else
780
		fprintf(fd, "#undef C_States\n");
781
 
782
	if (hastrack)
783
		c_add_def(fd);
784
 
785
	c_add_globinit(fd);
786
	do_locinits(fd);
787
}
788
 
789
static void
790
check_inline(IType *tmp)
791
{	char buf[128];
792
	ProcList *p;
793
 
794
	if (!X) return;
795
 
796
	for (p = rdy; p; p = p->nxt)
797
	{	if (strcmp(p->n->name, X->n->name) == 0)
798
			continue;
799
		sprintf(buf, "P%s->", p->n->name);
800
		if (strstr((char *)tmp->cn, buf))
801
		{	printf("spin: in proctype %s, ref to object in proctype %s\n",
802
				X->n->name, p->n->name);
803
			fatal("invalid variable ref in '%s'", tmp->nm->name);
804
	}	}
805
}
806
 
807
void
808
plunk_expr(FILE *fd, char *s)
809
{	IType *tmp;
810
 
811
	tmp = find_inline(s);
812
	check_inline(tmp);
813
 
814
	fprintf(fd, "%s", (char *) tmp->cn);
815
}
816
 
817
void
818
preruse(FILE *fd, Lextok *n)	/* check a condition for c_expr with preconditions */
819
{	IType *tmp;
820
 
821
	if (!n) return;
822
	if (n->ntyp == C_EXPR)
823
	{	tmp = find_inline(n->sym->name);
824
		if (tmp->prec)
825
		{	fprintf(fd, "if (!(%s)) { if (!readtrail) { depth++; ", tmp->prec);
826
			fprintf(fd, "trpt++; trpt->pr = II; trpt->o_t = t;");
827
			fprintf(fd, "trpt->st = tt; uerror(\"%s\"); continue; } ", tmp->prec);
828
			fprintf(fd, "else { printf(\"pan: precondition false: %s\\n\"); ", tmp->prec);
829
			fprintf(fd, "_m = 3; goto P999; } } \n\t\t");
830
		}
831
	} else
832
	{	preruse(fd, n->rgt);
833
		preruse(fd, n->lft);
834
	}
835
}
836
 
837
int
838
glob_inline(char *s)
839
{	IType *tmp;
840
	char *bdy;
841
 
842
	tmp = find_inline(s);
843
	bdy = (char *) tmp->cn;
844
	return (strstr(bdy, "now.")		/* global ref or   */
845
	||      strchr(bdy, '(') > bdy);	/* possible C-function call */
846
}
847
 
848
void
849
plunk_inline(FILE *fd, char *s, int how, int gencode)	/* c_code with precondition */
850
{	IType *tmp;
851
 
852
	tmp = find_inline(s);
853
	check_inline(tmp);
854
 
855
	fprintf(fd, "{ ");
856
	if (how && tmp->prec)
857
	{	fprintf(fd, "if (!(%s)) { if (!readtrail) {",
858
			tmp->prec);
859
		fprintf(fd, " uerror(\"%s\"); continue; ",
860
			tmp->prec);
861
		fprintf(fd, "} else { ");
862
		fprintf(fd, "printf(\"pan: precondition false: %s\\n\"); _m = 3; goto P999; } } ",
863
			tmp->prec);
864
	}
865
 
866
	if (!gencode)	/* not in d_step */
867
	{	fprintf(fd, "\n\t\tsv_save();");
868
	}
869
 
870
	fprintf(fd, "%s", (char *) tmp->cn);
871
	fprintf(fd, " }\n");
872
}
873
 
874
void
875
no_side_effects(char *s)
876
{	IType *tmp;
877
	char *t;
878
 
879
	/* could still defeat this check via hidden
880
	 * side effects in function calls,
881
	 * but this will catch at least some cases
882
	 */
883
 
884
	tmp = find_inline(s);
885
	t = (char *) tmp->cn;
886
 
887
	if (strchr(t, ';')
888
	||  strstr(t, "++")
889
	||  strstr(t, "--"))
890
	{
891
bad:		lineno = tmp->dln;
892
		Fname = tmp->dfn;
893
		non_fatal("c_expr %s has side-effects", s);
894
		return;
895
	}
896
	while ((t = strchr(t, '=')) != NULL)
897
	{	if (*(t-1) == '!'
898
		||  *(t-1) == '>'
899
		||  *(t-1) == '<')
900
		{	t++;
901
			continue;
902
		}
903
		t++;
904
		if (*t != '=')
905
			goto bad;
906
		t++;
907
	}
908
}
909
 
910
void
911
pickup_inline(Symbol *t, Lextok *apars)
912
{	IType *tmp; Lextok *p, *q; int j;
913
 
914
	tmp = find_inline(t->name);
915
 
916
	if (++Inlining >= MAXINL)
917
		fatal("inlines nested too deeply", 0);
918
	tmp->cln = lineno;	/* remember calling point */
919
	tmp->cfn = Fname;	/* and filename */
920
 
921
	for (p = apars, q = tmp->params, j = 0; p && q; p = p->rgt, q = q->rgt)
922
		j++; /* count them */
923
	if (p || q)
924
		fatal("wrong nr of params on call of '%s'", t->name);
925
 
926
	tmp->anms  = (char **) emalloc(j * sizeof(char *));
927
	for (p = apars, j = 0; p; p = p->rgt, j++)
928
	{	tmp->anms[j] = (char *) emalloc(strlen(IArg_cont[j])+1);
929
		strcpy(tmp->anms[j], IArg_cont[j]);
930
	}
931
 
932
	lineno = tmp->dln;	/* linenr of def */
933
	Fname = tmp->dfn;	/* filename of same */
934
	Inliner[Inlining] = (char *)tmp->cn;
935
	Inline_stub[Inlining] = tmp;
936
#if 0
937
	if (verbose&32)
938
	printf("spin: %s:%d, inlining '%s' (from %s:%d)\n",
939
		tmp->cfn->name, tmp->cln, t->name, tmp->dfn->name, tmp->dln);
940
#endif
941
	for (j = 0; j < Inlining; j++)
942
		if (Inline_stub[j] == Inline_stub[Inlining])
943
		fatal("cyclic inline attempt on: %s", t->name);
944
}
945
 
946
static void
947
do_directive(int first)
948
{	int c = first;	/* handles lines starting with pound */
949
 
950
	getword(c, isalpha_);
951
 
952
	if (strcmp(yytext, "#ident") == 0)
953
		goto done;
954
 
955
	if ((c = Getchar()) != ' ')
956
		fatal("malformed preprocessor directive - # .", 0);
957
 
958
	if (!isdigit_(c = Getchar()))
959
		fatal("malformed preprocessor directive - # .lineno", 0);
960
 
961
	getword(c, isdigit_);
962
	lineno = atoi(yytext);	/* pickup the line number */
963
 
964
	if ((c = Getchar()) == '\n')
965
		return;	/* no filename */
966
 
967
	if (c != ' ')
968
		fatal("malformed preprocessor directive - .fname", 0);
969
 
970
	if ((c = Getchar()) != '\"')
971
	{	printf("got %c, expected \" -- lineno %d\n", c, lineno);
972
		fatal("malformed preprocessor directive - .fname (%s)", yytext);
973
	}
974
 
975
	getword(Getchar(), notquote);	/* was getword(c, notquote); */
976
	if (Getchar() != '\"')
977
		fatal("malformed preprocessor directive - fname.", 0);
978
 
979
	/* strcat(yytext, "\""); */
980
	Fname = lookup(yytext);
981
done:
982
	while (Getchar() != '\n')
983
		;
984
}
985
 
986
void
987
precondition(char *q)
988
{	int c, nest = 1;
989
 
990
	for (;;)
991
	{	c = Getchar();
992
		*q++ = c;
993
		switch (c) {
994
		case '\n':
995
			lineno++;
996
			break;
997
		case '[':
998
			nest++;
999
			break;
1000
		case ']':
1001
			if (--nest <= 0)
1002
			{	*--q = '\0';
1003
				return;
1004
			}
1005
			break;
1006
		}
1007
	}
1008
	fatal("cannot happen", (char *) 0); /* unreachable */
1009
}
1010
 
1011
 
1012
Symbol *
1013
prep_inline(Symbol *s, Lextok *nms)
1014
{	int c, nest = 1, dln, firstchar, cnr;
1015
	char *p;
1016
	Lextok *t;
1017
	static char Buf1[SOMETHINGBIG], Buf2[RATHERSMALL];
1018
	static int c_code = 1;
1019
 
1020
	for (t = nms; t; t = t->rgt)
1021
		if (t->lft)
1022
		{	if (t->lft->ntyp != NAME)
1023
			fatal("bad param to inline %s", s?s->name:"--");
1024
			t->lft->sym->hidden |= 32;
1025
		}
1026
 
1027
	if (!s)	/* C_Code fragment */
1028
	{	s = (Symbol *) emalloc(sizeof(Symbol));
1029
		s->name = (char *) emalloc(strlen("c_code")+26);
1030
		sprintf(s->name, "c_code%d", c_code++);
1031
		s->context = context;
1032
		s->type = CODE_FRAG;
1033
	} else
1034
		s->type = PREDEF;
1035
 
1036
	p = &Buf1[0];
1037
	Buf2[0] = '\0';
1038
	for (;;)
1039
	{	c = Getchar();
1040
		switch (c) {
1041
		case '[':
1042
			if (s->type != CODE_FRAG)
1043
				goto bad;
1044
			precondition(&Buf2[0]);	/* e.g., c_code [p] { r = p-r; } */
1045
			continue;
1046
		case '{':
1047
			break;
1048
		case '\n':
1049
			lineno++;
1050
			/* fall through */
1051
		case ' ': case '\t': case '\f': case '\r':
1052
			continue;
1053
		default :
1054
			 printf("spin: saw char '%c'\n", c);
1055
bad:			 fatal("bad inline: %s", s->name);
1056
		}
1057
		break;
1058
	}
1059
	dln = lineno;
1060
	if (s->type == CODE_FRAG)
1061
	{	if (verbose&32)
1062
			sprintf(Buf1, "\t/* line %d %s */\n\t\t",
1063
				lineno, Fname->name);
1064
		else
1065
			strcpy(Buf1, "");
1066
	} else
1067
		sprintf(Buf1, "\n#line %d \"%s\"\n{", lineno, Fname->name);
1068
	p += strlen(Buf1);
1069
	firstchar = 1;
1070
 
1071
	cnr = 1; /* not zero */
1072
more:
1073
	c = Getchar();
1074
	*p++ = (char) c;
1075
	if (p - Buf1 >= SOMETHINGBIG)
1076
		fatal("inline text too long", 0);
1077
	switch (c) {
1078
	case '\n':
1079
		lineno++;
1080
		cnr = 0;
1081
		break;
1082
	case '{':
1083
		cnr++;
1084
		nest++;
1085
		break;
1086
	case '}':
1087
		cnr++;
1088
		if (--nest <= 0)
1089
		{	*p = '\0';
1090
			if (s->type == CODE_FRAG)
1091
				*--p = '\0';	/* remove trailing '}' */	
1092
			def_inline(s, dln, &Buf1[0], &Buf2[0], nms);
1093
			if (firstchar)
1094
				printf("%3d: %s, warning: empty inline definition (%s)\n",
1095
					dln, Fname->name, s->name);
1096
			return s;	/* normal return */
1097
		}
1098
		break;
1099
	case '#':
1100
		if (cnr == 0)
1101
		{	p--;
1102
			do_directive(c); /* reads to newline */
1103
		} else
1104
		{	firstchar = 0;
1105
			cnr++;
1106
		}
1107
		break;
1108
	case '\t':
1109
	case ' ':
1110
	case '\f':
1111
		cnr++;
1112
		break;
1113
	default:
1114
		firstchar = 0;
1115
		cnr++;
1116
		break;
1117
	}
1118
	goto more;
1119
}
1120
 
1121
static void
1122
set_cur_scope(void)
1123
{	int i;
1124
	char tmpbuf[256];
1125
 
1126
	strcpy(CurScope, "_");
1127
 
1128
	if (context)
1129
	for (i = 0; i < scope_level; i++)
1130
	{	sprintf(tmpbuf, "%d_", scope_seq[i]);
1131
		strcat(CurScope, tmpbuf);
1132
	}
1133
}
1134
 
1135
static int
1136
lex(void)
1137
{	int c;
1138
 
1139
again:
1140
	c = Getchar();
1141
	yytext[0] = (char) c;
1142
	yytext[1] = '\0';
1143
	switch (c) {
1144
	case EOF:
1145
		return c;
1146
	case '\n':		/* newline */
1147
		lineno++;
1148
	case '\r':		/* carriage return */
1149
		goto again;
1150
 
1151
	case  ' ': case '\t': case '\f':	/* white space */
1152
		goto again;
1153
 
1154
	case '#':		/* preprocessor directive */
1155
		if (in_comment) goto again;
1156
		do_directive(c);
1157
		goto again;
1158
 
1159
	case '\"':
1160
		getword(c, notquote);
1161
		if (Getchar() != '\"')
1162
			fatal("string not terminated", yytext);
1163
		strcat(yytext, "\"");
1164
		SymToken(lookup(yytext), STRING)
1165
 
1166
	case '$':
1167
		getword('\"', notdollar);
1168
		if (Getchar() != '$')
1169
			fatal("ltl definition not terminated", yytext);
1170
		strcat(yytext, "\""); 
1171
		SymToken(lookup(yytext), STRING)
1172
 
1173
	case '\'':	/* new 3.0.9 */
1174
		c = Getchar();
1175
		if (c == '\\')
1176
		{	c = Getchar();
1177
			if (c == 'n') c = '\n';
1178
			else if (c == 'r') c = '\r';
1179
			else if (c == 't') c = '\t';
1180
			else if (c == 'f') c = '\f';
1181
		}
1182
		if (Getchar() != '\'' && !in_comment)
1183
			fatal("character quote missing: %s", yytext);
1184
		ValToken(c, CONST)
1185
 
1186
	default:
1187
		break;
1188
	}
1189
 
1190
	if (isdigit_(c))
1191
	{	getword(c, isdigit_);
1192
		ValToken(atoi(yytext), CONST)
1193
	}
1194
 
1195
	if (isalpha_(c) || c == '_')
1196
	{	getword(c, isalnum_);
1197
		if (!in_comment)
1198
		{	c = check_name(yytext);
1199
			if (c) return c;
1200
			/* else fall through */
1201
		}
1202
		goto again;
1203
	}
1204
 
1205
	if (ltl_mode)
1206
	{	switch (c) {
1207
		case '-': c = follow('>', IMPLIES,    '-'); break;
1208
		case '[': c = follow(']', ALWAYS,     '['); break;
1209
		case '<': c = follow('>', EVENTUALLY, '<');
1210
			  if (c == '<')
1211
			  {	c = Getchar();
1212
				if (c == '-')
1213
				{	c = follow('>', EQUIV, '-');
1214
					if (c == '-')
1215
					{	Ungetch(c);
1216
						c = '<';
1217
					}
1218
				} else
1219
				{	Ungetch(c);
1220
					c = '<';
1221
			  }	}
1222
		default:  break;
1223
	}	}
1224
 
1225
	switch (c) {
1226
	case '/': c = follow('*', 0, '/');
1227
		  if (!c) { in_comment = 1; goto again; }
1228
		  break;
1229
	case '*': c = follow('/', 0, '*');
1230
		  if (!c) { in_comment = 0; goto again; }
1231
		  break;
1232
	case ':': c = follow(':', SEP, ':'); break;
1233
	case '-': c = follow('>', SEMI, follow('-', DECR, '-')); break;
1234
	case '+': c = follow('+', INCR, '+'); break;
1235
	case '<': c = follow('<', LSHIFT, follow('=', LE, LT)); break;
1236
	case '>': c = follow('>', RSHIFT, follow('=', GE, GT)); break;
1237
	case '=': c = follow('=', EQ, ASGN); break;
1238
	case '!': c = follow('=', NE, follow('!', O_SND, SND)); break;
1239
	case '?': c = follow('?', R_RCV, RCV); break;
1240
	case '&': c = follow('&', AND, '&'); break;
1241
	case '|': c = follow('|', OR, '|'); break;
1242
	case ';': c = SEMI; break;
1243
	case '.': c = follow('.', DOTDOT, '.'); break;
1244
	case '{': scope_seq[scope_level++]++; set_cur_scope(); break;
1245
	case '}': scope_level--; set_cur_scope(); break;
1246
	default : break;
1247
	}
1248
	Token(c)
1249
}
1250
 
1251
static struct {
1252
	char *s;	int tok;
1253
} LTL_syms[] = {
1254
	/* [], <>, ->, and <-> are intercepted in lex() */
1255
	{ "U",		UNTIL   },
1256
	{ "V",		RELEASE },
1257
	{ "W",		WEAK_UNTIL },
1258
	{ "X",		NEXT    },
1259
	{ "always",	ALWAYS  },
1260
	{ "eventually",	EVENTUALLY },
1261
	{ "until",	UNTIL   },
1262
	{ "stronguntil",UNTIL   },
1263
	{ "weakuntil",	WEAK_UNTIL   },
1264
	{ "release",	RELEASE },
1265
	{ "next",	NEXT    },
1266
	{ "implies",	IMPLIES },
1267
	{ "equivalent",	EQUIV   },
1268
	{ 0, 		0       },
1269
};
1270
 
1271
static struct {
1272
	char *s;	int tok;	int val;	char *sym;
1273
} Names[] = {
1274
	{"active",	ACTIVE,		0,		0},
1275
	{"assert",	ASSERT,		0,		0},
1276
	{"atomic",	ATOMIC,		0,		0},
1277
	{"bit",		TYPE,		BIT,		0},
1278
	{"bool",	TYPE,		BIT,		0},
1279
	{"break",	BREAK,		0,		0},
1280
	{"byte",	TYPE,		BYTE,		0},
1281
	{"c_code",	C_CODE,		0,		0},
1282
	{"c_decl",	C_DECL,		0,		0},
1283
	{"c_expr",	C_EXPR,		0,		0},
1284
	{"c_state",	C_STATE,	0,		0},
1285
	{"c_track",	C_TRACK,	0,		0},
1286
	{"D_proctype",	D_PROCTYPE,	0,		0},
1287
	{"do",		DO,		0,		0},
1288
	{"chan",	TYPE,		CHAN,		0},
1289
	{"else", 	ELSE,		0,		0},
1290
	{"empty",	EMPTY,		0,		0},
1291
	{"enabled",	ENABLED,	0,		0},
1292
	{"eval",	EVAL,		0,		0},
1293
	{"false",	CONST,		0,		0},
1294
	{"fi",		FI,		0,		0},
1295
	{"for",		FOR,		0,		0},
1296
	{"full",	FULL,		0,		0},
1297
	{"goto",	GOTO,		0,		0},
1298
	{"hidden",	HIDDEN,		0,		":hide:"},
1299
	{"if",		IF,		0,		0},
1300
	{"in",		IN,		0,		0},
1301
	{"init",	INIT,		0,		":init:"},
1302
	{"inline",	INLINE,		0,		0},
1303
	{"int",		TYPE,		INT,		0},
1304
	{"len",		LEN,		0,		0},
1305
	{"local",	ISLOCAL,	0,		":local:"},
1306
	{"ltl",		LTL,		0,		":ltl:"},
1307
	{"mtype",	TYPE,		MTYPE,		0},
1308
	{"nempty",	NEMPTY,		0,		0},
1309
	{"never",	CLAIM,		0,		":never:"},
1310
	{"nfull",	NFULL,		0,		0},
1311
	{"notrace",	TRACE,		0,		":notrace:"},
1312
	{"np_",		NONPROGRESS,	0,		0},
1313
	{"od",		OD,		0,		0},
1314
	{"of",		OF,		0,		0},
1315
	{"pc_value",	PC_VAL,		0,		0},
1316
	{"pid",		TYPE,		BYTE,		0},
1317
	{"printf",	PRINT,		0,		0},
1318
	{"printm",	PRINTM,		0,		0},
1319
	{"priority",	PRIORITY,	0,		0},
1320
	{"proctype",	PROCTYPE,	0,		0},
1321
	{"provided",	PROVIDED,	0,		0},
1322
	{"run",		RUN,		0,		0},
1323
	{"d_step",	D_STEP,		0,		0},
1324
	{"select",	SELECT,		0,	0},
1325
	{"short",	TYPE,		SHORT,		0},
1326
	{"skip",	CONST,		1,		0},
1327
	{"timeout",	TIMEOUT,	0,		0},
1328
	{"trace",	TRACE,		0,		":trace:"},
1329
	{"true",	CONST,		1,		0},
1330
	{"show",	SHOW,		0,		":show:"},
1331
	{"typedef",	TYPEDEF,	0,		0},
1332
	{"unless",	UNLESS,		0,		0},
1333
	{"unsigned",	TYPE,		UNSIGNED,	0},
1334
	{"xr",		XU,		XR,		0},
1335
	{"xs",		XU,		XS,		0},
1336
	{0, 		0,		0,		0},
1337
};
1338
 
1339
static int
1340
check_name(char *s)
1341
{	int i;
1342
 
1343
	yylval = nn(ZN, 0, ZN, ZN);
1344
 
1345
	if (ltl_mode)
1346
	{	for (i = 0; LTL_syms[i].s; i++)
1347
		{	if (strcmp(s, LTL_syms[i].s) == 0)
1348
			{	return LTL_syms[i].tok;
1349
	}	}	}
1350
 
1351
	for (i = 0; Names[i].s; i++)
1352
	{	if (strcmp(s, Names[i].s) == 0)
1353
		{	yylval->val = Names[i].val;
1354
			if (Names[i].sym)
1355
				yylval->sym = lookup(Names[i].sym);
1356
			return Names[i].tok;
1357
	}	}
1358
 
1359
	if ((yylval->val = ismtype(s)) != 0)
1360
	{	yylval->ismtyp = 1;
1361
		return CONST;
1362
	}
1363
 
1364
	if (strcmp(s, "_last") == 0)
1365
		has_last++;
1366
 
1367
	if (Inlining >= 0 && !ReDiRect)
1368
	{	Lextok *tt, *t = Inline_stub[Inlining]->params;
1369
 
1370
		for (i = 0; t; t = t->rgt, i++)				/* formal pars */
1371
		 if (!strcmp(s, t->lft->sym->name)			/* varname matches formal */
1372
		 &&   strcmp(s, Inline_stub[Inlining]->anms[i]) != 0)	/* actual pars */
1373
		 {
1374
#if 0
1375
			if (verbose&32)
1376
			printf("\tline %d, replace %s in call of '%s' with %s\n",
1377
				lineno, s,
1378
				Inline_stub[Inlining]->nm->name,
1379
				Inline_stub[Inlining]->anms[i]);
1380
#endif
1381
			for (tt = Inline_stub[Inlining]->params; tt; tt = tt->rgt)
1382
				if (!strcmp(Inline_stub[Inlining]->anms[i],
1383
					tt->lft->sym->name))
1384
				{	/* would be cyclic if not caught */
1385
					printf("spin: %s:%d replacement value: %s\n",
1386
						oFname->name?oFname->name:"--", lineno, tt->lft->sym->name);
1387
					fatal("formal par of %s contains replacement value",
1388
						Inline_stub[Inlining]->nm->name);
1389
					yylval->ntyp = tt->lft->ntyp;
1390
					yylval->sym = lookup(tt->lft->sym->name);
1391
					return NAME;
1392
				}
1393
 
1394
			/* check for occurrence of param as field of struct */
1395
			{ char *ptr = Inline_stub[Inlining]->anms[i];
1396
				while ((ptr = strstr(ptr, s)) != NULL)
1397
				{	if (*(ptr-1) == '.'
1398
					||  *(ptr+strlen(s)) == '.')
1399
					{	fatal("formal par of %s used in structure name",
1400
						Inline_stub[Inlining]->nm->name);
1401
					}
1402
					ptr++;
1403
			}	}
1404
			ReDiRect = Inline_stub[Inlining]->anms[i];
1405
			return 0;
1406
	}	 }
1407
 
1408
	yylval->sym = lookup(s);	/* symbol table */
1409
	if (isutype(s))
1410
		return UNAME;
1411
	if (isproctype(s))
1412
		return PNAME;
1413
	if (iseqname(s))
1414
		return INAME;
1415
 
1416
	return NAME;
1417
}
1418
 
1419
int
1420
yylex(void)
1421
{	static int last = 0;
1422
	static int hold = 0;
1423
	int c;
1424
	/*
1425
	 * repair two common syntax mistakes with
1426
	 * semi-colons before or after a '}'
1427
	 */
1428
	if (hold)
1429
	{	c = hold;
1430
		hold = 0;
1431
	} else
1432
	{	c = lex();
1433
		if (last == ELSE
1434
		&&  c != SEMI
1435
		&&  c != FI)
1436
		{	hold = c;
1437
			last = 0;
1438
			return SEMI;
1439
		}
1440
		if (last == '}'
1441
		&&  c != PROCTYPE
1442
		&&  c != INIT
1443
		&&  c != CLAIM
1444
		&&  c != SEP
1445
		&&  c != FI
1446
		&&  c != OD
1447
		&&  c != '}'
1448
		&&  c != UNLESS
1449
		&&  c != SEMI
1450
		&&  c != EOF)
1451
		{	hold = c;
1452
			last = 0;
1453
			return SEMI;	/* insert ';' */
1454
		}
1455
		if (c == SEMI)
1456
		{	/* if context, we're not in a typedef
1457
			 * because they're global.
1458
			 * if owner, we're at the end of a ref
1459
			 * to a struct field -- prevent that the
1460
			 * lookahead is interpreted as a field of
1461
			 * the same struct...
1462
			 */
1463
			if (context) owner = ZS;
1464
			hold = lex();	/* look ahead */
1465
			if (hold == '}'
1466
			||  hold == SEMI)
1467
			{	c = hold; /* omit ';' */
1468
				hold = 0;
1469
			}
1470
		}
1471
	}
1472
	last = c;
1473
 
1474
	if (IArgs)
1475
	{	static int IArg_nst = 0;
1476
 
1477
		if (strcmp(yytext, ",") == 0)
1478
		{	IArg_cont[++IArgno][0] = '\0';
1479
		} else if (strcmp(yytext, "(") == 0)
1480
		{	if (IArg_nst++ == 0)
1481
			{	IArgno = 0;
1482
				IArg_cont[0][0] = '\0';
1483
			} else
1484
				strcat(IArg_cont[IArgno], yytext);
1485
		} else if (strcmp(yytext, ")") == 0)
1486
		{	if (--IArg_nst > 0)
1487
				strcat(IArg_cont[IArgno], yytext);
1488
		} else if (c == CONST && yytext[0] == '\'')
1489
		{	sprintf(yytext, "'%c'", yylval->val);
1490
			strcat(IArg_cont[IArgno], yytext);
1491
		} else if (c == CONST)
1492
		{	sprintf(yytext, "%d", yylval->val);
1493
			strcat(IArg_cont[IArgno], yytext);
1494
		} else
1495
		{
1496
			switch (c) {
1497
			case SEP:	strcpy(yytext, "::"); break;
1498
			case SEMI:	strcpy(yytext, ";"); break;
1499
			case DECR:	strcpy(yytext, "--"); break;
1500
			case INCR: 	strcpy(yytext, "++"); break;
1501
			case LSHIFT:	strcpy(yytext, "<<"); break;
1502
			case RSHIFT:	strcpy(yytext, ">>"); break;
1503
			case LE:	strcpy(yytext, "<="); break;
1504
			case LT:	strcpy(yytext, "<"); break;
1505
			case GE:	strcpy(yytext, ">="); break;
1506
			case GT:	strcpy(yytext, ">"); break;
1507
			case EQ:	strcpy(yytext, "=="); break;
1508
			case ASGN:	strcpy(yytext, "="); break;
1509
			case NE:	strcpy(yytext, "!="); break;
1510
			case R_RCV:	strcpy(yytext, "??"); break;
1511
			case RCV:	strcpy(yytext, "?"); break;
1512
			case O_SND:	strcpy(yytext, "!!"); break;
1513
			case SND:	strcpy(yytext, "!"); break;
1514
			case AND: 	strcpy(yytext, "&&"); break;
1515
			case OR:	strcpy(yytext, "||"); break;
1516
			}
1517
			strcat(IArg_cont[IArgno], yytext);
1518
		}
1519
	}
1520
	return c;
1521
}