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