|
|
1.1 root 1: %{
2: #include <stdio.h>
3: #include "pret.h"
4: #include "pret.d"
5:
6: #define YYDEBUG 1
7:
8: struct Node {
9: int ntyp; /* OP ~ nval&left&right, NM ~ val */
10: int nval;
11: struct Node *left, *right;
12: };
13:
14: extern struct Node *newnode();
15:
16: struct PARS {
17: int home;
18: int dest;
19: int bpnt;
20: } ties[MAXDEPTH];
21:
22: FILE *tb; /* temp file to store tables */
23:
24: char procname[MAXNAME], refname[MAXNAME], qsetname[MAXNAME];
25: char str[256], filename[256];
26: char strings[MANY][MAXNAME];
27: extern char yytext[];
28: extern struct QTABLE qtable[NQUEUES];
29: extern int varwidths;
30: int nnames = 0;
31: int linenumber = 1;
32: int linecode = 0; /* include source code references */
33: int nest = 0; /* nesting level of comments (lex) */
34: int anyerror = 0;
35:
36: int pid = NONE; /* process number */
37: int qid = NONE; /* queue number */
38: int rid = NONE; /* template number when defined */
39: int sid = NONE; /* qset number */
40: int nid = NONE; /* template number when refered */
41: int cid = NONE; /* index in call table */
42: int qind, qisz; /* queue's initial string size */
43: int parnum; /* counts actual parameters */
44: int assertion = -1; /* id of assertion table, if any */
45: int inertion = -1; /* id of error table, if any */
46: int vartype, inside;
47: int n, m, from, xx, zz;
48: int soo = 0; /* start of optionlist */
49: int curstate = 0;
50: int curdepth = 0;
51: int lastloop = -1;
52:
53: int verbose = 0;
54: int nopurge = 0;
55:
56: checknames()
57: {
58: checkrefs();
59: checkglobvars();
60: checkqs();
61: }
62:
63: putglobals(fd)
64: FILE *fd;
65: {
66: numrefs(fd);
67: numprocs(fd);
68: numsorts(fd);
69: numinits(fd);
70: numglobvars(fd);
71: }
72:
73: puttables(fd1)
74: FILE *fd1;
75: { FILE *fd2;
76: char buffer[MANY];
77: int howmuch;
78:
79: if ((fd2 = fopen("pret.tmp", "r")) == NULL)
80: whoops("cannot find pret.tmp");
81:
82: while ((howmuch = fread(buffer, sizeof(*buffer), MANY, fd2)) > 0)
83: fwrite(buffer, sizeof(*buffer), howmuch, fd1);
84:
85: fclose(fd2);
86: unlink("pret.tmp");
87: }
88:
89: makebin()
90: { FILE *fd;
91:
92: if ((fd = fopen((anyerror)?"pret.err":"pret.out", "w")) == NULL)
93: whoops("cannot create output file");
94:
95: putglobals(fd);
96: puttables(fd);
97: numexps(fd);
98: fclose(fd);
99: if (anyerror)
100: fprintf(stderr, "output written to `pret.err'\n");
101: }
102:
103: transfer(cl, tg)
104: { int i = curstate;
105: curstate = enterowname(NEW, "", DAR);
106: setrans(i, cl, curstate, tg);
107: }
108:
109: #include "pret.expr.c"
110:
111: %}
112: %union{
113: int resu;
114: struct Node *node;
115: }
116:
117: %type <resu> PREIO INDEX QINDEX IMPORT ASGN ASGN
118: %type <node> expr VARNAME
119: %token <resu> NAME VALUE ARNAME QSNAME
120:
121: %start PROT_SPEC
122: %token ASSERT ERROR
123: %token PROCESS PBEGIN END IF FI DO OD
124: %token timeout skip BREAK DEFAULT GOTO
125: %token FLAG ARROW SEMICOLON COLON
126: %token QUEUES QSET PVAR MESG
127: %right '=' ADDEQ SUBEQ MULEQ DIVEQ MODEQ
128: %left OR
129: %left AND
130: %left GT GE LT LE EQ NE
131: %left '+' '-'
132: %left '*' '/' '%'
133: %left UNARYMINUS NOT INC DEC
134: %right '^'
135:
136: %%
137:
138: PROT_SPEC : ONEMODULE
139: | PROT_SPEC ONEMODULE
140: ;
141:
142: ONEMODULE : PROC_SPEC
143: | TASK_SPEC
144: | ONEDECL
145: | REQUIREMENT
146: ;
147:
148: PROC_SPEC : PROCESS NAME QINDEX
149: { strcpy(procname, strings[$2]);
150: pid = newprocname(strings[$2], $3);
151: }
152: PBEGIN ANYDECLS
153: { extern int extras;
154: int ival;
155: curstate = enterowname(NEW, "", DAR);
156: newcalltable();
157: ival = 3*MANY+pid+extras;
158: addvarname("_PROCID", (DCL|RFR), ival, NONE, 0);
159: }
160: SEQUENCE END
161: { wrapup(NONE, pid, tb, nopurge, verbose);
162: pid = NONE;
163: strcpy(procname, "_");
164: }
165: ;
166:
167: ANYDECLS : /* empty */
168: | DECLS
169: ;
170: DECLS : ONEDECL
171: | DECLS ONEDECL
172: ;
173:
174: ONEDECL : QDECLS
175: | VARDECLS
176: ;
177: /*
178: * QUEUES
179: * ======
180: */
181:
182: QDECLS : QUEUES QDECL SEPARATOR
183: ;
184: QDECL : ONEQ
185: | QNAMELIST
186: ;
187:
188: ONEQ : NAME QINDEX '='
189: { if ($2 == NONE || (qisz=$2) <= 0)
190: yyerror("illegal queue size, %s", strings[$1]);
191: qid = newqname(strings[$1], DCL, qisz, NONE);
192: }
193: PBEGIN MNAMELIST END
194: ;
195:
196: /*
197: * VARIABLES and QUEUESETS
198: * =======================
199: */
200:
201: VARDECLS : PVAR VNAMELIST SEPARATOR
202: | QSET QSETDECL SEPARATOR
203: ;
204:
205: QINDEX : /* empty */ { $$ = NONE; }
206: | '[' VALUE ']' { $$ = $2; }
207: ;
208:
209: QSETDECL : NAME PBEGIN NAME QINDEX COLON
210: { xx = newqname(strings[$3], RFR, NONE, $4);
211: sid = newqset(strings[$1], strings[$3], DCL, $4);
212: }
213: SNAMELIST END
214: { closeqset(sid);
215: }
216: ;
217: /*
218: * PROCEDURES
219: * ==========
220: */
221:
222: TASK_SPEC : NAME
223: { rid = newreftask(strings[$1], DCL);
224: curstate = enterowname(NEW, "", DAR);
225: strcpy(refname, strings[$1]);
226: newcalltable();
227: vartype = ISV;
228: inside = 1;
229: }
230: '(' ANYPARAMS ')'
231: { inside = 0;
232: }
233: ANYPARTYPES
234: { reorder(); /* renumber formal parameters */
235: }
236: PBEGIN
237: ANYDECLS
238: SEQUENCE
239: END
240: { wrapup(rid, NONE, tb, nopurge, verbose);
241: strcpy(refname, "_");
242: rid = NONE;
243: }
244: ;
245:
246: ANYPARAMS : /* empty */
247: | PNAMELIST
248: | error
249: { yyerror("bad namelist", "");
250: }
251:
252: ;
253:
254: ANYPARTYPES : /* empty */
255: | PARTYPES
256: | error
257: { yyerror("bad parameterlist", "");
258: }
259: ;
260:
261: PARTYPES : ONEPARTYPE SEMICOLON
262: | PARTYPES ONEPARTYPE SEMICOLON
263: ;
264: ONEPARTYPE : PVAR
265: { vartype = ISV;
266: }
267: PNAMELIST
268: | QSET NAME PBEGIN NAME COLON
269: { strcpy(qsetname, strings[$2]);
270: sid = newqset(strings[$2], strings[$4], DCL, NONE);
271: qid = addFpar(rid, strings[$2], sid, ISQ, inside);
272: vartype = ISM;
273: }
274: PNAMELIST END
275: { qid = NONE;
276: closeqset(sid);
277: }
278: ;
279: /*
280: * REQUIREMENTS
281: * ============
282: */
283: REQUIREMENT : ASSERT
284: PBEGIN
285: { rid = newreftask(" assert", DCL);
286: assertion = rid;
287: curstate = enterowname(NEW, "", DAR);
288: strcpy(refname, " assert");
289: newcalltable();
290: }
291: _SEQUENCE
292: END
293: { wrapup(rid, NONE, tb, nopurge, verbose);
294: strcpy(refname, "_");
295: rid = NONE;
296: lastloop = -1;
297: }
298: | ERROR
299: PBEGIN
300: { rid = newreftask(" error", DCL);
301: inertion = rid;
302: curstate = enterowname(NEW, "", DAR);
303: strcpy(refname, " error");
304: newcalltable();
305: }
306: _SEQUENCE
307: END
308: { wrapup(rid, NONE, tb, nopurge, verbose);
309: strcpy(refname, "_");
310: rid = NONE;
311: lastloop = -1;
312: }
313: ;
314: _SEQUENCE : _STMNT
315: | _SEQUENCE SEPARATOR _STMNT
316: ;
317:
318: _STMNT : skip { lastloop = -1; }
319: | _SELECT { lastloop = -1; }
320: | _CYCLE
321: | SEND { lastloop = -1; }
322: | GUARD { lastloop = -1; }
323: | STRUCTGOTO { lastloop = -1; }
324: | error
325: { yyerror("illegal assertion statement, %s", yytext);
326: }
327: ;
328: _SELECT : IF
329: { if (++curdepth == MAXDEPTH)
330: whoops("nesting too deep");
331:
332: ties[curdepth].home = curstate;
333: ties[curdepth].dest = enterowname(NEW, "", DAR);
334: ties[curdepth].bpnt =
335: (curdepth > 1) ? ties[curdepth-1].bpnt : -1;
336: }
337: _OPTIONLIST FI
338: { setrowname(ties[curdepth].dest);
339: curstate = ties[curdepth--].dest;
340: }
341: ;
342:
343: _CYCLE : DO
344: { if (curdepth++ == MAXDEPTH)
345: whoops("nesting too deep");
346:
347: labelrow(curstate);
348: ties[curdepth].home = curstate;
349: ties[curdepth].dest = curstate;
350: ties[curdepth].bpnt = enterowname(NEW, "", DAR);
351: }
352: _OPTIONLIST OD
353: { lastloop = ties[curdepth].home;
354: setrowname(ties[curdepth].bpnt);
355: curstate = ties[curdepth--].bpnt;
356: }
357: ;
358: _OPTIONLIST : _ONEOPTION
359: | _ONEOPTION _OPTIONLIST
360: ;
361:
362: _ONEOPTION : FLAG _SEQUENCE
363: { getrowname(str, ties[curdepth].dest);
364: from = curstate;
365: curstate = enterowname(OLD, str, DAR);
366: setrans(from, 0, curstate, NONE);
367: curstate = ties[curdepth].home;
368: }
369: ;
370: /*
371: * NAMELISTS
372: * =========
373: */
374:
375: ANAMELIST : ANAME
376: | ANAMELIST ',' ANAME
377: ;
378: MNAMELIST : MNAME
379: | MNAMELIST ',' MNAME
380: ;
381: PNAMELIST : PNAME
382: | PNAMELIST ',' PNAME
383: ;
384: QNAMELIST : QNAME
385: | QNAMELIST ',' QNAME
386: ;
387: SNAMELIST : SNAME
388: | SNAMELIST ',' SNAME
389: ;
390: VNAMELIST : VNAME
391: | VNAMELIST ',' VNAME
392: ;
393: /*
394: * NAMES
395: * =====
396: */
397:
398: ANAME : QSNAME { addApars(strings[$1], nid, parnum++, NONE); }
399: | expr { addAspecial(makeexpr($1), nid, parnum++); }
400: ;
401: MNAME : NAME
402: { qtable[qid].status |= ADR;
403: addmsg(strings[$1], qid, SND, INITM, NONE);
404: if (--qisz < 0)
405: yyerror("queue overfilled, %s", strings[$1]);
406: }
407: ;
408: PNAME : NAME
409: { if (vartype == ISM)
410: addsetname(strings[$1], sid, 1);
411: else
412: addFpar(rid, strings[$1], qid, vartype, inside);
413: }
414: ;
415: QNAME : NAME '[' VALUE ']'
416: { if ((qisz = $3) <= 0)
417: yyerror("illegal queue size, %s", strings[$1]);
418: newqname(strings[$1], DCL, $3, NONE);
419: }
420: | NAME '[' VALUE ']' '[' VALUE ']'
421: { if ((qisz = $6) <= 0)
422: yyerror("illegal queue size, %s", strings[$1]);
423: newqname(strings[$1], DCL, qisz, $3);
424: }
425: ;
426: SNAME : NAME { addsetname(strings[$1], sid, 0); }
427: ;
428: VNAME : NAME QINDEX
429: { addvarname(strings[$1], DCL, NONE, $2, 0);
430: }
431: | NAME QINDEX '=' expr
432: { addvarname(strings[$1], DCL, makeexpr($4), $2, 0);
433: }
434: | NAME QINDEX COLON VALUE
435: { addvarname(strings[$1], DCL, NONE, $2, $4);
436: }
437: ;
438: /*
439: * CODE
440: * ====
441: */
442:
443: SEQUENCE : STMNT
444: { soo = 0;
445: }
446: | SEQUENCE SEPARATOR STMNT
447: { soo = 0;
448: }
449: ;
450:
451: STMNT : skip
452: { if (soo) /* only if used as a guard */
453: transfer(0, NONE);
454: }
455: | SELECT
456: | CYCLE
457: | SEND
458: | GUARD
459: | JUMP
460: | LABEL STMNT
461: | TEMPLATE
462: | BUILTIN
463: | CONDITIONAL
464: | END
465: { yyerror("expecting a statement", "");
466: whoops("exit");
467: }
468: ;
469:
470: SELECT : IF
471: { if (++curdepth == MAXDEPTH)
472: whoops("nesting too deep");
473:
474: ties[curdepth].home = curstate;
475: ties[curdepth].dest = enterowname(NEW, "", DAR);
476: ties[curdepth].bpnt =
477: (curdepth>1) ? ties[curdepth-1].bpnt : -1;
478: }
479: OPTIONLIST FI
480: { setrowname(ties[curdepth].dest);
481: curstate = ties[curdepth--].dest;
482: }
483: ;
484:
485: CYCLE : DO
486: { if (curdepth++ == MAXDEPTH)
487: whoops("nesting too deep");
488:
489: labelrow(curstate);
490: ties[curdepth].home = curstate;
491: ties[curdepth].dest = curstate;
492: ties[curdepth].bpnt = enterowname(NEW, "", DAR);
493: }
494: OPTIONLIST OD
495: { setrowname(ties[curdepth].bpnt);
496: curstate = ties[curdepth--].bpnt;
497: }
498: ;
499:
500: OPTIONLIST : ONEOPTION
501: | ONEOPTION OPTIONLIST
502: ;
503:
504: ONEOPTION : FLAG
505: { soo = 1; /* start of an option string */
506: }
507: SEQUENCE
508: { getrowname(str, ties[curdepth].dest);
509: from = curstate;
510: curstate = enterowname(OLD, str, DAR);
511: setrans(from, 0, curstate, NONE);
512: curstate = ties[curdepth].home;
513: }
514: ;
515:
516: INDEX : /* empty */ { $$ = NONE; }
517: | '[' expr ']' { $$ = makeexpr($2); }
518: ;
519:
520: PREIO : NAME INDEX
521: { strcpy(str, strings[$1]); /* swivel away name */
522: $$ = $2;
523: }
524: ;
525:
526: SEND : PREIO NOT NAME EXPORT
527: { xx = newqname(str, ADR, NONE, $1);
528: zz = addmsg(strings[$3], xx, SND, NORM, $1);
529: n = entercolname(zz, OUTP);
530: transfer(n, m);
531: }
532: ;
533:
534: EXPORT : /* empty */ { m = NONE; }
535: | '(' expr ')' { m = makeexpr($2); }
536: ;
537:
538: GUARD : PREIO '?' timeout
539: { int x;
540: xx = newqname(str, RFR, NONE, $1);
541: x = addmsg(" tau", xx, SAR, NORM, $1);
542: /*
543: ** the leading space is to avoid
544: ** clashes with a user name `tau',
545: ** e.g. in a formal parameter list
546: */
547: n = entercolname(x, TMO);
548: transfer(n, NONE);
549: }
550: | PREIO '?' NAME IMPORT
551: { xx = newqname(str, RFR, NONE, $1);
552: zz = addmsg(strings[$3], xx, RCV, NORM, $1);
553: n = entercolname(zz, INP);
554: transfer(n, $4);
555: }
556: | PREIO '?' DEFAULT IMPORT
557: { xx = newqname(str, RFR, NONE, $1);
558: zz = addmsg(" any", xx, SAR, NORM, $1);
559: n = entercolname(zz, DFL);
560: transfer(n, $4);
561: }
562: ;
563:
564: IMPORT : /* empty */
565: { $$ = NONE;
566: }
567: | '(' ARNAME INDEX ')'
568: { $$ = addvarname(strings[$2], RFR, NONE, $3, 0);
569: }
570: | '(' NAME ')'
571: { $$ = addvarname(strings[$2], RFR, NONE, NONE, 0);
572: }
573: | '(' VALUE ')'
574: { yyerror("importing into constant", "");
575: }
576: ;
577:
578: SEPARATOR : ARROW
579: | SEMICOLON
580: | error
581: { yyerror("expecting a stmnt separator", "");
582: }
583: ;
584:
585: JUMP : GOTO NAME
586: { from = curstate;
587: curstate = enterowname(LAB, strings[$2], ADR);
588: setrans(from, 0, curstate, NONE);
589: curstate = enterowname(NEW, "", DAR);
590: }
591: | STRUCTGOTO
592: ;
593:
594: STRUCTGOTO : BREAK
595: { int i;
596: from = curstate;
597: i = ties[curdepth].bpnt;
598:
599: if (curdepth == 0 || i == -1)
600: whoops("illegal break statement");
601:
602: getrowname(str, i);
603: curstate = enterowname(OLD, str, DAR);
604: setrans(from, 0, curstate, NONE);
605: curstate = enterowname(NEW, "", DAR);
606: }
607: ;
608:
609: TEMPLATE : NAME
610: { nid = newreftask(strings[$1], RFR);
611: parnum = 0; qid = sid = NONE;
612: cid = newcall(nid);
613: }
614: '(' ANYACTUALS ')'
615: { int x;
616: parrefs(parnum, nid);
617: x = entercolname(cid, FCT);
618: transfer(x, NONE);
619: }
620: ;
621:
622: ANYACTUALS : /* empty */
623: | ANAMELIST
624: ;
625:
626: CONDITIONAL : '(' expr ')'
627: { transfer(entercolname(makeexpr($2), CND), NONE);
628: }
629: ;
630:
631: VARNAME : ARNAME INDEX
632: { m = addvarname(strings[$1], RFR, NONE, $2, 0);
633: $$ = newnode(NM, m, NULL, NULL);
634: }
635: | NAME
636: { m = addvarname(strings[$1], RFR, NONE, NONE, 0);
637: $$ = newnode(NM, m, NULL, NULL);
638: }
639: ;
640:
641: BUILTIN : VARNAME ASGN expr
642: { m = makeexpr(newnode(OP, $2, $1, $3));
643: transfer(0, m);
644: }
645: | VARNAME INC
646: { m = makeexpr(newnode(OP, poinc, $1, NULL));
647: transfer(0, m);
648: }
649: | VARNAME DEC
650: { m = makeexpr(newnode(OP, podec, $1, NULL));
651: transfer(0, m);
652: }
653: ;
654:
655: ASGN : '=' { $$ = setv; }
656: | ADDEQ { $$ = addeq; }
657: | SUBEQ { $$ = subeq; }
658: | MULEQ { $$ = muleq; }
659: | DIVEQ { $$ = diveq; }
660: | MODEQ { $$ = modeq; }
661: ;
662:
663: expr : expr '+' expr { $$ = newnode(OP, plus, $1, $3); }
664: | expr '-' expr { $$ = newnode(OP, minus, $1, $3); }
665: | expr '*' expr { $$ = newnode(OP, times, $1, $3); }
666: | expr '/' expr { $$ = newnode(OP, div, $1, $3); }
667: | expr '%' expr { $$ = newnode(OP, mod, $1, $3); }
668: | expr '^' expr { $$ = newnode(OP, power, $1, $3); }
669: | expr GT expr { $$ = newnode(OP, gt, $1, $3); }
670: | expr GE expr { $$ = newnode(OP, ge, $1, $3); }
671: | expr LT expr { $$ = newnode(OP, lt, $1, $3); }
672: | expr LE expr { $$ = newnode(OP, le, $1, $3); }
673: | expr EQ expr { $$ = newnode(OP, eq, $1, $3); }
674: | expr NE expr { $$ = newnode(OP, ne, $1, $3); }
675: | expr AND expr { $$ = newnode(OP, land, $1, $3); }
676: | expr OR expr { $$ = newnode(OP, lor, $1, $3); }
677: | '-' expr %prec UNARYMINUS
678: { $$ = newnode(OP, uminus, $2, NULL); }
679: | NOT expr
680: { $$ = newnode(OP, lnot, $2, NULL); }
681: | VALUE
682: { $$ = newnode(NM, $1+3*MANY, NULL, NULL); }
683: | ARNAME INDEX
684: { m = addvarname(strings[$1], RFR, NONE, $2, 0);
685: $$ = newnode(NM, m, NULL, NULL);
686: }
687: | NAME
688: { m = addvarname(strings[$1], RFR, NONE, NONE, 0);
689: $$ = newnode(NM, m, NULL, NULL);
690: }
691: | '(' expr ')' { $$ = $2; }
692: ;
693:
694: LABEL : NAME COLON
695: { from = curstate;
696: curstate = enterowname(LAB, strings[$1], DCL);
697: labelrow(curstate);
698: setrans(from, 0, curstate, NONE);
699: }
700: ;
701: %%
702:
703: extern FILE *yyin;
704:
705: main(argc, argv)
706: char **argv;
707: {
708: int base = 1, i = 1;
709: char c, buff[256];
710: char outfile[32];
711:
712: if (argc > base && argv[1][0] == '-')
713: { while ((c = argv[1][i++]) != '\0')
714: switch (c) {
715: case 's': varwidths = 1; break;
716: case 'v': verbose = 1; break;
717: case 'n': nopurge = 1; break;
718: case 'l': linecode = 1; break;
719: default : fprintf(stderr, "usage: pret [-vsnl] file\n");
720: fprintf(stderr, "\tv - verbose\n");
721: fprintf(stderr, "\ts - supertrace format\n");
722: fprintf(stderr, "\tn - no minimization\n");
723: fprintf(stderr, "\tl - enables linecode\n");
724: exit(1);
725: }
726: base++;
727: }
728: if (argc <= base)
729: { fprintf(stderr, "usage: pret [-vnl] file\n");
730: exit(1);
731:
732: }
733: if ((tb = fopen("pret.tmp", "w")) == NULL)
734: whoops("cannot create pret.tmp\n");
735:
736: strcpy(procname, "_");
737: strcpy(refname, "_");
738: unlink("pret.out");
739: unlink("pret.err");
740:
741: if (argc > base)
742: { strcpy(filename, argv[base]);
743:
744: mktemp(strcpy(outfile, "/tmp/trans.XXXXXX"));
745: sprintf(buff, "/lib/cpp %s > %s", filename, outfile);
746:
747: if (system(buff))
748: { unlink(outfile);
749: exit(1);
750: } else
751: if ((yyin = fopen(outfile, "r")) == NULL)
752: { printf("cannot open %s\n", outfile);
753: whoops("aborting");
754: }
755: unlink(outfile);
756: }
757: parsed = (struct REVPOL *)
758: Emalloc(EXPRMAX * sizeof(struct REVPOL));
759: prs = 0;
760:
761: yyparse();
762: prepsorts();
763: checknames();
764: fclose(tb);
765: chatter();
766: makebin();
767: exit(0);
768: }
769:
770: newstring(str)
771: char *str;
772: { register int i;
773:
774: for (i = 0; i < nnames; i++)
775: if (strcmp(str, strings[i]) == 0)
776: return i;
777: if (++nnames >= MANY)
778: yyerror("symbol table overflow, %s", str);
779: strncpy(strings[i], str, MAXNAME-1);
780: return i;
781: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.