FORM 4.3
startup.c
Go to the documentation of this file.
1
8/* #[ License : */
9/*
10 * Copyright (C) 1984-2022 J.A.M. Vermaseren
11 * When using this file you are requested to refer to the publication
12 * J.A.M.Vermaseren "New features of FORM" math-ph/0010025
13 * This is considered a matter of courtesy as the development was paid
14 * for by FOM the Dutch physics granting agency and we would like to
15 * be able to track its scientific use to convince FOM of its value
16 * for the community.
17 *
18 * This file is part of FORM.
19 *
20 * FORM is free software: you can redistribute it and/or modify it under the
21 * terms of the GNU General Public License as published by the Free Software
22 * Foundation, either version 3 of the License, or (at your option) any later
23 * version.
24 *
25 * FORM is distributed in the hope that it will be useful, but WITHOUT ANY
26 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
27 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
28 * details.
29 *
30 * You should have received a copy of the GNU General Public License along
31 * with FORM. If not, see <http://www.gnu.org/licenses/>.
32 */
33/* #] License : */
34/*
35 #[ includes :
36*/
37
38#include "form3.h"
39#include "inivar.h"
40
41#ifdef TRAPSIGNALS
42#include "portsignals.h"
43#else
44#include <signal.h>
45#endif
46
47/*
48 * A macro for translating the contents of `x' into a string after expanding.
49 */
50#define STRINGIFY(x) STRINGIFY__(x)
51#define STRINGIFY__(x) #x
52
53/*
54 * FORMNAME = "FORM" or "TFORM" or "ParFORM".
55 */
56#if defined(WITHPTHREADS)
57 #define FORMNAME "TFORM"
58#elif defined(WITHMPI)
59 #define FORMNAME "ParFORM"
60#else
61 #define FORMNAME "FORM"
62#endif
63
64/*
65 * VERSIONSTR is the version information printed in the header line.
66 */
67#ifdef HAVE_CONFIG_H
68 /* We have also version.h. */
69 #include "version.h"
70 #ifndef REPO_VERSION
71 #define REPO_VERSION STRINGIFY(REPO_MAJOR_VERSION) "." STRINGIFY(REPO_MINOR_VERSION)
72 #endif
73 #ifndef REPO_DATE
74 /* The build date, instead of the repo date. */
75 #define REPO_DATE __DATE__
76 #endif
77 #ifdef REPO_REVISION
78 #define VERSIONSTR FORMNAME " " REPO_VERSION " (" REPO_DATE ", " REPO_REVISION ")"
79 #else
80 #define VERSIONSTR FORMNAME " " REPO_VERSION " (" REPO_DATE ")"
81 #endif
82 #define MAJORVERSION REPO_MAJOR_VERSION
83 #define MINORVERSION REPO_MINOR_VERSION
84#else
85 /*
86 * Otherwise, form3.h defines MAJORVERSION, MINORVERSION and PRODUCTIONDATE,
87 * possibly BETAVERSION.
88 */
89 #ifdef BETAVERSION
90 #define VERSIONSTR__ STRINGIFY(MAJORVERSION) "." STRINGIFY(MINORVERSION) "Beta"
91 #else
92 #define VERSIONSTR__ STRINGIFY(MAJORVERSION) "." STRINGIFY(MINORVERSION)
93 #endif
94 #define VERSIONSTR FORMNAME " " VERSIONSTR__ " (" PRODUCTIONDATE ")"
95#endif
96
97/*
98 #] includes :
99 #[ PrintHeader :
100*/
101
107static void PrintHeader(int with_full_info)
108{
109#ifdef WITHMPI
110 if ( PF.me == MASTER && !AM.silent ) {
111#else
112 if ( !AM.silent ) {
113#endif
114 char buffer1[250], buffer2[80], *s = buffer1, *t = buffer2;
115 WORD length, n;
116 for ( n = 0; n < 250; n++ ) buffer1[n] = ' ';
117 /*
118 * NOTE: we expect that the compiler optimizes strlen("string literal")
119 * to just a number.
120 */
121 if ( strlen(VERSIONSTR) <= 100 ) {
122 strcpy(s,VERSIONSTR);
123 s += strlen(VERSIONSTR);
124 *s = 0;
125 }
126 else {
127 /*
128 * Truncate when it is too long.
129 */
130 strncpy(s,VERSIONSTR,97);
131 s[97] = '.';
132 s[98] = '.';
133 s[99] = ')';
134 s[100] = '\0';
135 s += 100;
136 }
137
138 s += sprintf(s," %d-bits",(WORD)(sizeof(WORD)*16));
139/* while ( *s ) s++; */
140 *s = 0;
141
142 if ( with_full_info ) {
143#if defined(WITHPTHREADS) || defined(WITHMPI)
144#if defined(WITHPTHREADS)
145 int nworkers = AM.totalnumberofthreads-1;
146#elif defined(WITHMPI)
147 int nworkers = PF.numtasks-1;
148#endif
149 s += sprintf(s," %d worker",nworkers);
150 *s = 0;
151/* while ( *s ) s++; */
152 if ( nworkers != 1 ) {
153 *s++ = 's';
154 *s = '\0';
155 }
156#endif
157
158 sprintf(t,"Run: %s",MakeDate());
159 while ( *t ) t++;
160
161 /*
162 * Align the date to the right, if it fits in a line.
163 */
164 length = (s-buffer1) + (t-buffer2);
165 if ( length+2 <= AC.LineLength ) {
166 for ( n = AC.LineLength-length; n > 0; n-- ) *s++ = ' ';
167 *s = 0;
168 strcat(s,buffer2);
169 while ( *s ) s++;
170 }
171 else {
172 *s = 0;
173 strcat(s," ");
174 while ( *s ) s++;
175 *s = 0;
176 strcat(s,buffer2);
177 while ( *s ) s++;
178 }
179 }
180
181 /*
182 * If the header information doesn't fit in a line, we need to extend
183 * the line length temporarily.
184 */
185 length = s-buffer1;
186 if ( length <= AC.LineLength ) {
187 MesPrint("%s",buffer1);
188 }
189 else {
190 WORD oldLineLength = AC.LineLength;
191 AC.LineLength = length;
192 MesPrint("%s",buffer1);
193 AC.LineLength = oldLineLength;
194 }
195 }
196}
197
198/*
199 #] PrintHeader :
200 #[ DoTail :
201
202 Routine reads the command tail and handles the commandline options.
203 It sets the flags for later actions and stored pathnames for
204 the setup file, include/prc/sub directories etc.
205 Finally the name of the program is passed on.
206 Note that we do not support interactive use yet. This will come
207 to pass in the distant future when we can couple STedi to FORM.
208 Routine made 23-feb-1993 by J.Vermaseren
209*/
210
211#ifdef WITHINTERACTION
212static UBYTE deflogname[] = "formsession.log";
213#endif
214
215#define TAKEPATH(x) if(s[1]== '=' ){x=s+2;} else{x=*argv++;argc--;}
216
217int DoTail(int argc, UBYTE **argv)
218{
219 int errorflag = 0, onlyversion = 1;
220 UBYTE *s, *t, *copy;
221 int threadnum = 0;
222 argc--; argv++;
223 AM.ClearStore = 0;
224 AM.TimeLimit = 0;
225 AM.LogType = -1;
226 AM.HoldFlag = AM.qError = AM.Interact = AM.FileOnlyFlag = 0;
227 AM.InputFileName = AM.LogFileName = AM.IncDir = AM.TempDir = AM.TempSortDir =
228 AM.SetupDir = AM.SetupFile = AM.Path = 0;
229 AM.FromStdin = 0;
230 if ( argc < 1 ) {
231 onlyversion = 0;
232 goto printversion;
233 }
234 while ( argc >= 1 ) {
235 s = *argv++; argc--;
236 if ( *s == '-' || ( *s == '/' && ( argc > 0 || AM.Interact ) ) ) {
237 s++;
238 switch (*s) {
239 case 'c': /* Error checking only */
240 AM.qError = 1; break;
241 case 'C': /* Next arg is filename of log file */
242 TAKEPATH(AM.LogFileName) break;
243 case 'D':
244 case 'd': /* Next arg is define preprocessor var. */
245 t = copy = strDup1(*argv,"Dotail");
246 while ( *t && *t != '=' ) t++;
247 if ( *t == 0 ) {
248 if ( PutPreVar(copy,(UBYTE *)"1",0,0) < 0 ) return(-1);
249 }
250 else {
251 *t++ = 0;
252 if ( PutPreVar(copy,t,0,0) < 0 ) return(-1);
253 t[-1] = '=';
254 }
255 M_free(copy,"-d prevar");
256 argv++; argc--; break;
257 case 'f': /* Output only to regular log file */
258 AM.FileOnlyFlag = 1; AM.LogType = 0; break;
259 case 'F': /* Output only to log file. Further like L. */
260 AM.FileOnlyFlag = 1; AM.LogType = 1; break;
261 case 'h': /* For old systems: wait for key before exit */
262 AM.HoldFlag = 1; break;
263#ifdef WITHINTERACTION
264 case 'i': /* Interactive session (not used yet) */
265 AM.Interact = 1; break;
266#endif
267 case 'I': /* Next arg is dir for inc/prc/sub files */
268 TAKEPATH(AM.IncDir) break;
269 case 'l': /* Make regular log file */
270 if ( s[1] == 'l' ) AM.LogType = 1; /*compatibility! */
271 else AM.LogType = 0;
272 break;
273 case 'L': /* Make log file with only final statistics */
274 AM.LogType = 1; break;
275 case 'M': /* Multirun. Name of tempfiles will contain PID */
276 AM.MultiRun = 1;
277 break;
278 case 'm': /* Read number of threads */
279 case 'w': /* Read number of workers */
280 t = s++;
281 threadnum = 0;
282 while ( *s >= '0' && *s <= '9' )
283 threadnum = 10*threadnum + *s++ - '0';
284 if ( *s ) {
285#ifdef WITHMPI
286 if ( PF.me == MASTER )
287#endif
288 printf("Illegal value for option m or w: %s\n",t);
289 errorflag++;
290 }
291/* if ( threadnum == 1 ) threadnum = 0; */
292 threadnum++;
293 break;
294 case 'W': /* Print the wall-clock time on the master. */
295 AM.ggWTimeStatsFlag = 1;
296 break;
297/*
298 case 'n':
299 Reserved for number of slaves without MPI
300*/
301 case 'p':
302#ifdef WITHEXTERNALCHANNEL
303 /*There are two possibilities: -p|-pipe*/
304 if(s[1]=='i'){
305 if( (s[2]=='p')&&(s[3]=='e')&&(s[4]=='\0') ){
306 argc--;
307 /*Initialize pre-set external channels, see
308 the file extcmd.c:*/
309 if(initPresetExternalChannels(*argv++,AX.timeout)<1){
310#ifdef WITHMPI
311 if ( PF.me == MASTER )
312#endif
313 printf("Error initializing preset external channels\n");
314 errorflag++;
315 }
316 AX.timeout=-1;/*This indicates that preset channels
317 are initialized from cmdline*/
318 }else{
319#ifdef WITHMPI
320 if ( PF.me == MASTER )
321#endif
322 printf("Illegal option in call of FORM: %s\n",s);
323 errorflag++;
324 }
325 }else
326#else
327 if ( s[1] ) {
328 if ( ( s[1]=='i' ) && ( s[2] == 'p' ) && (s[3] == 'e' )
329 && ( s[4] == '\0' ) ){
330#ifdef WITHMPI
331 if ( PF.me == MASTER )
332#endif
333 printf("Illegal option: Pipes not supported on this system.\n");
334 }
335 else {
336#ifdef WITHMPI
337 if ( PF.me == MASTER )
338#endif
339 printf("Illegal option: %s\n",s);
340 }
341 errorflag++;
342 }
343 else
344#endif
345 {
346 /* Next arg is a path variable like in environment */
347 TAKEPATH(AM.Path)
348 }
349 break;
350 case 'q': /* Quiet option. Only output. Same as -si */
351 AM.silent = 1; break;
352 case 'R': /* recover from saved snapshot */
353 AC.CheckpointFlag = -1;
354 break;
355 case 's': /* Next arg is dir with form.set to be used */
356 if ( ( s[1] == 'o' ) && ( s[2] == 'r' ) && ( s[3] == 't' ) ) {
357 if(s[4]== '=' ) {
358 AM.TempSortDir = s+5;
359 }
360 else {
361 AM.TempSortDir = *argv++;
362 argc--;
363 }
364 }
365 else if ( s[1] == 'i' ) { /* compatibility: silent/quiet */
366 AM.silent = 1;
367 }
368 else {
369 TAKEPATH(AM.SetupDir)
370 }
371 break;
372 case 'S': /* Next arg is setup file */
373 TAKEPATH(AM.SetupFile) break;
374 case 't': /* Next arg is directory for temp files */
375 if ( s[1] == 's' ) {
376 s++;
377 AM.havesortdir = 1;
378 TAKEPATH(AM.TempSortDir)
379 }
380 else {
381 TAKEPATH(AM.TempDir)
382 }
383 break;
384 case 'T': /* Print the total size used at end of job */
385 AM.PrintTotalSize = 1; break;
386 case 'v':
387printversion:;
388#ifdef WITHMPI
389 if ( PF.me == MASTER )
390#endif
391 PrintHeader(0);
392 if ( onlyversion ) return(1);
393 goto NoFile;
394 case 'y': /* Preprocessor dumps output. No compilation. */
395 AP.PreDebug = PREPROONLY; break;
396 case 'z': /* The number following is a time limit in sec. */
397 t = s++;
398 AM.TimeLimit = 0;
399 while ( *s >= '0' && *s <= '9' )
400 AM.TimeLimit = 10*AM.TimeLimit + *s++ - '0';
401 break;
402 case 'Z': /* Removes the .str file on crash, no matter its contents */
403 AM.ClearStore = 1; break;
404 case '\0': /* "-" to use STDIN for the input. */
405#ifdef WITHMPI
406 /* At the moment, ParFORM doesn't implement STDIN broadcasts. */
407 if ( PF.me == MASTER )
408 printf("Sorry, reading STDIN as input is currently not supported by ParFORM\n");
409 errorflag++;
410#endif
411 AM.FromStdin = 1;
412 AC.NoShowInput = 1; // disable input echoing by default
413 break;
414 default:
415 if ( FG.cTable[*s] == 1 ) {
416 AM.SkipClears = 0; t = s;
417 while ( FG.cTable[*t] == 1 )
418 AM.SkipClears = 10*AM.SkipClears + *t++ - '0';
419 if ( *t != 0 ) {
420#ifdef WITHMPI
421 if ( PF.me == MASTER )
422#endif
423 printf("Illegal numerical option in call of FORM: %s\n",s);
424 errorflag++;
425 }
426 }
427 else {
428#ifdef WITHMPI
429 if ( PF.me == MASTER )
430#endif
431 printf("Illegal option in call of FORM: %s\n",s);
432 errorflag++;
433 }
434 break;
435 }
436 }
437 else if ( argc == 0 && !AM.Interact ) AM.InputFileName = argv[-1];
438 else {
439#ifdef WITHMPI
440 if ( PF.me == MASTER )
441#endif
442 printf("Illegal option in call of FORM: %s\n",s);
443 errorflag++;
444 }
445 }
446 AM.totalnumberofthreads = threadnum;
447 if ( AM.InputFileName ) {
448 if ( AM.FromStdin ) {
449 printf("STDIN and the input filename cannot be specified simultaneously\n");
450 errorflag++;
451 }
452 s = AM.InputFileName;
453 while ( *s ) s++;
454 if ( s < AM.InputFileName+4 ||
455 s[-4] != '.' || s[-3] != 'f' || s[-2] != 'r' || s[-1] != 'm' ) {
456 t = (UBYTE *)Malloc1((s-AM.InputFileName)+5,"adding .frm");
457 s = AM.InputFileName;
458 AM.InputFileName = t;
459 while ( *s ) *t++ = *s++;
460 *t++ = '.'; *t++ = 'f'; *t++ = 'r'; *t++ = 'm'; *t = 0;
461 }
462 if ( AM.LogType >= 0 && AM.LogFileName == 0 ) {
463 AM.LogFileName = strDup1(AM.InputFileName,"name of logfile");
464 s = AM.LogFileName;
465 while ( *s ) s++;
466 s[-3] = 'l'; s[-2] = 'o'; s[-1] = 'g';
467 }
468 }
469#ifdef WITHINTERACTION
470 else if ( AM.Interact ) {
471 if ( AM.LogType >= 0 ) {
472/*
473 We may have to do better than just taking a name.
474 It is not unique! This will be left for later.
475*/
476 AM.LogFileName = deflogname;
477 }
478 }
479#endif
480 else if ( AM.FromStdin ) {
481 /* Do nothing. */
482 }
483 else {
484NoFile:
485#ifdef WITHMPI
486 if ( PF.me == MASTER )
487#endif
488 printf("No filename specified in call of FORM\n");
489 errorflag++;
490 }
491 if ( AM.Path == 0 ) AM.Path = (UBYTE *)getenv("FORMPATH");
492 if ( AM.Path ) {
493 /*
494 * AM.Path is taken from argv or getenv. Reallocate it to avoid invalid
495 * frees when AM.Path has to be changed.
496 */
497 AM.Path = strDup1(AM.Path,"DoTail Path");
498 }
499 return(errorflag);
500}
501
502/*
503 #] DoTail :
504 #[ OpenInput :
505
506 Major task here after opening is to skip the proper number of
507 .clear instructions if so desired without using interpretation
508*/
509
510int OpenInput()
511{
512 int oldNoShowInput = AC.NoShowInput;
513 UBYTE c;
514 if ( !AM.Interact ) {
515 if ( AM.FromStdin ) {
516 if ( OpenStream(0,INPUTSTREAM,0,PRENOACTION) == 0 ) {
517 Error0("Cannot open STDIN");
518 return(-1);
519 }
520 }
521 else {
522 if ( OpenStream(AM.InputFileName,FILESTREAM,0,PRENOACTION) == 0 ) {
523 Error1("Cannot open file",AM.InputFileName);
524 return(-1);
525 }
526 if ( AC.CurrentStream->inbuffer <= 0 ) {
527 Error1("No input in file",AM.InputFileName);
528 return(-1);
529 }
530 }
531 AC.NoShowInput = 1;
532 while ( AM.SkipClears > 0 ) {
533 c = GetInput();
534 if ( c == ENDOFINPUT ) {
535 Error0("Not enough .clear instructions in input file");
536 }
537 if ( c == '\\' ) {
538 c = GetInput();
539 if ( c == ENDOFINPUT )
540 Error0("Not enough .clear instructions in input file");
541 continue;
542 }
543 if ( c == ' ' || c == '\t' ) continue;
544 if ( c == '.' ) {
545 c = GetInput();
546 if ( tolower(c) == 'c' ) {
547 c = GetInput();
548 if ( tolower(c) == 'l' ) {
549 c = GetInput();
550 if ( tolower(c) == 'e' ) {
551 c = GetInput();
552 if ( tolower(c) == 'a' ) {
553 c = GetInput();
554 if ( tolower(c) == 'r' ) {
555 c = GetInput();
556 if ( FG.cTable[c] > 2 ) {
557 AM.SkipClears--;
558 }
559 }
560 }
561 }
562 }
563 }
564 while ( c != '\n' && c != '\r' && c != ENDOFINPUT ) {
565 c = GetInput();
566 if ( c == '\\' ) c = GetInput();
567 }
568 }
569 else if ( c == '\n' || c == '\r' ) continue;
570 else {
571 while ( ( c = GetInput() ) != '\n' && c != '\r' ) {
572 if ( c == ENDOFINPUT ) {
573 Error0("Not enough .clear instructions in input file");
574 }
575 }
576 }
577 }
578 AC.NoShowInput = oldNoShowInput;
579 }
580 if ( AM.LogFileName ) {
581#ifdef WITHMPI
582 if ( PF.me != MASTER ) {
583 /*
584 * Only the master writes to the log file. On slaves, we need
585 * a dummy handle, without opening the file.
586 */
587 extern FILES **filelist; /* in tools.c */
588 int i = CreateHandle();
589 RWLOCKW(AM.handlelock);
590 filelist[i] = (FILES *)123; /* Must be nonzero to prevent a reuse in CreateHandle. */
591 UNRWLOCK(AM.handlelock);
592 AC.LogHandle = i;
593 }
594 else
595#endif
596 if ( AC.CheckpointFlag != -1 ) {
597 if ( ( AC.LogHandle = CreateLogFile((char *)(AM.LogFileName)) ) < 0 ) {
598 Error1("Cannot create logfile",AM.LogFileName);
599 return(-1);
600 }
601 }
602 else {
603 if ( ( AC.LogHandle = OpenAddFile((char *)(AM.LogFileName)) ) < 0 ) {
604 Error1("Cannot re-open logfile",AM.LogFileName);
605 return(-1);
606 }
607 }
608 }
609 return(0);
610}
611
612/*
613 #] OpenInput :
614 #[ ReserveTempFiles :
615
616 Order of preference:
617 a: if there is a path in the commandtail, take that.
618 b: if none, try in the form.set file.
619 c: if still none, try in the environment for the variable FORMTMP
620 d: if still none, try the current directory.
621
622 The parameter indicates action in the case of multithreaded running.
623 par = 0 : We just run on a single processor. Keep everything normal.
624 par = 1 : Multithreaded running startup phase 1.
625 par = 2 : Multithreaded running startup phase 2.
626*/
627
628UBYTE *emptystring = (UBYTE *)".";
629UBYTE *defaulttempfilename = (UBYTE *)"xformxxx.str";
630
631VOID ReserveTempFiles(int par)
632{
633 GETIDENTITY
634 SETUPPARAMETERS *sp;
635 UBYTE *s, *t, *tenddir, *tenddir2, c;
636 int i = 0;
637 WORD j;
638 if ( par == 0 || par == 1 ) {
639 if ( AM.TempDir == 0 ) {
640 sp = GetSetupPar((UBYTE *)"tempdir");
641 if ( ( sp->flags & USEDFLAG ) != USEDFLAG ) {
642 AM.TempDir = (UBYTE *)getenv("FORMTMP");
643 if ( AM.TempDir == 0 ) AM.TempDir = emptystring;
644 }
645 else AM.TempDir = (UBYTE *)(sp->value);
646 }
647 if ( AM.TempSortDir == 0 ) {
648 if ( AM.havesortdir ) {
649 sp = GetSetupPar((UBYTE *)"tempsortdir");
650 AM.TempSortDir = (UBYTE *)(sp->value);
651 }
652 else {
653 AM.TempSortDir = (UBYTE *)getenv("FORMTMPSORT");
654 if ( AM.TempSortDir == 0 ) AM.TempSortDir = AM.TempDir;
655 }
656 }
657/*
658 We have now in principle a path but we will use its first element only.
659 Later that should become more complicated. Then we will use a path and
660 when one device is full we can continue on the next one.
661*/
662 s = AM.TempDir; i = 200; /* Some extra for VMS */
663 while ( *s && *s != ':' ) { if ( *s == '\\' ) s++; s++; i++; }
664
665 FG.fname = (char *)Malloc1(sizeof(UBYTE)*(i+14),"name for temporary files");
666 s = AM.TempDir; t = (UBYTE *)FG.fname;
667 while ( *s && *s != ':' ) { if ( *s == '\\' ) s++; *t++ = *s++; }
668 if ( (char *)t > FG.fname && t[-1] != SEPARATOR && t[-1] != ALTSEPARATOR )
669 *t++ = SEPARATOR;
670 *t = 0;
671 tenddir = t;
672 FG.fnamebase = t-(UBYTE *)(FG.fname);
673
674 s = AM.TempSortDir; i = 200; /* Some extra for VMS */
675 while ( *s && *s != ':' ) { if ( *s == '\\' ) s++; s++; i++; }
676
677 FG.fname2 = (char *)Malloc1(sizeof(UBYTE)*(i+14),"name for sort files");
678 s = AM.TempSortDir; t = (UBYTE *)FG.fname2;
679 while ( *s && *s != ':' ) { if ( *s == '\\' ) s++; *t++ = *s++; }
680 if ( (char *)t > FG.fname2 && t[-1] != SEPARATOR && t[-1] != ALTSEPARATOR )
681 *t++ = SEPARATOR;
682 *t = 0;
683 tenddir2 = t;
684 FG.fname2base = t-(UBYTE *)(FG.fname2);
685
686 t = tenddir;
687 s = defaulttempfilename;
688#ifdef WITHMPI
689 {
690 int iii;
691#ifdef SMP
692 /* Very dirty quick-hack for the qcm smp machine at TTP */
693 M_free(FG.fname,"name for temporary files");
694 if(PF.me == 0){
695 /*[04nov2003 mt] To avoid segfault with -fast optimization option*/
696 /*[04nov2003 mt]:*/ /*NOTE, this is only a temporary stub!*/
697 /*FG.fname = "/formswap/xxxxxxxxxxxxxxxxxxxxx";*/
698 FG.fname = calloc(128,1);
699 strcpy(FG.fname,"/formswap/xxxxxxxxxxxxxxxxxxxxx");
700 /*:[04nov2003 mt]*/
701 t = (UBYTE *)FG.fname + 10;
702 FG.fnamebase = t-FG.fname;
703 }
704 else{
705 /*[04nov2003 mt]:*/
706 /*FG.fname = "/formswapx/xxxxxxxxxxxxxxxxxxxxx";*/
707 FG.fname = calloc(128,1);
708 strcpy(FG.fname,"/formswapx/xxxxxxxxxxxxxxxxxxxxx");
709 /*:[04nov2003 mt]*/
710 FG.fname[9] = '0' + PF.me;
711 t = (UBYTE *)FG.fname + 11;
712 FG.fnamebase = t-FG.fname;
713 }
714#else
715 iii = sprintf((char*)t,"%d",PF.me);
716 t+= iii;
717 s+= iii; /* in case defaulttmpfilename is too short */
718#endif
719 }
720#endif
721 while ( *s ) *t++ = *s++;
722 *t = 0;
723/*
724 There are problems when running many FORM jobs at the same time
725 from make or minos. If they start up simultaneously, occasionally
726 they can make the same .str file. We prevent this with first trying
727 a file that contains the digits of the pid. If this file
728 has already been taken we fall back on the old scheme.
729 The whole is controled with the -M (MultiRun) parameter in the
730 command tail.
731*/
732 if ( AM.MultiRun ) {
733 int num = ((int)GetPID())%100000;
734 t += 2;
735 *t = 0;
736 t[-1] = 'r';
737 t[-2] = 't';
738 t[-3] = 's';
739 t[-4] = '.';
740 t[-5] = (UBYTE)('0' + num%10);
741 t[-6] = (UBYTE)('0' + (num/10)%10);
742 t[-7] = (UBYTE)('0' + (num/100)%10);
743 t[-8] = (UBYTE)('0' + (num/1000)%10);
744 t[-9] = (UBYTE)('0' + num/10000);
745 if ( ( AC.StoreHandle = CreateFile((char *)FG.fname) ) < 0 ) {
746 t[-5] = 'x'; t[-6] = 'x'; t[-7] = 'x'; t[-8] = 'x'; t[-9] = 'x';
747 goto classic;
748 }
749 }
750 else
751 {
752classic:;
753 for(;;) {
754 if ( ( AC.StoreHandle = OpenFile((char *)FG.fname) ) < 0 ) {
755 if ( ( AC.StoreHandle = CreateFile((char *)FG.fname) ) >= 0 ) break;
756 }
757 else CloseFile(AC.StoreHandle);
758 c = t[-5];
759 if ( c == 'x' ) t[-5] = '0';
760 else if ( c == '9' ) {
761 t[-5] = '0';
762 c = t[-6];
763 if ( c == 'x' ) t[-6] = '0';
764 else if ( c == '9' ) {
765 t[-6] = '0';
766 c = t[-7];
767 if ( c == 'x' ) t[-7] = '0';
768 else if ( c == '9' ) {
769/*
770 Note that we tried 1111 names!
771*/
772 MesPrint("Name space for temp files exhausted");
773 t[-7] = 0;
774 MesPrint("Please remove files of the type %s or try a different directory"
775 ,FG.fname);
776 Terminate(-1);
777 }
778 else t[-7] = (UBYTE)(c+1);
779 }
780 else t[-6] = (UBYTE)(c+1);
781 }
782 else t[-5] = (UBYTE)(c+1);
783 }
784 }
785/*
786 Now we should make sure that the tempsortdir cq tempsortfilename makes it
787 into a similar construction.
788*/
789 s = tenddir; t = tenddir2; while ( *s ) *t++ = *s++;
790 *t = 0;
791
792/*
793 Now we should asign a name to the main sort file and the two stage 4 files.
794*/
795 AM.S0->file.name = (char *)Malloc1(sizeof(char)*(i+14),"name for temporary files");
796 s = (UBYTE *)AM.S0->file.name;
797 t = (UBYTE *)FG.fname2;
798 i = 1;
799 while ( *t ) { *s++ = *t++; i++; }
800 s[-2] = 'o'; *s = 0;
801 }
802/*
803 With the stage4 and scratch file names we have to be a bit more careful.
804 They are to be allocated after the threads are initialized when there
805 are threads of course.
806*/
807 if ( par == 0 ) {
808 s = (UBYTE *)((void *)(FG.fname2)); i = 0;
809 while ( *s ) { s++; i++; }
810 s = (UBYTE *)Malloc1(sizeof(char)*(i+1),"name for stage4 file a");
811 AR.FoStage4[1].name = (char *)s;
812 t = (UBYTE *)FG.fname2;
813 while ( *t ) *s++ = *t++;
814 s[-2] = '4'; s[-1] = 'a'; *s = 0;
815 s = (UBYTE *)((void *)(FG.fname)); i = 0;
816 while ( *s ) { s++; i++; }
817 s = (UBYTE *)Malloc1(sizeof(char)*(i+1),"name for stage4 file b");
818 AR.FoStage4[0].name = (char *)s;
819 t = (UBYTE *)FG.fname;
820 while ( *t ) *s++ = *t++;
821 s[-2] = '4'; s[-1] = 'b'; *s = 0;
822 for ( j = 0; j < 3; j++ ) {
823 s = (UBYTE *)Malloc1(sizeof(char)*(i+1),"name for scratch file");
824 AR.Fscr[j].name = (char *)s;
825 t = (UBYTE *)FG.fname;
826 while ( *t ) *s++ = *t++;
827 s[-2] = 'c'; s[-1] = (UBYTE)('0'+j); *s = 0;
828 }
829 }
830#ifdef WITHPTHREADS
831 else if ( par == 2 ) {
832 s = (UBYTE *)((void *)(FG.fname2)); i = 0;
833 while ( *s ) { s++; i++; }
834 s = (UBYTE *)Malloc1(sizeof(char)*(i+12),"name for stage4 file a");
835 sprintf((char *)s,"%s.%d",FG.fname2,AT.identity);
836 s[i-2] = '4'; s[i-1] = 'a';
837 AR.FoStage4[1].name = (char *)s;
838 s = (UBYTE *)((void *)(FG.fname)); i = 0;
839 while ( *s ) { s++; i++; }
840 s = (UBYTE *)Malloc1(sizeof(char)*(i+12),"name for stage4 file b");
841 sprintf((char *)s,"%s.%d",FG.fname,AT.identity);
842 s[i-2] = '4'; s[i-1] = 'b';
843 AR.FoStage4[0].name = (char *)s;
844 if ( AT.identity == 0 ) {
845 for ( j = 0; j < 3; j++ ) {
846 s = (UBYTE *)Malloc1(sizeof(char)*(i+1),"name for scratch file");
847 AR.Fscr[j].name = (char *)s;
848 t = (UBYTE *)FG.fname;
849 while ( *t ) *s++ = *t++;
850 s[-2] = 'c'; s[-1] = (UBYTE)('0'+j); *s = 0;
851 }
852 }
853 }
854#endif
855}
856
857/*
858 #] ReserveTempFiles :
859 #[ StartVariables :
860*/
861
862#ifdef WITHPTHREADS
863ALLPRIVATES *DummyPointer = 0;
864#endif
865
867{
868 int i, ii;
869 PUTZERO(AM.zeropos);
870 StartPrepro();
871/*
872 The module counter:
873*/
874 AC.CModule=0;
875#ifdef WITHPTHREADS
876/*
877 We need a value in AB because in the startup some routines may call AB[0].
878*/
879 AB = (ALLPRIVATES **)&DummyPointer;
880#endif
881/*
882 separators used to delimit arguments in #call and #do, by default ',' and '|':
883 Be sure, it is en empty set:
884*/
885 set_sub(AC.separators,AC.separators,AC.separators);
886 set_set(',',AC.separators);
887 set_set('|',AC.separators);
888
889 AM.BracketFactors[0] = 8;
890 AM.BracketFactors[1] = SYMBOL;
891 AM.BracketFactors[2] = 4;
892 AM.BracketFactors[3] = FACTORSYMBOL;
893 AM.BracketFactors[4] = 1;
894 AM.BracketFactors[5] = 1;
895 AM.BracketFactors[6] = 1;
896 AM.BracketFactors[7] = 3;
897
898 AM.SkipClears = 0;
899 AC.Cnumpows = 0;
900 AC.OutputMode = 72;
901 AC.OutputSpaces = NORMALFORMAT;
902 AC.LineLength = 79;
903 AM.gIsFortran90 = AC.IsFortran90 = ISNOTFORTRAN90;
904 AM.gFortran90Kind = AC.Fortran90Kind = 0;
905 AM.gCnumpows = 0;
906 AC.exprfillwarning = 0;
907 AM.gLineLength = 79;
908 AM.OutBufSize = 80;
909 AM.MaxStreamSize = MAXFILESTREAMSIZE;
910 AP.MaxPreAssignLevel = 4;
911 AC.iBufferSize = 512;
912 AP.pSize = 128;
913 AP.MaxPreIfLevel = 10;
914 AP.cComChar = AP.ComChar = '*';
915 AM.OffsetVector = -2*WILDOFFSET+MINSPEC;
916 AC.cbufList.num = 0;
917 AM.hparallelflag = AM.gparallelflag =
918 AC.parallelflag = AC.mparallelflag = PARALLELFLAG;
919#ifdef WITHMPI
920 if ( PF.numtasks < 2 ) AM.hparallelflag |= NOPARALLEL_NPROC;
921#endif
922 AC.tablefilling = 0;
923 AM.resetTimeOnClear = 1;
924 AM.gnumextrasym = AM.ggnumextrasym = 0;
925 AM.havesortdir = 0;
926 AM.SpectatorFiles = 0;
927 AM.NumSpectatorFiles = 0;
928 AM.SizeForSpectatorFiles = 0;
929/*
930 Information for the lists of variables. Part of error message and size:
931*/
932 AP.ProcList.message = "procedure";
933 AP.ProcList.size = sizeof(PROCEDURE);
934 AP.LoopList.message = "doloop";
935 AP.LoopList.size = sizeof(DOLOOP);
936 AP.PreVarList.message = "PreVariable";
937 AP.PreVarList.size = sizeof(PREVAR);
938 AC.SymbolList.message = "symbol";
939 AC.SymbolList.size = sizeof(struct SyMbOl);
940 AC.IndexList.message = "index";
941 AC.IndexList.size = sizeof(struct InDeX);
942 AC.VectorList.message = "vector";
943 AC.VectorList.size = sizeof(struct VeCtOr);
944 AC.FunctionList.message = "function";
945 AC.FunctionList.size = sizeof(struct FuNcTiOn);
946 AC.SetList.message = "set";
947 AC.SetList.size = sizeof(struct SeTs);
948 AC.SetElementList.message = "set element";
949 AC.SetElementList.size = sizeof(WORD);
950 AC.ExpressionList.message = "expression";
951 AC.ExpressionList.size = sizeof(struct ExPrEsSiOn);
952 AC.cbufList.message = "compiler buffer";
953 AC.cbufList.size = sizeof(CBUF);
954 AC.ChannelList.message = "channel buffer";
955 AC.ChannelList.size = sizeof(CHANNEL);
956 AP.DollarList.message = "$-variable";
957 AP.DollarList.size = sizeof(struct DoLlArS);
958 AC.DubiousList.message = "ambiguous variable";
959 AC.DubiousList.size = sizeof(struct DuBiOuS);
960 AC.TableBaseList.message = "list of tablebases";
961 AC.TableBaseList.size = sizeof(DBASE);
962 AC.TestValue = 0;
963 AC.InnerTest = 0;
964
965 AC.AutoSymbolList.message = "autosymbol";
966 AC.AutoSymbolList.size = sizeof(struct SyMbOl);
967 AC.AutoIndexList.message = "autoindex";
968 AC.AutoIndexList.size = sizeof(struct InDeX);
969 AC.AutoVectorList.message = "autovector";
970 AC.AutoVectorList.size = sizeof(struct VeCtOr);
971 AC.AutoFunctionList.message = "autofunction";
972 AC.AutoFunctionList.size = sizeof(struct FuNcTiOn);
973 AC.PotModDolList.message = "potentially modified dollar";
974 AC.PotModDolList.size = sizeof(WORD);
975 AC.ModOptDolList.message = "moduleoptiondollar";
976 AC.ModOptDolList.size = sizeof(MODOPTDOLLAR);
977
978 AO.FortDotChar = '_';
979 AO.ErrorBlock = 0;
980 AC.firstconstindex = 1;
981 AO.Optimize.mctsconstant.fval = 1.0;
982 AO.Optimize.horner = O_MCTS;
983 AO.Optimize.hornerdirection = O_FORWARDORBACKWARD;
984 AO.Optimize.method = O_GREEDY;
985 AO.Optimize.mctstimelimit = 0;
986 AO.Optimize.mctsnumexpand = 1000;
987 AO.Optimize.mctsnumkeep = 10;
988 AO.Optimize.mctsnumrepeat = 1;
989 AO.Optimize.greedytimelimit = 0;
990 AO.Optimize.greedyminnum = 10;
991 AO.Optimize.greedymaxperc = 5;
992 AO.Optimize.printstats = 0;
993 AO.Optimize.debugflags = 0;
994 AO.OptimizeResult.code = NULL;
995 AO.inscheme = 0;
996 AO.schemenum = 0;
997 AO.wpos = 0;
998 AO.wpoin = 0;
999 AO.wlen = 0;
1000 AM.dollarzero = 0;
1001 AC.doloopstack = 0;
1002 AC.doloopstacksize = 0;
1003 AC.dolooplevel = 0;
1004/*
1005 Set up the main name trees:
1006*/
1007 AC.varnames = MakeNameTree();
1008 AC.exprnames = MakeNameTree();
1009 AC.dollarnames = MakeNameTree();
1010 AC.autonames = MakeNameTree();
1011 AC.activenames = &(AC.varnames);
1012 AP.preError = 0;
1013/*
1014 Initialize the compiler:
1015*/
1016 inictable();
1017 AM.rbufnum = inicbufs(); /* Regular compiler buffer */
1018#ifndef WITHPTHREADS
1019 AT.ebufnum = inicbufs(); /* Buffer for extras during execution */
1020 AT.fbufnum = inicbufs(); /* Buffer for caching in factorization */
1021 AT.allbufnum = inicbufs(); /* Buffer for id,all */
1022 AT.aebufnum = inicbufs(); /* Buffer for id,all */
1023 AN.tryterm = 0;
1024#else
1025 AS.MasterSort = 0;
1026#endif
1027 AM.dbufnum = inicbufs(); /* Buffer for dollar variables */
1028 AM.sbufnum = inicbufs(); /* Subterm buffer for polynomials and optimization */
1029 AC.ffbufnum = inicbufs(); /* Buffer number for user defined factorizations */
1030 AM.zbufnum = inicbufs(); /* For very special values */
1031 {
1032 CBUF *C = cbuf+AM.zbufnum;
1033 WORD one[5] = {4,1,1,3,0};
1034 WORD zero = 0;
1035 AddRHS(AM.zbufnum,1);
1036 AM.zerorhs = C->numrhs;
1037 AddNtoC(AM.zbufnum,1,&zero,17);
1038 AddRHS(AM.zbufnum,1);
1039 AM.onerhs = C->numrhs;
1040 AddNtoC(AM.zbufnum,5,one,17);
1041 }
1042 AP.inside.inscbuf = inicbufs(); /* For the #inside instruction */
1043/*
1044 Enter the built in objects
1045*/
1046 AC.Symbols = &(AC.SymbolList);
1047 AC.Indices = &(AC.IndexList);
1048 AC.Vectors = &(AC.VectorList);
1049 AC.Functions = &(AC.FunctionList);
1050 AC.vetofilling = 0;
1051
1052 AddDollar((UBYTE *)"$",DOLUNDEFINED,0,0);
1053
1054 cbuf[AM.dbufnum].mnumlhs = cbuf[AM.dbufnum].numlhs;
1055 cbuf[AM.dbufnum].mnumrhs = cbuf[AM.dbufnum].numrhs;
1056
1057 AddSymbol((UBYTE *)"i_",-MAXPOWER,MAXPOWER,VARTYPEIMAGINARY,0);
1058 AddSymbol((UBYTE *)"pi_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1059 AddSymbol((UBYTE *)"coeff_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1060 AddSymbol((UBYTE *)"num_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1061 AddSymbol((UBYTE *)"den_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1062 AddSymbol((UBYTE *)"xarg_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1063 AddSymbol((UBYTE *)"dimension_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1064 AddSymbol((UBYTE *)"factor_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1065 AddSymbol((UBYTE *)"sep_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1066 i = BUILTINSYMBOLS; /* update this in ftypes.h when we add new symbols */
1067/*
1068 Next we add a number of dummy symbols for ensuring that the user defined
1069 symbols start at a fixed given number FIRSTUSERSYMBOL
1070 We do want to give them unique names though that the user cannot access.
1071*/
1072 {
1073 char dumstr[20];
1074 for ( ; i < FIRSTUSERSYMBOL; i++ ) {
1075 sprintf(dumstr,":%d:",i);
1076 AddSymbol((UBYTE *)dumstr,-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1077 }
1078 }
1079
1080 AddIndex((UBYTE *)"iarg_",4,0);
1081 AddVector((UBYTE *)"parg_",VARTYPENONE,0);
1082
1083 AM.NumFixedFunctions = sizeof(fixedfunctions)/sizeof(struct fixedfun);
1084 for ( i = 0; i < AM.NumFixedFunctions; i++ ) {
1085 ii = AddFunction((UBYTE *)fixedfunctions[i].name
1086 ,fixedfunctions[i].commu
1087 ,fixedfunctions[i].tensor
1088 ,fixedfunctions[i].complx
1089 ,fixedfunctions[i].symmetric
1090 ,0,-1,-1);
1091 if ( fixedfunctions[i].tensor == GAMMAFUNCTION )
1092 functions[ii].flags |= COULDCOMMUTE;
1093 }
1094/*
1095 Next we add a number of dummy functions for ensuring that the user defined
1096 functions start at a fixed given number FIRSTUSERFUNCTION.
1097 We do want to give them unique names though that the user cannot access.
1098*/
1099 {
1100 char dumstr[20];
1101 for ( ; i < FIRSTUSERFUNCTION-FUNCTION; i++ ) {
1102 sprintf(dumstr,"::%d::",i);
1103 AddFunction((UBYTE *)dumstr,0,0,0,0,0,-1,-1);
1104 }
1105 }
1106 AM.NumFixedSets = sizeof(fixedsets)/sizeof(struct fixedset);
1107 for ( i = 0; i < AM.NumFixedSets; i++ ) {
1108 ii = AddSet((UBYTE *)fixedsets[i].name,fixedsets[i].dimension);
1109 Sets[ii].type = fixedsets[i].type;
1110 }
1111 AM.RepMax = MAXREPEAT;
1112#ifndef WITHPTHREADS
1113 AT.RepCount = (int *)Malloc1((LONG)((AM.RepMax+3)*sizeof(int)),"repeat buffers");
1114 AN.RepPoint = AT.RepCount;
1115 AT.RepTop = AT.RepCount + AM.RepMax;
1116 AN.polysortflag = 0;
1117 AN.subsubveto = 0;
1118#endif
1119 AC.NumWildcardNames = 0;
1120 AC.WildcardBufferSize = 50;
1121 AC.WildcardNames = (UBYTE *)Malloc1((LONG)AC.WildcardBufferSize,"argument list names");
1122#ifndef WITHPTHREADS
1123 AT.WildArgTaken = (WORD *)Malloc1((LONG)AC.WildcardBufferSize*sizeof(WORD)/2
1124 ,"argument list names");
1125 AT.WildcardBufferSize = AC.WildcardBufferSize;
1126 AR.CompareRoutine = &Compare1;
1127 AT.nfac = AT.nBer = 0;
1128 AT.factorials = 0;
1129 AT.bernoullis = 0;
1130 AR.wranfia = 0;
1131 AR.wranfcall = 0;
1132 AR.wranfnpair1 = NPAIR1;
1133 AR.wranfnpair2 = NPAIR2;
1134 AR.wranfseed = 0;
1135#endif
1136 AM.atstartup = 1;
1137 AM.oldnumextrasymbols = strDup1((UBYTE *)"OLDNUMEXTRASYMBOLS_","oldnumextrasymbols");
1138 PutPreVar((UBYTE *)"VERSION_",(UBYTE *)STRINGIFY(MAJORVERSION),0,0);
1139 PutPreVar((UBYTE *)"SUBVERSION_",(UBYTE *)STRINGIFY(MINORVERSION),0,0);
1140 PutPreVar((UBYTE *)"DATE_",(UBYTE *)MakeDate(),0,0);
1141 PutPreVar((UBYTE *)"random_",(UBYTE *)"________",(UBYTE *)"?a",0);
1142 PutPreVar((UBYTE *)"optimminvar_",(UBYTE *)("0"),0,0);
1143 PutPreVar((UBYTE *)"optimmaxvar_",(UBYTE *)("0"),0,0);
1144 PutPreVar(AM.oldnumextrasymbols,(UBYTE *)("0"),0,0);
1145 PutPreVar((UBYTE *)"optimvalue_",(UBYTE *)("0"),0,0);
1146 PutPreVar((UBYTE *)"optimscheme_",(UBYTE *)("0"),0,0);
1147 PutPreVar((UBYTE *)"tolower_",(UBYTE *)("0"),(UBYTE *)("?a"),0);
1148 PutPreVar((UBYTE *)"toupper_",(UBYTE *)("0"),(UBYTE *)("?a"),0);
1149 PutPreVar((UBYTE *)"SYSTEMERROR_",(UBYTE *)("0"),0,0);
1150 {
1151 char buf[41]; /* up to 128-bit */
1152 LONG pid;
1153#ifndef WITHMPI
1154 pid = GetPID();
1155#else
1156 pid = ( PF.me == MASTER ) ? GetPID() : (LONG)0;
1157 pid = PF_BroadcastNumber(pid);
1158#endif
1159 LongCopy(pid,buf);
1160 PutPreVar((UBYTE *)"PID_",(UBYTE *)buf,0,0);
1161 }
1162 AM.atstartup = 0;
1163 AP.MaxPreTypes = 10;
1164 AP.NumPreTypes = 0;
1165 AP.PreTypes = (int *)Malloc1(sizeof(int)*(AP.MaxPreTypes+1),"preprocessor types");
1166 AP.inside.buffer = 0;
1167 AP.inside.size = 0;
1168
1169 AC.SortType = AC.lSortType = AM.gSortType = SORTLOWFIRST;
1170#ifdef WITHPTHREADS
1171#else
1172 AR.SortType = AC.SortType;
1173#endif
1174 AC.LogHandle = -1;
1175 AC.SetList.numtemp = AC.SetList.num;
1176 AC.SetElementList.numtemp = AC.SetElementList.num;
1177
1178 GetName(AC.varnames,(UBYTE *)"exp_",&AM.expnum,NOAUTO);
1179 GetName(AC.varnames,(UBYTE *)"denom_",&AM.denomnum,NOAUTO);
1180 GetName(AC.varnames,(UBYTE *)"fac_",&AM.facnum,NOAUTO);
1181 GetName(AC.varnames,(UBYTE *)"invfac_",&AM.invfacnum,NOAUTO);
1182 GetName(AC.varnames,(UBYTE *)"sum_",&AM.sumnum,NOAUTO);
1183 GetName(AC.varnames,(UBYTE *)"sump_",&AM.sumpnum,NOAUTO);
1184 GetName(AC.varnames,(UBYTE *)"term_",&AM.termfunnum,NOAUTO);
1185 GetName(AC.varnames,(UBYTE *)"match_",&AM.matchfunnum,NOAUTO);
1186 GetName(AC.varnames,(UBYTE *)"count_",&AM.countfunnum,NOAUTO);
1187 AM.termfunnum += FUNCTION;
1188 AM.matchfunnum += FUNCTION;
1189 AM.countfunnum += FUNCTION;
1190
1191 AC.ThreadStats = AM.gThreadStats = AM.ggThreadStats = 1;
1192 AC.FinalStats = AM.gFinalStats = AM.ggFinalStats = 1;
1193 AC.StatsFlag = AM.gStatsFlag = AM.ggStatsFlag = 1;
1194 AC.ThreadsFlag = AM.gThreadsFlag = AM.ggThreadsFlag = 1;
1195 AC.ThreadBalancing = AM.gThreadBalancing = AM.ggThreadBalancing = 1;
1196 AC.ThreadSortFileSynch = AM.gThreadSortFileSynch = AM.ggThreadSortFileSynch = 0;
1197 AC.ProcessStats = AM.gProcessStats = AM.ggProcessStats = 1;
1198 AC.OldParallelStats = AM.gOldParallelStats = AM.ggOldParallelStats = 0;
1199 AC.OldFactArgFlag = AM.gOldFactArgFlag = AM.ggOldFactArgFlag = NEWFACTARG;
1200 AC.OldGCDflag = AM.gOldGCDflag = AM.ggOldGCDflag = 1;
1201 AC.WTimeStatsFlag = AM.gWTimeStatsFlag = AM.ggWTimeStatsFlag = 0;
1202 AM.gcNumDollars = AP.DollarList.num;
1203 AC.SizeCommuteInSet = AM.gSizeCommuteInSet = 0;
1204 AC.CommuteInSet = 0;
1205
1206 AM.PrintTotalSize = 0;
1207
1208 AO.NoSpacesInNumbers = AM.gNoSpacesInNumbers = AM.ggNoSpacesInNumbers = 0;
1209 AO.IndentSpace = AM.gIndentSpace = AM.ggIndentSpace = INDENTSPACE;
1210 AO.BlockSpaces = 0;
1211 AO.OptimizationLevel = 0;
1212 PUTZERO(AS.MaxExprSize);
1213 PUTZERO(AC.StoreFileSize);
1214
1215#ifdef WITHPTHREADS
1216 AC.inputnumbers = 0;
1217 AC.pfirstnum = 0;
1218 AC.numpfirstnum = AC.sizepfirstnum = 0;
1219#endif
1220 AC.MemDebugFlag = 1;
1221
1222#ifdef WITHEXTERNALCHANNEL
1223 AX.currentExternalChannel=0;
1224 AX.killSignal=SIGKILL;
1225 AX.killWholeGroup=1;
1226 AX.daemonize=1;
1227 AX.currentPrompt=0;
1228 AX.timeout=1000;/*One second to initialize preset channels*/
1229 AX.shellname=strDup1((UBYTE *)"/bin/sh -c","external channel shellname");
1230 AX.stderrname=strDup1((UBYTE *)"/dev/null","external channel stderrname");
1231#endif
1232}
1233
1234/*
1235 #] StartVariables :
1236 #[ StartMore :
1237*/
1238
1239VOID StartMore()
1240{
1241#ifdef WITHEXTERNALCHANNEL
1242 /*If env.variable "FORM_PIPES" is defined, we have to initialize
1243 corresponding pre-set external channels, see file extcmd.c.*/
1244 /*This line must be after all setup settings: in future, timeout
1245 could be changed at setup.*/
1246 if(AX.timeout>=0)/*if AX.timeout<0, this was done by cmdline option -pipe*/
1247 initPresetExternalChannels((UBYTE*)getenv("FORM_PIPES"),AX.timeout);
1248#endif
1249
1250#ifdef WITHMPI
1251/*
1252 Define preprocessor variable PARALLELTASK_ as a process number, 0 is the master
1253 Define preprocessor variable NPARALLELTASKS_ as a total number of processes
1254*/
1255 {
1256 UBYTE buf[32];
1257 sprintf((char*)buf,"%d",PF.me);
1258 PutPreVar((UBYTE *)"PARALLELTASK_",buf,0,0);
1259 sprintf((char*)buf,"%d",PF.numtasks);
1260 PutPreVar((UBYTE *)"NPARALLELTASKS_",buf,0,0);
1261 }
1262#else
1263 PutPreVar((UBYTE *)"PARALLELTASK_",(UBYTE *)"0",0,0);
1264 PutPreVar((UBYTE *)"NPARALLELTASKS_",(UBYTE *)"1",0,0);
1265#endif
1266
1267 PutPreVar((UBYTE *)"NAME_",AM.InputFileName ? AM.InputFileName : (UBYTE *)"STDIN",0,0);
1268}
1269
1270/*
1271 #] StartMore :
1272 #[ IniVars :
1273
1274 This routine initializes the parameters that may change during the run.
1275*/
1276
1277WORD IniVars()
1278{
1279#ifdef WITHPTHREADS
1280 GETIDENTITY
1281#else
1282 WORD *t;
1283#endif
1284 WORD *fi, i, one = 1;
1285 CBUF *C = cbuf+AC.cbufnum;
1286
1287#ifdef WITHPTHREADS
1288 UBYTE buf[32];
1289 sprintf((char*)buf,"%d",AM.totalnumberofthreads);
1290 PutPreVar((UBYTE *)"NTHREADS_",buf,0,1);
1291#else
1292 PutPreVar((UBYTE *)"NTHREADS_",(UBYTE *)"1",0,1);
1293#endif
1294
1295 AC.ShortStats = 0;
1296 AC.WarnFlag = 1;
1297 AR.SortType = AC.SortType = AC.lSortType = AM.gSortType;
1298 AC.OutputMode = 72;
1299 AC.OutputSpaces = NORMALFORMAT;
1300 AR.Eside = 0;
1301 AC.DumNum = 0;
1302 AC.ncmod = AM.gncmod = 0;
1303 AC.modmode = AM.gmodmode = 0;
1304 AC.npowmod = AM.gnpowmod = 0;
1305 AC.halfmod = 0; AC.nhalfmod = 0;
1306 AC.modinverses = 0;
1307 AC.lPolyFun = AM.gPolyFun = 0;
1308 AC.lPolyFunInv = AM.gPolyFunInv = 0;
1309 AC.lPolyFunType = AM.gPolyFunType = 0;
1310 AC.lPolyFunExp = AM.gPolyFunExp = 0;
1311 AC.lPolyFunVar = AM.gPolyFunVar = 0;
1312 AC.lPolyFunPow = AM.gPolyFunPow = 0;
1313 AC.DirtPow = 0;
1314 AC.lDefDim = AM.gDefDim = 4;
1315 AC.lDefDim4 = AM.gDefDim4 = 0;
1316 AC.lUnitTrace = AM.gUnitTrace = 4;
1317 AC.NamesFlag = AM.gNamesFlag = 0;
1318 AC.CodesFlag = AM.gCodesFlag = 0;
1319 AC.extrasymbols = AM.gextrasymbols = AM.ggextrasymbols = 0;
1320 AC.extrasym = (UBYTE *)Malloc1(2*sizeof(UBYTE),"extrasym");
1321 AM.gextrasym = (UBYTE *)Malloc1(2*sizeof(UBYTE),"extrasym");
1322 AM.ggextrasym = (UBYTE *)Malloc1(2*sizeof(UBYTE),"extrasym");
1323 AC.extrasym[0] = AM.gextrasym[0] = AM.ggextrasym[0] = 'Z';
1324 AC.extrasym[1] = AM.gextrasym[1] = AM.ggextrasym[1] = 0;
1325 AC.TokensWriteFlag = AM.gTokensWriteFlag = 0;
1326 AC.SetupFlag = 0;
1327 AC.LineLength = AM.gLineLength = 79;
1328 AC.NwildC = 0;
1329 AC.OutputMode = 0;
1330 AM.gOutputMode = 0;
1331 AC.OutputSpaces = NORMALFORMAT;
1332 AM.gOutputSpaces = NORMALFORMAT;
1333 AC.OutNumberType = RATIONALMODE;
1334 AM.gOutNumberType = RATIONALMODE;
1335#ifdef WITHZLIB
1336 AR.gzipCompress = GZIPDEFAULT;
1337 AR.FoStage4[0].ziobuffer = 0;
1338 AR.FoStage4[1].ziobuffer = 0;
1339#endif
1340 AR.BracketOn = 0;
1341 AC.bracketindexflag = 0;
1342 AT.bracketindexflag = 0;
1343 AT.bracketinfo = 0;
1344 AO.IsBracket = 0;
1345 AM.gfunpowers = AC.funpowers = COMFUNPOWERS;
1346 AC.parallelflag = AM.gparallelflag;
1347 AC.properorderflag = AM.gproperorderflag = PROPERORDERFLAG;
1348 AC.ProcessBucketSize = AC.mProcessBucketSize = AM.gProcessBucketSize;
1349 AC.ThreadBucketSize = AM.gThreadBucketSize;
1350 AC.ShortStatsMax = 0;
1351 AM.gShortStatsMax = 0;
1352 AM.ggShortStatsMax = 0;
1353
1354 GlobalSymbols = NumSymbols;
1355 GlobalIndices = NumIndices;
1356 GlobalVectors = NumVectors;
1357 GlobalFunctions = NumFunctions;
1358 GlobalSets = NumSets;
1359 GlobalSetElements = NumSetElements;
1360 AC.modpowers = (UWORD *)0;
1361
1362 i = AM.OffsetIndex;
1363 fi = AC.FixIndices;
1364 if ( i > 0 ) do { *fi++ = one; } while ( --i >= 0 );
1365 AR.sLevel = -1;
1366 AM.Ordering[0] = 5;
1367 AM.Ordering[1] = 6;
1368 AM.Ordering[2] = 7;
1369 AM.Ordering[3] = 0;
1370 AM.Ordering[4] = 1;
1371 AM.Ordering[5] = 2;
1372 AM.Ordering[6] = 3;
1373 AM.Ordering[7] = 4;
1374 for ( i = 8; i < 15; i++ ) AM.Ordering[i] = i;
1375 AM.gUniTrace[0] =
1376 AC.lUniTrace[0] = SNUMBER;
1377 AM.gUniTrace[1] =
1378 AC.lUniTrace[1] =
1379 AM.gUniTrace[2] =
1380 AC.lUniTrace[2] = 4;
1381 AM.gUniTrace[3] =
1382 AC.lUniTrace[3] = 1;
1383#ifdef WITHPTHREADS
1384 AS.Balancing = 0;
1385#else
1386 AT.MinVecArg[0] = 7+ARGHEAD;
1387 AT.MinVecArg[ARGHEAD] = 7;
1388 AT.MinVecArg[1+ARGHEAD] = INDEX;
1389 AT.MinVecArg[2+ARGHEAD] = 3;
1390 AT.MinVecArg[3+ARGHEAD] = 0;
1391 AT.MinVecArg[4+ARGHEAD] = 1;
1392 AT.MinVecArg[5+ARGHEAD] = 1;
1393 AT.MinVecArg[6+ARGHEAD] = -3;
1394 t = AT.FunArg;
1395 *t++ = 4+ARGHEAD+FUNHEAD;
1396 for ( i = 1; i < ARGHEAD; i++ ) *t++ = 0;
1397 *t++ = 4+FUNHEAD;
1398 *t++ = 0;
1399 *t++ = FUNHEAD;
1400 for ( i = 2; i < FUNHEAD; i++ ) *t++ = 0;
1401 *t++ = 1; *t++ = 1; *t++ = 3;
1402
1403#ifdef WITHMPI
1404 AS.printflag = 0;
1405#endif
1406
1407 AT.comsym[0] = 8;
1408 AT.comsym[1] = SYMBOL;
1409 AT.comsym[2] = 4;
1410 AT.comsym[3] = 0;
1411 AT.comsym[4] = 1;
1412 AT.comsym[5] = 1;
1413 AT.comsym[6] = 1;
1414 AT.comsym[7] = 3;
1415 AT.comnum[0] = 4;
1416 AT.comnum[1] = 1;
1417 AT.comnum[2] = 1;
1418 AT.comnum[3] = 3;
1419 AT.comfun[0] = FUNHEAD+4;
1420 AT.comfun[1] = FUNCTION;
1421 AT.comfun[2] = FUNHEAD;
1422 AT.comfun[3] = 0;
1423#if FUNHEAD == 4
1424 AT.comfun[4] = 0;
1425#endif
1426 AT.comfun[FUNHEAD+1] = 1;
1427 AT.comfun[FUNHEAD+2] = 1;
1428 AT.comfun[FUNHEAD+3] = 3;
1429 AT.comind[0] = 7;
1430 AT.comind[1] = INDEX;
1431 AT.comind[2] = 3;
1432 AT.comind[3] = 0;
1433 AT.comind[4] = 1;
1434 AT.comind[5] = 1;
1435 AT.comind[6] = 3;
1436 AT.locwildvalue[0] = SUBEXPRESSION;
1437 AT.locwildvalue[1] = SUBEXPSIZE;
1438 for ( i = 2; i < SUBEXPSIZE; i++ ) AT.locwildvalue[i] = 0;
1439 AT.mulpat[0] = TYPEMULT;
1440 AT.mulpat[1] = SUBEXPSIZE+3;
1441 AT.mulpat[2] = 0;
1442 AT.mulpat[3] = SUBEXPRESSION;
1443 AT.mulpat[4] = SUBEXPSIZE;
1444 AT.mulpat[5] = 0;
1445 AT.mulpat[6] = 1;
1446 for ( i = 7; i < SUBEXPSIZE+5; i++ ) AT.mulpat[i] = 0;
1447 AT.proexp[0] = SUBEXPSIZE+4;
1448 AT.proexp[1] = EXPRESSION;
1449 AT.proexp[2] = SUBEXPSIZE;
1450 AT.proexp[3] = -1;
1451 AT.proexp[4] = 1;
1452 for ( i = 5; i < SUBEXPSIZE+1; i++ ) AT.proexp[i] = 0;
1453 AT.proexp[SUBEXPSIZE+1] = 1;
1454 AT.proexp[SUBEXPSIZE+2] = 1;
1455 AT.proexp[SUBEXPSIZE+3] = 3;
1456 AT.proexp[SUBEXPSIZE+4] = 0;
1457 AT.dummysubexp[0] = SUBEXPRESSION;
1458 AT.dummysubexp[1] = SUBEXPSIZE+4;
1459 for ( i = 2; i < SUBEXPSIZE; i++ ) AT.dummysubexp[i] = 0;
1460 AT.dummysubexp[SUBEXPSIZE] = WILDDUMMY;
1461 AT.dummysubexp[SUBEXPSIZE+1] = 4;
1462 AT.dummysubexp[SUBEXPSIZE+2] = 0;
1463 AT.dummysubexp[SUBEXPSIZE+3] = 0;
1464
1465 AT.inprimelist = -1;
1466 AT.sizeprimelist = 0;
1467 AT.primelist = 0;
1468 AT.LeaveNegative = 0;
1469 AT.TrimPower = 0;
1470 AN.SplitScratch = 0;
1471 AN.SplitScratchSize = AN.InScratch = 0;
1472 AN.SplitScratch1 = 0;
1473 AN.SplitScratchSize1 = AN.InScratch1 = 0;
1474 AN.idfunctionflag = 0;
1475#endif
1476 AO.OutputLine = AO.OutFill = BufferForOutput;
1477 AO.FactorMode = 0;
1478 C->Pointer = C->Buffer;
1479
1480 AP.PreOut = 0;
1481 AP.ComChar = AP.cComChar;
1482 AC.cbufnum = AM.rbufnum; /* Select the default compiler buffer */
1483 AC.HideLevel = 0;
1484 AP.PreAssignFlag = 0;
1485 return(0);
1486}
1487
1488/*
1489 #] IniVars :
1490 #[ Signal handlers :
1491*/
1492/*[28apr2004 mt]:*/
1493#ifdef TRAPSIGNALS
1494
1495static int exitInProgress = 0;
1496static int trappedTerminate = 0;
1497
1498/*INTSIGHANDLER : some systems require a signal handler to return an integer,
1499 so define the macro INTSIGHANDLER if compiler fails:*/
1500#ifdef INTSIGHANDLER
1501static int onErrSig(int i)
1502#else
1503static VOID onErrSig(int i)
1504#endif
1505{
1506 if (exitInProgress){
1507 signal(i,SIG_DFL);/* Use default behaviour*/
1508 raise (i);/*reproduce trapped signal*/
1509#ifdef INTSIGHANDLER
1510 return(i);
1511#else
1512 return;
1513#endif
1514 }
1515 trappedTerminate = 1;
1516 /*[13jul2005 mt]*//*Terminate(-1) on signal is here:*/
1517 Terminate(-1);
1518}
1519
1520#ifdef INTSIGHANDLER
1521static VOID setNewSig(int i, int (*handler)(int))
1522#else
1523static VOID setNewSig(int i, void (*handler)(int))
1524#endif
1525{
1526 if(! (i<NSIG) )/* Invalid signal -- see comments in the file */
1527 return;
1528 if ( signal(i,SIG_IGN) !=SIG_IGN)
1529 /* if compiler fails here, try to define INTSIGHANDLER):*/
1530 signal(i,handler);
1531}
1532
1533VOID setSignalHandlers()
1534{
1535 /* Reset various unrecoverable error signals:*/
1536 setNewSig(SIGSEGV,onErrSig);
1537 setNewSig(SIGFPE,onErrSig);
1538 setNewSig(SIGILL,onErrSig);
1539 setNewSig(SIGEMT,onErrSig);
1540 setNewSig(SIGSYS,onErrSig);
1541 setNewSig(SIGPIPE,onErrSig);
1542 setNewSig(SIGLOST,onErrSig);
1543 setNewSig(SIGXCPU,onErrSig);
1544 setNewSig(SIGXFSZ,onErrSig);
1545
1546 /* Reset interrupt signals:*/
1547 setNewSig(SIGTERM,onErrSig);
1548 setNewSig(SIGINT,onErrSig);
1549 setNewSig(SIGQUIT,onErrSig);
1550 setNewSig(SIGHUP,onErrSig);
1551 setNewSig(SIGALRM,onErrSig);
1552 setNewSig(SIGVTALRM,onErrSig);
1553/* setNewSig(SIGPROF,onErrSig); */ /* Why did Tentukov forbid profilers?? */
1554}
1555
1556#endif
1557/*:[28apr2004 mt]*/
1558/*
1559 #] Signal handlers :
1560 #[ main :
1561*/
1562
1563#ifdef WITHPTHREADS
1564ALLPRIVATES *ABdummy[10];
1565#endif
1566
1567int main(int argc, char **argv)
1568{
1569 int retval;
1570 bzero((VOID *)(&A),sizeof(A)); /* make sure A is initialized at zero */
1571 iniTools();
1572#ifdef TRAPSIGNALS
1573 setSignalHandlers();
1574#endif
1575
1576#ifdef WITHPTHREADS
1577 AB = ABdummy;
1578 StartHandleLock();
1579 BeginIdentities();
1580#else
1581 AM.SumTime = TimeCPU(0);
1582 TimeWallClock(0);
1583#endif
1584
1585#ifdef WITHMPI
1586 if ( PF_Init(&argc,&argv) ) exit(-1);
1587#endif
1588
1589 StartFiles();
1591#ifdef WITHMPI
1592 /*
1593 * Here MesPrint() is ready. We turn on AS.printflag to print possible
1594 * errors occurring on slaves in the initialization. With AS.printflag = -1
1595 * MesPrint() does not use the synchronized output. This may lead broken
1596 * texts in the output somewhat, but it is safer to implement in this way
1597 * for the situation in which some of MesPrint() calls use MLOCK()-MUNLOCK()
1598 * and some do not. In future if we set AS.printflag = 1 and modify the
1599 * source code such that all MesPrint() calls are sandwiched by MLOCK()-
1600 * MUNLOCK(), we need also to modify the code for the master to catch
1601 * messages corresponding to MUNLOCK() calls at some point.
1602 *
1603 * AS.printflag will be set to 0 in IniVars() to prevent slaves from
1604 * printing redundant errors in the preprocessor and compiler (e.g., syntax
1605 * errors).
1606 */
1607 AS.printflag = -1;
1608#endif
1609
1610 if ( ( retval = DoTail(argc,(UBYTE **)argv) ) != 0 ) {
1611 if ( retval > 0 ) Terminate(0);
1612 else Terminate(-1);
1613 }
1614 if ( DoSetups() ) Terminate(-2);
1615#ifdef WITHMPI
1616 /* It is messy if all errors in OpenInput() on slaves are printed. */
1617 AS.printflag = 0;
1618#endif
1619 if ( OpenInput() ) Terminate(-3);
1620#ifdef WITHMPI
1621 AS.printflag = -1;
1622#endif
1623 if ( TryEnvironment() ) Terminate(-2);
1624 if ( TryFileSetups() ) Terminate(-2);
1625 if ( MakeSetupAllocs() ) Terminate(-2);
1626 StartMore();
1627 InitRecovery();
1629 if ( AM.totalnumberofthreads == 0 ) AM.totalnumberofthreads = 1;
1630 AS.MultiThreaded = 0;
1631#ifdef WITHPTHREADS
1632 if ( AM.totalnumberofthreads > 1 ) AS.MultiThreaded = 1;
1633 ReserveTempFiles(1);
1634 StartAllThreads(AM.totalnumberofthreads);
1635 IniFbufs();
1636#else
1637 ReserveTempFiles(0);
1638 IniFbuffer(AT.fbufnum);
1639#endif
1640 if ( !AM.FromStdin ) PrintHeader(1);
1641 IniVars();
1642 Globalize(1);
1643 if ( AM.TimeLimit > 0 ) alarm(AM.TimeLimit);
1644 TimeCPU(0);
1645 TimeChildren(0);
1646 TimeWallClock(0);
1647 PreProcessor();
1648 Terminate(0);
1649 return(0);
1650}
1651/*
1652 #] main :
1653 #[ CleanUp :
1654
1655 if par < 0 we have to keep the storage file.
1656 when par > 0 we ran into a .clear statement.
1657 In that case we keep the zero level input and the log file.
1658
1659*/
1660
1661VOID CleanUp(WORD par)
1662{
1663 GETIDENTITY
1664 int i;
1665
1666 if ( FG.fname ) {
1667 CleanUpSort(0);
1668 for ( i = 0; i < 3; i++ ) {
1669 if ( AR.Fscr[i].handle >= 0 ) {
1670 if ( AR.Fscr[i].name ) {
1671/*
1672 If there are more threads referring to the same file
1673 only the one with the name is the owner of the file.
1674*/
1675 CloseFile(AR.Fscr[i].handle);
1676 remove(AR.Fscr[i].name);
1677 }
1678 AR.Fscr[i].handle = - 1;
1679 AR.Fscr[i].POfill = 0;
1680 }
1681 }
1682 if ( par > 0 ) {
1683/*
1684 Close all input levels above the lowest?
1685*/
1686 }
1687 if ( AC.StoreHandle >= 0 && par <= 0 ) {
1688#ifdef TRAPSIGNALS
1689 if ( trappedTerminate ) { /* We don't throw .str if it has contents */
1690 POSITION pos;
1691 PUTZERO(pos);
1692 SeekFile(AC.StoreHandle,&pos,SEEK_END);
1693 if ( ISNOTZEROPOS(pos) ) {
1694 CloseFile(AC.StoreHandle);
1695 goto dontremove;
1696 }
1697 }
1698 CloseFile(AC.StoreHandle);
1699 if ( par >= 0 || AR.StoreData.Handle < 0 || AM.ClearStore ) {
1700 remove(FG.fname);
1701 }
1702dontremove:;
1703#else
1704 CloseFile(AC.StoreHandle);
1705 if ( par >= 0 || AR.StoreData.Handle < 0 || AM.ClearStore > 0 ) {
1706 remove(FG.fname);
1707 }
1708#endif
1709 }
1710 }
1711 ClearSpectators(CLEARMODULE);
1712/*
1713 Remove recovery file on exit if everything went well
1714*/
1715 if ( par == 0 ) {
1717 }
1718/*
1719 Now the final message concerning the total time
1720*/
1721 if ( AC.LogHandle >= 0 && par <= 0 ) {
1722 WORD lh = AC.LogHandle;
1723 AC.LogHandle = -1;
1724#ifdef WITHMPI
1725 if ( PF.me == MASTER ) /* Only the master opened the real file. */
1726#endif
1727 CloseFile(lh);
1728 }
1729}
1730
1731/*
1732 #] CleanUp :
1733 #[ Terminate :
1734*/
1735
1736static int firstterminate = 1;
1737
1738VOID Terminate(int errorcode)
1739{
1740 if ( errorcode && firstterminate ) {
1741 firstterminate = 0;
1742#ifdef WITHPTHREADS
1743 MesPrint("Program terminating in thread %w at &");
1744#elif defined(WITHMPI)
1745 MesPrint("Program terminating in process %w at &");
1746#else
1747 MesPrint("Program terminating at &");
1748#endif
1749 Crash();
1750 }
1751#ifdef TRAPSIGNALS
1752 exitInProgress=1;
1753#endif
1754#ifdef WITHEXTERNALCHANNEL
1755/*
1756 This function can be called from the error handler, so it is better to
1757 clean up all started processes before any activity:
1758*/
1759 closeAllExternalChannels();
1760 AX.currentExternalChannel=0;
1761 /*[08may2006 mt]:*/
1762 AX.killSignal=SIGKILL;
1763 AX.killWholeGroup=1;
1764 AX.daemonize=1;
1765 /*:[08may2006 mt]*/
1766 if(AX.currentPrompt){
1767 M_free(AX.currentPrompt,"external channel prompt");
1768 AX.currentPrompt=0;
1769 }
1770 /*[08may2006 mt]:*/
1771 if(AX.shellname){
1772 M_free(AX.shellname,"external channel shellname");
1773 AX.shellname=0;
1774 }
1775 if(AX.stderrname){
1776 M_free(AX.stderrname,"external channel stderrname");
1777 AX.stderrname=0;
1778 }
1779 /*:[08may2006 mt]*/
1780#endif
1781#ifdef WITHPTHREADS
1782 if ( !WhoAmI() && !errorcode ) {
1783 TerminateAllThreads();
1784 }
1785#endif
1786 if ( AC.FinalStats ) {
1787 if ( AM.PrintTotalSize ) {
1788 MesPrint("Max. space for expressions: %19p bytes",&(AS.MaxExprSize));
1789 }
1790 PrintRunningTime();
1791 }
1792#ifdef WITHMPI
1793 if ( AM.HoldFlag && PF.me == MASTER ) {
1794 WriteFile(AM.StdOut,(UBYTE *)("Hit any key "),12);
1796 getchar();
1797 }
1798#else
1799 if ( AM.HoldFlag ) {
1800 WriteFile(AM.StdOut,(UBYTE *)("Hit any key "),12);
1801 getchar();
1802 }
1803#endif
1804#ifdef WITHMPI
1805 PF_Terminate(errorcode);
1806#endif
1807 CleanUp(errorcode);
1808 M_print();
1809#ifdef VMS
1810 P_term(errorcode? 0: 1);
1811#else
1812 P_term(errorcode);
1813#endif
1814}
1815
1816/*
1817 #] Terminate :
1818 #[ PrintRunningTime :
1819*/
1820
1821VOID PrintRunningTime()
1822{
1823#if (defined(WITHPTHREADS) && (defined(WITHPOSIXCLOCK) || defined(WINDOWS))) || defined(WITHMPI)
1824 LONG mastertime;
1825 LONG workertime;
1826 LONG wallclocktime;
1827 LONG totaltime;
1828#if defined(WITHPTHREADS)
1829 if ( AB[0] != 0 ) {
1830 workertime = GetWorkerTimes();
1831#else
1832 workertime = PF_GetSlaveTimes(); /* must be called on all processors */
1833 if ( PF.me == MASTER ) {
1834#endif
1835 mastertime = AM.SumTime + TimeCPU(1);
1836 wallclocktime = TimeWallClock(1);
1837 totaltime = mastertime+workertime;
1838 if ( !AM.silent ) {
1839 MesPrint(" %l.%2i sec + %l.%2i sec: %l.%2i sec out of %l.%2i sec",
1840 mastertime/1000,(WORD)((mastertime%1000)/10),
1841 workertime/1000,(WORD)((workertime%1000)/10),
1842 totaltime/1000,(WORD)((totaltime%1000)/10),
1843 wallclocktime/100,(WORD)(wallclocktime%100));
1844 }
1845 }
1846#else
1847 LONG mastertime = AM.SumTime + TimeCPU(1);
1848 LONG wallclocktime = TimeWallClock(1);
1849 if ( !AM.silent ) {
1850 MesPrint(" %l.%2i sec out of %l.%2i sec",
1851 mastertime/1000,(WORD)((mastertime%1000)/10),
1852 wallclocktime/100,(WORD)(wallclocktime%100));
1853 }
1854#endif
1855}
1856
1857/*
1858 #] PrintRunningTime :
1859 #[ GetRunningTime :
1860*/
1861
1862LONG GetRunningTime()
1863{
1864#if defined(WITHPTHREADS) && (defined(WITHPOSIXCLOCK) || defined(WINDOWS))
1865 LONG mastertime;
1866 if ( AB[0] != 0 ) {
1867/*
1868#if ( defined(APPLE64) || defined(APPLE32) )
1869 mastertime = AM.SumTime + TimeCPU(1);
1870 return(mastertime);
1871#else
1872*/
1873 LONG workertime = GetWorkerTimes();
1874 mastertime = AM.SumTime + TimeCPU(1);
1875 return(mastertime+workertime);
1876/*
1877#endif
1878*/
1879 }
1880 else {
1881 return(AM.SumTime + TimeCPU(1));
1882 }
1883#elif defined(WITHMPI)
1884 LONG mastertime, t = 0;
1885 LONG workertime = PF_GetSlaveTimes(); /* must be called on all processors */
1886 if ( PF.me == MASTER ) {
1887 mastertime = AM.SumTime + TimeCPU(1);
1888 t = mastertime + workertime;
1889 }
1890 return PF_BroadcastNumber(t); /* must be called on all processors */
1891#else
1892 return(AM.SumTime + TimeCPU(1));
1893#endif
1894}
1895
1896/*
1897 #] GetRunningTime :
1898*/
void InitRecovery()
Definition checkpoint.c:399
int CheckRecoveryFile()
Definition checkpoint.c:278
void DeleteRecoveryFile()
Definition checkpoint.c:333
WORD * AddRHS(int num, int type)
Definition comtool.c:214
int IniFbuffer(WORD bufnum)
Definition comtool.c:614
int AddNtoC(int bufnum, int n, WORD *array, int par)
Definition comtool.c:317
int inicbufs(VOID)
Definition comtool.c:47
void CleanUpSort(int)
Definition sort.c:4644
LONG TimeWallClock(WORD)
Definition tools.c:3476
LONG TimeCPU(WORD)
Definition tools.c:3550
WORD Compare1(WORD *, WORD *, WORD)
Definition sort.c:2536
int PutPreVar(UBYTE *, UBYTE *, UBYTE *, int)
Definition pre.c:642
int PF_Init(int *argc, char ***argv)
Definition parallel.c:1953
LONG PF_GetSlaveTimes(void)
Definition parallel.c:2063
int PF_Terminate(int errorcode)
Definition parallel.c:2047
void PF_FlushStdOutBuffer(void)
Definition parallel.c:4465
LONG PF_BroadcastNumber(LONG x)
Definition parallel.c:2083
VOID StartVariables()
Definition startup.c:866
WORD * Buffer
Definition structs.h:939
WORD * Pointer
Definition structs.h:941
WORD symmetric
Definition structs.h:484
LONG name
Definition structs.h:478
struct CbUf CBUF
struct DoLoOp DOLOOP
struct ChAnNeL CHANNEL
struct pReVaR PREVAR