1 /***** spin: pangen2.c *****/
2
3 /*
4 * This file is part of the public release of Spin. It is subject to the
5 * terms in the LICENSE file that is included in this source directory.
6 * Tool documentation is available at http://spinroot.com
7 */
8
9 #include "spin.h"
10 #include "version.h"
11 #include "y.tab.h"
12 #include "pangen2.h"
13 #include "pangen4.h"
14 #include "pangen5.h"
15 #include "pangen7.h"
16
17 #define DELTA 500 /* sets an upperbound on nr of chan names */
18
19 #define blurb(fd, e) { fprintf(fd, "\n"); if (!merger) fprintf(fd, "\t\t/* %s:%d */\n", \
20 e->n->fn->name, e->n->ln); }
21 #define tr_map(m, e) { if (!merger) fprintf(fd_tt, "\t\ttr_2_src(%d, \"%s\", %d);\n", \
22 m, e->n->fn->name, e->n->ln); }
23
24 extern ProcList *ready;
25 extern RunList *run_lst;
26 extern Lextok *runstmnts;
27 extern Symbol *Fname, *oFname, *context;
28 extern char *claimproc, *eventmap;
29 extern int lineno, verbose, Npars, Mpars, nclaims;
30 extern int m_loss, has_remote, has_remvar, merger, rvopt, separate;
31 extern int Ntimeouts, Etimeouts, deadvar, old_scope_rules, old_priority_rules;
32 extern int u_sync, u_async, nrRdy, Unique;
33 extern int GenCode, IsGuard, Level, TestOnly;
34 extern int globmin, globmax, ltl_mode, dont_simplify;
35
36 extern short has_stack;
37 extern char *NextLab[64]; /* must match value in dstep.c:18 */
38
39 int buzzed;
40 FILE *fd_tc, *fd_th, *fd_tt, *fd_tb;
41 static FILE *fd_tm;
42
43 int OkBreak = -1, has_hidden = 0; /* has_hidden set in sym.c and structs.c */
44 short nocast=0; /* to turn off casts in lvalues */
45 short terse=0; /* terse printing of varnames */
46 short no_arrays=0;
47 short has_last=0; /* spec refers to _last */
48 short has_priority=0; /* spec refers to _priority */
49 short has_badelse=0; /* spec contains else combined with chan refs */
50 short has_enabled=0; /* spec contains enabled() */
51 short has_pcvalue=0; /* spec contains pc_value() */
52 short has_np=0; /* spec contains np_ */
53 short has_sorted=0; /* spec contains `!!' (sorted-send) operator */
54 short has_random=0; /* spec contains `??' (random-recv) operator */
55 short has_xu=0; /* spec contains xr or xs assertions */
56 short has_unless=0; /* spec contains unless statements */
57 short has_provided=0; /* spec contains PROVIDED clauses on procs */
58 short has_code=0; /* spec contains c_code, c_expr, c_state */
59 short has_ltl=0; /* has inline ltl formulae */
60 int mstp=0; /* max nr of state/process */
61 int claimnr = -1; /* claim process, if any */
62 int eventmapnr = -1; /* event trace, if any */
63 int Pid_nr; /* proc currently processed */
64 int multi_oval; /* set in merges, used also in pangen4.c */
65 int in_settr; /* avoid quotes inside quotes */
66
67 #define MAXMERGE 256 /* max nr of bups per merge sequence */
68
69 static short CnT[MAXMERGE];
70 static Lextok XZ, YZ[MAXMERGE];
71 static int didcase, YZmax, YZcnt;
72
73 static Lextok *Nn[2];
74 static int Det; /* set if deterministic */
75 static int T_sum, T_mus, t_cyc;
76 static int TPE[2], EPT[2];
77 static int uniq=1;
78 static int multi_needed, multi_undo;
79 static short AllGlobal=0; /* set if process has provided clause */
80 static short withprocname=0; /* prefix local varnames with procname */
81 static short _isok=0; /* checks usage of predefined variable _ */
82 static short evalindex=0; /* evaluate index of var names */
83
84 extern int has_global(Lextok *);
85 extern void check_mtypes(Lextok *, Lextok *);
86 extern void walk2_struct(char *, Symbol *);
87 extern int find_min(Sequence *);
88 extern int find_max(Sequence *);
89
90 static int getweight(Lextok *);
91 static int scan_seq(Sequence *);
92 static void genconditionals(void);
93 static void mark_seq(Sequence *);
94 static void patch_atomic(Sequence *);
95 static void put_seq(Sequence *, int, int);
96 static void putproc(ProcList *);
97 static void Tpe(Lextok *);
98 extern void spit_recvs(FILE *, FILE*);
99
100 static L_List *keep_track;
101
102 void
keep_track_off(Lextok * n)103 keep_track_off(Lextok *n)
104 { L_List *p;
105
106 p = (L_List *) emalloc(sizeof(L_List));
107 p->n = n;
108 p->nxt = keep_track;
109 keep_track = p;
110 }
111
112 int
check_track(Lextok * n)113 check_track(Lextok *n)
114 { L_List *p;
115
116 for (p = keep_track; p; p = p->nxt)
117 { if (p->n == n)
118 { return n->sym?n->sym->type:0;
119 } }
120 return 0;
121 }
122
123 static int
fproc(char * s)124 fproc(char *s)
125 { ProcList *p;
126
127 for (p = ready; p; p = p->nxt)
128 if (strcmp(p->n->name, s) == 0)
129 return p->tn;
130
131 fatal("proctype %s not found", s);
132 return -1;
133 }
134
135 int
pid_is_claim(int p)136 pid_is_claim(int p) /* Pid_nr (p->tn) to type (p->b) */
137 { ProcList *r;
138
139 for (r = ready; r; r = r->nxt)
140 { if (r->tn == p) return (r->b == N_CLAIM);
141 }
142 printf("spin: error, cannot find pid %d\n", p);
143 return 0;
144 }
145
146 static void
reverse_procs(RunList * q)147 reverse_procs(RunList *q)
148 {
149 if (!q) return;
150 reverse_procs(q->nxt);
151 fprintf(fd_tc, " Addproc(%d, %d);\n",
152 q->tn, q->priority < 1 ? 1 : q->priority);
153 }
154
155 static void
forward_procs(RunList * q)156 forward_procs(RunList *q)
157 {
158 if (!q) return;
159 fprintf(fd_tc, " Addproc(%d, %d);\n",
160 q->tn, q->priority < 1 ? 1 : q->priority);
161 forward_procs(q->nxt);
162 }
163
164 static void
tm_predef_np(void)165 tm_predef_np(void)
166 {
167 fprintf(fd_th, "#define _T5 %d\n", uniq++);
168 fprintf(fd_th, "#define _T2 %d\n", uniq++);
169
170 fprintf(fd_tm, "\tcase _T5:\t/* np_ */\n");
171
172 if (separate == 2)
173 { fprintf(fd_tm, "\t\tif (!((!(o_pm&4) && !(tau&128))))\n");
174 } else
175 { fprintf(fd_tm, "\t\tif (!((!(trpt->o_pm&4) && !(trpt->tau&128))))\n");
176 }
177 fprintf(fd_tm, "\t\t\tcontinue;\n");
178 fprintf(fd_tm, "\t\t/* else fall through */\n");
179 fprintf(fd_tm, "\tcase _T2:\t/* true */\n");
180 fprintf(fd_tm, "\t\t_m = 3; goto P999;\n");
181 }
182
183 static void
tt_predef_np(void)184 tt_predef_np(void)
185 {
186 fprintf(fd_tt, "\t/* np_ demon: */\n");
187 fprintf(fd_tt, "\ttrans[_NP_] = ");
188 fprintf(fd_tt, "(Trans **) emalloc(3*sizeof(Trans *));\n");
189 fprintf(fd_tt, "\tT = trans[_NP_][0] = ");
190 fprintf(fd_tt, "settr(9997,0,1,_T5,0,\"(np_)\", 1,2,0);\n");
191 fprintf(fd_tt, "\t T->nxt = ");
192 fprintf(fd_tt, "settr(9998,0,0,_T2,0,\"(1)\", 0,2,0);\n");
193 fprintf(fd_tt, "\tT = trans[_NP_][1] = ");
194 fprintf(fd_tt, "settr(9999,0,1,_T5,0,\"(np_)\", 1,2,0);\n");
195 }
196
197 static struct {
198 char *nm[3];
199 } Cfile[] = {
200 { { "pan.c", "pan_s.c", "pan_t.c" } },
201 { { "pan.h", "pan_s.h", "pan_t.h" } },
202 { { "pan.t", "pan_s.t", "pan_t.t" } },
203 { { "pan.m", "pan_s.m", "pan_t.m" } },
204 { { "pan.b", "pan_s.b", "pan_t.b" } }
205 };
206
207 void
gensrc(void)208 gensrc(void)
209 { ProcList *p;
210 int i;
211
212 disambiguate(); /* avoid name-clashes between scopes */
213
214 if (!(fd_tc = fopen(Cfile[0].nm[separate], MFLAGS)) /* main routines */
215 || !(fd_th = fopen(Cfile[1].nm[separate], MFLAGS)) /* header file */
216 || !(fd_tt = fopen(Cfile[2].nm[separate], MFLAGS)) /* transition matrix */
217 || !(fd_tm = fopen(Cfile[3].nm[separate], MFLAGS)) /* forward moves */
218 || !(fd_tb = fopen(Cfile[4].nm[separate], MFLAGS))) /* backward moves */
219 { printf("spin: cannot create pan.[chtmfb]\n");
220 alldone(1);
221 }
222
223 fprintf(fd_th, "#ifndef PAN_H\n");
224 fprintf(fd_th, "#define PAN_H\n\n");
225
226 fprintf(fd_th, "#define SpinVersion \"%s\"\n", SpinVersion);
227 fprintf(fd_th, "#define PanSource \"");
228 for (i = 0; oFname->name[i] != '\0'; i++)
229 { char c = oFname->name[i];
230 if (c == '\\') /* Windows path */
231 { fprintf(fd_th, "\\");
232 }
233 fprintf(fd_th, "%c", c);
234 }
235 fprintf(fd_th, "\"\n\n");
236
237 fprintf(fd_th, "#define G_long %d\n", (int) sizeof(long));
238 fprintf(fd_th, "#define G_int %d\n\n", (int) sizeof(int));
239 fprintf(fd_th, "#define ulong unsigned long\n");
240 fprintf(fd_th, "#define ushort unsigned short\n");
241
242 fprintf(fd_th, "#ifdef WIN64\n");
243 fprintf(fd_th, " #define ONE_L (1L)\n");
244 fprintf(fd_th, "/* #define long long long */\n");
245 fprintf(fd_th, "#else\n");
246 fprintf(fd_th, " #define ONE_L (1L)\n");
247 fprintf(fd_th, "#endif\n\n");
248
249 fprintf(fd_th, "#ifdef BFS_PAR\n");
250 fprintf(fd_th, " #define NRUNS %d\n", (runstmnts)?1:0);
251 fprintf(fd_th, " #ifndef BFS\n");
252 fprintf(fd_th, " #define BFS\n");
253 fprintf(fd_th, " #endif\n");
254 fprintf(fd_th, " #ifndef PUTPID\n");
255 fprintf(fd_th, " #define PUTPID\n");
256 fprintf(fd_th, " #endif\n\n");
257 fprintf(fd_th, " #if !defined(USE_TDH) && !defined(NO_TDH)\n");
258 fprintf(fd_th, " #define USE_TDH\n");
259 fprintf(fd_th, " #endif\n");
260 fprintf(fd_th, " #if defined(USE_TDH) && !defined(NO_HC)\n");
261 fprintf(fd_th, " #define HC /* default for USE_TDH */\n");
262 fprintf(fd_th, " #endif\n");
263 fprintf(fd_th, " #ifndef BFS_MAXPROCS\n");
264 fprintf(fd_th, " #define BFS_MAXPROCS 64 /* max nr of cores to use */\n");
265 fprintf(fd_th, " #endif\n");
266
267 fprintf(fd_th, " #define BFS_GLOB 0 /* global lock */\n");
268 fprintf(fd_th, " #define BFS_ORD 1 /* used with -DCOLLAPSE */\n");
269 fprintf(fd_th, " #define BFS_MEM 2 /* malloc from shared heap */\n");
270 fprintf(fd_th, " #define BFS_PRINT 3 /* protect printfs */\n");
271 fprintf(fd_th, " #define BFS_STATE 4 /* hashtable */\n\n");
272 fprintf(fd_th, " #define BFS_INQ 2 /* state is in q */\n\n");
273
274 fprintf(fd_th, " #ifdef BFS_FIFO\n"); /* queue access */
275 fprintf(fd_th, " #define BFS_ID(a,b) (BFS_STATE + (int) ((a)*BFS_MAXPROCS+(b)))\n");
276 fprintf(fd_th, " #define BFS_MAXLOCKS (BFS_STATE + (BFS_MAXPROCS*BFS_MAXPROCS))\n");
277 fprintf(fd_th, " #else\n"); /* h_store access (not needed for o_store) */
278 fprintf(fd_th, " #ifndef BFS_W\n");
279 fprintf(fd_th, " #define BFS_W 10\n"); /* 1<<BFS_W locks */
280 fprintf(fd_th, " #endif\n");
281 fprintf(fd_th, " #define BFS_MASK ((1<<BFS_W) - 1)\n");
282 fprintf(fd_th, " #define BFS_ID (BFS_STATE + (int) (j1_spin & (BFS_MASK)))\n");
283 fprintf(fd_th, " #define BFS_MAXLOCKS (BFS_STATE + (1<<BFS_W))\n"); /* 4+1024 */
284 fprintf(fd_th, " #endif\n");
285
286 fprintf(fd_th, " #undef NCORE\n");
287 fprintf(fd_th, " extern int Cores, who_am_i;\n");
288 fprintf(fd_th, " #ifndef SAFETY\n");
289 fprintf(fd_th, " #if !defined(BFS_STAGGER) && !defined(BFS_DISK)\n");
290 fprintf(fd_th, " #define BFS_STAGGER 64 /* randomizer, was 16 */\n");
291 fprintf(fd_th, " #endif\n");
292 fprintf(fd_th, " #ifndef L_BOUND\n");
293 fprintf(fd_th, " #define L_BOUND 10 /* default */\n");
294 fprintf(fd_th, " #endif\n");
295 fprintf(fd_th, " extern int L_bound;\n");
296 fprintf(fd_th, " #endif\n");
297 fprintf(fd_th, " #if defined(BFS_DISK) && defined(BFS_STAGGER)\n");
298 fprintf(fd_th, " #error BFS_DISK and BFS_STAGGER are not compatible\n");
299 fprintf(fd_th, " #endif\n");
300 fprintf(fd_th, "#endif\n\n");
301
302 fprintf(fd_th, "#if defined(BFS)\n");
303 fprintf(fd_th, " #ifndef SAFETY\n");
304 fprintf(fd_th, " #define SAFETY\n");
305 fprintf(fd_th, " #endif\n");
306 fprintf(fd_th, " #ifndef XUSAFE\n");
307 fprintf(fd_th, " #define XUSAFE\n");
308 fprintf(fd_th, " #endif\n");
309 fprintf(fd_th, "#endif\n");
310
311 fprintf(fd_th, "#ifndef uchar\n");
312 fprintf(fd_th, " #define uchar unsigned char\n");
313 fprintf(fd_th, "#endif\n");
314 fprintf(fd_th, "#ifndef uint\n");
315 fprintf(fd_th, " #define uint unsigned int\n");
316 fprintf(fd_th, "#endif\n");
317
318 if (separate == 1 && !claimproc)
319 { Symbol *n = (Symbol *) emalloc(sizeof(Symbol));
320 Sequence *s = (Sequence *) emalloc(sizeof(Sequence));
321 s->minel = -1;
322 claimproc = n->name = "_:never_template:_";
323 mk_rdy(n, ZN, s, 0, ZN, N_CLAIM);
324 }
325 if (separate == 2)
326 { if (has_remote)
327 { printf("spin: warning, make sure that the S1 model\n");
328 printf(" includes the same remote references\n");
329 }
330 fprintf(fd_th, "#ifndef NFAIR\n");
331 fprintf(fd_th, "#define NFAIR 2 /* must be >= 2 */\n");
332 fprintf(fd_th, "#endif\n");
333 if (has_last)
334 fprintf(fd_th, "#define HAS_LAST %d\n", has_last);
335 if (has_priority && !old_priority_rules)
336 fprintf(fd_th, "#define HAS_PRIORITY %d\n", has_priority);
337 goto doless;
338 }
339
340 fprintf(fd_th, "#define DELTA %d\n", DELTA);
341 fprintf(fd_th, "#ifdef MA\n");
342 fprintf(fd_th, " #if NCORE>1 && !defined(SEP_STATE)\n");
343 fprintf(fd_th, " #define SEP_STATE\n");
344 fprintf(fd_th, " #endif\n");
345 fprintf(fd_th, " #if MA==1\n"); /* user typed -DMA without size */
346 fprintf(fd_th, " #undef MA\n");
347 fprintf(fd_th, " #define MA 100\n");
348 fprintf(fd_th, " #endif\n");
349 fprintf(fd_th, "#endif\n");
350 fprintf(fd_th, "#ifdef W_XPT\n");
351 fprintf(fd_th, " #if W_XPT==1\n"); /* user typed -DW_XPT without size */
352 fprintf(fd_th, " #undef W_XPT\n");
353 fprintf(fd_th, " #define W_XPT 1000000\n");
354 fprintf(fd_th, " #endif\n");
355 fprintf(fd_th, "#endif\n");
356 fprintf(fd_th, "#ifndef NFAIR\n");
357 fprintf(fd_th, " #define NFAIR 2 /* must be >= 2 */\n");
358 fprintf(fd_th, "#endif\n");
359 if (Ntimeouts)
360 fprintf(fd_th, "#define NTIM %d\n", Ntimeouts);
361 if (Etimeouts)
362 fprintf(fd_th, "#define ETIM %d\n", Etimeouts);
363 if (has_remvar)
364 fprintf(fd_th, "#define REM_VARS 1\n");
365 if (has_remote)
366 fprintf(fd_th, "#define REM_REFS %d\n", has_remote); /* not yet used */
367 if (has_hidden)
368 { fprintf(fd_th, "#define HAS_HIDDEN %d\n", has_hidden);
369 fprintf(fd_th, "#if defined(BFS_PAR) || defined(BFS)\n");
370 fprintf(fd_th, " #error cannot use BFS on models with variables declared hidden\n");
371 fprintf(fd_th, "#endif\n");
372 }
373 if (has_last)
374 fprintf(fd_th, "#define HAS_LAST %d\n", has_last);
375 if (has_priority && !old_priority_rules)
376 fprintf(fd_th, "#define HAS_PRIORITY %d\n", has_priority);
377 if (has_sorted)
378 fprintf(fd_th, "#define HAS_SORTED %d\n", has_sorted);
379 if (m_loss)
380 fprintf(fd_th, "#define M_LOSS\n");
381 if (has_random)
382 fprintf(fd_th, "#define HAS_RANDOM %d\n", has_random);
383 if (has_ltl)
384 fprintf(fd_th, "#define HAS_LTL 1\n");
385 fprintf(fd_th, "#define HAS_CODE 1\n"); /* could also be set to has_code */
386 /* always defining it doesn't seem to cause measurable overhead though */
387 /* and allows for pan -r etc to work for non-embedded code as well */
388 fprintf(fd_th, "#if defined(RANDSTORE) && !defined(RANDSTOR)\n");
389 fprintf(fd_th, " #define RANDSTOR RANDSTORE\n"); /* xspin uses RANDSTORE... */
390 fprintf(fd_th, "#endif\n");
391 if (has_stack)
392 fprintf(fd_th, "#define HAS_STACK %d\n", has_stack);
393 if (has_enabled || (has_priority && !old_priority_rules))
394 fprintf(fd_th, "#define HAS_ENABLED 1\n");
395 if (has_unless)
396 fprintf(fd_th, "#define HAS_UNLESS %d\n", has_unless);
397 if (has_provided)
398 fprintf(fd_th, "#define HAS_PROVIDED %d\n", has_provided);
399 if (has_pcvalue)
400 fprintf(fd_th, "#define HAS_PCVALUE %d\n", has_pcvalue);
401 if (has_badelse)
402 fprintf(fd_th, "#define HAS_BADELSE %d\n", has_badelse);
403 if (has_enabled
404 || (has_priority && !old_priority_rules)
405 || has_pcvalue
406 || has_badelse
407 || has_last)
408 { fprintf(fd_th, "#ifndef NOREDUCE\n");
409 fprintf(fd_th, " #define NOREDUCE 1\n");
410 fprintf(fd_th, "#endif\n");
411 }
412 if (has_np)
413 fprintf(fd_th, "#define HAS_NP %d\n", has_np);
414 if (merger)
415 fprintf(fd_th, "#define MERGED 1\n");
416
417 doless:
418 fprintf(fd_th, "#if !defined(HAS_LAST) && defined(BCS)\n");
419 fprintf(fd_th, " #define HAS_LAST 1 /* use it, but */\n");
420 fprintf(fd_th, " #ifndef STORE_LAST\n"); /* unless the user insists */
421 fprintf(fd_th, " #define NO_LAST 1 /* don't store it */\n");
422 fprintf(fd_th, " #endif\n");
423 fprintf(fd_th, "#endif\n");
424
425 fprintf(fd_th, "#if defined(BCS) && defined(BITSTATE)\n");
426 fprintf(fd_th, " #ifndef NO_CTX\n");
427 fprintf(fd_th, " #define STORE_CTX 1\n");
428 fprintf(fd_th, " #endif\n");
429 fprintf(fd_th, "#endif\n");
430
431 fprintf(fd_th, "#ifdef NP\n");
432 if (!has_np)
433 fprintf(fd_th, " #define HAS_NP 2\n");
434 fprintf(fd_th, " #define VERI %d /* np_ */\n", nrRdy);
435 fprintf(fd_th, "#endif\n");
436
437 fprintf(fd_th, "#if defined(NOCLAIM) && defined(NP)\n");
438 fprintf(fd_th, " #undef NOCLAIM\n");
439 fprintf(fd_th, "#endif\n");
440 if (claimproc)
441 { claimnr = fproc(claimproc); /* the default claim */
442 fprintf(fd_th, "#ifndef NOCLAIM\n");
443 fprintf(fd_th, " #define NCLAIMS %d\n", nclaims);
444 fprintf(fd_th, " #ifndef NP\n");
445 fprintf(fd_th, " #define VERI %d\n", claimnr);
446 fprintf(fd_th, " #endif\n");
447 fprintf(fd_th, "#endif\n");
448 }
449 if (eventmap)
450 { eventmapnr = fproc(eventmap);
451 fprintf(fd_th, "#define EVENT_TRACE %d\n", eventmapnr);
452 fprintf(fd_th, "#define endevent _endstate%d\n", eventmapnr);
453 if (eventmap[2] == 'o') /* ":notrace:" */
454 fprintf(fd_th, "#define NEGATED_TRACE 1\n");
455 }
456
457 fprintf(fd_th, "\ntypedef struct S_F_MAP {\n");
458 fprintf(fd_th, " char *fnm;\n\tint from;\n\tint upto;\n");
459 fprintf(fd_th, "} S_F_MAP;\n");
460
461 fprintf(fd_tc, "/*** Generated by %s ***/\n", SpinVersion);
462 fprintf(fd_tc, "/*** From source: %s ***/\n\n", oFname->name);
463
464 ntimes(fd_tc, 0, 1, Pre0);
465
466 plunk_c_decls(fd_tc); /* types can be refered to in State */
467
468 switch (separate) {
469 case 0: fprintf(fd_tc, "#include \"pan.h\"\n"); break;
470 case 1: fprintf(fd_tc, "#include \"pan_s.h\"\n"); break;
471 case 2: fprintf(fd_tc, "#include \"pan_t.h\"\n"); break;
472 }
473
474 if (separate != 2)
475 { fprintf(fd_tc, "char *TrailFile = PanSource; /* default */\n");
476 fprintf(fd_tc, "char *trailfilename;\n");
477 }
478
479 fprintf(fd_tc, "#ifdef LOOPSTATE\n");
480 fprintf(fd_tc, "double cnt_loops;\n");
481 fprintf(fd_tc, "#endif\n");
482
483 fprintf(fd_tc, "State A_Root; /* seed-state for cycles */\n");
484 fprintf(fd_tc, "State now; /* the full state-vector */\n");
485 fprintf(fd_tc, "#if NQS > 0\n");
486 fprintf(fd_tc, "short q_flds[NQS+1];\n");
487 fprintf(fd_tc, "short q_max[NQS+1];\n");
488 fprintf(fd_tc, "#endif\n");
489
490 fprintf(fd_tc, "#ifndef XUSAFE\n");
491 fprintf(fd_tc, " uchar q_claim[MAXQ+1];\n");
492 fprintf(fd_tc, " char *q_name[MAXQ+1];\n");
493 fprintf(fd_tc, " char *p_name[MAXPROC+1];\n");
494 fprintf(fd_tc, "#endif\n");
495
496 plunk_c_fcts(fd_tc); /* State can be used in fcts */
497
498 if (separate != 2)
499 { ntimes(fd_tc, 0, 1, Preamble);
500 ntimes(fd_tc, 0, 1, Separate); /* things that moved out of pan.h */
501 } else
502 { fprintf(fd_tc, "extern int verbose;\n");
503 fprintf(fd_tc, "extern long depth, depthfound;\n");
504 }
505
506 fprintf(fd_tc, "#ifndef NOBOUNDCHECK\n");
507 fprintf(fd_tc, " #define Index(x, y)\tBoundcheck(x, y, II, tt, t)\n");
508 fprintf(fd_tc, "#else\n");
509 fprintf(fd_tc, " #define Index(x, y)\tx\n");
510 fprintf(fd_tc, "#endif\n");
511
512 c_preview(); /* sets hastrack */
513
514 for (p = ready; p; p = p->nxt)
515 mstp = max(p->s->maxel, mstp);
516
517 if (separate != 2)
518 { fprintf(fd_tt, "#ifdef PEG\n");
519 fprintf(fd_tt, "struct T_SRC {\n");
520 fprintf(fd_tt, " char *fl; int ln;\n");
521 fprintf(fd_tt, "} T_SRC[NTRANS];\n\n");
522 fprintf(fd_tt, "void\ntr_2_src(int m, char *file, int ln)\n");
523 fprintf(fd_tt, "{ T_SRC[m].fl = file;\n");
524 fprintf(fd_tt, " T_SRC[m].ln = ln;\n");
525 fprintf(fd_tt, "}\n\n");
526 fprintf(fd_tt, "void\nputpeg(int n, int m)\n");
527 fprintf(fd_tt, "{ printf(\"%%5d\ttrans %%4d \", m, n);\n");
528 fprintf(fd_tt, " printf(\"%%s:%%d\\n\",\n");
529 fprintf(fd_tt, " T_SRC[n].fl, T_SRC[n].ln);\n");
530 fprintf(fd_tt, "}\n");
531 if (!merger)
532 { fprintf(fd_tt, "#else\n");
533 fprintf(fd_tt, "#define tr_2_src(m,f,l)\n");
534 }
535 fprintf(fd_tt, "#endif\n\n");
536 fprintf(fd_tt, "void\nsettable(void)\n{\tTrans *T;\n");
537 fprintf(fd_tt, "\tTrans *settr(int, int, int, int, int,");
538 fprintf(fd_tt, " char *, int, int, int);\n\n");
539 fprintf(fd_tt, "\ttrans = (Trans ***) ");
540 fprintf(fd_tt, "emalloc(%d*sizeof(Trans **));\n", nrRdy+1);
541 /* +1 for np_ automaton */
542
543 if (separate == 1)
544 {
545 fprintf(fd_tm, " if (II == 0)\n");
546 fprintf(fd_tm, " { _m = step_claim(trpt->o_pm, trpt->tau, tt, ot, t);\n");
547 fprintf(fd_tm, " if (_m) goto P999; else continue;\n");
548 fprintf(fd_tm, " } else\n");
549 }
550
551 fprintf(fd_tm, "#define rand pan_rand\n");
552 fprintf(fd_tm, "#define pthread_equal(a,b) ((a)==(b))\n");
553 fprintf(fd_tm, "#if defined(HAS_CODE) && defined(VERBOSE)\n");
554 fprintf(fd_tm, " #ifdef BFS_PAR\n");
555 fprintf(fd_tm, " bfs_printf(\"Pr: %%d Tr: %%d\\n\", II, t->forw);\n");
556 fprintf(fd_tm, " #else\n");
557 fprintf(fd_tm, " cpu_printf(\"Pr: %%d Tr: %%d\\n\", II, t->forw);\n");
558 fprintf(fd_tm, " #endif\n");
559 fprintf(fd_tm, "#endif\n");
560 fprintf(fd_tm, " switch (t->forw) {\n");
561 } else
562 { fprintf(fd_tt, "#ifndef PEG\n");
563 fprintf(fd_tt, " #define tr_2_src(m,f,l)\n");
564 fprintf(fd_tt, "#endif\n");
565 fprintf(fd_tt, "void\nset_claim(void)\n{\tTrans *T;\n");
566 fprintf(fd_tt, "\textern Trans ***trans;\n");
567 fprintf(fd_tt, "\textern Trans *settr(int, int, int, int, int,");
568 fprintf(fd_tt, " char *, int, int, int);\n\n");
569
570 fprintf(fd_tm, "#define rand pan_rand\n");
571 fprintf(fd_tm, "#define pthread_equal(a,b) ((a)==(b))\n");
572 fprintf(fd_tm, "#if defined(HAS_CODE) && defined(VERBOSE)\n");
573 fprintf(fd_tm, " cpu_printf(\"Pr: %%d Tr: %%d\\n\", II, forw);\n");
574 fprintf(fd_tm, "#endif\n");
575 fprintf(fd_tm, " switch (forw) {\n");
576 }
577
578 fprintf(fd_tm, " default: Uerror(\"bad forward move\");\n");
579 fprintf(fd_tm, " case 0: /* if without executable clauses */\n");
580 fprintf(fd_tm, " continue;\n");
581 fprintf(fd_tm, " case 1: /* generic 'goto' or 'skip' */\n");
582 if (separate != 2)
583 fprintf(fd_tm, " IfNotBlocked\n");
584 fprintf(fd_tm, " _m = 3; goto P999;\n");
585 fprintf(fd_tm, " case 2: /* generic 'else' */\n");
586 if (separate == 2)
587 fprintf(fd_tm, " if (o_pm&1) continue;\n");
588 else
589 { fprintf(fd_tm, " IfNotBlocked\n");
590 fprintf(fd_tm, " if (trpt->o_pm&1) continue;\n");
591 }
592 fprintf(fd_tm, " _m = 3; goto P999;\n");
593 uniq = 3;
594
595 if (separate == 1)
596 fprintf(fd_tb, " if (II == 0) goto R999;\n");
597
598 fprintf(fd_tb, " switch (t->back) {\n");
599 fprintf(fd_tb, " default: Uerror(\"bad return move\");\n");
600 fprintf(fd_tb, " case 0: goto R999; /* nothing to undo */\n");
601
602 for (p = ready; p; p = p->nxt)
603 { putproc(p);
604 }
605
606 if (separate != 2)
607 { fprintf(fd_th, "\n");
608 for (p = ready; p; p = p->nxt)
609 fprintf(fd_th, "extern short src_ln%d[];\n", p->tn);
610 for (p = ready; p; p = p->nxt)
611 fprintf(fd_th, "extern S_F_MAP src_file%d[];\n", p->tn);
612 fprintf(fd_th, "\n");
613
614 fprintf(fd_tc, "uchar reached%d[3]; /* np_ */\n", nrRdy);
615 fprintf(fd_tc, "uchar *loopstate%d; /* np_ */\n", nrRdy);
616
617 fprintf(fd_tc, "struct {\n");
618 fprintf(fd_tc, " int tp; short *src;\n");
619 fprintf(fd_tc, "} src_all[] = {\n");
620 for (p = ready; p; p = p->nxt)
621 fprintf(fd_tc, " { %d, &src_ln%d[0] },\n",
622 p->tn, p->tn);
623 fprintf(fd_tc, " { 0, (short *) 0 }\n");
624 fprintf(fd_tc, "};\n");
625
626 fprintf(fd_tc, "S_F_MAP *flref[] = {\n"); /* 5.3.0 */
627 for (p = ready; p; p = p->nxt)
628 { fprintf(fd_tc, " src_file%d%c\n", p->tn, p->nxt?',':' ');
629 }
630 fprintf(fd_tc, "};\n\n");
631 } else
632 { fprintf(fd_tc, "extern uchar reached%d[3]; /* np_ */\n", nrRdy);
633 }
634
635 gencodetable(fd_tc); /* was th */
636
637 if (Unique < (1 << (8*sizeof(unsigned char)) )) /* was uniq before */
638 { fprintf(fd_th, "#define T_ID unsigned char\n");
639 } else if (Unique < (1 << (8*sizeof(unsigned short)) ))
640 { fprintf(fd_th, "#define T_ID unsigned short\n");
641 } else
642 { fprintf(fd_th, "#define T_ID unsigned int\n");
643 }
644
645 if (separate != 1)
646 { tm_predef_np();
647 tt_predef_np();
648 }
649 fprintf(fd_tt, "}\n\n"); /* end of settable() */
650
651 fprintf(fd_tm, "#undef rand\n");
652 fprintf(fd_tm, " }\n\n");
653 fprintf(fd_tb, " }\n\n");
654
655 if (separate != 2)
656 { ntimes(fd_tt, 0, 1, Tail);
657 genheader();
658 if (separate == 1)
659 { fprintf(fd_th, "#define FORWARD_MOVES\t\"pan_s.m\"\n");
660 fprintf(fd_th, "#define BACKWARD_MOVES\t\"pan_s.b\"\n");
661 fprintf(fd_th, "#define SEPARATE\n");
662 fprintf(fd_th, "#define TRANSITIONS\t\"pan_s.t\"\n");
663 fprintf(fd_th, "extern void ini_claim(int, int);\n");
664 } else
665 { fprintf(fd_th, "#define FORWARD_MOVES\t\"pan.m\"\n");
666 fprintf(fd_th, "#define BACKWARD_MOVES\t\"pan.b\"\n");
667 fprintf(fd_th, "#define TRANSITIONS\t\"pan.t\"\n");
668 }
669 genaddproc();
670 genother();
671 genaddqueue();
672 genunio();
673 genconditionals();
674 gensvmap();
675 if (!run_lst) fatal("no runable process", (char *)0);
676 fprintf(fd_tc, "void\n");
677 fprintf(fd_tc, "active_procs(void)\n{\n");
678
679 fprintf(fd_tc, " if (reversing == 0) {\n");
680 reverse_procs(run_lst);
681 fprintf(fd_tc, " } else {\n");
682 forward_procs(run_lst);
683 fprintf(fd_tc, " }\n");
684
685 fprintf(fd_tc, "}\n");
686 ntimes(fd_tc, 0, 1, Dfa);
687 ntimes(fd_tc, 0, 1, Xpt);
688
689 fprintf(fd_th, "#define NTRANS %d\n", uniq);
690 if (u_sync && !u_async)
691 { spit_recvs(fd_th, fd_tc);
692 }
693 } else
694 { genheader();
695 fprintf(fd_th, "#define FORWARD_MOVES\t\"pan_t.m\"\n");
696 fprintf(fd_th, "#define BACKWARD_MOVES\t\"pan_t.b\"\n");
697 fprintf(fd_th, "#define TRANSITIONS\t\"pan_t.t\"\n");
698 fprintf(fd_tc, "extern int Maxbody;\n");
699 fprintf(fd_tc, "#if VECTORSZ>32000\n");
700 fprintf(fd_tc, " extern int *proc_offset;\n");
701 fprintf(fd_tc, "#else\n");
702 fprintf(fd_tc, " extern short *proc_offset;\n");
703 fprintf(fd_tc, "#endif\n");
704 fprintf(fd_tc, "extern uchar *proc_skip;\n");
705 fprintf(fd_tc, "extern uchar *reached[];\n");
706 fprintf(fd_tc, "extern uchar *accpstate[];\n");
707 fprintf(fd_tc, "extern uchar *progstate[];\n");
708 fprintf(fd_tc, "extern uchar *loopstate[];\n");
709 fprintf(fd_tc, "extern uchar *stopstate[];\n");
710 fprintf(fd_tc, "extern uchar *visstate[];\n\n");
711 fprintf(fd_tc, "extern short *mapstate[];\n");
712
713 fprintf(fd_tc, "void\nini_claim(int n, int h)\n{");
714 fprintf(fd_tc, "\textern State now;\n");
715 fprintf(fd_tc, "\textern void set_claim(void);\n\n");
716 fprintf(fd_tc, "#ifdef PROV\n");
717 fprintf(fd_tc, " #include PROV\n");
718 fprintf(fd_tc, "#endif\n");
719 fprintf(fd_tc, "\tset_claim();\n");
720 genother();
721 fprintf(fd_tc, "\n\tswitch (n) {\n");
722 genaddproc();
723 fprintf(fd_tc, "\t}\n");
724 fprintf(fd_tc, "\n}\n");
725 fprintf(fd_tc, "int\nstep_claim(int o_pm, int tau, int tt, int ot, Trans *t)\n");
726 fprintf(fd_tc, "{ int forw = t->forw; int _m = 0; extern char *noptr; int II=0;\n");
727 fprintf(fd_tc, " extern State now;\n");
728 fprintf(fd_tc, "#define continue return 0\n");
729 fprintf(fd_tc, "#include \"pan_t.m\"\n");
730 fprintf(fd_tc, "P999:\n\treturn _m;\n}\n");
731 fprintf(fd_tc, "#undef continue\n");
732 fprintf(fd_tc, "int\nrev_claim(int backw)\n{ return 0; }\n");
733 fprintf(fd_tc, "#include TRANSITIONS\n");
734 }
735
736 if (separate != 2)
737 { c_wrapper(fd_tc);
738 c_chandump(fd_tc);
739 }
740
741 fprintf(fd_th, "#if defined(BFS_PAR) || NCORE>1\n");
742 fprintf(fd_th, " void e_critical(int);\n");
743 fprintf(fd_th, " void x_critical(int);\n");
744 fprintf(fd_th, " #ifdef BFS_PAR\n");
745 fprintf(fd_th, " void bfs_main(int, int);\n");
746 fprintf(fd_th, " void bfs_report_mem(void);\n");
747 fprintf(fd_th, " #endif\n");
748 fprintf(fd_th, "#endif\n");
749
750 fprintf(fd_th, "\n\n/* end of PAN_H */\n#endif\n");
751 fclose(fd_th);
752 fclose(fd_tt);
753 fclose(fd_tm);
754 fclose(fd_tb);
755
756 if (!(fd_th = fopen("pan.p", MFLAGS)))
757 { printf("spin: cannot create pan.p for -DBFS_PAR\n");
758 return; /* we're done anyway */
759 }
760
761 ntimes(fd_th, 0, 1, pan_par); /* BFS_PAR */
762 fclose(fd_th);
763
764 fprintf(fd_tc, "\nTrans *t_id_lkup[%d];\n\n", globmax+1);
765
766 if (separate != 2)
767 { fprintf(fd_tc, "\n#ifdef BFS_PAR\n\t#include \"pan.p\"\n#endif\n");
768 }
769 fprintf(fd_tc, "\n/* end of pan.c */\n");
770 fclose(fd_tc);
771 }
772
773 static int
find_id(Symbol * s)774 find_id(Symbol *s)
775 { ProcList *p;
776
777 if (s)
778 for (p = ready; p; p = p->nxt)
779 if (s == p->n)
780 return p->tn;
781 return 0;
782 }
783
784 static void
dolen(Symbol * s,char * pre,int pid,int ai,int qln)785 dolen(Symbol *s, char *pre, int pid, int ai, int qln)
786 {
787 if (ai > 0)
788 fprintf(fd_tc, "\n\t\t\t || ");
789 fprintf(fd_tc, "%s(", pre);
790 if (!(s->hidden&1))
791 { if (s->context)
792 fprintf(fd_tc, "(int) ( ((P%d *)_this)->", pid);
793 else
794 fprintf(fd_tc, "(int) ( now.");
795 }
796 fprintf(fd_tc, "%s", s->name);
797 if (qln > 1 || s->isarray) fprintf(fd_tc, "[%d]", ai);
798 fprintf(fd_tc, ") )");
799 }
800
801 struct AA { char TT[9]; char CC[8]; };
802
803 static struct AA BB[4] = {
804 { "Q_FULL_F", " q_full" },
805 { "Q_FULL_T", "!q_full" },
806 { "Q_EMPT_F", " !q_len" },
807 { "Q_EMPT_T", " q_len" }
808 };
809
810 static struct AA DD[4] = {
811 { "Q_FULL_F", " q_e_f" }, /* empty or full */
812 { "Q_FULL_T", "!q_full" },
813 { "Q_EMPT_F", " q_e_f" },
814 { "Q_EMPT_T", " q_len" }
815 };
816 /* this reduces the number of cases where 's' and 'r'
817 are considered conditionally safe under the
818 partial order reduction rules; as a price for
819 this simple implementation, it also affects the
820 cases where nfull and nempty can be considered
821 safe -- since these are labeled the same way as
822 's' and 'r' respectively
823 it only affects reduction, not functionality
824 */
825
826 void
bb_or_dd(int j,int which)827 bb_or_dd(int j, int which)
828 {
829 if (which)
830 { if (has_unless)
831 fprintf(fd_tc, "%s", DD[j].CC);
832 else
833 fprintf(fd_tc, "%s", BB[j].CC);
834 } else
835 { if (has_unless)
836 fprintf(fd_tc, "%s", DD[j].TT);
837 else
838 fprintf(fd_tc, "%s", BB[j].TT);
839 }
840 }
841
842 void
Done_case(char * nm,Symbol * z)843 Done_case(char *nm, Symbol *z)
844 { int j, k;
845 int nid = z->Nid;
846 int qln = z->nel;
847
848 fprintf(fd_tc, "\t\tcase %d: if (", nid);
849 for (j = 0; j < 4; j++)
850 { fprintf(fd_tc, "\t(t->ty[i] == ");
851 bb_or_dd(j, 0);
852 fprintf(fd_tc, " && (");
853 for (k = 0; k < qln; k++)
854 { if (k > 0)
855 fprintf(fd_tc, "\n\t\t\t || ");
856 bb_or_dd(j, 1);
857 fprintf(fd_tc, "(%s%s", nm, z->name);
858 if (qln > 1)
859 fprintf(fd_tc, "[%d]", k);
860 fprintf(fd_tc, ")");
861 }
862 fprintf(fd_tc, "))\n\t\t\t ");
863 if (j < 3)
864 fprintf(fd_tc, "|| ");
865 else
866 fprintf(fd_tc, " ");
867 }
868 fprintf(fd_tc, ") return 0; break;\n");
869 }
870
871 static void
Docase(Symbol * s,int pid,int nid)872 Docase(Symbol *s, int pid, int nid)
873 { int i, j;
874
875 fprintf(fd_tc, "\t\tcase %d: if (", nid);
876 for (j = 0; j < 4; j++)
877 { fprintf(fd_tc, "\t(t->ty[i] == ");
878 bb_or_dd(j, 0);
879 fprintf(fd_tc, " && (");
880 if (has_unless)
881 { for (i = 0; i < s->nel; i++)
882 dolen(s, DD[j].CC, pid, i, s->nel);
883 } else
884 { for (i = 0; i < s->nel; i++)
885 dolen(s, BB[j].CC, pid, i, s->nel);
886 }
887 fprintf(fd_tc, "))\n\t\t\t ");
888 if (j < 3)
889 fprintf(fd_tc, "|| ");
890 else
891 fprintf(fd_tc, " ");
892 }
893 fprintf(fd_tc, ") return 0; break;\n");
894 }
895
896 static void
genconditionals(void)897 genconditionals(void)
898 { Symbol *s;
899 int last=0, j;
900 extern Ordered *all_names;
901 Ordered *walk;
902
903 fprintf(fd_th, "#define LOCAL 1\n");
904 fprintf(fd_th, "#define Q_FULL_F 2\n");
905 fprintf(fd_th, "#define Q_EMPT_F 3\n");
906 fprintf(fd_th, "#define Q_EMPT_T 4\n");
907 fprintf(fd_th, "#define Q_FULL_T 5\n");
908 fprintf(fd_th, "#define TIMEOUT_F 6\n");
909 fprintf(fd_th, "#define GLOBAL 7\n");
910 fprintf(fd_th, "#define BAD 8\n");
911 fprintf(fd_th, "#define ALPHA_F 9\n");
912
913 fprintf(fd_tc, "int\n");
914 fprintf(fd_tc, "q_cond(short II, Trans *t)\n");
915 fprintf(fd_tc, "{ int i = 0;\n");
916 fprintf(fd_tc, " for (i = 0; i < 6; i++)\n");
917 fprintf(fd_tc, " { if (t->ty[i] == TIMEOUT_F) return %s;\n",
918 (Etimeouts)?"(!(trpt->tau&1))":"1");
919 fprintf(fd_tc, " if (t->ty[i] == ALPHA_F)\n");
920 fprintf(fd_tc, "#ifdef GLOB_ALPHA\n");
921 fprintf(fd_tc, " return 0;\n");
922 fprintf(fd_tc, "#else\n\t\t\treturn ");
923 fprintf(fd_tc, "(II+1 == (short) now._nr_pr && II+1 < MAXPROC);\n");
924 fprintf(fd_tc, "#endif\n");
925
926 /* we switch on the chan name from the spec (as identified by
927 * the corresponding Nid number) rather than the actual qid
928 * because we cannot predict at compile time which specific qid
929 * will be accessed by the statement at runtime. that is:
930 * we do not know which qid to pass to q_cond at runtime
931 * but we do know which name is used. if it's a chan array, we
932 * must check all elements of the array for compliance (bummer)
933 */
934 fprintf(fd_tc, " switch (t->qu[i]) {\n");
935 fprintf(fd_tc, " case 0: break;\n");
936
937 for (walk = all_names; walk; walk = walk->next)
938 { s = walk->entry;
939 if (s->owner) continue;
940 j = find_id(s->context);
941 if (s->type == CHAN)
942 { if (last == s->Nid) continue; /* chan array */
943 last = s->Nid;
944 Docase(s, j, last);
945 } else if (s->type == STRUCT)
946 { /* struct may contain a chan */
947 char pregat[128];
948 strcpy(pregat, "");
949 if (!(s->hidden&1))
950 { if (s->context)
951 sprintf(pregat, "((P%d *)_this)->",j);
952 else
953 sprintf(pregat, "now.");
954 }
955 walk2_struct(pregat, s);
956 }
957 }
958 fprintf(fd_tc, " \tdefault: Uerror(\"unknown qid - q_cond\");\n");
959 fprintf(fd_tc, " \t\t\treturn 0;\n");
960 fprintf(fd_tc, " \t}\n");
961 fprintf(fd_tc, " }\n");
962 fprintf(fd_tc, " return 1;\n");
963 fprintf(fd_tc, "}\n");
964 }
965
966 static void
putproc(ProcList * p)967 putproc(ProcList *p)
968 { Pid_nr = p->tn;
969 Det = p->det;
970
971 if (pid_is_claim(Pid_nr)
972 && separate == 1)
973 { fprintf(fd_th, "extern uchar reached%d[];\n", Pid_nr);
974 #if 0
975 fprintf(fd_th, "extern short _nstates%d;\n", Pid_nr);
976 #else
977 fprintf(fd_th, "\n#define _nstates%d %d\t/* %s */\n",
978 Pid_nr, p->s->maxel, p->n->name);
979 #endif
980 fprintf(fd_th, "extern short src_ln%d[];\n", Pid_nr);
981 fprintf(fd_th, "extern uchar *loopstate%d;\n", Pid_nr);
982 fprintf(fd_th, "extern S_F_MAP src_file%d[];\n", Pid_nr);
983 fprintf(fd_th, "#define _endstate%d %d\n",
984 Pid_nr, p->s->last?p->s->last->seqno:0);
985 return;
986 }
987 if (!pid_is_claim(Pid_nr)
988 && separate == 2)
989 { fprintf(fd_th, "extern short src_ln%d[];\n", Pid_nr);
990 fprintf(fd_th, "extern uchar *loopstate%d;\n", Pid_nr);
991 return;
992 }
993
994 AllGlobal = (p->prov)?1:0; /* process has provided clause */
995
996 fprintf(fd_th, "\n#define _nstates%d %d\t/* %s */\n",
997 Pid_nr, p->s->maxel, p->n->name);
998 /* new */
999 fprintf(fd_th, "#define minseq%d %d\n", Pid_nr, find_min(p->s));
1000 fprintf(fd_th, "#define maxseq%d %d\n", Pid_nr, find_max(p->s));
1001
1002 /* end */
1003
1004 if (Pid_nr == eventmapnr)
1005 fprintf(fd_th, "#define nstates_event _nstates%d\n", Pid_nr);
1006
1007 fprintf(fd_th, "#define _endstate%d %d\n", Pid_nr, p->s->last?p->s->last->seqno:0);
1008
1009 if (p->b == N_CLAIM || p->b == E_TRACE || p->b == N_TRACE)
1010 { fprintf(fd_tm, "\n /* CLAIM %s */\n", p->n->name);
1011 fprintf(fd_tb, "\n /* CLAIM %s */\n", p->n->name);
1012 }
1013 else
1014 { fprintf(fd_tm, "\n /* PROC %s */\n", p->n->name);
1015 fprintf(fd_tb, "\n /* PROC %s */\n", p->n->name);
1016 }
1017 fprintf(fd_tt, "\n /* proctype %d: %s */\n", Pid_nr, p->n->name);
1018 fprintf(fd_tt, "\n trans[%d] = (Trans **)", Pid_nr);
1019 fprintf(fd_tt, " emalloc(%d*sizeof(Trans *));\n\n", p->s->maxel);
1020
1021 if (Pid_nr == eventmapnr)
1022 { fprintf(fd_th, "\n#define in_s_scope(x_y3_) 0");
1023 fprintf(fd_tc, "\n#define in_r_scope(x_y3_) 0");
1024 }
1025 put_seq(p->s, 2, 0);
1026 if (Pid_nr == eventmapnr)
1027 { fprintf(fd_th, "\n\n");
1028 fprintf(fd_tc, "\n\n");
1029 }
1030 dumpsrc(p->s->maxel, Pid_nr);
1031 }
1032
1033 static void
addTpe(int x)1034 addTpe(int x)
1035 { int i;
1036
1037 if (x <= 2) return;
1038
1039 for (i = 0; i < T_sum; i++)
1040 if (TPE[i] == x)
1041 return;
1042 TPE[(T_sum++)%2] = x;
1043 }
1044
1045 static void
cnt_seq(Sequence * s)1046 cnt_seq(Sequence *s)
1047 { Element *f;
1048 SeqList *h;
1049
1050 if (s)
1051 for (f = s->frst; f; f = f->nxt)
1052 { Tpe(f->n); /* sets EPT */
1053 addTpe(EPT[0]);
1054 addTpe(EPT[1]);
1055 for (h = f->sub; h; h = h->nxt)
1056 cnt_seq(h->this);
1057 if (f == s->last)
1058 break;
1059 }
1060 }
1061
1062 static void
typ_seq(Sequence * s)1063 typ_seq(Sequence *s)
1064 {
1065 T_sum = 0;
1066 TPE[0] = 2; TPE[1] = 0;
1067 cnt_seq(s);
1068 if (T_sum > 2) /* more than one type */
1069 { TPE[0] = 5*DELTA; /* non-mixing */
1070 TPE[1] = 0;
1071 }
1072 }
1073
1074 static int
hidden(Lextok * n)1075 hidden(Lextok *n)
1076 {
1077 if (n)
1078 switch (n->ntyp) {
1079 case FULL: case EMPTY:
1080 case NFULL: case NEMPTY: case TIMEOUT:
1081 Nn[(T_mus++)%2] = n;
1082 break;
1083 case '!': case UMIN: case '~': case ASSERT: case 'c':
1084 (void) hidden(n->lft);
1085 break;
1086 case '/': case '*': case '-': case '+':
1087 case '%': case LT: case GT: case '&': case '^':
1088 case '|': case LE: case GE: case NE: case '?':
1089 case EQ: case OR: case AND: case LSHIFT: case RSHIFT:
1090 (void) hidden(n->lft);
1091 (void) hidden(n->rgt);
1092 break;
1093 }
1094 return T_mus;
1095 }
1096
1097 static int
getNid(Lextok * n)1098 getNid(Lextok *n)
1099 {
1100 if (n->sym
1101 && n->sym->type == STRUCT
1102 && n->rgt && n->rgt->lft)
1103 return getNid(n->rgt->lft);
1104
1105 if (!n->sym || n->sym->Nid == 0)
1106 { fatal("bad channel name '%s'",
1107 (n->sym)?n->sym->name:"no name");
1108 }
1109 return n->sym->Nid;
1110 }
1111
1112 static int
valTpe(Lextok * n)1113 valTpe(Lextok *n)
1114 { int res = 2;
1115 /*
1116 2 = local
1117 2+1 .. 2+1*DELTA = nfull, 's' - require q_full==false
1118 2+1+1*DELTA .. 2+2*DELTA = nempty, 'r' - require q_len!=0
1119 2+1+2*DELTA .. 2+3*DELTA = empty - require q_len==0
1120 2+1+3*DELTA .. 2+4*DELTA = full - require q_full==true
1121 5*DELTA = non-mixing (i.e., always makes the selection global)
1122 6*DELTA = timeout (conditionally safe)
1123 7*DELTA = @, process deletion (conditionally safe)
1124 */
1125 switch (n->ntyp) { /* a series of fall-thru cases: */
1126 case FULL: res += DELTA; /* add 3*DELTA + chan nr */
1127 case EMPTY: res += DELTA; /* add 2*DELTA + chan nr */
1128 case 'r':
1129 case NEMPTY: res += DELTA; /* add 1*DELTA + chan nr */
1130 case 's':
1131 case NFULL: res += getNid(n->lft); /* add channel nr */
1132 break;
1133
1134 case TIMEOUT: res = 6*DELTA; break;
1135 case '@': res = 7*DELTA; break;
1136 default: break;
1137 }
1138 return res;
1139 }
1140
1141 static void
Tpe(Lextok * n)1142 Tpe(Lextok *n) /* mixing in selections */
1143 {
1144 EPT[0] = 2; EPT[1] = 0;
1145
1146 if (!n) return;
1147
1148 T_mus = 0;
1149 Nn[0] = Nn[1] = ZN;
1150
1151 if (n->ntyp == 'c')
1152 { if (hidden(n->lft) > 2)
1153 { EPT[0] = 5*DELTA; /* non-mixing */
1154 EPT[1] = 0;
1155 return;
1156 }
1157 } else
1158 Nn[0] = n;
1159
1160 if (Nn[0]) EPT[0] = valTpe(Nn[0]);
1161 if (Nn[1]) EPT[1] = valTpe(Nn[1]);
1162 }
1163
1164 static void
put_escp(Element * e)1165 put_escp(Element *e)
1166 { int n;
1167 SeqList *x;
1168
1169 if (e->esc /* && e->n->ntyp != GOTO */ && e->n->ntyp != '.')
1170 { for (x = e->esc, n = 0; x; x = x->nxt, n++)
1171 { int i = huntele(x->this->frst, e->status, -1)->seqno;
1172 fprintf(fd_tt, "\ttrans[%d][%d]->escp[%d] = %d;\n",
1173 Pid_nr, e->seqno, n, i);
1174 fprintf(fd_tt, "\treached%d[%d] = 1;\n",
1175 Pid_nr, i);
1176 }
1177 for (x = e->esc, n=0; x; x = x->nxt, n++)
1178 { fprintf(fd_tt, " /* escape #%d: %d */\n", n,
1179 huntele(x->this->frst, e->status, -1)->seqno);
1180 put_seq(x->this, 2, 0); /* args?? */
1181 }
1182 fprintf(fd_tt, " /* end-escapes */\n");
1183 }
1184 }
1185
1186 static void
put_sub(Element * e,int Tt0,int Tt1)1187 put_sub(Element *e, int Tt0, int Tt1)
1188 { Sequence *s = e->n->sl->this;
1189 Element *g = ZE;
1190 int a;
1191
1192 patch_atomic(s);
1193 putskip(s->frst->seqno);
1194 g = huntstart(s->frst);
1195 a = g->seqno;
1196
1197 if (0) printf("put_sub %d -> %d -> %d\n", e->seqno, s->frst->seqno, a);
1198
1199 if ((e->n->ntyp == ATOMIC
1200 || e->n->ntyp == D_STEP)
1201 && scan_seq(s))
1202 mark_seq(s);
1203 s->last->nxt = e->nxt;
1204
1205 typ_seq(s); /* sets TPE */
1206
1207 if (e->n->ntyp == D_STEP)
1208 { int inherit = (e->status&(ATOM|L_ATOM));
1209 fprintf(fd_tm, "\tcase %d: ", uniq++);
1210 fprintf(fd_tm, "// STATE %d - %s:%d - [",
1211 e->seqno, e->n->fn->name, e->n->ln);
1212 comment(fd_tm, e->n, 0);
1213 fprintf(fd_tm, "]\n\t\t");
1214
1215 if (s->last->n->ntyp == BREAK)
1216 OkBreak = target(huntele(s->last->nxt,
1217 s->last->status, -1))->Seqno;
1218 else
1219 OkBreak = -1;
1220
1221 if (!putcode(fd_tm, s, e->nxt, 0, e->n->ln, e->seqno))
1222 {
1223 fprintf(fd_tm, "\n#if defined(C_States) && (HAS_TRACK==1)\n");
1224 fprintf(fd_tm, "\t\tc_update((uchar *) &(now.c_state[0]));\n");
1225 fprintf(fd_tm, "#endif\n");
1226
1227 fprintf(fd_tm, "\t\t_m = %d", getweight(s->frst->n));
1228 if (m_loss && s->frst->n->ntyp == 's')
1229 fprintf(fd_tm, "+delta_m; delta_m = 0");
1230 fprintf(fd_tm, "; goto P999;\n\n");
1231 }
1232
1233 fprintf(fd_tb, "\tcase %d: ", uniq-1);
1234 fprintf(fd_tb, "// STATE %d\n", e->seqno);
1235 fprintf(fd_tb, "\t\tsv_restor();\n");
1236 fprintf(fd_tb, "\t\tgoto R999;\n");
1237 if (e->nxt)
1238 a = huntele(e->nxt, e->status, -1)->seqno;
1239 else
1240 a = 0;
1241 tr_map(uniq-1, e);
1242 fprintf(fd_tt, "/*->*/\ttrans[%d][%d]\t= ",
1243 Pid_nr, e->seqno);
1244 fprintf(fd_tt, "settr(%d,%d,%d,%d,%d,\"",
1245 e->Seqno, D_ATOM|inherit, a, uniq-1, uniq-1);
1246 in_settr++;
1247 comment(fd_tt, e->n, e->seqno);
1248 in_settr--;
1249 fprintf(fd_tt, "\", %d, ", (s->frst->status&I_GLOB)?1:0);
1250 fprintf(fd_tt, "%d, %d);\n", TPE[0], TPE[1]);
1251 put_escp(e);
1252 } else
1253 { /* ATOMIC or NON_ATOMIC */
1254 fprintf(fd_tt, "\tT = trans[ %d][%d] = ", Pid_nr, e->seqno);
1255 fprintf(fd_tt, "settr(%d,%d,0,0,0,\"",
1256 e->Seqno, (e->n->ntyp == ATOMIC)?ATOM:0);
1257 in_settr++;
1258 comment(fd_tt, e->n, e->seqno);
1259 in_settr--;
1260 if ((e->status&CHECK2)
1261 || (g->status&CHECK2))
1262 s->frst->status |= I_GLOB;
1263 fprintf(fd_tt, "\", %d, %d, %d);",
1264 (s->frst->status&I_GLOB)?1:0, Tt0, Tt1);
1265 blurb(fd_tt, e);
1266 fprintf(fd_tt, "\tT->nxt\t= ");
1267 fprintf(fd_tt, "settr(%d,%d,%d,0,0,\"",
1268 e->Seqno, (e->n->ntyp == ATOMIC)?ATOM:0, a);
1269 in_settr++;
1270 comment(fd_tt, e->n, e->seqno);
1271 in_settr--;
1272 fprintf(fd_tt, "\", %d, ", (s->frst->status&I_GLOB)?1:0);
1273 if (e->n->ntyp == NON_ATOMIC)
1274 { fprintf(fd_tt, "%d, %d);", Tt0, Tt1);
1275 blurb(fd_tt, e);
1276 put_seq(s, Tt0, Tt1);
1277 } else
1278 { fprintf(fd_tt, "%d, %d);", TPE[0], TPE[1]);
1279 blurb(fd_tt, e);
1280 put_seq(s, TPE[0], TPE[1]);
1281 }
1282 }
1283 }
1284
1285 typedef struct CaseCache {
1286 int m, b, owner;
1287 Element *e;
1288 Lextok *n;
1289 FSM_use *u;
1290 struct CaseCache *nxt;
1291 } CaseCache;
1292
1293 static CaseCache *casing[6];
1294
1295 static int
identical(Lextok * p,Lextok * q)1296 identical(Lextok *p, Lextok *q)
1297 {
1298 if ((!p && q) || (p && !q))
1299 return 0;
1300 if (!p)
1301 return 1;
1302
1303 if (p->ntyp != q->ntyp
1304 || p->ismtyp != q->ismtyp
1305 || p->val != q->val
1306 || p->indstep != q->indstep
1307 || p->sym != q->sym
1308 || p->sq != q->sq
1309 || p->sl != q->sl)
1310 return 0;
1311
1312 return identical(p->lft, q->lft)
1313 && identical(p->rgt, q->rgt);
1314 }
1315
1316 static int
samedeads(FSM_use * a,FSM_use * b)1317 samedeads(FSM_use *a, FSM_use *b)
1318 { FSM_use *p, *q;
1319
1320 for (p = a, q = b; p && q; p = p->nxt, q = q->nxt)
1321 if (p->var != q->var
1322 || p->special != q->special)
1323 return 0;
1324 return (!p && !q);
1325 }
1326
1327 static Element *
findnext(Element * f)1328 findnext(Element *f)
1329 { Element *g;
1330
1331 if (f->n->ntyp == GOTO)
1332 { g = get_lab(f->n, 1);
1333 return huntele(g, f->status, -1);
1334 }
1335 return f->nxt;
1336 }
1337
1338 static Element *
advance(Element * e,int stopat)1339 advance(Element *e, int stopat)
1340 { Element *f = e;
1341
1342 if (stopat)
1343 while (f && f->seqno != stopat)
1344 { f = findnext(f);
1345 if (!f)
1346 { break;
1347 }
1348 switch (f->n->ntyp) {
1349 case GOTO:
1350 case '.':
1351 case PRINT:
1352 case PRINTM:
1353 break;
1354 default:
1355 return f;
1356 } }
1357 return (Element *) 0;
1358 }
1359
1360 static int
equiv_merges(Element * a,Element * b)1361 equiv_merges(Element *a, Element *b)
1362 { Element *f, *g;
1363 int stopat_a, stopat_b;
1364
1365 if (a->merge_start)
1366 stopat_a = a->merge_start;
1367 else
1368 stopat_a = a->merge;
1369
1370 if (b->merge_start)
1371 stopat_b = b->merge_start;
1372 else
1373 stopat_b = b->merge;
1374
1375 if (!stopat_a && !stopat_b)
1376 return 1;
1377
1378 f = advance(a, stopat_a);
1379 g = advance(b, stopat_b);
1380
1381 if (!f && !g)
1382 return 1;
1383
1384 if (f && g)
1385 return identical(f->n, g->n);
1386
1387 return 0;
1388 }
1389
1390 static CaseCache *
prev_case(Element * e,int owner)1391 prev_case(Element *e, int owner)
1392 { int j; CaseCache *nc;
1393
1394 switch (e->n->ntyp) {
1395 case 'r': j = 0; break;
1396 case 's': j = 1; break;
1397 case 'c': j = 2; break;
1398 case ASGN: j = 3; break;
1399 case ASSERT: j = 4; break;
1400 default: j = 5; break;
1401 }
1402 for (nc = casing[j]; nc; nc = nc->nxt)
1403 if (identical(nc->n, e->n)
1404 && samedeads(nc->u, e->dead)
1405 && equiv_merges(nc->e, e)
1406 && nc->owner == owner)
1407 return nc;
1408
1409 return (CaseCache *) 0;
1410 }
1411
1412 static void
new_case(Element * e,int m,int b,int owner)1413 new_case(Element *e, int m, int b, int owner)
1414 { int j; CaseCache *nc;
1415
1416 switch (e->n->ntyp) {
1417 case 'r': j = 0; break;
1418 case 's': j = 1; break;
1419 case 'c': j = 2; break;
1420 case ASGN: j = 3; break;
1421 case ASSERT: j = 4; break;
1422 default: j = 5; break;
1423 }
1424 nc = (CaseCache *) emalloc(sizeof(CaseCache));
1425 nc->owner = owner;
1426 nc->m = m;
1427 nc->b = b;
1428 nc->e = e;
1429 nc->n = e->n;
1430 nc->u = e->dead;
1431 nc->nxt = casing[j];
1432 casing[j] = nc;
1433 }
1434
1435 static int
nr_bup(Element * e)1436 nr_bup(Element *e)
1437 { FSM_use *u;
1438 Lextok *v;
1439 int nr = 0;
1440
1441 switch (e->n->ntyp) {
1442 case ASGN:
1443 if (check_track(e->n) == STRUCT) { break; }
1444 nr++;
1445 break;
1446 case 'r':
1447 if (e->n->val >= 1)
1448 nr++; /* random recv */
1449 for (v = e->n->rgt; v; v = v->rgt)
1450 { if ((v->lft->ntyp == CONST
1451 || v->lft->ntyp == EVAL))
1452 continue;
1453 nr++;
1454 }
1455 break;
1456 default:
1457 break;
1458 }
1459 for (u = e->dead; u; u = u->nxt)
1460 { switch (u->special) {
1461 case 2: /* dead after write */
1462 if (e->n->ntyp == ASGN
1463 && e->n->rgt->ntyp == CONST
1464 && e->n->rgt->val == 0)
1465 break;
1466 nr++;
1467 break;
1468 case 1: /* dead after read */
1469 nr++;
1470 break;
1471 } }
1472 return nr;
1473 }
1474
1475 static int
nrhops(Element * e)1476 nrhops(Element *e)
1477 { Element *f = e, *g;
1478 int cnt = 0;
1479 int stopat;
1480
1481 if (e->merge_start)
1482 stopat = e->merge_start;
1483 else
1484 stopat = e->merge;
1485 #if 0
1486 printf("merge: %d merge_start %d - seqno %d\n",
1487 e->merge, e->merge_start, e->seqno);
1488 #endif
1489 do {
1490 cnt += nr_bup(f);
1491
1492 if (f->n->ntyp == GOTO)
1493 { g = get_lab(f->n, 1);
1494 if (g->seqno == stopat)
1495 f = g;
1496 else
1497 f = huntele(g, f->status, stopat);
1498 } else
1499 {
1500 f = f->nxt;
1501 }
1502
1503 if (f && !f->merge && !f->merge_single && f->seqno != stopat)
1504 { fprintf(fd_tm, "\n\t\t// bad hop %s:%d -- at %d, <",
1505 f->n->fn->name,f->n->ln, f->seqno);
1506 comment(fd_tm, f->n, 0);
1507 fprintf(fd_tm, "> looking for %d -- merge %d:%d:%d ",
1508 stopat, f->merge, f->merge_start, f->merge_single);
1509 break;
1510 }
1511 } while (f && f->seqno != stopat);
1512
1513 return cnt;
1514 }
1515
1516 static void
check_needed(void)1517 check_needed(void)
1518 {
1519 if (multi_needed)
1520 { fprintf(fd_tm, "(trpt+1)->bup.ovals = grab_ints(%d);\n\t\t",
1521 multi_needed);
1522 multi_undo = multi_needed;
1523 multi_needed = 0;
1524 }
1525 }
1526
1527 static void
doforward(FILE * tm_fd,Element * e)1528 doforward(FILE *tm_fd, Element *e)
1529 { FSM_use *u;
1530
1531 putstmnt(tm_fd, e->n, e->seqno);
1532
1533 if (e->n->ntyp != ELSE && Det)
1534 { fprintf(tm_fd, ";\n\t\tif (trpt->o_pm&1)\n\t\t");
1535 fprintf(tm_fd, "\tuerror(\"non-determinism in D_proctype\")");
1536 }
1537 if (deadvar && !has_code)
1538 for (u = e->dead; u; u = u->nxt)
1539 { fprintf(tm_fd, ";\n\t\t");
1540 fprintf(tm_fd, "if (TstOnly) return 1; /* TT */\n");
1541 fprintf(tm_fd, "\t\t/* dead %d: %s */ ",
1542 u->special, u->var->name);
1543
1544 switch (u->special) {
1545 case 2: /* dead after write -- lval already bupped */
1546 if (e->n->ntyp == ASGN) /* could be recv or asgn */
1547 { if (e->n->rgt->ntyp == CONST
1548 && e->n->rgt->val == 0)
1549 continue; /* already set to 0 */
1550 }
1551 if (e->n->ntyp != 'r')
1552 { XZ.sym = u->var;
1553 fprintf(tm_fd, "\n#ifdef HAS_CODE\n");
1554 fprintf(tm_fd, "\t\tif (!readtrail)\n");
1555 fprintf(tm_fd, "#endif\n\t\t\t");
1556 putname(tm_fd, "", &XZ, 0, " = 0");
1557 break;
1558 } /* else fall through */
1559 case 1: /* dead after read -- add asgn of rval -- needs bup */
1560 YZ[YZmax].sym = u->var; /* store for pan.b */
1561 CnT[YZcnt]++; /* this step added bups */
1562 if (multi_oval)
1563 { check_needed();
1564 fprintf(tm_fd, "(trpt+1)->bup.ovals[%d] = ",
1565 multi_oval-1);
1566 multi_oval++;
1567 } else
1568 fprintf(tm_fd, "(trpt+1)->bup.oval = ");
1569 putname(tm_fd, "", &YZ[YZmax], 0, ";\n");
1570 fprintf(tm_fd, "#ifdef HAS_CODE\n");
1571 fprintf(tm_fd, "\t\tif (!readtrail)\n");
1572 fprintf(tm_fd, "#endif\n\t\t\t");
1573 putname(tm_fd, "", &YZ[YZmax], 0, " = 0");
1574 YZmax++;
1575 break;
1576 } }
1577 fprintf(tm_fd, ";\n\t\t");
1578 }
1579
1580 static int
dobackward(Element * e,int casenr)1581 dobackward(Element *e, int casenr)
1582 {
1583 if (!any_undo(e->n) && CnT[YZcnt] == 0)
1584 { YZcnt--;
1585 return 0;
1586 }
1587
1588 if (!didcase)
1589 { fprintf(fd_tb, "\n\tcase %d: ", casenr);
1590 fprintf(fd_tb, "// STATE %d\n\t\t", e->seqno);
1591 didcase++;
1592 }
1593
1594 _isok++;
1595 while (CnT[YZcnt] > 0) /* undo dead variable resets */
1596 { CnT[YZcnt]--;
1597 YZmax--;
1598 if (YZmax < 0)
1599 fatal("cannot happen, dobackward", (char *)0);
1600 fprintf(fd_tb, ";\n\t/* %d */\t", YZmax);
1601 putname(fd_tb, "", &YZ[YZmax], 0, " = trpt->bup.oval");
1602 if (multi_oval > 0)
1603 { multi_oval--;
1604 fprintf(fd_tb, "s[%d]", multi_oval-1);
1605 }
1606 }
1607
1608 if (e->n->ntyp != '.')
1609 { fprintf(fd_tb, ";\n\t\t");
1610 undostmnt(e->n, e->seqno);
1611 }
1612 _isok--;
1613
1614 YZcnt--;
1615 return 1;
1616 }
1617
1618 static void
lastfirst(int stopat,Element * fin,int casenr)1619 lastfirst(int stopat, Element *fin, int casenr)
1620 { Element *f = fin, *g;
1621
1622 if (f->n->ntyp == GOTO)
1623 { g = get_lab(f->n, 1);
1624 if (g->seqno == stopat)
1625 f = g;
1626 else
1627 f = huntele(g, f->status, stopat);
1628 } else
1629 f = f->nxt;
1630
1631 if (!f || f->seqno == stopat
1632 || (!f->merge && !f->merge_single))
1633 return;
1634 lastfirst(stopat, f, casenr);
1635 #if 0
1636 fprintf(fd_tb, "\n\t/* merge %d -- %d:%d %d:%d:%d (casenr %d) ",
1637 YZcnt,
1638 f->merge_start, f->merge,
1639 f->seqno, f?f->seqno:-1, stopat,
1640 casenr);
1641 comment(fd_tb, f->n, 0);
1642 fprintf(fd_tb, " */\n");
1643 fflush(fd_tb);
1644 #endif
1645 dobackward(f, casenr);
1646 }
1647
1648 static int modifier;
1649
1650 static void
lab_transfer(Element * to,Element * from)1651 lab_transfer(Element *to, Element *from)
1652 { Symbol *ns, *s = has_lab(from, (1|2|4));
1653 Symbol *oc;
1654 int ltp, usedit=0;
1655
1656 if (!s) return;
1657
1658 /* "from" could have all three labels -- rename
1659 * to prevent jumps to the transfered copies
1660 */
1661 oc = context; /* remember */
1662 for (ltp = 1; ltp < 8; ltp *= 2) /* 1, 2, and 4 */
1663 if ((s = has_lab(from, ltp)) != (Symbol *) 0)
1664 { ns = (Symbol *) emalloc(sizeof(Symbol));
1665 ns->name = (char *) emalloc((int) strlen(s->name) + 4);
1666 sprintf(ns->name, "%s%d", s->name, modifier);
1667
1668 context = s->context;
1669 set_lab(ns, to);
1670 usedit++;
1671 }
1672 context = oc; /* restore */
1673 if (usedit)
1674 { if (modifier++ > 990)
1675 fatal("modifier overflow error", (char *) 0);
1676 }
1677 }
1678
1679 static int
case_cache(Element * e,int a)1680 case_cache(Element *e, int a)
1681 { int bupcase = 0, casenr = uniq, fromcache = 0;
1682 CaseCache *Cached = (CaseCache *) 0;
1683 Element *f, *g;
1684 int j, nrbups, mark, ntarget;
1685 extern int ccache;
1686
1687 mark = (e->status&ATOM); /* could lose atomicity in a merge chain */
1688
1689 if (e->merge_mark > 0
1690 || (merger && e->merge_in == 0))
1691 { /* state nominally unreachable (part of merge chains) */
1692 if (e->n->ntyp != '.'
1693 && e->n->ntyp != GOTO)
1694 { fprintf(fd_tt, "\ttrans[%d][%d]\t= ", Pid_nr, e->seqno);
1695 fprintf(fd_tt, "settr(0,0,0,0,0,\"");
1696 in_settr++;
1697 comment(fd_tt, e->n, e->seqno);
1698 in_settr--;
1699 fprintf(fd_tt, "\",0,0,0);\n");
1700 } else
1701 { fprintf(fd_tt, "\ttrans[%d][%d]\t= ", Pid_nr, e->seqno);
1702 casenr = 1; /* mhs example */
1703 j = a;
1704 goto haveit; /* pakula's example */
1705 }
1706
1707 return -1;
1708 }
1709
1710 fprintf(fd_tt, "\ttrans[%d][%d]\t= ", Pid_nr, e->seqno);
1711
1712 if (ccache
1713 && !pid_is_claim(Pid_nr)
1714 && Pid_nr != eventmapnr
1715 && (Cached = prev_case(e, Pid_nr)))
1716 { bupcase = Cached->b;
1717 casenr = Cached->m;
1718 fromcache = 1;
1719
1720 fprintf(fd_tm, "// STATE %d - %s:%d - [",
1721 e->seqno, e->n->fn->name, e->n->ln);
1722 comment(fd_tm, e->n, 0);
1723 fprintf(fd_tm, "] (%d:%d - %d) same as %d (%d:%d - %d)\n",
1724 e->merge_start, e->merge, e->merge_in,
1725 casenr,
1726 Cached->e->merge_start, Cached->e->merge, Cached->e->merge_in);
1727
1728 goto gotit;
1729 }
1730
1731 fprintf(fd_tm, "\tcase %d: // STATE %d - %s:%d - [",
1732 uniq++, e->seqno, e->n->fn->name, e->n->ln);
1733 comment(fd_tm, e->n, 0);
1734 nrbups = (e->merge || e->merge_start) ? nrhops(e) : nr_bup(e);
1735 fprintf(fd_tm, "] (%d:%d:%d - %d)\n\t\t",
1736 e->merge_start, e->merge, nrbups, e->merge_in);
1737
1738 if (nrbups > MAXMERGE-1)
1739 fatal("merge requires more than 256 bups", (char *)0);
1740
1741 if (e->n->ntyp != 'r' && !pid_is_claim(Pid_nr) && Pid_nr != eventmapnr)
1742 fprintf(fd_tm, "IfNotBlocked\n\t\t");
1743
1744 if (multi_needed != 0 || multi_undo != 0)
1745 fatal("cannot happen, case_cache", (char *) 0);
1746
1747 if (nrbups > 1)
1748 { multi_oval = 1;
1749 multi_needed = nrbups; /* allocated after edge condition */
1750 } else
1751 multi_oval = 0;
1752
1753 memset(CnT, 0, sizeof(CnT));
1754 YZmax = YZcnt = 0;
1755
1756 /* new 4.2.6, revised 6.0.0 */
1757 if (pid_is_claim(Pid_nr))
1758 { fprintf(fd_tm, "\n#if defined(VERI) && !defined(NP)\n");
1759 fprintf(fd_tm, "#if NCLAIMS>1\n\t\t");
1760 fprintf(fd_tm, "{ static int reported%d = 0;\n\t\t", e->seqno);
1761 fprintf(fd_tm, " if (verbose && !reported%d)\n\t\t", e->seqno);
1762 fprintf(fd_tm, " { int nn = (int) ((Pclaim *)pptr(0))->_n;\n\t\t");
1763 fprintf(fd_tm, " printf(\"depth %%ld: Claim %%s (%%d), state %%d (line %%d)\\n\",\n\t\t");
1764 fprintf(fd_tm, " depth, procname[spin_c_typ[nn]], nn, ");
1765 fprintf(fd_tm, "(int) ((Pclaim *)pptr(0))->_p, src_claim[ (int) ((Pclaim *)pptr(0))->_p ]);\n\t\t");
1766 fprintf(fd_tm, " reported%d = 1;\n\t\t", e->seqno);
1767 fprintf(fd_tm, " fflush(stdout);\n\t\t");
1768 fprintf(fd_tm, "} }\n");
1769 fprintf(fd_tm, "#else\n\t\t");
1770 fprintf(fd_tm, "{ static int reported%d = 0;\n\t\t", e->seqno);
1771 fprintf(fd_tm, " if (verbose && !reported%d)\n\t\t", e->seqno);
1772 fprintf(fd_tm, " { printf(\"depth %%d: Claim, state %%d (line %%d)\\n\",\n\t\t");
1773 fprintf(fd_tm, " (int) depth, (int) ((Pclaim *)pptr(0))->_p, ");
1774 fprintf(fd_tm, "src_claim[ (int) ((Pclaim *)pptr(0))->_p ]);\n\t\t");
1775 fprintf(fd_tm, " reported%d = 1;\n\t\t", e->seqno);
1776 fprintf(fd_tm, " fflush(stdout);\n\t\t");
1777 fprintf(fd_tm, "} }\n");
1778 fprintf(fd_tm, "#endif\n");
1779 fprintf(fd_tm, "#endif\n\t\t");
1780 }
1781 /* end */
1782
1783 /* the src xrefs have the numbers in e->seqno builtin */
1784 fprintf(fd_tm, "reached[%d][%d] = 1;\n\t\t", Pid_nr, e->seqno);
1785
1786 doforward(fd_tm, e);
1787
1788 if (e->merge_start)
1789 ntarget = e->merge_start;
1790 else
1791 ntarget = e->merge;
1792
1793 if (ntarget)
1794 { f = e;
1795
1796 more: if (f->n->ntyp == GOTO)
1797 { g = get_lab(f->n, 1);
1798 if (g->seqno == ntarget)
1799 f = g;
1800 else
1801 f = huntele(g, f->status, ntarget);
1802 } else
1803 f = f->nxt;
1804
1805
1806 if (f && f->seqno != ntarget)
1807 { if (!f->merge && !f->merge_single)
1808 { fprintf(fd_tm, "/* stop at bad hop %d, %d */\n\t\t",
1809 f->seqno, ntarget);
1810 goto out;
1811 }
1812 fprintf(fd_tm, "/* merge: ");
1813 comment(fd_tm, f->n, 0);
1814 fprintf(fd_tm, "(%d, %d, %d) */\n\t\t", f->merge, f->seqno, ntarget);
1815 fprintf(fd_tm, "reached[%d][%d] = 1;\n\t\t", Pid_nr, f->seqno);
1816 YZcnt++;
1817 lab_transfer(e, f);
1818 mark = f->status&(ATOM|L_ATOM); /* last step wins */
1819 doforward(fd_tm, f);
1820 if (f->merge_in == 1) f->merge_mark++;
1821
1822 goto more;
1823 } }
1824 out:
1825 fprintf(fd_tm, "_m = %d", getweight(e->n));
1826 if (m_loss && e->n->ntyp == 's') fprintf(fd_tm, "+delta_m; delta_m = 0");
1827 fprintf(fd_tm, "; goto P999; /* %d */\n", YZcnt);
1828
1829 multi_needed = 0;
1830 didcase = 0;
1831
1832 if (ntarget)
1833 lastfirst(ntarget, e, casenr); /* mergesteps only */
1834
1835 dobackward(e, casenr); /* the original step */
1836
1837 fprintf(fd_tb, ";\n\t\t");
1838
1839 if (e->merge || e->merge_start)
1840 { if (!didcase)
1841 { fprintf(fd_tb, "\n\tcase %d: ", casenr);
1842 fprintf(fd_tb, "// STATE %d", e->seqno);
1843 didcase++;
1844 } else
1845 fprintf(fd_tb, ";");
1846 } else
1847 fprintf(fd_tb, ";");
1848 fprintf(fd_tb, "\n\t\t");
1849
1850 if (multi_undo)
1851 { fprintf(fd_tb, "ungrab_ints(trpt->bup.ovals, %d);\n\t\t",
1852 multi_undo);
1853 multi_undo = 0;
1854 }
1855 if (didcase)
1856 { fprintf(fd_tb, "goto R999;\n");
1857 bupcase = casenr;
1858 }
1859
1860 if (!e->merge && !e->merge_start)
1861 new_case(e, casenr, bupcase, Pid_nr);
1862
1863 gotit:
1864 j = a;
1865 if (e->merge_start)
1866 j = e->merge_start;
1867 else if (e->merge)
1868 j = e->merge;
1869 haveit:
1870 fprintf(fd_tt, "%ssettr(%d,%d,%d,%d,%d,\"", fromcache?"/* c */ ":"",
1871 e->Seqno, mark, j, casenr, bupcase);
1872
1873 return (fromcache)?0:casenr;
1874 }
1875
1876 static void
put_el(Element * e,int Tt0,int Tt1)1877 put_el(Element *e, int Tt0, int Tt1)
1878 { int a, casenr, Global_ref;
1879 Element *g = ZE;
1880
1881 if (e->n->ntyp == GOTO)
1882 { g = get_lab(e->n, 1);
1883 g = huntele(g, e->status, -1);
1884 cross_dsteps(e->n, g->n);
1885 a = g->seqno;
1886 } else if (e->nxt)
1887 { g = huntele(e->nxt, e->status, -1);
1888 a = g->seqno;
1889 } else
1890 a = 0;
1891 if (g
1892 && ((g->status&CHECK2) /* entering remotely ref'd state */
1893 || (e->status&CHECK2))) /* leaving remotely ref'd state */
1894 e->status |= I_GLOB;
1895
1896 /* don't remove dead edges in here, to preserve structure of fsm */
1897 if (e->merge_start || e->merge)
1898 goto non_generic;
1899
1900 /*** avoid duplicate or redundant cases in pan.m ***/
1901 switch (e->n->ntyp) {
1902 case ELSE:
1903 casenr = 2; /* standard else */
1904 putskip(e->seqno);
1905 goto generic_case;
1906 /* break; */
1907 case '.':
1908 case GOTO:
1909 case BREAK:
1910 putskip(e->seqno);
1911 casenr = 1; /* standard goto */
1912 generic_case: fprintf(fd_tt, "\ttrans[%d][%d]\t= ", Pid_nr, e->seqno);
1913 fprintf(fd_tt, "settr(%d,%d,%d,%d,0,\"",
1914 e->Seqno, e->status&ATOM, a, casenr);
1915 break;
1916 #ifndef PRINTF
1917 case PRINT:
1918 goto non_generic;
1919 case PRINTM:
1920 goto non_generic;
1921 #endif
1922 case 'c':
1923 if (e->n->lft->ntyp == CONST
1924 && e->n->lft->val == 1) /* skip or true */
1925 { casenr = 1;
1926 putskip(e->seqno);
1927 goto generic_case;
1928 }
1929 goto non_generic;
1930
1931 default:
1932 non_generic:
1933 casenr = case_cache(e, a);
1934 if (casenr < 0) return; /* unreachable state */
1935 break;
1936 }
1937 /* tailend of settr(...); */
1938 Global_ref = (e->status&I_GLOB)?1:has_global(e->n);
1939 in_settr++;
1940 comment(fd_tt, e->n, e->seqno);
1941 in_settr--;
1942 fprintf(fd_tt, "\", %d, ", Global_ref);
1943 if (Tt0 != 2)
1944 { fprintf(fd_tt, "%d, %d);", Tt0, Tt1);
1945 } else
1946 { Tpe(e->n); /* sets EPT */
1947 fprintf(fd_tt, "%d, %d);", EPT[0], EPT[1]);
1948 }
1949 if ((e->merge_start && e->merge_start != a)
1950 || (e->merge && e->merge != a))
1951 { fprintf(fd_tt, " /* m: %d -> %d,%d */\n",
1952 a, e->merge_start, e->merge);
1953 fprintf(fd_tt, " reached%d[%d] = 1;",
1954 Pid_nr, a); /* Sheinman's example */
1955 }
1956 fprintf(fd_tt, "\n");
1957
1958 if (casenr > 2)
1959 tr_map(casenr, e);
1960 put_escp(e);
1961 }
1962
1963 static void
nested_unless(Element * e,Element * g)1964 nested_unless(Element *e, Element *g)
1965 { struct SeqList *y = e->esc, *z = g->esc;
1966
1967 for ( ; y && z; y = y->nxt, z = z->nxt)
1968 if (z->this != y->this)
1969 break;
1970 if (!y && !z)
1971 return;
1972
1973 if (g->n->ntyp != GOTO
1974 && g->n->ntyp != '.'
1975 && e->sub->nxt)
1976 { printf("error: (%s:%d) saw 'unless' on a guard:\n",
1977 (e->n)?e->n->fn->name:"-",
1978 (e->n)?e->n->ln:0);
1979 printf("=====>instead of\n");
1980 printf(" do (or if)\n");
1981 printf(" :: ...\n");
1982 printf(" :: stmnt1 unless stmnt2\n");
1983 printf(" od (of fi)\n");
1984 printf("=====>use\n");
1985 printf(" do (or if)\n");
1986 printf(" :: ...\n");
1987 printf(" :: stmnt1\n");
1988 printf(" od (or fi) unless stmnt2\n");
1989 printf("=====>or rewrite\n");
1990 }
1991 }
1992
1993 static void
put_seq(Sequence * s,int Tt0,int Tt1)1994 put_seq(Sequence *s, int Tt0, int Tt1)
1995 { SeqList *h;
1996 Element *e, *g;
1997 int a, deadlink;
1998
1999 if (0) printf("put_seq %d\n", s->frst->seqno);
2000
2001 for (e = s->frst; e; e = e->nxt)
2002 {
2003 if (0) printf(" step %d\n", e->seqno);
2004 if (e->status & DONE)
2005 {
2006 if (0) printf(" done before\n");
2007 goto checklast;
2008 }
2009 e->status |= DONE;
2010
2011 if (e->n->ln)
2012 putsrc(e);
2013
2014 if (e->n->ntyp == UNLESS)
2015 {
2016 if (0) printf(" an unless\n");
2017 put_seq(e->sub->this, Tt0, Tt1);
2018 } else if (e->sub)
2019 {
2020 if (0) printf(" has sub\n");
2021 fprintf(fd_tt, "\tT = trans[%d][%d] = ",
2022 Pid_nr, e->seqno);
2023 fprintf(fd_tt, "settr(%d,%d,0,0,0,\"",
2024 e->Seqno, e->status&ATOM);
2025 in_settr++;
2026 comment(fd_tt, e->n, e->seqno);
2027 in_settr--;
2028 if (e->status&CHECK2)
2029 e->status |= I_GLOB;
2030 fprintf(fd_tt, "\", %d, %d, %d);",
2031 (e->status&I_GLOB)?1:0, Tt0, Tt1);
2032 blurb(fd_tt, e);
2033 for (h = e->sub; h; h = h->nxt)
2034 { putskip(h->this->frst->seqno);
2035 g = huntstart(h->this->frst);
2036 if (g->esc)
2037 nested_unless(e, g);
2038 a = g->seqno;
2039
2040 if (g->n->ntyp == 'c'
2041 && g->n->lft->ntyp == CONST
2042 && g->n->lft->val == 0 /* 0 or false */
2043 && !g->esc)
2044 { fprintf(fd_tt, "#if 0\n\t/* dead link: */\n");
2045 deadlink = 1;
2046 if (verbose&32)
2047 printf("spin: %s:%d, warning, condition is always false\n",
2048 g->n->fn?g->n->fn->name:"", g->n->ln);
2049 } else
2050 deadlink = 0;
2051 if (0) printf(" settr %d %d\n", a, 0);
2052 if (h->nxt)
2053 fprintf(fd_tt, "\tT = T->nxt\t= ");
2054 else
2055 fprintf(fd_tt, "\t T->nxt\t= ");
2056 fprintf(fd_tt, "settr(%d,%d,%d,0,0,\"",
2057 e->Seqno, e->status&ATOM, a);
2058 in_settr++;
2059 comment(fd_tt, e->n, e->seqno);
2060 in_settr--;
2061 if (g->status&CHECK2)
2062 h->this->frst->status |= I_GLOB;
2063 fprintf(fd_tt, "\", %d, %d, %d);",
2064 (h->this->frst->status&I_GLOB)?1:0,
2065 Tt0, Tt1);
2066 blurb(fd_tt, e);
2067 if (deadlink)
2068 fprintf(fd_tt, "#endif\n");
2069 }
2070 for (h = e->sub; h; h = h->nxt)
2071 put_seq(h->this, Tt0, Tt1);
2072 } else
2073 {
2074 if (0) printf(" [non]atomic %d\n", e->n->ntyp);
2075 if (e->n->ntyp == ATOMIC
2076 || e->n->ntyp == D_STEP
2077 || e->n->ntyp == NON_ATOMIC)
2078 put_sub(e, Tt0, Tt1);
2079 else
2080 {
2081 if (0) printf(" put_el %d\n", e->seqno);
2082 put_el(e, Tt0, Tt1);
2083 }
2084 }
2085 checklast: if (e == s->last)
2086 break;
2087 }
2088 if (0) printf("put_seq done\n");
2089 }
2090
2091 static void
patch_atomic(Sequence * s)2092 patch_atomic(Sequence *s) /* catch goto's that break the chain */
2093 { Element *f, *g;
2094 SeqList *h;
2095
2096 for (f = s->frst; f ; f = f->nxt)
2097 {
2098 if (f->n && f->n->ntyp == GOTO)
2099 { g = get_lab(f->n,1);
2100 cross_dsteps(f->n, g->n);
2101 if ((f->status & (ATOM|L_ATOM))
2102 && !(g->status & (ATOM|L_ATOM)))
2103 { f->status &= ~ATOM;
2104 f->status |= L_ATOM;
2105 }
2106 /* bridge atomics */
2107 if ((f->status & L_ATOM)
2108 && (g->status & (ATOM|L_ATOM)))
2109 { f->status &= ~L_ATOM;
2110 f->status |= ATOM;
2111 }
2112 } else
2113 for (h = f->sub; h; h = h->nxt)
2114 patch_atomic(h->this);
2115 if (f == s->extent)
2116 break;
2117 }
2118 }
2119
2120 static void
mark_seq(Sequence * s)2121 mark_seq(Sequence *s)
2122 { Element *f;
2123 SeqList *h;
2124
2125 for (f = s->frst; f; f = f->nxt)
2126 { f->status |= I_GLOB;
2127
2128 if (f->n->ntyp == ATOMIC
2129 || f->n->ntyp == NON_ATOMIC
2130 || f->n->ntyp == D_STEP)
2131 mark_seq(f->n->sl->this);
2132
2133 for (h = f->sub; h; h = h->nxt)
2134 mark_seq(h->this);
2135 if (f == s->last)
2136 return;
2137 }
2138 }
2139
2140 static Element *
find_target(Element * e)2141 find_target(Element *e)
2142 { Element *f;
2143
2144 if (!e) return e;
2145
2146 if (t_cyc++ > 32)
2147 { fatal("cycle of goto jumps", (char *) 0);
2148 }
2149 switch (e->n->ntyp) {
2150 case GOTO:
2151 f = get_lab(e->n,1);
2152 cross_dsteps(e->n, f->n);
2153 f = find_target(f);
2154 break;
2155 case BREAK:
2156 if (e->nxt)
2157 { f = find_target(huntele(e->nxt, e->status, -1));
2158 break; /* new 5.0 -- was missing */
2159 }
2160 /* else fall through */
2161 default:
2162 f = e;
2163 break;
2164 }
2165 return f;
2166 }
2167
2168 Element *
target(Element * e)2169 target(Element *e)
2170 {
2171 if (!e) return e;
2172 lineno = e->n->ln;
2173 Fname = e->n->fn;
2174 t_cyc = 0;
2175 return find_target(e);
2176 }
2177
2178 static int
seq_has_el(Sequence * s,Element * g)2179 seq_has_el(Sequence *s, Element *g) /* new to version 5.0 */
2180 { Element *f;
2181 SeqList *h;
2182
2183 for (f = s->frst; f; f = f->nxt) /* g in same atomic? */
2184 { if (f == g)
2185 { return 1;
2186 }
2187 if (f->status & CHECK3)
2188 { continue;
2189 }
2190 f->status |= CHECK3; /* protect against cycles */
2191 for (h = f->sub; h; h = h->nxt)
2192 { if (h->this && seq_has_el(h->this, g))
2193 { return 1;
2194 } } }
2195 return 0;
2196 }
2197
2198 static int
scan_seq(Sequence * s)2199 scan_seq(Sequence *s)
2200 { Element *f, *g;
2201 SeqList *h;
2202
2203 for (f = s->frst; f; f = f->nxt)
2204 { if ((f->status&CHECK2)
2205 || has_global(f->n))
2206 return 1;
2207 if (f->n->ntyp == GOTO /* may exit or reach other atomic */
2208 && !(f->status & D_ATOM)) /* cannot jump from d_step */
2209 { /* consider jump from an atomic without globals into
2210 * an atomic with globals
2211 * example by Claus Traulsen, 22 June 2007
2212 */
2213 g = target(f);
2214 #if 1
2215 if (g && !seq_has_el(s, g)) /* not internal to this atomic/dstep */
2216
2217 #else
2218 if (g
2219 && !(f->status & L_ATOM)
2220 && !(g->status & (ATOM|L_ATOM)))
2221 #endif
2222 { fprintf(fd_tt, "\t/* mark-down line %d status %d = %d */\n", f->n->ln, f->status, (f->status & D_ATOM));
2223 return 1; /* assume worst case */
2224 } }
2225 for (h = f->sub; h; h = h->nxt)
2226 if (scan_seq(h->this))
2227 return 1;
2228 if (f == s->last)
2229 break;
2230 }
2231 return 0;
2232 }
2233
2234 static int
glob_args(Lextok * n)2235 glob_args(Lextok *n)
2236 { int result = 0;
2237 Lextok *v;
2238
2239 for (v = n->rgt; v; v = v->rgt)
2240 { if (v->lft->ntyp == CONST)
2241 continue;
2242 if (v->lft->ntyp == EVAL)
2243 result += has_global(v->lft->lft);
2244 else
2245 result += has_global(v->lft);
2246 }
2247 return result;
2248 }
2249
2250 static int
proc_is_safe(const Lextok * n)2251 proc_is_safe(const Lextok *n)
2252 { ProcList *p;
2253 /* not safe unless no local var inits are used */
2254 /* note that a local variable init could refer to a global */
2255
2256 for (p = ready; p; p = p->nxt)
2257 { if (strcmp(n->sym->name, p->n->name) == 0)
2258 { /* printf("proc %s safety: %d\n", p->n->name, p->unsafe); */
2259 return (p->unsafe != 0);
2260 } }
2261 /* non_fatal("bad call to proc_is_safe", (char *) 0); */
2262 /* cannot happen */
2263 return 0;
2264 }
2265
2266 int
has_global(Lextok * n)2267 has_global(Lextok *n)
2268 { Lextok *v;
2269 static Symbol *n_seen = (Symbol *) 0;
2270
2271 if (!n) return 0;
2272 if (AllGlobal) return 1; /* global provided clause */
2273
2274 switch (n->ntyp) {
2275 case ATOMIC:
2276 case D_STEP:
2277 case NON_ATOMIC:
2278 return scan_seq(n->sl->this);
2279
2280 case '.':
2281 case BREAK:
2282 case GOTO:
2283 case CONST:
2284 return 0;
2285
2286 case ELSE: return n->val; /* true if combined with chan refs */
2287
2288 case 's': return glob_args(n)!=0 || ((n->sym->xu&(XS|XX)) != XS);
2289 case 'r': return glob_args(n)!=0 || ((n->sym->xu&(XR|XX)) != XR);
2290 case 'R': return glob_args(n)!=0 || (((n->sym->xu)&(XR|XS|XX)) != (XR|XS));
2291 case NEMPTY: return ((n->sym->xu&(XR|XX)) != XR);
2292 case NFULL: return ((n->sym->xu&(XS|XX)) != XS);
2293 case FULL: return ((n->sym->xu&(XR|XX)) != XR);
2294 case EMPTY: return ((n->sym->xu&(XS|XX)) != XS);
2295 case LEN: return (((n->sym->xu)&(XR|XS|XX)) != (XR|XS));
2296
2297 case NAME:
2298 if (strcmp(n->sym->name, "_priority") == 0)
2299 { if (old_priority_rules)
2300 { if (n_seen != n->sym)
2301 fatal("cannot refer to _priority with -o6", (char *) 0);
2302 n_seen = n->sym;
2303 }
2304 return 0;
2305 }
2306 if (n->sym->context
2307 || (n->sym->hidden&64)
2308 || strcmp(n->sym->name, "_pid") == 0
2309 || strcmp(n->sym->name, "_") == 0)
2310 return 0;
2311 return 1;
2312
2313 case RUN:
2314 return proc_is_safe(n);
2315
2316 case C_CODE: case C_EXPR:
2317 return glob_inline(n->sym->name);
2318
2319 case ENABLED: case PC_VAL: case NONPROGRESS:
2320 case 'p': case 'q':
2321 case TIMEOUT: case SET_P: case GET_P:
2322 return 1;
2323
2324 /* @ was 1 (global) since 2.8.5
2325 in 3.0 it is considered local and
2326 conditionally safe, provided:
2327 II is the youngest process
2328 and nrprocs < MAXPROCS
2329 */
2330 case '@': return 0;
2331
2332 case '!': case UMIN: case '~': case ASSERT:
2333 return has_global(n->lft);
2334
2335 case '/': case '*': case '-': case '+':
2336 case '%': case LT: case GT: case '&': case '^':
2337 case '|': case LE: case GE: case NE: case '?':
2338 case EQ: case OR: case AND: case LSHIFT:
2339 case RSHIFT: case 'c': case ASGN:
2340 return has_global(n->lft) || has_global(n->rgt);
2341
2342 case PRINT:
2343 for (v = n->lft; v; v = v->rgt)
2344 if (has_global(v->lft)) return 1;
2345 return 0;
2346 case PRINTM:
2347 return has_global(n->lft);
2348 }
2349 return 0;
2350 }
2351
2352 static void
Bailout(FILE * fd,char * str)2353 Bailout(FILE *fd, char *str)
2354 {
2355 if (!GenCode)
2356 { fprintf(fd, "continue%s", str);
2357 } else if (IsGuard)
2358 { fprintf(fd, "%s%s", NextLab[Level], str);
2359 } else
2360 { fprintf(fd, "Uerror(\"block in d_step seq\")%s", str);
2361 }
2362 }
2363
2364 #define cat0(x) putstmnt(fd,now->lft,m); fprintf(fd, x); \
2365 putstmnt(fd,now->rgt,m)
2366 #define cat1(x) fprintf(fd,"("); cat0(x); fprintf(fd,")")
2367 #define cat2(x,y) fprintf(fd,x); putstmnt(fd,y,m)
2368 #define cat3(x,y,z) fprintf(fd,x); putstmnt(fd,y,m); fprintf(fd,z)
2369 #define cat30(x,y,z) fprintf(fd,x,0); putstmnt(fd,y,m); fprintf(fd,z)
2370
2371 extern void explain(int);
2372 void
dump_tree(const char * s,Lextok * p)2373 dump_tree(const char *s, Lextok *p)
2374 { char z[64];
2375
2376 if (!p) return;
2377
2378 printf("\n%s:\t%2d:\t%3d (", s, p->ln, p->ntyp);
2379 explain(p->ntyp);
2380 if (p->ntyp == 315) printf(": %s", p->sym->name);
2381 if (p->ntyp == 312) printf(": %d", p->val);
2382 printf(")");
2383
2384 if (p->lft) { sprintf(z, "%sL", s); dump_tree(z, p->lft); }
2385 if (p->rgt) { sprintf(z, "%sR", s); dump_tree(z, p->rgt); }
2386 }
2387
2388 void
putstmnt(FILE * fd,Lextok * now,int m)2389 putstmnt(FILE *fd, Lextok *now, int m)
2390 { Lextok *v;
2391 int i, j;
2392
2393 if (!now) { fprintf(fd, "0"); return; }
2394 lineno = now->ln;
2395 Fname = now->fn;
2396
2397 switch (now->ntyp) {
2398 case CONST: fprintf(fd, "%d", now->val); break;
2399 case '!': cat3(" !(", now->lft, ")"); break;
2400 case UMIN: cat3(" -(", now->lft, ")"); break;
2401 case '~': cat3(" ~(", now->lft, ")"); break;
2402
2403 case '/': cat1("/"); break;
2404 case '*': cat1("*"); break;
2405 case '-': cat1("-"); break;
2406 case '+': cat1("+"); break;
2407 case '%': cat1("%%"); break;
2408 case '&': cat1("&"); break;
2409 case '^': cat1("^"); break;
2410 case '|': cat1("|"); break;
2411 case LT: cat1("<"); break;
2412 case GT: cat1(">"); break;
2413 case LE: cat1("<="); break;
2414 case GE: cat1(">="); break;
2415 case NE: cat1("!="); break;
2416 case EQ: cat1("=="); break;
2417 case OR: cat1("||"); break;
2418 case AND: cat1("&&"); break;
2419 case LSHIFT: cat1("<<"); break;
2420 case RSHIFT: cat1(">>"); break;
2421
2422 case TIMEOUT:
2423 if (separate == 2)
2424 fprintf(fd, "((tau)&1)");
2425 else
2426 fprintf(fd, "((trpt->tau)&1)");
2427 if (GenCode)
2428 printf("spin: %s:%d, warning, 'timeout' in d_step sequence\n",
2429 Fname->name, lineno);
2430 /* is okay as a guard */
2431 break;
2432
2433 case RUN:
2434 if (now->sym == NULL)
2435 fatal("internal error pangen2.c", (char *) 0);
2436 if (claimproc
2437 && strcmp(now->sym->name, claimproc) == 0)
2438 fatal("claim %s, (not runnable)", claimproc);
2439 if (eventmap
2440 && strcmp(now->sym->name, eventmap) == 0)
2441 fatal("eventmap %s, (not runnable)", eventmap);
2442
2443 if (GenCode)
2444 fatal("'run' in d_step sequence (use atomic)", (char *)0);
2445
2446 fprintf(fd,"addproc(II, %d, %d",
2447 (now->val > 0 && !old_priority_rules) ? now->val : 1,
2448 fproc(now->sym->name));
2449 for (v = now->lft, i = 0; v; v = v->rgt, i++)
2450 { cat2(", ", v->lft);
2451 }
2452 check_param_count(i, now);
2453
2454 if (i > Npars)
2455 { /* printf("\t%d parameters used, max %d expected\n", i, Npars); */
2456 fatal("too many parameters in run %s(...)", now->sym->name);
2457 }
2458 for ( ; i < Npars; i++)
2459 fprintf(fd, ", 0");
2460 fprintf(fd, ")");
2461 check_mtypes(now, now->lft);
2462 #if 0
2463 /* process now->sym->name has run priority now->val */
2464 if (now->val > 0 && now->val < 256 && !old_priority_rules)
2465 { fprintf(fd, " && (((P0 *)pptr(now._nr_pr - 1))->_priority = %d)", now->val);
2466 }
2467 #endif
2468 if (now->val < 0 || now->val > 255) /* 0 itself is allowed */
2469 { fatal("bad process in run %s, valid range: 1..255", now->sym->name);
2470 }
2471 break;
2472
2473 case ENABLED:
2474 cat3("enabled(II, ", now->lft, ")");
2475 break;
2476
2477 case GET_P:
2478 if (old_priority_rules)
2479 { fprintf(fd, "1");
2480 } else
2481 { cat3("get_priority(", now->lft, ")");
2482 }
2483 break;
2484
2485 case SET_P:
2486 if (!old_priority_rules)
2487 { fprintf(fd, "if (TstOnly) return 1; /* T30 */\n\t\t");
2488 fprintf(fd, "set_priority(");
2489 putstmnt(fd, now->lft->lft, m);
2490 fprintf(fd, ", ");
2491 putstmnt(fd, now->lft->rgt, m);
2492 fprintf(fd, ")");
2493 }
2494 break;
2495
2496 case NONPROGRESS:
2497 /* o_pm&4=progress, tau&128=claim stutter */
2498 if (separate == 2)
2499 fprintf(fd, "(!(o_pm&4) && !(tau&128))");
2500 else
2501 fprintf(fd, "(!(trpt->o_pm&4) && !(trpt->tau&128))");
2502 break;
2503
2504 case PC_VAL:
2505 cat3("((P0 *) Pptr(", now->lft, "+BASE))->_p");
2506 break;
2507
2508 case LEN:
2509 if (!terse && !TestOnly && has_xu)
2510 { fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
2511 putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
2512 putname(fd, "q_R_check(", now->lft, m, "");
2513 fprintf(fd, ", II)) &&\n\t\t");
2514 putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
2515 putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
2516 fprintf(fd, "\n#endif\n\t\t");
2517 }
2518 putname(fd, "q_len(", now->lft, m, ")");
2519 break;
2520
2521 case FULL:
2522 if (!terse && !TestOnly && has_xu)
2523 { fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
2524 putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
2525 putname(fd, "q_R_check(", now->lft, m, "");
2526 fprintf(fd, ", II)) &&\n\t\t");
2527 putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
2528 putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
2529 fprintf(fd, "\n#endif\n\t\t");
2530 }
2531 putname(fd, "q_full(", now->lft, m, ")");
2532 break;
2533
2534 case EMPTY:
2535 if (!terse && !TestOnly && has_xu)
2536 { fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
2537 putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
2538 putname(fd, "q_R_check(", now->lft, m, "");
2539 fprintf(fd, ", II)) &&\n\t\t");
2540 putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
2541 putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
2542 fprintf(fd, "\n#endif\n\t\t");
2543 }
2544 putname(fd, "(q_len(", now->lft, m, ")==0)");
2545 break;
2546
2547 case NFULL:
2548 if (!terse && !TestOnly && has_xu)
2549 { fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
2550 putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
2551 putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
2552 fprintf(fd, "\n#endif\n\t\t");
2553 }
2554 putname(fd, "(!q_full(", now->lft, m, "))");
2555 break;
2556
2557 case NEMPTY:
2558 if (!terse && !TestOnly && has_xu)
2559 { fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
2560 putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
2561 putname(fd, "q_R_check(", now->lft, m, ", II)) &&");
2562 fprintf(fd, "\n#endif\n\t\t");
2563 }
2564 putname(fd, "(q_len(", now->lft, m, ")>0)");
2565 break;
2566
2567 case 's':
2568 if (Pid_nr == eventmapnr)
2569 { fprintf(fd, "if ((II == -EVENT_TRACE && _tp != 's') ");
2570 putname(fd, "|| _qid+1 != ", now->lft, m, "");
2571 for (v = now->rgt, i=0; v; v = v->rgt, i++)
2572 { if (v->lft->ntyp != CONST
2573 && v->lft->ntyp != EVAL)
2574 continue;
2575 fprintf(fd, " \\\n\t\t|| qrecv(");
2576 putname(fd, "", now->lft, m, ", ");
2577 putname(fd, "q_len(", now->lft, m, ")-1, ");
2578 fprintf(fd, "%d, 0) != ", i);
2579 if (v->lft->ntyp == CONST)
2580 putstmnt(fd, v->lft, m);
2581 else /* EVAL */
2582 putstmnt(fd, v->lft->lft, m);
2583 }
2584 fprintf(fd, ")\n");
2585 fprintf(fd, "\t\t continue");
2586 putname(fd_th, " || (x_y3_ == ", now->lft, m, ")");
2587 break;
2588 }
2589 if (TestOnly)
2590 { if (m_loss)
2591 fprintf(fd, "1");
2592 else
2593 putname(fd, "!q_full(", now->lft, m, ")");
2594 break;
2595 }
2596 if (has_xu)
2597 { fprintf(fd, "\n#if !defined(XUSAFE) && !defined(NOREDUCE)\n\t\t");
2598 putname(fd, "if (q_claim[", now->lft, m, "]&2)\n\t\t");
2599 putname(fd, "{ q_S_check(", now->lft, m, ", II);\n\t\t");
2600 fprintf(fd, "}\n");
2601 if (has_sorted && now->val == 1)
2602 { putname(fd, "\t\tif (q_claim[", now->lft, m, "]&1)\n\t\t"); /* &1 iso &2 */
2603 fprintf(fd, "{ uerror(\"sorted send on xr channel violates po reduction\");\n\t\t");
2604 fprintf(fd, "}\n");
2605 }
2606 fprintf(fd, "#endif\n\t\t");
2607 }
2608 fprintf(fd, "if (q_%s",
2609 (u_sync > 0 && u_async == 0)?"len":"full");
2610 putname(fd, "(", now->lft, m, "))\n");
2611
2612 if (m_loss)
2613 { fprintf(fd, "\t\t{ nlost++; delta_m = 1; } else {");
2614 } else
2615 { fprintf(fd, "\t\t\t");
2616 Bailout(fd, ";");
2617 }
2618
2619 if (has_enabled || has_priority)
2620 fprintf(fd, "\n\t\tif (TstOnly) return 1; /* T1 */");
2621
2622 if (u_sync && !u_async && rvopt)
2623 fprintf(fd, "\n\n\t\tif (no_recvs(II)) continue;\n");
2624
2625 fprintf(fd, "\n#ifdef HAS_CODE\n");
2626 fprintf(fd, "\t\tif (readtrail && gui) {\n");
2627 fprintf(fd, "\t\t\tchar simtmp[64];\n");
2628 putname(fd, "\t\t\tsprintf(simvals, \"%%d!\", ", now->lft, m, ");\n");
2629 _isok++;
2630 for (v = now->rgt, i = 0; v; v = v->rgt, i++)
2631 { cat3("\t\tsprintf(simtmp, \"%%d\", ", v->lft, "); strcat(simvals, simtmp);");
2632 if (v->rgt)
2633 fprintf(fd, "\t\tstrcat(simvals, \",\");\n");
2634 }
2635 _isok--;
2636 fprintf(fd, "\t\t}\n");
2637 fprintf(fd, "#endif\n\t\t");
2638
2639 putname(fd, "\n\t\tqsend(", now->lft, m, "");
2640 fprintf(fd, ", %d", now->val);
2641 for (v = now->rgt, i = 0; v; v = v->rgt, i++)
2642 { cat2(", ", v->lft);
2643 }
2644 if (i > Mpars)
2645 { terse++;
2646 putname(stdout, "channel name: ", now->lft, m, "\n");
2647 terse--;
2648 printf(" %d msg parameters sent, %d expected\n", i, Mpars);
2649 fatal("too many pars in send", "");
2650 }
2651 for (j = i; i < Mpars; i++)
2652 { fprintf(fd, ", 0");
2653 }
2654 fprintf(fd, ", %d)", j);
2655 if (u_sync)
2656 { fprintf(fd, ";\n\t\t");
2657 if (u_async)
2658 { putname(fd, "if (q_zero(", now->lft, m, ")) ");
2659 }
2660 putname(fd, "{ boq = ", now->lft, m, "");
2661 if (GenCode)
2662 { fprintf(fd, "; Uerror(\"rv-attempt in d_step\")");
2663 }
2664 fprintf(fd, "; }");
2665 }
2666 if (m_loss)
2667 { fprintf(fd, ";\n\t\t}\n\t\t"); /* end of m_loss else */
2668 }
2669 break;
2670
2671 case 'r':
2672 if (Pid_nr == eventmapnr)
2673 { fprintf(fd, "if ((II == -EVENT_TRACE && _tp != 'r') ");
2674 putname(fd, "|| _qid+1 != ", now->lft, m, "");
2675 for (v = now->rgt, i=0; v; v = v->rgt, i++)
2676 { if (v->lft->ntyp != CONST
2677 && v->lft->ntyp != EVAL)
2678 continue;
2679 fprintf(fd, " \\\n\t\t|| qrecv(");
2680 putname(fd, "", now->lft, m, ", ");
2681 fprintf(fd, "0, %d, 0) != ", i);
2682 if (v->lft->ntyp == CONST)
2683 putstmnt(fd, v->lft, m);
2684 else /* EVAL */
2685 putstmnt(fd, v->lft->lft, m);
2686 }
2687 fprintf(fd, ")\n");
2688 fprintf(fd, "\t\t continue");
2689
2690 putname(fd_tc, " || (x_y3_ == ", now->lft, m, ")");
2691
2692 break;
2693 }
2694 if (TestOnly)
2695 { fprintf(fd, "((");
2696 if (u_sync) fprintf(fd, "(boq == -1 && ");
2697
2698 putname(fd, "q_len(", now->lft, m, ")");
2699
2700 if (u_sync && now->val <= 1)
2701 { putname(fd, ") || (boq == ", now->lft,m," && ");
2702 putname(fd, "q_zero(", now->lft,m,"))");
2703 }
2704
2705 fprintf(fd, ")");
2706 if (now->val == 0 || now->val == 2)
2707 { for (v = now->rgt, i=j=0; v; v = v->rgt, i++)
2708 { if (v->lft->ntyp == CONST)
2709 { cat3("\n\t\t&& (", v->lft, " == ");
2710 putname(fd, "qrecv(", now->lft, m, ", ");
2711 fprintf(fd, "0, %d, 0))", i);
2712 } else if (v->lft->ntyp == EVAL)
2713 { cat3("\n\t\t&& (", v->lft->lft, " == ");
2714 putname(fd, "qrecv(", now->lft, m, ", ");
2715 fprintf(fd, "0, %d, 0))", i);
2716 } else
2717 { j++; continue;
2718 }
2719 }
2720 } else
2721 { fprintf(fd, "\n\t\t&& Q_has(");
2722 putname(fd, "", now->lft, m, "");
2723 for (v = now->rgt, i=0; v; v = v->rgt, i++)
2724 { if (v->lft->ntyp == CONST)
2725 { fprintf(fd, ", 1, ");
2726 putstmnt(fd, v->lft, m);
2727 } else if (v->lft->ntyp == EVAL)
2728 { if (v->lft->lft->ntyp == ',') /* usertype1 */
2729 { if (0) { dump_tree("1", v->lft->lft); }
2730 Lextok *fix = v->lft->lft;
2731 do { i++;
2732 fprintf(fd, ", 1, ");
2733 putstmnt(fd, fix->lft, m);
2734 fix = fix->rgt;
2735 } while (fix && fix->ntyp == ',');
2736 } else
2737 { fprintf(fd, ", 1, ");
2738 putstmnt(fd, v->lft->lft, m);
2739 }
2740 } else
2741 { fprintf(fd, ", 0, 0");
2742 } }
2743 for ( ; i < Mpars; i++)
2744 { fprintf(fd, ", 0, 0");
2745 }
2746 fprintf(fd, ")");
2747 }
2748 fprintf(fd, ")");
2749 break;
2750 }
2751 if (has_xu)
2752 { fprintf(fd, "\n#if !defined(XUSAFE) && !defined(NOREDUCE)\n\t\t");
2753 putname(fd, "if (q_claim[", now->lft, m, "]&1)\n\t\t");
2754 putname(fd, "{ q_R_check(", now->lft, m, ", II);\n\t\t");
2755 if (has_random && now->val != 0)
2756 fprintf(fd, " uerror(\"rand receive on xr channel violates po reduction\");\n\t\t");
2757 fprintf(fd, "}\n");
2758 fprintf(fd, "#endif\n\t\t");
2759 }
2760 if (u_sync)
2761 { if (now->val >= 2)
2762 { if (u_async)
2763 { fprintf(fd, "if (");
2764 putname(fd, "q_zero(", now->lft,m,"))");
2765 fprintf(fd, "\n\t\t{\t");
2766 }
2767 fprintf(fd, "uerror(\"polling ");
2768 fprintf(fd, "rv chan\");\n\t\t");
2769 if (u_async)
2770 fprintf(fd, " continue;\n\t\t}\n\t\t");
2771 fprintf(fd, "IfNotBlocked\n\t\t");
2772 } else
2773 { fprintf(fd, "if (");
2774 if (u_async == 0)
2775 putname(fd, "boq != ", now->lft,m,") ");
2776 else
2777 { putname(fd, "q_zero(", now->lft,m,"))");
2778 fprintf(fd, "\n\t\t{\tif (boq != ");
2779 putname(fd, "", now->lft,m,") ");
2780 Bailout(fd, ";\n\t\t} else\n\t\t");
2781 fprintf(fd, "{\tif (boq != -1) ");
2782 }
2783 Bailout(fd, ";\n\t\t");
2784 if (u_async)
2785 fprintf(fd, "}\n\t\t");
2786 } }
2787 putname(fd, "if (q_len(", now->lft, m, ") == 0) ");
2788 Bailout(fd, "");
2789
2790 for (v = now->rgt, j=0; v; v = v->rgt)
2791 { if (v->lft->ntyp != CONST
2792 && v->lft->ntyp != EVAL)
2793 { j++; /* count settables */
2794 } }
2795
2796 fprintf(fd, ";\n\n\t\tXX=1");
2797 /* test */ if (now->val == 0 || now->val == 2)
2798 { for (v = now->rgt, i=0; v; v = v->rgt, i++)
2799 { if (v->lft->ntyp == CONST)
2800 { fprintf(fd, ";\n\t\t");
2801 cat3("if (", v->lft, " != ");
2802 putname(fd, "qrecv(", now->lft, m, ", ");
2803 fprintf(fd, "0, %d, 0)) ", i);
2804 Bailout(fd, "");
2805 } else if (v->lft->ntyp == EVAL)
2806 { fprintf(fd, ";\n\t\t");
2807 cat3("if (", v->lft->lft, " != ");
2808 putname(fd, "qrecv(", now->lft, m, ", ");
2809 fprintf(fd, "0, %d, 0)) ", i);
2810 Bailout(fd, "");
2811 } }
2812 if (has_enabled || has_priority)
2813 fprintf(fd, ";\n\t\tif (TstOnly) return 1 /* T2 */");
2814 } else /* random receive: val 1 or 3 */
2815 { fprintf(fd, ";\n\t\tif (!(XX = Q_has(");
2816 putname(fd, "", now->lft, m, "");
2817 for (v = now->rgt, i=0; v; v = v->rgt, i++)
2818 { if (v->lft->ntyp == CONST)
2819 { fprintf(fd, ", 1, ");
2820 putstmnt(fd, v->lft, m);
2821 } else if (v->lft->ntyp == EVAL)
2822 { if (v->lft->lft->ntyp == ',') /* usertype2 */
2823 { if (0) { dump_tree("2", v->lft->lft); }
2824 Lextok *fix = v->lft->lft;
2825 do { i++;
2826 fprintf(fd, ", 1, ");
2827 putstmnt(fd, fix->lft, m);
2828 fix = fix->rgt;
2829 } while (fix && fix->ntyp == ',');
2830 } else
2831 { fprintf(fd, ", 1, ");
2832 putstmnt(fd, v->lft->lft, m);
2833 }
2834 } else
2835 { fprintf(fd, ", 0, 0");
2836 } }
2837 for ( ; i < Mpars; i++)
2838 { fprintf(fd, ", 0, 0");
2839 }
2840 fprintf(fd, "))) ");
2841 Bailout(fd, "");
2842
2843 if (has_enabled || has_priority)
2844 { fprintf(fd, ";\n\t\tif (TstOnly) return 1 /* T2 */");
2845 }
2846 if (!GenCode)
2847 { fprintf(fd, ";\n\t\t");
2848 if (multi_oval)
2849 { check_needed();
2850 fprintf(fd, "(trpt+1)->bup.ovals[%d] = ",
2851 multi_oval-1);
2852 multi_oval++;
2853 } else
2854 { fprintf(fd, "(trpt+1)->bup.oval = ");
2855 }
2856 fprintf(fd, "XX");
2857 } }
2858
2859 if (j == 0 && now->val >= 2)
2860 { fprintf(fd, ";\n\t\t");
2861 break; /* poll without side-effect */
2862 }
2863
2864 if (!GenCode)
2865 { int jj = 0;
2866 fprintf(fd, ";\n\t\t");
2867 /* no variables modified */
2868 if (j == 0 && now->val == 0)
2869 { fprintf(fd, "\n#ifndef BFS_PAR\n\t\t");
2870 /* q_flds values are not shared among cores */
2871 fprintf(fd, "if (q_flds[((Q0 *)qptr(");
2872 putname(fd, "", now->lft, m, "-1))->_t]");
2873 fprintf(fd, " != %d)\n\t\t\t", i);
2874 fprintf(fd, "Uerror(\"wrong nr of msg fields in rcv\");\n");
2875 fprintf(fd, "#endif\n\t\t");
2876 }
2877
2878 for (v = now->rgt; v; v = v->rgt)
2879 { if ((v->lft->ntyp != CONST
2880 && v->lft->ntyp != EVAL))
2881 { jj++; /* nr of vars needing bup */
2882 } }
2883
2884 if (jj)
2885 for (v = now->rgt, i = 0; v; v = v->rgt, i++)
2886 { char tempbuf[64];
2887
2888 if ((v->lft->ntyp == CONST
2889 || v->lft->ntyp == EVAL))
2890 continue;
2891
2892 if (multi_oval)
2893 { check_needed();
2894 sprintf(tempbuf, "(trpt+1)->bup.ovals[%d] = ",
2895 multi_oval-1);
2896 multi_oval++;
2897 } else
2898 sprintf(tempbuf, "(trpt+1)->bup.oval = ");
2899
2900 if (v->lft->sym && !strcmp(v->lft->sym->name, "_"))
2901 { fprintf(fd, tempbuf, (char *) 0);
2902 putname(fd, "qrecv(", now->lft, m, "");
2903 fprintf(fd, ", XX-1, %d, 0);\n\t\t", i);
2904 } else
2905 { _isok++;
2906 cat30(tempbuf, v->lft, ";\n\t\t");
2907 _isok--;
2908 }
2909 }
2910
2911 if (jj) /* check for double entries q?x,x */
2912 { Lextok *w;
2913
2914 for (v = now->rgt; v; v = v->rgt)
2915 { if (v->lft->ntyp != CONST
2916 && v->lft->ntyp != EVAL
2917 && v->lft->sym
2918 && v->lft->sym->type != STRUCT /* not a struct */
2919 && (v->lft->sym->nel == 1 && v->lft->sym->isarray == 0) /* not array */
2920 && strcmp(v->lft->sym->name, "_") != 0)
2921 for (w = v->rgt; w; w = w->rgt)
2922 if (v->lft->sym == w->lft->sym)
2923 { fatal("cannot use var ('%s') in multiple msg fields",
2924 v->lft->sym->name);
2925 } } }
2926 }
2927 /* set */ for (v = now->rgt, i = 0; v; v = v->rgt, i++)
2928 {
2929 if (v->lft->ntyp == CONST && v->rgt)
2930 { continue;
2931 }
2932
2933 if (v->lft->ntyp == EVAL)
2934 { Lextok *fix = v->lft->lft;
2935 int old_i = i;
2936 while (fix && fix->ntyp == ',') /* usertype9 */
2937 { i++;
2938 fix = fix->rgt;
2939 }
2940 if (i > old_i)
2941 { i--; /* next increment handles it */
2942 }
2943 if (v->rgt)
2944 { continue;
2945 }
2946 }
2947 fprintf(fd, ";\n\t\t");
2948
2949 if (v->lft->ntyp != CONST
2950 && v->lft->ntyp != EVAL
2951 && v->lft->sym != NULL
2952 && strcmp(v->lft->sym->name, "_") != 0)
2953 { nocast=1;
2954 _isok++;
2955 putstmnt(fd, v->lft, m);
2956 _isok--;
2957 nocast=0;
2958 fprintf(fd, " = ");
2959 }
2960
2961 putname(fd, "qrecv(", now->lft, m, ", ");
2962 fprintf(fd, "XX-1, %d, ", i);
2963 fprintf(fd, "%d)", (v->rgt || now->val >= 2)?0:1);
2964
2965 if (v->lft->ntyp != CONST
2966 && v->lft->ntyp != EVAL
2967 && v->lft->sym != NULL
2968 && strcmp(v->lft->sym->name, "_") != 0
2969 && (v->lft->ntyp != NAME
2970 || v->lft->sym->type != CHAN))
2971 { fprintf(fd, ";\n#ifdef VAR_RANGES");
2972 fprintf(fd, "\n\t\tlogval(\"");
2973 withprocname = terse = nocast = 1;
2974 _isok++;
2975 putstmnt(fd,v->lft,m);
2976 withprocname = terse = nocast = 0;
2977 fprintf(fd, "\", ");
2978 putstmnt(fd,v->lft,m);
2979 _isok--;
2980 fprintf(fd, ");\n#endif\n");
2981 fprintf(fd, "\t\t");
2982 }
2983 }
2984 fprintf(fd, ";\n\t\t");
2985
2986 fprintf(fd, "\n#ifdef HAS_CODE\n");
2987 fprintf(fd, "\t\tif (readtrail && gui) {\n");
2988 fprintf(fd, "\t\t\tchar simtmp[32];\n");
2989 putname(fd, "\t\t\tsprintf(simvals, \"%%d?\", ", now->lft, m, ");\n");
2990 _isok++;
2991 for (v = now->rgt, i = 0; v; v = v->rgt, i++)
2992 { if (v->lft->ntyp != EVAL)
2993 { cat3("\t\t\tsprintf(simtmp, \"%%d\", ", v->lft, "); strcat(simvals, simtmp);");
2994 } else
2995 { if (v->lft->lft->ntyp == ',') /* usertype4 */
2996 { if (0) { dump_tree("4", v->lft->lft); }
2997 Lextok *fix = v->lft->lft;
2998 do { i++;
2999 cat3("\n\t\t\tsprintf(simtmp, \"%%d,\", ", fix->lft, "); strcat(simvals, simtmp);");
3000 fix = fix->rgt;
3001 } while (fix && fix->ntyp == ',');
3002 } else
3003 { cat3("\n\t\t\tsprintf(simtmp, \"%%d\", ", v->lft->lft, "); strcat(simvals, simtmp);");
3004 } }
3005 if (v->rgt)
3006 { fprintf(fd, "\n\t\t\tstrcat(simvals, \",\");\n");
3007 } }
3008 _isok--;
3009 fprintf(fd, "\n\t\t}\n");
3010 fprintf(fd, "#endif\n\t\t");
3011
3012 if (u_sync)
3013 { putname(fd, "if (q_zero(", now->lft, m, "))");
3014 fprintf(fd, "\n\t\t{ boq = -1;\n");
3015
3016 fprintf(fd, "#ifndef NOFAIR\n"); /* NEW 3.0.8 */
3017 fprintf(fd, "\t\t\tif (fairness\n");
3018 fprintf(fd, "\t\t\t&& !(trpt->o_pm&32)\n");
3019 fprintf(fd, "\t\t\t&& (now._a_t&2)\n");
3020 fprintf(fd, "\t\t\t&& now._cnt[now._a_t&1] == II+2)\n");
3021 fprintf(fd, "\t\t\t{ now._cnt[now._a_t&1] -= 1;\n");
3022 fprintf(fd, "#ifdef VERI\n");
3023 fprintf(fd, "\t\t\t if (II == 1)\n");
3024 fprintf(fd, "\t\t\t now._cnt[now._a_t&1] = 1;\n");
3025 fprintf(fd, "#endif\n");
3026 fprintf(fd, "#ifdef DEBUG\n");
3027 fprintf(fd, "\t\t\tprintf(\"%%3ld: proc %%d fairness \", depth, II);\n");
3028 fprintf(fd, "\t\t\tprintf(\"Rule 2: --cnt to %%d (%%d)\\n\",\n");
3029 fprintf(fd, "\t\t\t now._cnt[now._a_t&1], now._a_t);\n");
3030 fprintf(fd, "#endif\n");
3031 fprintf(fd, "\t\t\t trpt->o_pm |= (32|64);\n");
3032 fprintf(fd, "\t\t\t}\n");
3033 fprintf(fd, "#endif\n");
3034
3035 fprintf(fd, "\n\t\t}");
3036 }
3037 break;
3038
3039 case 'R':
3040 if (!terse && !TestOnly && has_xu)
3041 { fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
3042 putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
3043 fprintf(fd, "q_R_check(");
3044 putname(fd, "", now->lft, m, ", II)) &&\n\t\t");
3045 putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
3046 putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
3047 fprintf(fd, "\n#endif\n\t\t");
3048 }
3049 if (u_sync>0)
3050 putname(fd, "not_RV(", now->lft, m, ") && \\\n\t\t");
3051
3052 for (v = now->rgt, i=j=0; v; v = v->rgt, i++)
3053 if (v->lft->ntyp != CONST
3054 && v->lft->ntyp != EVAL)
3055 { j++; continue;
3056 }
3057 if (now->val == 0 || i == j)
3058 { putname(fd, "(q_len(", now->lft, m, ") > 0");
3059 for (v = now->rgt, i=0; v; v = v->rgt, i++)
3060 { if (v->lft->ntyp != CONST
3061 && v->lft->ntyp != EVAL)
3062 continue;
3063 fprintf(fd, " \\\n\t\t&& qrecv(");
3064 putname(fd, "", now->lft, m, ", ");
3065 fprintf(fd, "0, %d, 0) == ", i);
3066 if (v->lft->ntyp == CONST)
3067 { putstmnt(fd, v->lft, m);
3068 } else /* EVAL */
3069 { if (v->lft->lft->ntyp == ',') /* usertype2 */
3070 { if (0) { dump_tree("8", v->lft->lft); }
3071 Lextok *fix = v->lft->lft;
3072 do { i++;
3073 putstmnt(fd, fix->lft, m);
3074 fix = fix->rgt;
3075 } while (fix && fix->ntyp == ',');
3076 } else
3077 { putstmnt(fd, v->lft->lft, m);
3078 }
3079 }
3080 }
3081 fprintf(fd, ")");
3082 } else
3083 { putname(fd, "Q_has(", now->lft, m, "");
3084 for (v = now->rgt, i=0; v; v = v->rgt, i++)
3085 { if (v->lft->ntyp == CONST)
3086 { fprintf(fd, ", 1, ");
3087 putstmnt(fd, v->lft, m);
3088 } else if (v->lft->ntyp == EVAL)
3089 { if (v->lft->lft->ntyp == ',') /* usertype3 */
3090 { if (0) { dump_tree("3", v->lft->lft); }
3091 Lextok *fix = v->lft->lft;
3092 do { i++;
3093 fprintf(fd, ", 1, ");
3094 putstmnt(fd, fix->lft, m);
3095 fix = fix->rgt;
3096 } while (fix && fix->ntyp == ',');
3097 } else
3098 { fprintf(fd, ", 1, ");
3099 putstmnt(fd, v->lft->lft, m);
3100 }
3101 } else
3102 fprintf(fd, ", 0, 0");
3103 }
3104 for ( ; i < Mpars; i++)
3105 { fprintf(fd, ", 0, 0");
3106 }
3107 fprintf(fd, ")");
3108 }
3109 break;
3110
3111 case 'c':
3112 preruse(fd, now->lft); /* preconditions */
3113 cat3("if (!(", now->lft, "))\n\t\t\t");
3114 Bailout(fd, "");
3115 break;
3116
3117 case ELSE:
3118 if (!GenCode)
3119 { if (separate == 2)
3120 fprintf(fd, "if (o_pm&1)\n\t\t\t");
3121 else
3122 fprintf(fd, "if (trpt->o_pm&1)\n\t\t\t");
3123 Bailout(fd, "");
3124 } else
3125 { fprintf(fd, "/* else */");
3126 }
3127 break;
3128
3129 case '?':
3130 if (now->lft)
3131 { cat3("( (", now->lft, ") ? ");
3132 }
3133 if (now->rgt)
3134 { cat3("(", now->rgt->lft, ") : ");
3135 cat3("(", now->rgt->rgt, ") )");
3136 }
3137 break;
3138
3139 case ASGN:
3140 if (check_track(now) == STRUCT) { break; }
3141
3142 if (has_enabled || has_priority)
3143 fprintf(fd, "if (TstOnly) return 1; /* T3 */\n\t\t");
3144 _isok++;
3145
3146 if (!GenCode)
3147 { if (multi_oval)
3148 { char tempbuf[64];
3149 check_needed();
3150 sprintf(tempbuf, "(trpt+1)->bup.ovals[%d] = ",
3151 multi_oval-1);
3152 multi_oval++;
3153 cat30(tempbuf, now->lft, ";\n\t\t");
3154 } else
3155 { cat3("(trpt+1)->bup.oval = ", now->lft, ";\n\t\t");
3156 } }
3157 if (now->lft->sym
3158 && now->lft->sym->type == PREDEF
3159 && strcmp(now->lft->sym->name, "_") != 0
3160 && strcmp(now->lft->sym->name, "_priority") != 0)
3161 { fatal("invalid assignment to %s", now->lft->sym->name);
3162 }
3163
3164 nocast = 1; putstmnt(fd,now->lft,m); nocast = 0;
3165 fprintf(fd," = ");
3166 _isok--;
3167 if (now->lft->sym->isarray
3168 && now->rgt->ntyp == ',') /* array initializer */
3169 { putstmnt(fd, now->rgt->lft, m);
3170 non_fatal("cannot use an array list initializer here", (char *) 0);
3171 } else
3172 { putstmnt(fd, now->rgt, m);
3173 }
3174
3175 if (now->sym->type != CHAN
3176 || verbose > 0)
3177 { fprintf(fd, ";\n#ifdef VAR_RANGES");
3178 fprintf(fd, "\n\t\tlogval(\"");
3179 withprocname = terse = nocast = 1;
3180 _isok++;
3181 putstmnt(fd,now->lft,m);
3182 withprocname = terse = nocast = 0;
3183 fprintf(fd, "\", ");
3184 putstmnt(fd,now->lft,m);
3185 _isok--;
3186 fprintf(fd, ");\n#endif\n");
3187 fprintf(fd, "\t\t");
3188 }
3189 break;
3190
3191 case PRINT:
3192 if (has_enabled || has_priority)
3193 fprintf(fd, "if (TstOnly) return 1; /* T4 */\n\t\t");
3194 #ifdef PRINTF
3195 fprintf(fd, "printf(%s", now->sym->name);
3196 #else
3197 fprintf(fd, "Printf(%s", now->sym->name);
3198 #endif
3199 for (v = now->lft; v; v = v->rgt)
3200 { cat2(", ", v->lft);
3201 }
3202 fprintf(fd, ")");
3203 break;
3204
3205 case PRINTM:
3206 { char *s = 0;
3207 if (now->lft->sym
3208 && now->lft->sym->mtype_name)
3209 { s = now->lft->sym->mtype_name->name;
3210 }
3211
3212 if (has_enabled || has_priority)
3213 { fprintf(fd, "if (TstOnly) return 1; /* T5 */\n\t\t");
3214 }
3215 fprintf(fd, "/* YY */ printm(");
3216 if (now->lft
3217 && now->lft->ismtyp)
3218 { fprintf(fd, "%d", now->lft->val);
3219 } else
3220 { putstmnt(fd, now->lft, m);
3221 }
3222 if (s)
3223 { fprintf(fd, ", \"%s\"", s);
3224 } else
3225 { fprintf(fd, ", 0");
3226 }
3227 fprintf(fd, ")");
3228 }
3229 break;
3230
3231 case NAME:
3232 if (!nocast && now->sym && Sym_typ(now) < SHORT)
3233 putname(fd, "((int)", now, m, ")");
3234 else
3235 putname(fd, "", now, m, "");
3236 break;
3237
3238 case 'p':
3239 putremote(fd, now, m);
3240 break;
3241
3242 case 'q':
3243 if (terse)
3244 fprintf(fd, "%s", now->sym?now->sym->name:"?");
3245 else
3246 fprintf(fd, "%d", remotelab(now));
3247 break;
3248
3249 case C_EXPR:
3250 fprintf(fd, "(");
3251 plunk_expr(fd, now->sym->name);
3252 #if 1
3253 fprintf(fd, ")");
3254 #else
3255 fprintf(fd, ") /* %s */ ", now->sym->name);
3256 #endif
3257 break;
3258
3259 case C_CODE:
3260 if (now->sym)
3261 fprintf(fd, "/* %s */\n\t\t", now->sym->name);
3262 if (has_enabled || has_priority)
3263 fprintf(fd, "if (TstOnly) return 1; /* T6 */\n\t\t");
3264
3265 if (now->sym)
3266 plunk_inline(fd, now->sym->name, 1, GenCode);
3267 else
3268 fatal("internal error pangen2.c", (char *) 0);
3269
3270 if (!GenCode)
3271 { fprintf(fd, "\n"); /* state changed, capture it */
3272 fprintf(fd, "#if defined(C_States) && (HAS_TRACK==1)\n");
3273 fprintf(fd, "\t\tc_update((uchar *) &(now.c_state[0]));\n");
3274 fprintf(fd, "#endif\n");
3275 }
3276 break;
3277
3278 case ASSERT:
3279 if (has_enabled || has_priority)
3280 fprintf(fd, "if (TstOnly) return 1; /* T7 */\n\t\t");
3281
3282 cat3("spin_assert(", now->lft, ", ");
3283 terse = nocast = 1;
3284 cat3("\"", now->lft, "\", II, tt, t)");
3285 terse = nocast = 0;
3286 break;
3287
3288 case '.':
3289 case BREAK:
3290 case GOTO:
3291 if (Pid_nr == eventmapnr)
3292 fprintf(fd, "Uerror(\"cannot get here\")");
3293 putskip(m);
3294 break;
3295
3296 case '@':
3297 if (Pid_nr == eventmapnr)
3298 { fprintf(fd, "return 0");
3299 break;
3300 }
3301
3302 if (has_enabled || has_priority)
3303 { fprintf(fd, "if (TstOnly)\n\t\t\t");
3304 fprintf(fd, "return (II+1 == now._nr_pr);\n\t\t");
3305 }
3306 fprintf(fd, "if (!delproc(1, II)) ");
3307 Bailout(fd, "");
3308 break;
3309
3310 default:
3311 printf("spin: error, %s:%d, bad node type %d (.m)\n",
3312 now->fn->name, now->ln, now->ntyp);
3313 fflush(fd);
3314 alldone(1);
3315 }
3316 }
3317
3318 char *
simplify_name(char * s)3319 simplify_name(char *s)
3320 { char *t = s;
3321
3322 if (!old_scope_rules)
3323 { while (*t == '_' || isdigit((int)*t))
3324 { t++;
3325 } }
3326
3327 return t;
3328 }
3329
3330 void
putname(FILE * fd,char * pre,Lextok * n,int m,char * suff)3331 putname(FILE *fd, char *pre, Lextok *n, int m, char *suff) /* varref */
3332 { Symbol *s = n->sym;
3333 char *ptr;
3334
3335 lineno = n->ln; Fname = n->fn;
3336
3337 if (!s)
3338 fatal("no name - putname", (char *) 0);
3339
3340 if (s->context && context && s->type)
3341 s = findloc(s); /* it's a local var */
3342
3343 if (!s)
3344 { fprintf(fd, "%s%s%s", pre, n->sym->name, suff);
3345 return;
3346 }
3347
3348 if (!s->type) /* not a local name */
3349 s = lookup(s->name); /* must be a global */
3350
3351 if (!s->type)
3352 { if (strcmp(pre, ".") != 0)
3353 fatal("undeclared variable '%s'", s->name);
3354 s->type = INT;
3355 }
3356
3357 if (s->type == PROCTYPE)
3358 fatal("proctype-name '%s' used as array-name", s->name);
3359
3360 fprintf(fd, pre, 0);
3361 if (!terse && !s->owner && evalindex != 1)
3362 { if (old_priority_rules
3363 && strcmp(s->name, "_priority") == 0)
3364 { fprintf(fd, "1");
3365 goto shortcut;
3366 } else
3367 { if (s->context
3368 || strcmp(s->name, "_p") == 0
3369 || strcmp(s->name, "_pid") == 0
3370 || strcmp(s->name, "_priority") == 0)
3371 { fprintf(fd, "((P%d *)_this)->", Pid_nr);
3372 } else
3373 { int x = strcmp(s->name, "_");
3374 if (!(s->hidden&1) && x != 0)
3375 fprintf(fd, "now.");
3376 if (x == 0 && _isok == 0)
3377 fatal("attempt to read value of '_'", 0);
3378 } } }
3379
3380 if (terse && buzzed == 1)
3381 { fprintf(fd, "B_state.%s", (s->context)?"local[B_pid].":"");
3382 }
3383
3384 ptr = s->name;
3385
3386 if (!dont_simplify /* new 6.4.3 */
3387 && s->type != PREDEF) /* new 6.0.2 */
3388 { if (withprocname
3389 && s->context
3390 && strcmp(pre, "."))
3391 { fprintf(fd, "%s:", s->context->name);
3392 ptr = simplify_name(ptr);
3393 } else
3394 { if (terse)
3395 { ptr = simplify_name(ptr);
3396 } } }
3397
3398 if (evalindex != 1)
3399 fprintf(fd, "%s", ptr);
3400
3401 if (s->nel > 1 || s->isarray == 1)
3402 { if (no_arrays)
3403 { non_fatal("ref to array element invalid in this context",
3404 (char *)0);
3405 printf("\thint: instead of, e.g., x[rs] qu[3], use\n");
3406 printf("\tchan nm_3 = qu[3]; x[rs] nm_3;\n");
3407 printf("\tand use nm_3 in sends/recvs instead of qu[3]\n");
3408 }
3409 /* an xr or xs reference to an array element
3410 * becomes an exclusion tag on the array itself -
3411 * which could result in invalidly labeling
3412 * operations on other elements of this array to
3413 * be also safe under the partial order reduction
3414 * (see procedure has_global())
3415 */
3416
3417 if (evalindex == 2)
3418 { fprintf(fd, "[%%d]");
3419 } else if (evalindex == 1)
3420 { evalindex = 0; /* no good if index is indexed array */
3421 fprintf(fd, ", ");
3422 putstmnt(fd, n->lft, m);
3423 evalindex = 1;
3424 } else
3425 { if (terse
3426 || (n->lft
3427 && n->lft->ntyp == CONST
3428 && n->lft->val < s->nel)
3429 || (!n->lft && s->nel > 0))
3430 { cat3("[", n->lft, "]");
3431 } else
3432 { /* attempt to catch arrays that are indexed with an array element in the same array
3433 * this causes trouble in the verifier in the backtracking
3434 * e.g., restoring a[?] in the assignment: a [a[1]] = x where a[1] == 1
3435 * but it is hard when the array is inside a structure, so the names don't match
3436 */
3437 #if 0
3438 if (n->lft->ntyp == NAME)
3439 { printf("%4d: Basename %s index %s\n",
3440 n->lft->ln, s->name, n->lft->sym->name);
3441 }
3442 #endif
3443 cat3("[ Index(", n->lft, ", ");
3444 fprintf(fd, "%d) ]", s->nel);
3445 } }
3446 } else
3447 { if (n->lft /* effectively a scalar, but with an index */
3448 && (n->lft->ntyp != CONST
3449 || n->lft->val != 0))
3450 { fatal("ref to scalar '%s' using array index", (char *) ptr);
3451 } }
3452
3453 if (s->type == STRUCT && n->rgt && n->rgt->lft)
3454 { putname(fd, ".", n->rgt->lft, m, "");
3455 }
3456 shortcut:
3457 fprintf(fd, suff, 0);
3458 }
3459
3460 void
putremote(FILE * fd,Lextok * n,int m)3461 putremote(FILE *fd, Lextok *n, int m) /* remote reference */
3462 { int promoted = 0;
3463 int pt;
3464
3465 if (terse)
3466 { fprintf(fd, "%s", n->lft->sym->name); /* proctype name */
3467 if (n->lft->lft)
3468 { fprintf(fd, "[");
3469 putstmnt(fd, n->lft->lft, m); /* pid */
3470 fprintf(fd, "]");
3471 }
3472 if (ltl_mode)
3473 { fprintf(fd, ":%s", n->sym->name);
3474 } else
3475 { fprintf(fd, ".%s", n->sym->name);
3476 }
3477 } else
3478 { if (Sym_typ(n) < SHORT)
3479 { promoted = 1;
3480 fprintf(fd, "((int)");
3481 }
3482
3483 pt = fproc(n->lft->sym->name);
3484 fprintf(fd, "((P%d *)Pptr(", pt);
3485 if (n->lft->lft)
3486 { fprintf(fd, "BASE+");
3487 putstmnt(fd, n->lft->lft, m);
3488 } else
3489 fprintf(fd, "f_pid(%d)", pt);
3490 fprintf(fd, "))->%s", n->sym->name);
3491 }
3492 if (n->rgt)
3493 { fprintf(fd, "[");
3494 putstmnt(fd, n->rgt, m); /* array var ref */
3495 fprintf(fd, "]");
3496 }
3497 if (promoted) fprintf(fd, ")");
3498 }
3499
3500 static int
getweight(Lextok * n)3501 getweight(Lextok *n)
3502 { /* this piece of code is a remnant of early versions
3503 * of the verifier -- in the current version of Spin
3504 * only non-zero values matter - so this could probably
3505 * simply return 1 in all cases.
3506 */
3507 switch (n->ntyp) {
3508 case 'r': return 4;
3509 case 's': return 2;
3510 case TIMEOUT: return 1;
3511 case 'c': if (has_typ(n->lft, TIMEOUT)) return 1;
3512 }
3513 return 3;
3514 }
3515
3516 int
has_typ(Lextok * n,int m)3517 has_typ(Lextok *n, int m)
3518 {
3519 if (!n) return 0;
3520 if (n->ntyp == m) return 1;
3521 return (has_typ(n->lft, m) || has_typ(n->rgt, m));
3522 }
3523
3524 static int runcount, opcount;
3525
3526 static void
do_count(Lextok * n,int checkop)3527 do_count(Lextok *n, int checkop)
3528 {
3529 if (!n) return;
3530
3531 switch (n->ntyp) {
3532 case RUN:
3533 runcount++;
3534 break;
3535 default:
3536 if (checkop) opcount++;
3537 break;
3538 }
3539 do_count(n->lft, checkop && (n->ntyp != RUN));
3540 do_count(n->rgt, checkop);
3541 }
3542
3543 void
count_runs(Lextok * n)3544 count_runs(Lextok *n)
3545 {
3546 runcount = opcount = 0;
3547 do_count(n, 1);
3548 if (runcount > 1)
3549 fatal("more than one run operator in expression", "");
3550 if (runcount == 1 && opcount > 1)
3551 fatal("use of run operator in compound expression", "");
3552 }
3553
3554 void
any_runs(Lextok * n)3555 any_runs(Lextok *n)
3556 {
3557 runcount = opcount = 0;
3558 do_count(n, 0);
3559 if (runcount >= 1)
3560 fatal("run operator used in invalid context", "");
3561 }
3562