1
2 /**************************************************************************
3
4 util2.c
5 Colin Ramsay (cram@itee.uq.edu.au)
6 6 Dec 00
7
8 ADVANCED COSET ENUMERATOR, Version 3.001
9
10 Copyright 2000
11 Centre for Discrete Mathematics and Computing,
12 Department of Mathematics and
13 Department of Computer Science & Electrical Engineering,
14 The University of Queensland, QLD 4072.
15 (http://staff.itee.uq.edu.au/havas)
16
17 These are the utilities for Level 2 of ACE.
18
19 **************************************************************************/
20
21 #include "al2.h"
22
23 #include <string.h>
24 #include <ctype.h>
25 #include <sys/types.h>
26 #include <time.h>
27
28 /******************************************************************
29 void al2_init(void)
30
31 One-off initialisation of the Level 2 stuff, and all lower levels.
32 Note that there is no need to initialise, for example, intarr[].
33 ******************************************************************/
34
al2_init(void)35 void al2_init(void)
36 {
37 al1_init();
38
39 okstart = okcont = okredo = FALSE;
40 tabinfo = tabindex = FALSE;
41 lresult = -8192; /* invalid mode ! */
42
43 echo = FALSE;
44 skipnl = TRUE;
45
46 currip = currkey[0] = currname[0] = '\0';
47
48 currword = NULL;
49 currsiz = currexp = 0;
50
51 intcnt = 0;
52
53 srand((unsigned int)time(NULL)); /* Seed rand() with time */
54 }
55
56 /******************************************************************
57 char *al2_strdup(char *s)
58
59 strdup() is not ANSI C, so this is our version. Should we regard
60 an error as fatal, and abort?
61 ******************************************************************/
62
al2_strdup(char * s)63 char *al2_strdup(char *s)
64 {
65 char *t;
66
67 if ((t = malloc(strlen(s)+1)) == NULL)
68 { al2_continue("out of memory in al2_strdup()"); }
69
70 return(strcpy(t,s));
71 }
72
73 /******************************************************************
74 int al2_outlen(int i)
75
76 Returns the print-length of an integer i (i.e., ~ $\log_{10}i$).
77 The int i is assumed to satisfy i >= 0.
78 ******************************************************************/
79
al2_outlen(int i)80 int al2_outlen(int i)
81 {
82 int len = 1;
83
84 while ((i /= 10) != 0)
85 { len++; }
86
87 return(len);
88 }
89
90 /**************************************************************************
91 All Level 2 errors are filtered by one of the following three handlers.
92 These take the appropriate action, and then jump back to the top-level
93 main() routine; ie, the outermost level of Level 2. We swallow the
94 remainder of any input line (possibly losing some commands); so multi-line
95 commands in error may not be properly tidied-up. The question of what
96 exactly to do if fip/fop are not stdin/stdout is put in the `too hard'
97 basket; we simply switch them both back to their defaults. Note that,
98 although the code for _continue() & _restart() is the same, they return to
99 different points (& do different things) in main().
100
101 Warning: The error-handling is fairly basic, since it's not our intent to
102 develop a fully-fledged interactive interface. We simply tidy-up the best
103 we can and carry on.
104 **************************************************************************/
105
106 /******************************************************************
107 void al2_continue(char *msg)
108
109 An error has occurred, but it doesn't affected the ok... flags, or
110 the table's validity.
111 ******************************************************************/
112
al2_continue(char * msg)113 void al2_continue(char *msg)
114 {
115 if (fop != stdout)
116 {
117 if (fop != NULL)
118 { fclose(fop); }
119 fop = stdout;
120 }
121 if (fip != stdin)
122 {
123 if (fip != NULL)
124 { fclose(fip); }
125 fip = stdin;
126 currip = '\0';
127 }
128
129 fflush(fop);
130 fprintf(fop, "** ERROR (continuing with next line)\n");
131 fprintf(fop, " %s\n", msg);
132
133 while ( !(currip == '\n' || currip == '\r' || currip == EOF) )
134 { al2_nextip(); }
135
136 longjmp(env,1);
137 }
138
139 /******************************************************************
140 void al2_restart(char *msg)
141
142 Something nasty has happened & we'll be disallowing continue/redo.
143 ******************************************************************/
144
al2_restart(char * msg)145 void al2_restart(char *msg)
146 {
147 if (fop != stdout)
148 {
149 if (fop != NULL)
150 { fclose(fop); }
151 fop = stdout;
152 }
153 if (fip != stdin)
154 {
155 if (fip != NULL)
156 { fclose(fip); }
157 fip = stdin;
158 currip = '\0';
159 }
160
161 fflush(fop);
162 fprintf(fop, "** ERROR (restarting with next line)\n");
163 fprintf(fop, " %s\n", msg);
164
165 while ( !(currip == '\n' || currip == '\r' || currip == EOF) )
166 { al2_nextip(); }
167
168 longjmp(env,2);
169 }
170
171 /******************************************************************
172 void al2_abort(char *msg)
173
174 No point in being clever here, we're going to stop.
175 ******************************************************************/
176
al2_abort(char * msg)177 void al2_abort(char *msg)
178 {
179 if (fop != stdout)
180 {
181 if (fop != NULL)
182 { fclose(fop); }
183 fop = stdout;
184 }
185 if (fip != stdin)
186 {
187 if (fip != NULL)
188 { fclose(fip); }
189 fip = stdin;
190 currip = '\0';
191 }
192
193 fflush(fop);
194 fprintf(fop, "** ERROR (aborting)\n");
195 fprintf(fop, " %s\n", msg);
196
197 longjmp(env,3);
198 }
199
200 /******************************************************************
201 void al2_aip(char *name)
202
203 Switch to a new input file. We abort via _restart() if this is not
204 possible, and that call will reset fip/fop properly.
205 ******************************************************************/
206
al2_aip(char * name)207 void al2_aip(char *name)
208 {
209 /* Close the current input file (unless it is 'stdin'). */
210
211 if (fip != stdin && fip != NULL)
212 { fclose(fip); }
213 fip = NULL;
214
215 /* Try to open the new input file (unless it is 'stdin'). */
216
217 if (strcmp(name, "stdin") != 0)
218 {
219 if ((fip = fopen(name, "r")) == NULL)
220 { al2_restart("can't open new input, using 'stdin'"); }
221 }
222 else
223 { fip = stdin; }
224
225 currip = '\0'; /* Initialise current i/p char. */
226 }
227
228 /******************************************************************
229 void al2_aop(char *name)
230
231 Switch to a new output file. We abort via _restart() if this is
232 not possible, and that call will reset fip/fop properly. Note
233 that there is no need to run setvbuf() on stdout, since this was
234 done in the call to al0_init().
235 ******************************************************************/
236
al2_aop(char * name)237 void al2_aop(char *name)
238 {
239 /* Close the current output file (unless it is 'stdout'). */
240
241 if (fop != stdout && fop != NULL)
242 { fclose(fop); }
243 fop = NULL;
244
245 /* Try to open the new output file (unless it is 'stdout'). */
246
247 if (strcmp(name, "stdout") != 0)
248 {
249 if ((fop = fopen(name, "w")) == NULL)
250 {
251 fop = stdout;
252 fprintf(fop, "can't open new output, using 'stdout'");
253 }
254 else
255 { setvbuf(fop, NULL, _IOLBF, 0); } /* line buffered o/p */
256 }
257 else
258 { fop = stdout; }
259 }
260
261 /******************************************************************
262 void al2_dump(Logic allofit)
263
264 Dump out the internals of Level 2 of ACE, working through al2.h
265 more or less in order.
266 ******************************************************************/
267
al2_dump(Logic allofit)268 void al2_dump(Logic allofit)
269 {
270 int i;
271
272 fprintf(fop, " #---- %s: Level 2 Dump ----\n", ACE_VER);
273
274 /* env; - nothing (meaningful) we can do here! */
275
276 /* okstart, okcont, okredo; */
277 fprintf(fop, "okstart=%d okcont=%d okredo=%d\n",
278 okstart, okcont, okredo);
279
280 /* tabinfo, tabindex, lresult */
281 fprintf(fop, "tabinfo=%d tabindex=%d lresult=%d\n",
282 tabinfo, tabindex, lresult);
283
284 /* echo, skipnl, currip, currkey, currname; */
285 fprintf(fop, "echo=%d skipnl=%d currip=%d", echo, skipnl, currip);
286 if (isprint(currip))
287 { fprintf(fop, "(%c)\n", currip); }
288 else
289 { fprintf(fop, "\n"); }
290 fprintf(fop, "currkey=%s\n", currkey);
291 fprintf(fop, "currname=%s\n", currname);
292
293 /* *currword, currsiz, currexp; */
294 fprintf(fop, "currsize=%d currexp=%d currword=", currsiz, currexp);
295 if (currword == NULL)
296 { fprintf(fop, "NULL"); }
297 else
298 {
299 if (allofit)
300 {
301 for (i = 0; i < currsiz; i++)
302 { fprintf(fop, "%d ", currword[i]); }
303 }
304 else
305 { fprintf(fop, "non-NULL"); }
306 }
307 fprintf(fop, "\n");
308
309 /* intcnt, intarr[32]; */
310 if (intcnt == 0)
311 { fprintf(fop, "intcnt=0 (empty)\n"); }
312 else
313 {
314 fprintf(fop, "intcnt=%d intarr[]=", intcnt);
315 for (i = 0; i < intcnt; i++)
316 { fprintf(fop, "%d ", intarr[i]); }
317 fprintf(fop, "\n");
318 }
319
320 fprintf(fop, " #---------------------------------\n");
321 }
322
323 /******************************************************************
324 void al2_opt(void)
325
326 Pretty-print the date of compilation and all the various options
327 included in this build.
328 ******************************************************************/
329
al2_opt(void)330 void al2_opt(void)
331 {
332 fprintf(fop, "%s executable\n", ACE_VER);
333
334 fprintf(fop, "Level 0 options:\n");
335 #ifdef AL0_STAT
336 fprintf(fop, " statistics package = on\n");
337 #else
338 fprintf(fop, " statistics package = off\n");
339 #endif
340 #ifdef AL0_CC
341 fprintf(fop, " coinc processing messages = on\n");
342 #else
343 fprintf(fop, " coinc processing messages = off\n");
344 #endif
345 #ifdef AL0_DD
346 fprintf(fop, " dedn processing messages = on\n");
347 #else
348 fprintf(fop, " dedn processing messages = off\n");
349 #endif
350
351 fprintf(fop, "Level 1 options:\n");
352 #ifdef AL1_BINARY
353 fprintf(fop, " workspace multipliers = binary\n");
354 #else
355 fprintf(fop, " workspace multipliers = decimal\n");
356 #endif
357
358 fprintf(fop, "Level 2 options:\n");
359 #ifdef AL2_HINFO
360 fprintf(fop, " host info = on\n");
361 #else
362 fprintf(fop, " host info = off\n");
363 #endif
364 }
365
366 /******************************************************************
367 void al2_help(void)
368 ******************************************************************/
369
al2_help(void)370 void al2_help(void)
371 {
372 fprintf(fop, " #---- %s: Level 2 Help ----\n", ACE_VER);
373 fprintf(fop, "add gen[erators] / sg : <word list> ;\n");
374 fprintf(fop, "add rel[ators] / rl : <relation list> ;\n");
375 fprintf(fop, "aep : 1..7 ;\n");
376 fprintf(fop, "ai / alter i[nput] : [<filename>] ;\n");
377 fprintf(fop, "ao / alter o[utput] : [<filename>] ;\n");
378 fprintf(fop, "as[is] : [0/1] ;\n");
379 fprintf(fop, "beg[in] / end / start ;\n");
380 fprintf(fop, "bye / exit / q[uit] ;\n");
381 fprintf(fop, "cc / coset coinc[idence] : int ;\n");
382 fprintf(fop, "c[factor] / ct[ factor] : [int] ;\n");
383 fprintf(fop, "check / redo ;\n");
384 fprintf(fop, "com[paction] : [0..100] ;\n");
385 fprintf(fop, "cont[inue] ;\n");
386 fprintf(fop, "cy[cles] ;\n");
387 fprintf(fop, "ded mo[de] / dmod[e] : [0..4] ;\n");
388 fprintf(fop, "ded si[ze] / dsiz[e] : [0/1..] ;\n");
389 fprintf(fop, "def[ault] ;\n");
390 fprintf(fop, "del gen[erators] / ds : <int list> ;\n");
391 fprintf(fop, "del rel[ators] / dr : <int list> ;\n");
392 fprintf(fop, "d[ump] : [0/1/2[,0/1]] ;\n");
393 fprintf(fop, "easy ;\n");
394 fprintf(fop, "echo : [0/1] ;\n");
395 fprintf(fop, "enum[eration] / group name : <string> ;\n");
396 fprintf(fop, "fel[sch] : [0/1] ;\n");
397 fprintf(fop, "f[factor] / fi[ll factor] : [0/1..] ;\n");
398 fprintf(fop, "gen[erators] / subgroup gen[erators] : <word list> ;\n");
399 fprintf(fop, "gr[oup generators]: [<letter list> / int] ;\n");
400 fprintf(fop, "group relators / rel[ators] : <relation list> ;\n");
401 fprintf(fop, "hard ;\n");
402 fprintf(fop, "h[elp] ;\n");
403 fprintf(fop, "hlt ;\n");
404 fprintf(fop, "ho[le limit] : [-1/0..100] ;\n");
405 fprintf(fop, "look[ahead] : [0/1..4] ;\n");
406 fprintf(fop, "loop[ limit] : [0/1..] ;\n");
407 fprintf(fop, "max[ cosets] : [0/2..] ;\n");
408 fprintf(fop, "mend[elsohn] : [0/1] ;\n");
409 fprintf(fop, "mess[ages] / mon[itor] : [int] ;\n");
410 fprintf(fop, "mo[de] ;\n");
411 fprintf(fop, "nc / normal[ closure] : [0/1] ;\n");
412 fprintf(fop, "no[ relators in subgroup] : [-1/0/1..] ;\n");
413 fprintf(fop, "oo / order[ option] : int ;\n");
414 fprintf(fop, "opt[ions] ;\n");
415 fprintf(fop, "par[ameters] ; - old option (ignored)\n");
416 fprintf(fop, "path[ compression] : [0/1] ;\n");
417 fprintf(fop, "pd mo[de] / pmod[e] : [0/1..3] ;\n");
418 fprintf(fop, "pd si[ze] / psiz[e] : [0/2/4/8/...] ;\n");
419 fprintf(fop, "print det[ails] / sr : [int] ;\n");
420 fprintf(fop, "pr[int table] : [[-]int[,int[,int]]] ;\n");
421 fprintf(fop, "pure c[t] ;\n");
422 fprintf(fop, "pure r[t] ;\n");
423 fprintf(fop, "rc / random coinc[idences]: int[,int] ;\n");
424 fprintf(fop, "rec[over] / contig[uous] ;\n");
425 fprintf(fop, "rep : 1..7[,int] ;\n");
426 fprintf(fop, "restart ; - old option (ignored)\n");
427 fprintf(fop, "r[factor] / rt[ factor] : [int] ;\n");
428 fprintf(fop, "row[ filling] : [0/1] ;\n");
429 fprintf(fop, "sc / stabil[ising cosets] : int ;\n");
430 fprintf(fop, "sims : 1/3/5/7/9 ;\n");
431 fprintf(fop, "st[andard table] ;\n");
432 #ifdef AL0_STAT
433 fprintf(fop, "stat[istics] / stats ;\n");
434 #endif
435 fprintf(fop, "style ;\n");
436 fprintf(fop, "subg[roup name] : <string> ;\n");
437 fprintf(fop, "sys[tem] : <string> ;\n");
438 fprintf(fop, "text : <string> ;\n");
439 fprintf(fop, "ti[me limit] : [-1/0/1..] ;\n");
440 fprintf(fop, "tw / trace[ word] : int,<word> ;\n");
441 fprintf(fop, "wo[rkspace] : [int[k/m/g]] ;\n");
442 fprintf(fop, "# ... <newline> - a comment (ignored)\n");
443 fprintf(fop, " #---------------------------------\n");
444 }
445
446 /******************************************************************
447 void al2_nextip(void)
448
449 Primes currip with the next character from fip, if we're not at the
450 end-of-file. Echoes the character if echo is on.
451 ******************************************************************/
452
al2_nextip(void)453 void al2_nextip(void)
454 {
455 if (currip != EOF)
456 {
457 currip = fgetc(fip);
458
459 if (echo && currip != EOF)
460 { fputc(currip, fop); }
461 }
462 }
463
464 /******************************************************************
465 void al2_skipws(void)
466
467 Skip all whitespace characters.
468 ******************************************************************/
469
al2_skipws(void)470 void al2_skipws(void)
471 {
472 Logic comment = (currip == '#');
473
474 while ( currip == ' ' || currip == '\t' || comment ||
475 (skipnl && (currip == '\n' || currip == '\r')) )
476 {
477 al2_nextip();
478 comment = (currip == '#' ||
479 (comment && currip != '\n' && currip != '\r' && currip != EOF));
480 }
481 }
482
483 /******************************************************************
484 void al2_nextnw(void)
485
486 Skip to the next non-whitespace character.
487 ******************************************************************/
488
al2_nextnw(void)489 void al2_nextnw(void)
490 {
491 al2_nextip();
492 al2_skipws();
493 }
494
495
496