]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/spin/msc_tcl.c
audiohda: fix syntax error
[plan9front.git] / sys / src / cmd / spin / msc_tcl.c
1 /***** spin: msc_tcl.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 <stdlib.h>
10 #include "spin.h"
11 #include "version.h"
12
13 #define MW      500     /* page width */
14 #define RH      100     /* right margin */
15 #define WW       80     /* distance between process lines */
16 #define HH       12     /* vertical distance between steps */
17 #define LW        2     /* line width of message arrows */
18
19 #define RVC     "darkred"       /* rendezvous arrows */
20 #define MPC     "darkblue"      /* asynchronous message passing arrow */
21 #define GRC     "lightgrey"     /* grid lines */
22
23 static int      MH = 600;       /* anticipated page-length */
24 static FILE     *pfd;
25 static char     **I;            /* initial procs */
26 static int      *D,*R;          /* maps between depth (stepnr) and ldepth (msc-step) */
27 static short    *M;             /* x location of each box at index y */
28 static short    *T;             /* y index of match for each box at index y */
29 static char     **L;            /* text labels */
30 static int      ProcLine[256];  /* active processes */
31 static int      UsedLine[256];  /* process line has at least one entry */
32 static int      ldepth = 1;
33 static int      maxx, TotSteps = 2*4096; /* max nr of steps for simulation output */
34 static float    Scaler = (float) 1.0;
35
36 static int      xscale = 2;
37 static int      yscale = 1;
38 static int      no_box;
39
40 extern int      ntrail, s_trail, pno, depth;
41 extern Symbol   *oFname;
42
43 extern void     exit(int);
44 extern void     putpostlude(void);
45
46 static void     putpages(void);
47
48 static void
49 psline(int x0, int y0, int x1, int y1, char *color)
50 {       char *side = "last";
51
52         if (x0 == x1)   /* gridline */
53         {       fprintf(pfd, ".c create line %d %d %d %d -fill %s -tags grid -width 1 \n",
54                         xscale*(x0+1)*WW-20, yscale*y0+20,
55                         xscale*(x1+1)*WW-20, yscale*y1+20, color);
56                 fprintf(pfd, ".c lower grid\n");
57         } else
58         {       int xm = xscale*(x0+1)*WW + (xscale*(x1 - x0)*WW)/2 - 20;       /* mid x */
59
60                 if (y1 - y0  <= HH+20)
61                 {       y1 = y0+20; /* close enough to horizontal - looks better */
62                 }
63  
64                 fprintf(pfd, ".c create line %d %d %d %d -fill %s -tags mesg -width %d\n",
65                         xscale*(x0+1)*WW-20, yscale*y0+20+10,
66                         xm,                  yscale*y0+20+10, color, LW);
67
68                 if (y1 != y0+20)
69                 {       fprintf(pfd, ".c create line %d %d %d %d -fill %s -tags mesg -width %d\n",
70                                 xm, yscale*y0+20+10,
71                                 xm, yscale*y1+20-10, color, LW);
72                 }
73
74                 fprintf(pfd, ".c create line %d %d %d %d -fill %s -width %d ",
75                         xm,                  yscale*y1+20-10,
76                         xscale*(x1+1)*WW-20, yscale*y1+20-10, color, LW);
77
78                 if (strcmp(color, RVC) == 0)
79                 {       side = "both";
80                 }
81                 fprintf(pfd, "-arrow %s -arrowshape {5 5 5} -tags mesg\n", side);
82                 fprintf(pfd, ".c raise mesg\n");
83         }
84 }
85
86 static void
87 colbox(int ix, int iy, int w, int h_unused, char *color)
88 {       int x = ix*WW;
89         int y = iy*HH;
90
91         if (ix < 0 || ix > 255)
92         {       fatal("msc_tcl: unexpected\n", (char *) 0);
93         }
94
95         if (ProcLine[ix] < iy)
96         {       /* if (ProcLine[ix] > 0) */
97                 {       psline(ix-1, ProcLine[ix]*HH+HH+4,
98                                ix-1, iy*HH-HH, GRC);
99                 }
100                 fprintf(pfd, "# ProcLine[%d] from %d to %d (Used %d nobox %d)\n",
101                         ix, ProcLine[ix], iy, UsedLine[ix], no_box);
102                 ProcLine[ix] = iy;
103         } else
104         {       fprintf(pfd, "# ProcLine[%d] stays at %d (Used %d nobox %d)\n",
105                         ix, ProcLine[ix], UsedLine[ix], no_box);
106         }
107
108         if (UsedLine[ix])
109         {       no_box = 2;
110         }
111
112         if (strcmp(color, "black") == 0)
113         {       if (no_box == 0)        /* shadow */
114                 {       fprintf(pfd, ".c create rectangle %d %d %d %d -fill black\n",
115                                 xscale*x-(xscale*4*w/3)-20+4, (yscale*y-10)+20+2,
116                                 xscale*x+(xscale*4*w/3)-20,   (yscale*y+10)+20+2);
117                 }
118         } else
119         {       if (no_box == 0)        /* box with outline */
120                 {       fprintf(pfd, ".c create rectangle %d %d %d %d -fill ivory\n",
121                                 xscale*x-(xscale*4*w/3)-20, (yscale*y-10)+20,
122                                 xscale*x+(xscale*4*w/3)-20, (yscale*y+10)+20);
123                         UsedLine[ix]++;
124                 } else                  /* no outline */
125                 {       fprintf(pfd, ".c create rectangle %d %d %d %d -fill white -width 0\n",
126                                 xscale*x-(xscale*4*w/3)-20, (yscale*y-10)+20,
127                                 xscale*x+(xscale*4*w/3)-20, (yscale*y+10)+20);
128         }       }
129         if (no_box > 0)
130         {       no_box--;
131         }
132 }
133
134 static void
135 stepnumber(int i)
136 {       int y = (yscale*i*HH) + 20;
137
138         fprintf(pfd, ".c create text %d %d -fill #eef -text \"%d\"\n",
139                 -10+(xscale*WW)/2, y, i);
140
141         /* horizontal dashed grid line */
142         fprintf(pfd, ".c create line %d %d %d %d -fill #eef -dash {6 4}\n",
143                 -20+WW*xscale, y, (maxx+1)*WW*xscale-20, y);
144 }
145
146 static void
147 spitbox(int ix, int y, char *s)
148 {       float bw;       /* box width */
149         char d[256], *t, *z;
150         int a, i, x = ix+1;
151         char *color = "black";
152
153         if (y > 0)
154         {       stepnumber(y);
155         }
156
157         bw = (float)1.8*(float)strlen(s);       /* guess at default font width */
158         colbox(x, y, (int) (bw+1.0), 5, "black");
159         if (s[0] == '~')
160         {       switch (s[1]) {
161                 default :
162                 case 'R': color = "red";   break;
163                 case 'B': color = "blue";  break;
164                 case 'G': color = "green"; break;
165                 }
166                 s += 2;
167         } else if (strchr(s, '!'))
168         {       color = "ivory";
169         } else if (strchr(s, '?'))
170         {       color = "azure";
171         } else
172         {       color = "pink";
173                 if (sscanf(s, "%d:%250s", &a, d) == 2
174                 &&  a >= 0 && a < TotSteps)
175                 {       if (!I[a]  || strlen(I[a]) <= strlen(s))
176                         {       I[a] = (char *) emalloc((int) strlen(s)+1);
177                         }
178                         strcpy(I[a], s);
179         }       }
180
181         colbox(x, y, (int) bw, 4, color);
182
183         z = t = (char *) emalloc(2*strlen(s)+1);
184
185         for (i = 0; i < (int) strlen(s); i++)
186         {       if (s[i] == '\n')
187                 {       continue;
188                 }
189                 if (s[i] == '[' || s[i] == ']')
190                 {       *t++ = '\\';
191                 }
192                 *t++ = s[i];
193         }
194
195         fprintf(pfd, ".c create text %d %d -text \"%s\"\n",
196                 xscale*x*WW-20, yscale*y*HH+20, z);
197 }
198
199 static void
200 putpages(void)
201 {       int i, lasti=0; float nmh;
202
203         if (maxx*xscale*WW > MW-RH/2)
204         {       Scaler = (float) (MW-RH/2) / (float) (maxx*xscale*WW);
205                 nmh = (float) MH; nmh /= Scaler; MH = (int) nmh;
206                 fprintf(pfd, "# Scaler %f, MH %d\n", Scaler, MH);
207         }
208         if (ldepth >= TotSteps)
209         {       ldepth = TotSteps-1;
210         }
211
212 /* W: (maxx+2)*xscale*WW  */
213 /* H: ldepth*HH*yscale+50 */
214         fprintf(pfd, "wm title . \"scenario\"\n");
215         fprintf(pfd, "wm geometry . %dx600+650+100\n", (maxx+2)*xscale*WW);
216
217         fprintf(pfd, "canvas .c -width 800 -height 800 \\\n");
218         fprintf(pfd, "  -scrollregion {0c -1c 30c 100c} \\\n");
219         fprintf(pfd, "  -xscrollcommand \".hscroll set\" \\\n");
220         fprintf(pfd, "  -yscrollcommand \".vscroll set\" \\\n");
221         fprintf(pfd, "  -bg white -relief raised -bd 2\n");
222
223         fprintf(pfd, "scrollbar .vscroll -relief sunken ");
224         fprintf(pfd, " -command \".c yview\"\n");
225         fprintf(pfd, "scrollbar .hscroll -relief sunken -orient horiz ");
226         fprintf(pfd, " -command \".c xview\"\n");
227
228         fprintf(pfd, "pack append . \\\n");
229         fprintf(pfd, "  .vscroll {right filly} \\\n");
230         fprintf(pfd, "  .hscroll {bottom fillx} \\\n");
231         fprintf(pfd, "  .c {top expand fill}\n");
232
233         fprintf(pfd, ".c yview moveto 0\n");
234
235         for (i = TotSteps-1; i >= 0; i--)
236         {       if (I[i])
237                 {       spitbox(i, -1, I[i]);
238         }       }
239
240         for (i = 0; i <= ldepth; i++)
241         {       if (!M[i] && !L[i])
242                 {       continue;       /* no box */
243                 }
244                 if (T[i] > 0)           /* arrow */
245                 {       if (T[i] == i)  /* rv handshake */
246                         {       psline( M[lasti], lasti*HH,
247                                         M[i],     i*HH, RVC);
248                         } else
249                         {       psline( M[i],     i*HH,
250                                         M[T[i]],  T[i]*HH, MPC);
251                 }       }
252                 if (L[i])
253                 {       spitbox(M[i], i, L[i]);
254                         lasti = i;
255         }       }
256 }
257
258 static void
259 putbox(int x)
260 {
261         if (ldepth >= TotSteps)
262         {       fprintf(stderr, "max length of %d steps exceeded - ps file truncated\n",
263                         TotSteps);
264                 putpostlude();
265         }
266         M[ldepth] = x;
267         if (x > maxx)
268         {       maxx = x;
269                 fprintf(pfd, "# maxx %d\n", x);
270         }
271 }
272
273 /* functions called externally: */
274
275 extern int WhatSeed(void);
276
277 void
278 putpostlude(void)
279 {       char cmd[512];
280
281         putpages();
282         fprintf(pfd, ".c lower grid\n");
283         fprintf(pfd, ".c raise mesg\n");
284         fclose(pfd);
285
286         fprintf(stderr, "seed used: -n%d\n", WhatSeed());
287         sprintf(cmd, "wish -f %s.tcl &", oFname?oFname->name:"msc");
288         fprintf(stderr, "%s\n", cmd);
289         (void) unlink("pan.pre");
290         exit (system(cmd));
291 }
292
293 void
294 putprelude(void)
295 {       char snap[256]; FILE *fd;
296
297         sprintf(snap, "%s.tcl", oFname?oFname->name:"msc");
298         if (!(pfd = fopen(snap, MFLAGS)))
299         {       fatal("cannot create file '%s'", snap);
300         }
301         if (s_trail)
302         {       if (ntrail)
303                 sprintf(snap, "%s%d.trail", oFname?oFname->name:"msc", ntrail);
304                 else
305                 sprintf(snap, "%s.trail", oFname?oFname->name:"msc");
306                 if (!(fd = fopen(snap, "r")))
307                 {       snap[strlen(snap)-2] = '\0';
308                         if (!(fd = fopen(snap, "r")))
309                                 fatal("cannot open trail file", (char *) 0);
310                 }
311                 TotSteps = 1;
312                 while (fgets(snap, 256, fd)) TotSteps++;
313                 fclose(fd);
314         }
315         TotSteps *= 2;
316         R = (int   *) emalloc(TotSteps * sizeof(int));
317         D = (int   *) emalloc(TotSteps * sizeof(int));
318         M = (short *) emalloc(TotSteps * sizeof(short));
319         T = (short *) emalloc(TotSteps * sizeof(short));
320         L = (char **) emalloc(TotSteps * sizeof(char *));
321         I = (char **) emalloc(TotSteps * sizeof(char *));
322 }
323
324 void
325 putarrow(int from, int to)
326 {
327         /* from rv if from == to */
328         /* which means that D[from] == D[to] */
329         /* which means that T[x] == x */
330
331         if (from    < TotSteps
332         &&  to      < TotSteps
333         &&  D[from] < TotSteps)
334         {       T[D[from]] = D[to];
335         }
336 }
337
338 void
339 pstext(int x, char *s)
340 {       char *tmp = emalloc((int) strlen(s)+1);
341
342         strcpy(tmp, s);
343         if (depth == 0)
344         {       I[x] = tmp;
345         } else
346         {       if (depth >= TotSteps || ldepth >= TotSteps)
347                 {       fprintf(stderr, "spin: error: max nr of %d steps exceeded\n",
348                                 TotSteps);
349                         fatal("use -uN to limit steps", (char *) 0);
350                 }
351                 putbox(x);
352                 D[depth] = ldepth;
353                 R[ldepth] = depth;
354                 L[ldepth] = tmp;
355                 ldepth += 2;
356         }
357 }
358
359 void
360 dotag(FILE *fd, char *s)
361 {       extern int columns, notabs; extern RunList *X;
362         int i = (!strncmp(s, "MSC: ", 5))?5:0;
363         int pid = s_trail ? pno : (X?X->pid:0);
364
365         if (columns == 2)
366         {       pstext(pid, &s[i]);
367         } else
368         {       if (!notabs)
369                 {       printf("  ");
370                         for (i = 0; i <= pid; i++)
371                         {       printf("    ");
372                 }       }
373                 fprintf(fd, "%s", s);
374                 fflush(fd);
375         }
376 }