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