• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vermaseren / form / 11293612887

11 Oct 2024 01:52PM UTC coverage: 49.986% (+0.02%) from 49.968%
11293612887

Pull #526

github

web-flow
Merge 8495db7be into 4fc8e4047
Pull Request #526: RFC: better debugging

39 of 68 new or added lines in 2 files covered. (57.35%)

3 existing lines in 2 files now uncovered.

41423 of 82869 relevant lines covered (49.99%)

874620.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.07
/sources/startup.c
1
/** @file startup.c
2
 * 
3
 *  This file contains the main program.
4
 *  It also deals with the very early stages of the startup of FORM
5
 *        and the final stages when the program attempts some cleanup.
6
 *        Here is the routine that analyses the command tail.
7
 */
8
/* #[ License : */
9
/*
10
 *   Copyright (C) 1984-2023 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
#ifdef ENABLE_BACKTRACE
47
        #include <execinfo.h>
48
#ifdef LINUX
49
        #include <stdint.h>
50
        #include <inttypes.h>
51
#endif
52
#endif
53

54
/*
55
 * A macro for translating the contents of `x' into a string after expanding.
56
 */
57
#define STRINGIFY(x)  STRINGIFY__(x)
58
#define STRINGIFY__(x) #x
59

60
/*
61
 * FORMNAME = "FORM" or "TFORM" or "ParFORM".
62
 */
63
#if defined(WITHPTHREADS)
64
        #define FORMNAME "TFORM"
65
#elif defined(WITHMPI)
66
        #define FORMNAME "ParFORM"
67
#else
68
        #define FORMNAME "FORM"
69
#endif
70

71
/*
72
 * VERSIONSTR is the version information printed in the header line.
73
 */
74
#ifdef HAVE_CONFIG_H
75
        /* We have also version.h. */
76
        #include "version.h"
77
        #ifndef REPO_VERSION
78
                #define REPO_VERSION STRINGIFY(REPO_MAJOR_VERSION) "." STRINGIFY(REPO_MINOR_VERSION)
79
        #endif
80
        #ifndef REPO_DATE
81
                /* The build date, instead of the repo date. */
82
                #define REPO_DATE __DATE__
83
        #endif
84
        #ifdef REPO_REVISION
85
                #define VERSIONSTR FORMNAME " " REPO_VERSION " (" REPO_DATE ", " REPO_REVISION ")"
86
        #else
87
                #define VERSIONSTR FORMNAME " " REPO_VERSION " (" REPO_DATE ")"
88
        #endif
89
        #define MAJORVERSION REPO_MAJOR_VERSION
90
        #define MINORVERSION REPO_MINOR_VERSION
91
#else
92
        /*
93
         * Otherwise, form3.h defines MAJORVERSION, MINORVERSION and PRODUCTIONDATE,
94
         * possibly BETAVERSION.
95
         */
96
        #ifdef BETAVERSION
97
                #define VERSIONSTR__ STRINGIFY(MAJORVERSION) "." STRINGIFY(MINORVERSION) "Beta"
98
        #else
99
                #define VERSIONSTR__ STRINGIFY(MAJORVERSION) "." STRINGIFY(MINORVERSION)
100
        #endif
101
        #define VERSIONSTR FORMNAME " " VERSIONSTR__ " (" PRODUCTIONDATE ")"
102
#endif
103

104
/*
105
                 #] includes : 
106
                 #[ PrintHeader :
107
*/
108

109
/**
110
 * Prints the header line of the output.
111
 *
112
 * @param  with_full_info  True for printing also runtime information.
113
 */
114
static void PrintHeader(int with_full_info)
1,776✔
115
{
116
#ifdef WITHMPI
117
        if ( PF.me == MASTER && !AM.silent ) {
989✔
118
#else
119
        if ( !AM.silent ) {
787✔
120
#endif
121
                char buffer1[250], buffer2[80], *s = buffer1, *t = buffer2;
259,785✔
122
                WORD length, n;
123
                for ( n = 0; n < 250; n++ ) buffer1[n] = ' ';
259,785✔
124
                /*
125
                 * NOTE: we expect that the compiler optimizes strlen("string literal")
126
                 * to just a number.
127
                 */
128
                if ( strlen(VERSIONSTR) <= 100 ) {
1,035✔
129
                        strcpy(s,VERSIONSTR);
1,035✔
130
                        s += strlen(VERSIONSTR);
1,035✔
131
                        *s = 0;
1,035✔
132
                }
133
                else {
134
                        /*
135
                         * Truncate when it is too long.
136
                         */
137
                        strncpy(s,VERSIONSTR,97);
138
                        s[97] = '.';
139
                        s[98] = '.';
140
                        s[99] = ')';
141
                        s[100] = '\0';
142
                        s += 100;
143
                }
144
/*
145
                By now we omit the message about 32/64 bits. It should all be 64.
146

147
                s += snprintf(s,250-(s-buffer1)," %d-bits",(WORD)(sizeof(WORD)*16));
148
                *s = 0;
149
*/
150
                if ( with_full_info ) {
1,035✔
151
#if defined(WITHPTHREADS) || defined(WITHMPI)
152
#if defined(WITHPTHREADS)
153
                        int nworkers = AM.totalnumberofthreads-1;
524✔
154
#elif defined(WITHMPI)
155
                        int nworkers = PF.numtasks-1;
248✔
156
#endif
157
                        s += snprintf(s,250-(s-buffer1)," %d worker",nworkers);
772✔
158
                        *s = 0;
772✔
159
/*                        while ( *s ) s++; */
160
                        if ( nworkers != 1 ) {
772✔
161
                                *s++ = 's';
772✔
162
                                *s = '\0';
772✔
163
                        }
164
#endif
165

166
                        snprintf(t,80-(t-buffer2),"Run: %s",MakeDate());
1,035✔
167
                        while ( *t ) t++;
32,085✔
168

169
                        /*
170
                         * Align the date to the right, if it fits in a line.
171
                         */
172
                        length = (s-buffer1) + (t-buffer2);
1,035✔
173
                        if ( length+2 <= AC.LineLength ) {
1,035✔
174
                                for ( n = AC.LineLength-length; n > 0; n-- ) *s++ = ' ';
×
175
                                *s = 0;
×
176
                                strcat(s,buffer2);
×
177
                                while ( *s ) s++;
×
178
                        }
179
                        else {
180
                                *s = 0;
1,035✔
181
                                strcat(s,"  ");
1,035✔
182
                                while ( *s ) s++;
3,105✔
183
                                *s = 0;
1,035✔
184
                                strcat(s,buffer2);
1,035✔
185
                                while ( *s ) s++;
32,085✔
186
                        }
187
                }
188

189
                /*
190
                 * If the header information doesn't fit in a line, we need to extend
191
                 * the line length temporarily.
192
                 */
193
                length = s-buffer1;
1,035✔
194
                if ( length <= AC.LineLength ) {
1,035✔
195
                        MesPrint("%s",buffer1);
×
196
                }
197
                else {
198
                        WORD oldLineLength = AC.LineLength;
1,035✔
199
                        AC.LineLength = length;
1,035✔
200
                        MesPrint("%s",buffer1);
1,035✔
201
                        AC.LineLength = oldLineLength;
1,035✔
202
                }
203
        }
204
}
1,776✔
205

206
/*
207
                 #] PrintHeader : 
208
                 #[ DoTail :
209

210
                Routine reads the command tail and handles the commandline options.
211
                It sets the flags for later actions and stored pathnames for
212
                the setup file, include/prc/sub directories etc.
213
                Finally the name of the program is passed on.
214
                Note that we do not support interactive use yet. This will come
215
                to pass in the distant future when we can couple STedi to FORM.
216
                Routine made 23-feb-1993 by J.Vermaseren
217
*/
218

219
#ifdef WITHINTERACTION
220
static UBYTE deflogname[] = "formsession.log";
221
#endif
222

223
#define TAKEPATH(x) if(s[1]== '=' ){x=s+2;} else{x=*argv++;argc--;}
224

225
int DoTail(int argc, UBYTE **argv)
1,776✔
226
{
227
        int errorflag = 0, onlyversion = 1;
1,776✔
228
        UBYTE *s, *t, *copy;
1,776✔
229
        int threadnum = 0;
1,776✔
230
        argc--; argv++;
1,776✔
231
        AM.ClearStore = 0;
1,776✔
232
        AM.TimeLimit = 0;
1,776✔
233
        AM.LogType = -1;
1,776✔
234
        AM.HoldFlag = AM.qError = AM.Interact = AM.FileOnlyFlag = 0;
1,776✔
235
        AM.InputFileName = AM.LogFileName = AM.IncDir = AM.TempDir = AM.TempSortDir =
1,776✔
236
        AM.SetupDir = AM.SetupFile = AM.Path = 0;
1,776✔
237
        AM.FromStdin = 0;
1,776✔
238
        if ( argc < 1 ) {
1,776✔
239
                onlyversion = 0;
×
240
                goto printversion;
×
241
        }
242
        while ( argc >= 1 ) {
4,074✔
243
                s = *argv++; argc--;
2,298✔
244
                if ( *s == '-' || ( *s == '/' && ( argc > 0 || AM.Interact ) ) ) {
2,298✔
245
                        s++;
522✔
246
                        switch (*s) {
522✔
247
                                case 'c': /* Error checking only */
×
248
                                                        AM.qError = 1;   break;
×
249
                                case 'C': /* Next arg is filename of log file */
×
250
                                                        TAKEPATH(AM.LogFileName)  break;
×
251
                                case 'D':
×
252
                                case 'd': /* Next arg is define preprocessor var. */
253
                                                        t = copy = strDup1(*argv,"Dotail");
×
254
                                                        while ( *t && *t != '=' ) t++;
×
255
                                                        if ( *t == 0 ) {
×
256
                                                                if ( PutPreVar(copy,(UBYTE *)"1",0,0) < 0 ) return(-1);
×
257
                                                        }
258
                                                        else {
259
                                                                *t++ = 0;
×
260
                                                                if ( PutPreVar(copy,t,0,0) < 0 ) return(-1);
×
261
                                                                t[-1] = '=';
×
262
                                                        }
263
                                                        M_free(copy,"-d prevar");
×
264
                                                        argv++; argc--; break;
×
265
                                case 'f': /* Output only to regular log file */
×
266
                                                        AM.FileOnlyFlag = 1; AM.LogType = 0; break;
×
267
                                case 'F': /* Output only to log file. Further like L. */
×
268
                                                        AM.FileOnlyFlag = 1; AM.LogType = 1; break;
×
269
                                case 'h': /* For old systems: wait for key before exit */
×
270
                                                        AM.HoldFlag = 1; break;
×
271
#ifdef WITHINTERACTION
272
                                case 'i': /* Interactive session (not used yet) */
273
                                                        AM.Interact = 1; break;
274
#endif
275
                                case 'I': /* Next arg is dir for inc/prc/sub files */
×
276
                                                        TAKEPATH(AM.IncDir)  break;
×
277
                                case 'l': /* Make regular log file */
×
278
                                                        if ( s[1] == 'l' ) AM.LogType = 1; /*compatibility! */
×
279
                                                        else               AM.LogType = 0;
×
280
                                                        break;
281
                                case 'L': /* Make log file with only final statistics */
×
282
                                                        AM.LogType = 1;  break;
×
283
                                case 'M': /* Multirun. Name of tempfiles will contain PID */
×
284
                                                        AM.MultiRun = 1;
×
285
                                                        break;
×
286
                                case 'm': /* Read number of threads */
522✔
287
                                case 'w': /* Read number of workers */
288
                                                        t = s++;
522✔
289
                                                        threadnum = 0;
522✔
290
                                                        while ( *s >= '0' && *s <= '9' )
1,044✔
291
                                                                threadnum = 10*threadnum + *s++ - '0';
522✔
292
                                                        if ( *s ) {
522✔
293
#ifdef WITHMPI
294
                                                                if ( PF.me == MASTER )
295
#endif
296
                                                                printf("Illegal value for option m or w: %s\n",t);
×
297
                                                                errorflag++;
×
298
                                                        }
299
/*                                                        if ( threadnum == 1 ) threadnum = 0; */
300
                                                        threadnum++;
522✔
301
                                                        break;
522✔
302
                                case 'W': /* Print the wall-clock time on the master. */
×
303
                                                        AM.ggWTimeStatsFlag = 1;
×
304
                                                        break;
×
305
/*
306
                                case 'n':
307
                                                        Reserved for number of slaves without MPI
308
*/
309
                                case 'p':
×
310
#ifdef WITHEXTERNALCHANNEL
311
                                        /*There are two possibilities: -p|-pipe*/                
312
                                        if(s[1]=='i'){
×
313
                                                if( (s[2]=='p')&&(s[3]=='e')&&(s[4]=='\0') ){
×
314
                                                        argc--;
×
315
                                                        /*Initialize pre-set external channels, see 
316
                                                                the file extcmd.c:*/
317
                                                        if(initPresetExternalChannels(*argv++,AX.timeout)<1){
×
318
#ifdef WITHMPI
319
                                                                if ( PF.me == MASTER )
320
#endif
321
                                                                printf("Error initializing preset external channels\n");
×
322
                                                                errorflag++;
×
323
                                                        }
324
                                                        AX.timeout=-1;/*This indicates that preset channels 
×
325
                                                                                                        are initialized from cmdline*/
326
                                                }else{
327
#ifdef WITHMPI
328
                                                        if ( PF.me == MASTER )
329
#endif
330
                                                        printf("Illegal option in call of FORM: %s\n",s);
×
331
                                                        errorflag++;
×
332
                                                }
333
                                        }else
334
#else
335
                                        if ( s[1] ) {
336
                                                if ( ( s[1]=='i' ) && ( s[2] == 'p' ) && (s[3] == 'e' )
337
                                                && ( s[4] == '\0' ) ){
338
#ifdef WITHMPI
339
                                                        if ( PF.me == MASTER )
340
#endif
341
                                                        printf("Illegal option: Pipes not supported on this system.\n");
342
                                                }
343
                                                else {
344
#ifdef WITHMPI
345
                                                        if ( PF.me == MASTER )
346
#endif
347
                                                        printf("Illegal option: %s\n",s);
348
                                                }
349
                                                errorflag++;
350
                                        }
351
                                        else
352
#endif
353
                                        {
354
                                                         /* Next arg is a path variable like in environment */
355
                                                TAKEPATH(AM.Path)
×
356
                                        }
357
                                        break;
358
                                case 'q': /* Quiet option. Only output. Same as -si */
×
359
                                                        AM.silent = 1; break;
×
360
                                case 'R': /* recover from saved snapshot */
×
361
                                                        AC.CheckpointFlag = -1;
×
362
                                                        break;
×
363
                                case 's': /* Next arg is dir with form.set to be used */
×
364
                                                        if ( ( s[1] == 'o' ) && ( s[2] == 'r' ) && ( s[3] == 't' ) ) {
×
365
                                                                if(s[4]== '=' ) {
×
366
                                                                        AM.TempSortDir = s+5;
×
367
                                                                }
368
                                                                else {
369
                                                                        AM.TempSortDir = *argv++;
×
370
                                                                        argc--;
×
371
                                                                }
372
                                                        }
373
                                                        else if ( s[1] == 'i' ) { /* compatibility: silent/quiet */
×
374
                                                                AM.silent = 1;
×
375
                                                        }
376
                                                        else {
377
                                                                TAKEPATH(AM.SetupDir)
×
378
                                                        }
379
                                                        break;
380
                                case 'S': /* Next arg is setup file */
×
381
                                                        TAKEPATH(AM.SetupFile) break;
×
382
                                case 't': /* Next arg is directory for temp files */
×
383
                                                        if ( s[1] == 's' ) {
×
384
                                                                s++;
×
385
                                                                AM.havesortdir = 1;
×
386
                                                                TAKEPATH(AM.TempSortDir)
×
387
                                                        }
388
                                                        else {
389
                                                                TAKEPATH(AM.TempDir)
×
390
                                                        }
391
                                                        break;
392
                                case 'T': /* Print the total size used at end of job */
×
393
                                                        AM.PrintTotalSize = 1; break;
×
394
                                case 'v':
395
printversion:;
×
396
#ifdef WITHMPI
397
                                                        if ( PF.me == MASTER )
398
#endif
399
                                                                PrintHeader(0);
×
400
                                                        if ( onlyversion ) return(1);
×
401
                                                        goto NoFile;
×
402
                                case 'y': /* Preprocessor dumps output. No compilation. */
×
403
                                                        AP.PreDebug = PREPROONLY;   break;
×
404
                                case 'z': /* The number following is a time limit in sec. */
×
405
                                                        t = s++;
×
406
                                                        AM.TimeLimit = 0;
×
407
                                                        while ( *s >= '0' && *s <= '9' )
×
408
                                                                AM.TimeLimit = 10*AM.TimeLimit + *s++ - '0';
×
409
                                                        break;
410
                                case 'Z': /* Removes the .str file on crash, no matter its contents */
×
411
                                                        AM.ClearStore = 1;   break;
×
412
                                case '\0': /* "-" to use STDIN for the input. */
×
413
#ifdef WITHMPI
414
                                                        /* At the moment, ParFORM doesn't implement STDIN broadcasts. */
415
                                                        if ( PF.me == MASTER )
416
                                                                printf("Sorry, reading STDIN as input is currently not supported by ParFORM\n");
417
                                                        errorflag++;
418
#endif
419
                                                        AM.FromStdin = 1;
×
420
                                                        AC.NoShowInput = 1; // disable input echoing by default
×
421
                                                        break;
×
422
                                default:
×
423
                                                if ( FG.cTable[*s] == 1 ) {
×
424
                                                        AM.SkipClears = 0; t = s;
×
425
                                                        while ( FG.cTable[*t] == 1 )
×
426
                                                                AM.SkipClears = 10*AM.SkipClears + *t++ - '0';
×
427
                                                        if ( *t != 0 ) {
×
428
#ifdef WITHMPI
429
                                                                if ( PF.me == MASTER )
430
#endif
431
                                                                printf("Illegal numerical option in call of FORM: %s\n",s);
×
432
                                                                errorflag++;
×
433
                                                        }
434
                                                }
435
                                                else {
436
#ifdef WITHMPI
437
                                                        if ( PF.me == MASTER )
438
#endif
439
                                                        printf("Illegal option in call of FORM: %s\n",s);
×
440
                                                        errorflag++;
×
441
                                                }
442
                                                break;
443
                        }
444
                }
445
                else if ( argc == 0 && !AM.Interact ) AM.InputFileName = argv[-1];
1,776✔
446
                else {
447
#ifdef WITHMPI
448
                        if ( PF.me == MASTER )
449
#endif
450
                        printf("Illegal option in call of FORM: %s\n",s);
×
451
                        errorflag++;
×
452
                }
453
        }
454
        AM.totalnumberofthreads = threadnum;
1,776✔
455
        if ( AM.InputFileName ) {
1,776✔
456
                if ( AM.FromStdin ) {
1,776✔
457
                        printf("STDIN and the input filename cannot be specified simultaneously\n");
×
458
                        errorflag++;
×
459
                }
460
                s = AM.InputFileName;
1,776✔
461
                while ( *s ) s++;
11,367✔
462
                if ( s < AM.InputFileName+4 ||
1,776✔
463
                s[-4] != '.' || s[-3] != 'f' || s[-2] != 'r' || s[-1] != 'm' ) {
1,776✔
464
                        t = (UBYTE *)Malloc1((s-AM.InputFileName)+5,"adding .frm");
×
465
                        s = AM.InputFileName;
×
466
                        AM.InputFileName = t;
×
467
                        while ( *s ) *t++ = *s++;
×
468
                        *t++ = '.'; *t++ = 'f'; *t++ = 'r'; *t++ = 'm'; *t = 0;
×
469
                }
470
                if ( AM.LogType >= 0 && AM.LogFileName == 0 ) {
1,776✔
471
                        AM.LogFileName = strDup1(AM.InputFileName,"name of logfile");
×
472
                        s = AM.LogFileName;
×
473
                        while ( *s ) s++;
×
474
                        s[-3] = 'l'; s[-2] = 'o'; s[-1] = 'g';
×
475
                }
476
        }
477
#ifdef WITHINTERACTION
478
        else if ( AM.Interact ) {
479
                if ( AM.LogType >= 0 ) {
480
/*
481
                        We may have to do better than just taking a name.
482
                        It is not unique! This will be left for later.
483
*/
484
                        AM.LogFileName = deflogname;
485
                }
486
        }
487
#endif
488
        else if ( AM.FromStdin ) {
×
489
                /* Do nothing. */
490
        }
491
        else {
492
NoFile:
×
493
#ifdef WITHMPI
494
                if ( PF.me == MASTER )
495
#endif
496
                printf("No filename specified in call of FORM\n");
×
497
                errorflag++;
×
498
        }
499
        if ( AM.Path == 0 ) AM.Path = (UBYTE *)getenv("FORMPATH");
1,776✔
500
        if ( AM.Path ) {
1,776✔
501
                /*
502
                 * AM.Path is taken from argv or getenv. Reallocate it to avoid invalid
503
                 * frees when AM.Path has to be changed.
504
                 */
505
                AM.Path = strDup1(AM.Path,"DoTail Path");
1,776✔
506
        }
507
        return(errorflag);
508
}
509

510
/*
511
                 #] DoTail : 
512
                 #[ OpenInput :
513

514
                Major task here after opening is to skip the proper number of
515
                .clear instructions if so desired without using interpretation
516
*/
517

518
int OpenInput(VOID)
1,776✔
519
{
520
        int oldNoShowInput = AC.NoShowInput;
1,776✔
521
        UBYTE c;
1,776✔
522
        if ( !AM.Interact ) {
1,776✔
523
                if ( AM.FromStdin ) {
1,776✔
524
                        if ( OpenStream(0,INPUTSTREAM,0,PRENOACTION) == 0 ) {
×
525
                                Error0("Cannot open STDIN");
×
526
                                return(-1);
×
527
                        }
528
                }
529
                else {
530
                if ( OpenStream(AM.InputFileName,FILESTREAM,0,PRENOACTION) == 0 ) {
1,776✔
531
                        Error1("Cannot open file",AM.InputFileName);
×
532
                        return(-1);
×
533
                }
534
                if ( AC.CurrentStream->inbuffer <= 0 ) {
1,776✔
535
                        Error1("No input in file",AM.InputFileName);
×
536
                        return(-1);
×
537
                }
538
                }
539
                AC.NoShowInput = 1;
1,776✔
540
                while ( AM.SkipClears > 0 ) {
1,776✔
541
                        c = GetInput();
×
542
                        if ( c == ENDOFINPUT ) {
×
543
                                Error0("Not enough .clear instructions in input file");
×
544
                        }
545
                        if ( c == '\\' ) {
×
546
                                c = GetInput();
×
547
                                if ( c == ENDOFINPUT )
×
548
                                        Error0("Not enough .clear instructions in input file");
×
549
                                continue;
×
550
                        }
551
                        if ( c == ' ' || c == '\t' ) continue;
×
552
                        if ( c == '.' ) {
×
553
                                c = GetInput();
×
554
                                if ( tolower(c) == 'c' ) {
×
555
                                        c = GetInput();
×
556
                                        if ( tolower(c) == 'l' ) {
×
557
                                                c = GetInput();
×
558
                                                if ( tolower(c) == 'e' ) {
×
559
                                                        c = GetInput();
×
560
                                                        if ( tolower(c) == 'a' ) {
×
561
                                                                c = GetInput();
×
562
                                                                if ( tolower(c) == 'r' ) {
×
563
                                                                        c = GetInput();
×
564
                                                                        if ( FG.cTable[c] > 2 ) {
×
565
                                                                                AM.SkipClears--;
×
566
                                                                        }
567
                                                                }
568
                                                        }
569
                                                }
570
                                        }
571
                                }
572
                                while ( c != '\n' && c != '\r' && c != ENDOFINPUT ) {
×
573
                                        c = GetInput();
×
574
                                        if ( c == '\\' ) c = GetInput();
×
575
                                }
576
                        }
577
                        else if ( c == '\n' || c == '\r' ) continue;
×
578
                        else {
579
                                while ( ( c = GetInput() ) != '\n' && c != '\r' ) {
×
580
                                        if ( c == ENDOFINPUT ) {
×
581
                                                Error0("Not enough .clear instructions in input file");
×
582
                                        }
583
                                }
584
                        }
585
                }
586
                AC.NoShowInput = oldNoShowInput;
1,776✔
587
        }
588
        if ( AM.LogFileName ) {
1,776✔
589
#ifdef WITHMPI
590
                if ( PF.me != MASTER ) {
591
                        /*
592
                         * Only the master writes to the log file. On slaves, we need
593
                         * a dummy handle, without opening the file.
594
                         */
595
                        extern FILES **filelist;  /* in tools.c */
596
                        int i = CreateHandle();
597
                        RWLOCKW(AM.handlelock);
598
                        filelist[i] = (FILES *)123;  /* Must be nonzero to prevent a reuse in CreateHandle. */
599
                        UNRWLOCK(AM.handlelock);
600
                        AC.LogHandle = i;
601
                }
602
                else
603
#endif
604
                if ( AC.CheckpointFlag != -1 ) {
×
605
                        if ( ( AC.LogHandle = CreateLogFile((char *)(AM.LogFileName)) ) < 0 ) {
×
606
                                Error1("Cannot create logfile",AM.LogFileName);
×
607
                                return(-1);
×
608
                        }
609
                }
610
                else {
611
                        if ( ( AC.LogHandle = OpenAddFile((char *)(AM.LogFileName)) ) < 0 ) {
×
612
                                Error1("Cannot re-open logfile",AM.LogFileName);
×
613
                                return(-1);
×
614
                        }
615
                }
616
        }
617
        return(0);
618
}
619

620
/*
621
                 #] OpenInput : 
622
                 #[ ReserveTempFiles :
623

624
                Order of preference:
625
                a: if there is a path in the commandtail, take that.
626
                b: if none, try in the form.set file.
627
                c: if still none, try in the environment for the variable FORMTMP
628
                d: if still none, try the current directory.
629

630
                The parameter indicates action in the case of multithreaded running.
631
                par = 0 : We just run on a single processor. Keep everything normal.
632
                par = 1 : Multithreaded running startup phase 1.
633
                par = 2 : Multithreaded running startup phase 2.
634
*/
635

636
UBYTE *emptystring = (UBYTE *)".";
637
UBYTE *defaulttempfilename = (UBYTE *)"xformxxx.str";
638

639
VOID ReserveTempFiles(int par)
3,866✔
640
{
641
        GETIDENTITY
2,614✔
642
        SETUPPARAMETERS *sp;
3,866✔
643
        UBYTE *s, *t, *tenddir, *tenddir2, c;        
3,866✔
644
        int i = 0;
3,866✔
645
        WORD j;
3,866✔
646
        if ( par == 0 || par == 1 ) {
3,866✔
647
        if ( AM.TempDir == 0 ) {
1,776✔
648
                sp = GetSetupPar((UBYTE *)"tempdir");
1,776✔
649
                if ( ( sp->flags & USEDFLAG ) != USEDFLAG ) {
1,776✔
650
                        AM.TempDir = (UBYTE *)getenv("FORMTMP");
1,776✔
651
                        if ( AM.TempDir == 0 ) AM.TempDir = emptystring;
1,776✔
652
                }
653
                else AM.TempDir = (UBYTE *)(sp->value);
×
654
        }
655
        if ( AM.TempSortDir == 0 ) {
1,776✔
656
                if ( AM.havesortdir ) {
1,776✔
657
                        sp = GetSetupPar((UBYTE *)"tempsortdir");
×
658
                        AM.TempSortDir = (UBYTE *)(sp->value);
×
659
                }
660
                else {
661
                        AM.TempSortDir = (UBYTE *)getenv("FORMTMPSORT");
1,776✔
662
                        if ( AM.TempSortDir == 0 ) AM.TempSortDir = AM.TempDir;
1,776✔
663
                }
664
        }
665
/*
666
        We have now in principle a path but we will use its first element only.
667
        Later that should become more complicated. Then we will use a path and
668
        when one device is full we can continue on the next one.
669
*/
670
        s = AM.TempDir; i = 200;   /* Some extra for VMS */
1,776✔
671
        while ( *s && *s != ':' ) { if ( *s == '\\' ) s++; s++; i++; }
3,552✔
672
        FG.fnamesize = sizeof(UBYTE)*(i+14);
1,776✔
673
        FG.fname = (char *)Malloc1(FG.fnamesize,"name for temporary files");
1,776✔
674
        s = AM.TempDir; t = (UBYTE *)FG.fname;
1,776✔
675
        while ( *s && *s != ':' ) { if ( *s == '\\' ) s++; *t++ = *s++; }
3,552✔
676
        if ( (char *)t > FG.fname && t[-1] != SEPARATOR && t[-1] != ALTSEPARATOR )
1,776✔
677
                *t++ = SEPARATOR;
1,776✔
678
        *t = 0;
1,776✔
679
        tenddir = t;
1,776✔
680
        FG.fnamebase = t-(UBYTE *)(FG.fname);
1,776✔
681

682
        s = AM.TempSortDir; i = 200;   /* Some extra for VMS */
1,776✔
683
        while ( *s && *s != ':' ) { if ( *s == '\\' ) s++; s++; i++; }
3,552✔
684

685
        FG.fname2size = sizeof(UBYTE)*(i+14);
1,776✔
686
        FG.fname2 = (char *)Malloc1(FG.fname2size,"name for sort files");
1,776✔
687
        s = AM.TempSortDir; t = (UBYTE *)FG.fname2;
1,776✔
688
        while ( *s && *s != ':' ) { if ( *s == '\\' ) s++; *t++ = *s++; }
3,552✔
689
        if ( (char *)t > FG.fname2 && t[-1] != SEPARATOR && t[-1] != ALTSEPARATOR )
1,776✔
690
                *t++ = SEPARATOR;
1,776✔
691
        *t = 0;
1,776✔
692
        tenddir2 = t;
1,776✔
693
        FG.fname2base = t-(UBYTE *)(FG.fname2);
1,776✔
694

695
        t = tenddir;
1,776✔
696
        s = defaulttempfilename;
1,776✔
697
#ifdef WITHMPI
698
        { 
699
          int iii;
989✔
700
#ifdef SMP
701
          /* Very dirty quick-hack for the qcm smp machine at TTP */
702
          M_free(FG.fname,"name for temporary files");
703
          if(PF.me == 0){
704
      /*[04nov2003 mt] To avoid segfault with -fast optimization option*/
705
                /*[04nov2003 mt]:*/ /*NOTE, this is only a temporary stub!*/
706
                /*FG.fname = "/formswap/xxxxxxxxxxxxxxxxxxxxx";*/
707
                FG.fname = calloc(128,1);
708
                strcpy(FG.fname,"/formswap/xxxxxxxxxxxxxxxxxxxxx");
709
                /*:[04nov2003 mt]*/
710
                t = (UBYTE *)FG.fname + 10;
711
                FG.fnamebase = t-FG.fname;
712
          }
713
          else{
714
                /*[04nov2003 mt]:*/
715
                /*FG.fname = "/formswapx/xxxxxxxxxxxxxxxxxxxxx";*/
716
                FG.fname = calloc(128,1);
717
                strcpy(FG.fname,"/formswapx/xxxxxxxxxxxxxxxxxxxxx");
718
                /*:[04nov2003 mt]*/
719
                FG.fname[9] = '0' + PF.me;
720
                t = (UBYTE *)FG.fname + 11;
721
                FG.fnamebase = t-FG.fname;
722
          }
723
#else
724
          iii = snprintf((char*)t,FG.fnamesize-((char*)t-FG.fname),"%d",PF.me);
989✔
725
          t+= iii;
989✔
726
          s+= iii; /* in case defaulttmpfilename is too short */
989✔
727
#endif
728
        }
729
#endif
730
        while ( *s ) *t++ = *s++;
22,099✔
731
        *t = 0;
1,776✔
732
/*
733
                There are problems when running many FORM jobs at the same time
734
                from make or minos. If they start up simultaneously, occasionally
735
                they can make the same .str file. We prevent this with first trying
736
                a file that contains the digits of the pid. If this file
737
                has already been taken we fall back on the old scheme.
738
                The whole is controlled with the -M (MultiRun) parameter in the
739
                command tail.
740
*/
741
        if ( AM.MultiRun ) {
1,776✔
742
                int num = ((int)GetPID())%100000;
×
743
                t += 2;
×
744
                *t = 0;
×
745
                t[-1] = 'r';
×
746
                t[-2] = 't';
×
747
                t[-3] = 's';
×
748
                t[-4] = '.';
×
749
                t[-5] = (UBYTE)('0' + num%10);
×
750
                t[-6] = (UBYTE)('0' + (num/10)%10);
×
751
                t[-7] = (UBYTE)('0' + (num/100)%10);
×
752
                t[-8] = (UBYTE)('0' + (num/1000)%10);
×
753
                t[-9] = (UBYTE)('0' + num/10000);
×
754
                if ( ( AC.StoreHandle = CreateFile((char *)FG.fname) ) < 0 ) {
×
755
                        t[-5] = 'x'; t[-6] = 'x'; t[-7] = 'x'; t[-8] = 'x'; t[-9] = 'x';
×
756
                        goto classic;
×
757
                }
758
        }
759
        else
760
        {
761
classic:;
1,776✔
762
          for(;;) {
1,776✔
763
                if ( ( AC.StoreHandle = OpenFile((char *)FG.fname) ) < 0 ) {
1,776✔
764
                        if ( ( AC.StoreHandle = CreateFile((char *)FG.fname) ) >= 0 ) break;
1,776✔
765
                }
766
                else CloseFile(AC.StoreHandle);
×
767
                c = t[-5];
×
768
                if ( c == 'x' ) t[-5] = '0';
×
769
                else if ( c == '9' ) {
×
770
                        t[-5] = '0';
×
771
                        c = t[-6];
×
772
                        if ( c == 'x' ) t[-6] = '0';
×
773
                        else if ( c == '9' ) {
×
774
                                t[-6] = '0';
×
775
                                c = t[-7];
×
776
                                if ( c == 'x' ) t[-7] = '0';
×
777
                                else if ( c == '9' ) {
×
778
/*
779
                                        Note that we tried 1111 names!
780
*/
781
                                        MesPrint("Name space for temp files exhausted");
×
782
                                        t[-7] = 0;
×
783
                                        MesPrint("Please remove files of the type %s or try a different directory"
×
784
                                                ,FG.fname);
785
                                        Terminate(-1);
×
786
                                }
787
                                else t[-7] = (UBYTE)(c+1);
×
788
                        }
789
                        else t[-6] = (UBYTE)(c+1);
×
790
                }
791
                else t[-5] = (UBYTE)(c+1);
×
792
          }
793
        }
794
/*
795
        Now we should make sure that the tempsortdir cq tempsortfilename makes it
796
        into a similar construction.
797
*/
798
        s = tenddir; t = tenddir2; while ( *s ) *t++ = *s++;
23,088✔
799
        *t = 0;
1,776✔
800

801
/*
802
        Now we should assign a name to the main sort file and the two stage 4 files.
803
*/
804
        AM.S0->file.name = (char *)Malloc1(sizeof(char)*(i+14),"name for temporary files");
1,776✔
805
        s = (UBYTE *)AM.S0->file.name;
1,776✔
806
        t = (UBYTE *)FG.fname2;
1,776✔
807
        i = 1;
1,776✔
808
        while ( *t ) { *s++ = *t++; i++; }
26,640✔
809
        s[-2] = 'o'; *s = 0;
1,776✔
810
        }
811
/*
812
        With the stage4 and scratch file names we have to be a bit more careful.
813
        They are to be allocated after the threads are initialized when there
814
        are threads of course.
815
*/
816
        if ( par == 0 ) {
3,866✔
817
                s = (UBYTE *)((void *)(FG.fname2)); i = 0;
1,252✔
818
                while ( *s ) { s++; i++; }
18,780✔
819
                s = (UBYTE *)Malloc1(sizeof(char)*(i+1),"name for stage4 file a");
1,252✔
820
                AR.FoStage4[1].name = (char *)s;
1,252✔
821
                t = (UBYTE *)FG.fname2;
1,252✔
822
                while ( *t ) *s++ = *t++;
18,780✔
823
                s[-2] = '4'; s[-1] = 'a'; *s = 0;
1,252✔
824
                s = (UBYTE *)((void *)(FG.fname)); i = 0;
1,252✔
825
                while ( *s ) { s++; i++; }
18,780✔
826
                s = (UBYTE *)Malloc1(sizeof(char)*(i+1),"name for stage4 file b");
1,252✔
827
                AR.FoStage4[0].name = (char *)s;
1,252✔
828
                t = (UBYTE *)FG.fname;
1,252✔
829
                while ( *t ) *s++ = *t++;
18,780✔
830
                s[-2] = '4'; s[-1] = 'b'; *s = 0;
1,252✔
831
                for ( j = 0; j < 3; j++ ) {
5,008✔
832
                        s = (UBYTE *)Malloc1(sizeof(char)*(i+1),"name for scratch file");
3,756✔
833
                        AR.Fscr[j].name = (char *)s;
3,756✔
834
                        t = (UBYTE *)FG.fname;
3,756✔
835
                        while ( *t ) *s++ = *t++;
56,340✔
836
                        s[-2] = 'c'; s[-1] = (UBYTE)('0'+j); *s = 0;
3,756✔
837
                }
838
        }
839
#ifdef WITHPTHREADS
840
        else if ( par == 2 ) {
2,614✔
841
                size_t tname;
2,090✔
842
                s = (UBYTE *)((void *)(FG.fname2)); i = 0;
2,090✔
843
                while ( *s ) { s++; i++; }
31,350✔
844
                tname = sizeof(char)*(i+12);
2,090✔
845
                s = (UBYTE *)Malloc1(tname,"name for stage4 file a");
2,090✔
846
                snprintf((char *)s,tname,"%s.%d",FG.fname2,AT.identity);
2,090✔
847
                s[i-2] = '4'; s[i-1] = 'a';
2,090✔
848
                AR.FoStage4[1].name = (char *)s;
2,090✔
849
                s = (UBYTE *)((void *)(FG.fname)); i = 0;
2,090✔
850
                while ( *s ) { s++; i++; }
31,350✔
851
                tname = sizeof(char)*(i+12);
2,090✔
852
                s = (UBYTE *)Malloc1(tname,"name for stage4 file b");
2,090✔
853
                snprintf((char *)s,tname,"%s.%d",FG.fname,AT.identity);
2,090✔
854
                s[i-2] = '4'; s[i-1] = 'b';
2,090✔
855
                AR.FoStage4[0].name = (char *)s;
2,090✔
856
                if ( AT.identity == 0 ) {
2,090✔
857
                        for ( j = 0; j < 3; j++ ) {
2,096✔
858
                                s = (UBYTE *)Malloc1(sizeof(char)*(i+1),"name for scratch file");
1,572✔
859
                                AR.Fscr[j].name = (char *)s;
1,572✔
860
                                t = (UBYTE *)FG.fname;
1,572✔
861
                                while ( *t ) *s++ = *t++;
23,580✔
862
                                s[-2] = 'c'; s[-1] = (UBYTE)('0'+j); *s = 0;
1,572✔
863
                        }
864
                }
865
        }
866
#endif
867
}
3,866✔
868

869
/*
870
                 #] ReserveTempFiles : 
871
                 #[ StartVariables :
872
*/
873

874
#ifdef WITHPTHREADS
875
ALLPRIVATES *DummyPointer = 0;
876
#endif
877

878
VOID StartVariables(VOID)
1,776✔
879
{
880
        int i, ii;
1,776✔
881
        PUTZERO(AM.zeropos);
1,776✔
882
        StartPrepro();
1,776✔
883
/*
884
        The module counter:
885
*/
886
        AC.CModule=0;
1,776✔
887
#ifdef WITHPTHREADS
888
/*
889
        We need a value in AB because in the startup some routines may call AB[0].
890
*/
891
        AB = (ALLPRIVATES **)&DummyPointer;
524✔
892
#endif
893
/*
894
        separators used to delimit arguments in #call and #do, by default ',' and '|':
895
        Be sure, it is en empty set:
896
*/
897
        set_sub(AC.separators,AC.separators,AC.separators);
1,776✔
898
        set_set(',',AC.separators);
1,776✔
899
        set_set('|',AC.separators);
1,776✔
900

901
        AM.BracketFactors[0] = 8;
1,776✔
902
        AM.BracketFactors[1] = SYMBOL;
1,776✔
903
        AM.BracketFactors[2] = 4;
1,776✔
904
        AM.BracketFactors[3] = FACTORSYMBOL;
1,776✔
905
        AM.BracketFactors[4] = 1;
1,776✔
906
        AM.BracketFactors[5] = 1;
1,776✔
907
        AM.BracketFactors[6] = 1;
1,776✔
908
        AM.BracketFactors[7] = 3;
1,776✔
909

910
        AM.SkipClears = 0;
1,776✔
911
        AC.Cnumpows = 0;
1,776✔
912
        AC.OutputMode = 72;
1,776✔
913
        AC.OutputSpaces = NORMALFORMAT;
1,776✔
914
        AC.LineLength = 79;
1,776✔
915
        AM.gIsFortran90 = AC.IsFortran90 = ISNOTFORTRAN90;
1,776✔
916
        AM.gFortran90Kind = AC.Fortran90Kind = 0;
1,776✔
917
        AM.gCnumpows = 0;
1,776✔
918
        AC.exprfillwarning = 0;
1,776✔
919
        AM.gLineLength = 79;
1,776✔
920
        AM.OutBufSize = 80;
1,776✔
921
        AM.MaxStreamSize = MAXFILESTREAMSIZE;
1,776✔
922
        AP.MaxPreAssignLevel = 4;
1,776✔
923
        AC.iBufferSize = 512;
1,776✔
924
        AP.pSize = 128;
1,776✔
925
        AP.MaxPreIfLevel = 10;
1,776✔
926
        AP.cComChar = AP.ComChar = '*';
1,776✔
927
        AP.firstnamespace = 0;
1,776✔
928
        AP.lastnamespace = 0;
1,776✔
929
        AP.fullnamesize = 127;
1,776✔
930
        AP.fullname = (UBYTE *)Malloc1((AP.fullnamesize+1)*sizeof(UBYTE),"AP.fullname");
1,776✔
931
        AM.OffsetVector = -2*WILDOFFSET+MINSPEC;
1,776✔
932
        AC.cbufList.num = 0;
1,776✔
933
        AM.hparallelflag = AM.gparallelflag =
1,776✔
934
        AC.parallelflag = AC.mparallelflag = PARALLELFLAG;
1,776✔
935
#ifdef WITHMPI
936
        if ( PF.numtasks < 2 ) AM.hparallelflag |= NOPARALLEL_NPROC;
989✔
937
#endif
938
        AC.tablefilling = 0;
1,776✔
939
        AC.models = 0;
1,776✔
940
        AC.nummodels = 0;
1,776✔
941
        AC.ModelLevel = 0;
1,776✔
942
        AC.modelspace = 0;
1,776✔
943
        AM.resetTimeOnClear = 1;
1,776✔
944
        AM.gnumextrasym = AM.ggnumextrasym = 0;
1,776✔
945
        AM.havesortdir = 0;
1,776✔
946
        AM.SpectatorFiles = 0;
1,776✔
947
        AM.NumSpectatorFiles = 0;
1,776✔
948
        AM.SizeForSpectatorFiles = 0;
1,776✔
949
/*
950
        Information for the lists of variables. Part of error message and size:
951
*/
952
        AP.ProcList.message = "procedure";
1,776✔
953
        AP.ProcList.size = sizeof(PROCEDURE);
1,776✔
954
        AP.LoopList.message = "doloop";
1,776✔
955
        AP.LoopList.size = sizeof(DOLOOP);
1,776✔
956
        AP.PreVarList.message = "PreVariable";
1,776✔
957
        AP.PreVarList.size = sizeof(PREVAR);
1,776✔
958
        AC.SymbolList.message = "symbol";
1,776✔
959
        AC.SymbolList.size = sizeof(struct SyMbOl);
1,776✔
960
        AC.IndexList.message = "index";
1,776✔
961
        AC.IndexList.size = sizeof(struct InDeX);
1,776✔
962
        AC.VectorList.message = "vector";
1,776✔
963
        AC.VectorList.size = sizeof(struct VeCtOr);
1,776✔
964
        AC.FunctionList.message = "function";
1,776✔
965
        AC.FunctionList.size = sizeof(struct FuNcTiOn);
1,776✔
966
        AC.SetList.message = "set";
1,776✔
967
        AC.SetList.size = sizeof(struct SeTs);
1,776✔
968
        AC.SetElementList.message = "set element";
1,776✔
969
        AC.SetElementList.size = sizeof(WORD);
1,776✔
970
        AC.ExpressionList.message = "expression";
1,776✔
971
        AC.ExpressionList.size = sizeof(struct ExPrEsSiOn);
1,776✔
972
        AC.cbufList.message = "compiler buffer";
1,776✔
973
        AC.cbufList.size = sizeof(CBUF);
1,776✔
974
        AC.ChannelList.message = "channel buffer";
1,776✔
975
        AC.ChannelList.size = sizeof(CHANNEL);
1,776✔
976
        AP.DollarList.message = "$-variable";
1,776✔
977
        AP.DollarList.size = sizeof(struct DoLlArS);
1,776✔
978
        AC.DubiousList.message = "ambiguous variable";
1,776✔
979
        AC.DubiousList.size = sizeof(struct DuBiOuS);
1,776✔
980
        AC.TableBaseList.message = "list of tablebases";
1,776✔
981
        AC.TableBaseList.size = sizeof(DBASE);
1,776✔
982
        AC.TestValue = 0;
1,776✔
983
        AC.InnerTest = 0;
1,776✔
984

985
        AC.AutoSymbolList.message = "autosymbol";
1,776✔
986
        AC.AutoSymbolList.size = sizeof(struct SyMbOl);
1,776✔
987
        AC.AutoIndexList.message = "autoindex";
1,776✔
988
        AC.AutoIndexList.size = sizeof(struct InDeX);
1,776✔
989
        AC.AutoVectorList.message = "autovector";
1,776✔
990
        AC.AutoVectorList.size = sizeof(struct VeCtOr);
1,776✔
991
        AC.AutoFunctionList.message = "autofunction";
1,776✔
992
        AC.AutoFunctionList.size = sizeof(struct FuNcTiOn);
1,776✔
993
        AC.PotModDolList.message = "potentially modified dollar";
1,776✔
994
        AC.PotModDolList.size = sizeof(WORD);
1,776✔
995
        AC.ModOptDolList.message = "moduleoptiondollar";
1,776✔
996
        AC.ModOptDolList.size = sizeof(MODOPTDOLLAR);
1,776✔
997

998
        AO.FortDotChar = '_';
1,776✔
999
        AO.ErrorBlock = 0;
1,776✔
1000
        AC.firstconstindex = 1;
1,776✔
1001
        AO.Optimize.mctsconstant.fval = 1.0;
1,776✔
1002
        AO.Optimize.horner = O_MCTS;
1,776✔
1003
        AO.Optimize.hornerdirection = O_FORWARDORBACKWARD;
1,776✔
1004
        AO.Optimize.method = O_GREEDY;
1,776✔
1005
        AO.Optimize.mctstimelimit = 0;
1,776✔
1006
        AO.Optimize.mctsnumexpand = 1000;
1,776✔
1007
        AO.Optimize.mctsnumkeep = 10;
1,776✔
1008
        AO.Optimize.mctsnumrepeat = 1;
1,776✔
1009
        AO.Optimize.greedytimelimit = 0;
1,776✔
1010
        AO.Optimize.greedyminnum = 10;
1,776✔
1011
        AO.Optimize.greedymaxperc = 5;
1,776✔
1012
        AO.Optimize.printstats = 0;
1,776✔
1013
        AO.Optimize.debugflags = 0;
1,776✔
1014
        AO.OptimizeResult.code = NULL;
1,776✔
1015
        AO.inscheme = 0;
1,776✔
1016
        AO.schemenum = 0;
1,776✔
1017
        AO.wpos = 0;
1,776✔
1018
        AO.wpoin = 0;
1,776✔
1019
        AO.wlen = 0;
1,776✔
1020
        AM.dollarzero = 0;
1,776✔
1021
         AC.doloopstack = 0;
1,776✔
1022
         AC.doloopstacksize = 0;
1,776✔
1023
         AC.dolooplevel = 0;
1,776✔
1024
/*
1025
        Set up the main name trees:
1026
*/
1027
        AC.varnames  = MakeNameTree();
1,776✔
1028
        AC.exprnames = MakeNameTree();
1,776✔
1029
        AC.dollarnames = MakeNameTree();
1,776✔
1030
        AC.autonames = MakeNameTree();
1,776✔
1031
        AC.activenames = &(AC.varnames);
1,776✔
1032
        AP.preError = 0;
1,776✔
1033
/*
1034
        Initialize the compiler:
1035
*/
1036
        inictable();
1,776✔
1037
        AM.rbufnum = inicbufs();                /* Regular compiler buffer */
1,776✔
1038
#ifndef WITHPTHREADS
1039
        AT.ebufnum = inicbufs();                /* Buffer for extras during execution */
1,252✔
1040
        AT.fbufnum = inicbufs();                /* Buffer for caching in factorization */
1,252✔
1041
        AT.allbufnum = inicbufs();                /* Buffer for id,all */
1,252✔
1042
        AT.aebufnum = inicbufs();                /* Buffer for id,all */
1,252✔
1043
        AN.tryterm = 0;
1,252✔
1044
#else
1045
        AS.MasterSort = 0;
524✔
1046
#endif
1047
        AM.dbufnum = inicbufs();                /* Buffer for dollar variables */
1,776✔
1048
        AM.sbufnum = inicbufs();                /* Subterm buffer for polynomials and optimization */
1,776✔
1049
        AC.ffbufnum = inicbufs();                /* Buffer number for user defined factorizations */
1,776✔
1050
        AM.zbufnum = inicbufs();                /* For very special values */
1,776✔
1051
        {
1052
                CBUF *C = cbuf+AM.zbufnum;
1,776✔
1053
                WORD one[5] = {4,1,1,3,0};
1,776✔
1054
                WORD zero = 0;
1,776✔
1055
                AddRHS(AM.zbufnum,1);
1,776✔
1056
                AM.zerorhs = C->numrhs;
1,776✔
1057
                AddNtoC(AM.zbufnum,1,&zero,17);
1,776✔
1058
                AddRHS(AM.zbufnum,1);
1,776✔
1059
                AM.onerhs = C->numrhs;
1,776✔
1060
                AddNtoC(AM.zbufnum,5,one,17);
1,776✔
1061
        }
1062
        AP.inside.inscbuf = inicbufs();        /* For the #inside instruction */
1,776✔
1063
/*
1064
        Enter the built in objects
1065
*/
1066
        AC.Symbols = &(AC.SymbolList);
1,776✔
1067
        AC.Indices = &(AC.IndexList);
1,776✔
1068
        AC.Vectors = &(AC.VectorList);
1,776✔
1069
        AC.Functions = &(AC.FunctionList);
1,776✔
1070
        AC.vetofilling = 0;
1,776✔
1071

1072
        AddDollar((UBYTE *)"$",DOLUNDEFINED,0,0);
1,776✔
1073

1074
        cbuf[AM.dbufnum].mnumlhs = cbuf[AM.dbufnum].numlhs;
1,776✔
1075
        cbuf[AM.dbufnum].mnumrhs = cbuf[AM.dbufnum].numrhs;
1,776✔
1076

1077
        AddSymbol((UBYTE *)"i_",-MAXPOWER,MAXPOWER,VARTYPEIMAGINARY,0);
1,776✔
1078
        AM.numpi = AddSymbol((UBYTE *)"pi_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1,776✔
1079
/*
1080
        coeff_ should have the number COEFFSYMBOL and den_ the number DENOMINATOR
1081
    and the three should be in this order!
1082
*/
1083
        AddSymbol((UBYTE *)"coeff_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1,776✔
1084
        AddSymbol((UBYTE *)"num_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1,776✔
1085
        AddSymbol((UBYTE *)"den_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1,776✔
1086
        AddSymbol((UBYTE *)"xarg_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1,776✔
1087
        AddSymbol((UBYTE *)"dimension_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1,776✔
1088
        AddSymbol((UBYTE *)"factor_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1,776✔
1089
        AddSymbol((UBYTE *)"sep_",-MAXPOWER,MAXPOWER,VARTYPENONE,0);
1,776✔
1090
        i = BUILTINSYMBOLS;  /* update this in ftypes.h when we add new symbols */
1,776✔
1091
/*
1092
        Next we add a number of dummy symbols for ensuring that the user defined
1093
        symbols start at a fixed given number FIRSTUSERSYMBOL
1094
        We do want to give them unique names though that the user cannot access.
1095
*/
1096
        {
1097
                char dumstr[20];
1,776✔
1098
                for ( ; i < FIRSTUSERSYMBOL; i++ ) {
23,088✔
1099
                        snprintf(dumstr,20,":%d:",i);
19,536✔
1100
                        AddSymbol((UBYTE *)dumstr,-MAXPOWER,MAXPOWER,VARTYPENONE,0);
19,536✔
1101
                }
1102
        }
1103

1104
        AddIndex((UBYTE *)"iarg_",4,0);
1,776✔
1105
        AddVector((UBYTE *)"parg_",VARTYPENONE,0);
1,776✔
1106

1107
        AM.NumFixedFunctions = sizeof(fixedfunctions)/sizeof(struct fixedfun);
1,776✔
1108
        for ( i = 0; i < AM.NumFixedFunctions; i++ ) {
186,480✔
1109
                ii = AddFunction((UBYTE *)fixedfunctions[i].name
184,704✔
1110
                                         ,fixedfunctions[i].commu
1111
                                         ,fixedfunctions[i].tensor
1112
                                         ,fixedfunctions[i].complx
1113
                                         ,fixedfunctions[i].symmetric
1114
                                         ,0,-1,-1);
1115
                if ( fixedfunctions[i].tensor == GAMMAFUNCTION )
184,704✔
1116
                                                        functions[ii].flags |= COULDCOMMUTE;
8,880✔
1117
        }
1118
/*
1119
        Next we add a number of dummy functions for ensuring that the user defined
1120
        functions start at a fixed given number FIRSTUSERFUNCTION.
1121
        We do want to give them unique names though that the user cannot access.
1122
*/
1123
        {
1124
                char dumstr[20];
1125
                for ( ; i < FIRSTUSERFUNCTION-FUNCTION; i++ ) {
47,952✔
1126
                        snprintf(dumstr,20,"::%d::",i);
46,176✔
1127
                        AddFunction((UBYTE *)dumstr,0,0,0,0,0,-1,-1);
46,176✔
1128
                }
1129
        }
1130
        AM.NumFixedSets = sizeof(fixedsets)/sizeof(struct fixedset);
1,776✔
1131
        for ( i = 0; i < AM.NumFixedSets; i++ ) {
24,864✔
1132
                ii = AddSet((UBYTE *)fixedsets[i].name,fixedsets[i].dimension);
23,088✔
1133
                Sets[ii].type = fixedsets[i].type;
23,088✔
1134
        }
1135
        AM.RepMax = MAXREPEAT;
1,776✔
1136
#ifndef WITHPTHREADS
1137
        AT.RepCount = (int *)Malloc1((LONG)((AM.RepMax+3)*sizeof(int)),"repeat buffers");
1,252✔
1138
        AN.RepPoint = AT.RepCount;
1,252✔
1139
        AT.RepTop = AT.RepCount + AM.RepMax;
1,252✔
1140
        AN.polysortflag = 0;
1,252✔
1141
        AN.subsubveto = 0;
1,252✔
1142
#endif
1143
        AC.NumWildcardNames = 0;
1,776✔
1144
        AC.WildcardBufferSize = 50;
1,776✔
1145
        AC.WildcardNames = (UBYTE *)Malloc1((LONG)AC.WildcardBufferSize,"argument list names");
1,776✔
1146
#ifndef WITHPTHREADS
1147
        AT.WildArgTaken = (WORD *)Malloc1((LONG)AC.WildcardBufferSize*sizeof(WORD)/2
1,252✔
1148
                                ,"argument list names");
1149
        AT.WildcardBufferSize = AC.WildcardBufferSize;
1,252✔
1150
        AR.CompareRoutine = (COMPAREDUMMY)(&Compare1);
1,252✔
1151
        AT.nfac = AT.nBer = 0;
1,252✔
1152
        AT.factorials = 0;
1,252✔
1153
        AT.bernoullis = 0;
1,252✔
1154
        AR.wranfia = 0;
1,252✔
1155
        AR.wranfcall = 0;
1,252✔
1156
        AR.wranfnpair1 = NPAIR1;
1,252✔
1157
        AR.wranfnpair2 = NPAIR2;
1,252✔
1158
        AR.wranfseed = 0;
1,252✔
1159
#endif
1160
        AM.atstartup = 1;
1,776✔
1161
        AM.oldnumextrasymbols = strDup1((UBYTE *)"OLDNUMEXTRASYMBOLS_","oldnumextrasymbols");
1,776✔
1162
        PutPreVar((UBYTE *)"VERSION_",(UBYTE *)STRINGIFY(MAJORVERSION),0,0);
1,776✔
1163
        PutPreVar((UBYTE *)"SUBVERSION_",(UBYTE *)STRINGIFY(MINORVERSION),0,0);
1,776✔
1164
        PutPreVar((UBYTE *)"DATE_",(UBYTE *)MakeDate(),0,0);
1,776✔
1165
        PutPreVar((UBYTE *)"random_",(UBYTE *)"________",(UBYTE *)"?a",0);
1,776✔
1166
        PutPreVar((UBYTE *)"optimminvar_",(UBYTE *)("0"),0,0);
1,776✔
1167
        PutPreVar((UBYTE *)"optimmaxvar_",(UBYTE *)("0"),0,0);
1,776✔
1168
        PutPreVar(AM.oldnumextrasymbols,(UBYTE *)("0"),0,0);
1,776✔
1169
        PutPreVar((UBYTE *)"optimvalue_",(UBYTE *)("0"),0,0);
1,776✔
1170
        PutPreVar((UBYTE *)"optimscheme_",(UBYTE *)("0"),0,0);
1,776✔
1171
        PutPreVar((UBYTE *)"tolower_",(UBYTE *)("0"),(UBYTE *)("?a"),0);
1,776✔
1172
        PutPreVar((UBYTE *)"toupper_",(UBYTE *)("0"),(UBYTE *)("?a"),0);
1,776✔
1173
        PutPreVar((UBYTE *)"takeleft_",(UBYTE *)("0"),(UBYTE *)("?a"),0);
1,776✔
1174
        PutPreVar((UBYTE *)"takeright_",(UBYTE *)("0"),(UBYTE *)("?a"),0);
1,776✔
1175
        PutPreVar((UBYTE *)"keepleft_",(UBYTE *)("0"),(UBYTE *)("?a"),0);
1,776✔
1176
        PutPreVar((UBYTE *)"keepright_",(UBYTE *)("0"),(UBYTE *)("?a"),0);
1,776✔
1177
        PutPreVar((UBYTE *)"SYSTEMERROR_",(UBYTE *)("0"),0,0);
1,776✔
1178
/*
1179
        Next are a few 'constants' for diagram generation
1180
*/
1181
        PutPreVar((UBYTE *)"ONEPI_",(UBYTE *)("1"),0,0);
1,776✔
1182
        PutPreVar((UBYTE *)"WITHOUTINSERTIONS_",(UBYTE *)("2"),0,0);
1,776✔
1183
        PutPreVar((UBYTE *)"NOTADPOLES_",(UBYTE *)("4"),0,0);
1,776✔
1184
        PutPreVar((UBYTE *)"SYMMETRIZE_",(UBYTE *)("8"),0,0);
1,776✔
1185
        PutPreVar((UBYTE *)"TOPOLOGIESONLY_",(UBYTE *)("16"),0,0);
1,776✔
1186
        PutPreVar((UBYTE *)"NONODES_",(UBYTE *)("32"),0,0);
1,776✔
1187
        PutPreVar((UBYTE *)"WITHEDGES_",(UBYTE *)("64"),0,0);
1,776✔
1188
/*                Note that CHECKEXTERN is 128 */
1189
        PutPreVar((UBYTE *)"WITHBLOCKS_",(UBYTE *)("256"),0,0);
1,776✔
1190
                PutPreVar((UBYTE *)"WITHONEPISETS_",(UBYTE *)("512"),0,0);
1,776✔
1191
        PutPreVar((UBYTE *)"NOSNAILS_",(UBYTE *)("1024"),0,0);
1,776✔
1192
        PutPreVar((UBYTE *)"NOEXTSELF_",(UBYTE *)("2048"),0,0);
1,776✔
1193

1194
        {
1195
                char buf[41];  /* up to 128-bit */
1,776✔
1196
                LONG pid;
1,776✔
1197
#ifndef WITHMPI
1198
                pid = GetPID();
787✔
1199
#else
1200
                pid = ( PF.me == MASTER ) ? GetPID() : (LONG)0;
989✔
1201
                pid = PF_BroadcastNumber(pid);
989✔
1202
#endif
1203
                LongCopy(pid,buf);
1,776✔
1204
                PutPreVar((UBYTE *)"PID_",(UBYTE *)buf,0,0);
1,776✔
1205
        }
1206
        AM.atstartup = 0;
1,776✔
1207
        AP.MaxPreTypes = 10;
1,776✔
1208
        AP.NumPreTypes = 0;
1,776✔
1209
        AP.PreTypes = (int *)Malloc1(sizeof(int)*(AP.MaxPreTypes+1),"preprocessor types");
1,776✔
1210
        AP.inside.buffer = 0;
1,776✔
1211
        AP.inside.size = 0;
1,776✔
1212

1213
        AC.SortType = AC.lSortType = AM.gSortType = SORTLOWFIRST;
1,776✔
1214
#ifdef WITHPTHREADS
1215
#else
1216
        AR.SortType = AC.SortType;
1,252✔
1217
#endif
1218
        AC.LogHandle = -1;
1,776✔
1219
        AC.SetList.numtemp        = AC.SetList.num;
1,776✔
1220
        AC.SetElementList.numtemp = AC.SetElementList.num;
1,776✔
1221

1222
        GetName(AC.varnames,(UBYTE *)"exp_",&AM.expnum,NOAUTO);
1,776✔
1223
        GetName(AC.varnames,(UBYTE *)"denom_",&AM.denomnum,NOAUTO);
1,776✔
1224
        GetName(AC.varnames,(UBYTE *)"fac_",&AM.facnum,NOAUTO);
1,776✔
1225
        GetName(AC.varnames,(UBYTE *)"invfac_",&AM.invfacnum,NOAUTO);
1,776✔
1226
        GetName(AC.varnames,(UBYTE *)"sum_",&AM.sumnum,NOAUTO);
1,776✔
1227
        GetName(AC.varnames,(UBYTE *)"sump_",&AM.sumpnum,NOAUTO);
1,776✔
1228
        GetName(AC.varnames,(UBYTE *)"term_",&AM.termfunnum,NOAUTO);
1,776✔
1229
        GetName(AC.varnames,(UBYTE *)"match_",&AM.matchfunnum,NOAUTO);
1,776✔
1230
        GetName(AC.varnames,(UBYTE *)"count_",&AM.countfunnum,NOAUTO);
1,776✔
1231
        AM.termfunnum += FUNCTION;
1,776✔
1232
        AM.matchfunnum += FUNCTION;
1,776✔
1233
        AM.countfunnum += FUNCTION;
1,776✔
1234

1235
        AC.ThreadStats = AM.gThreadStats = AM.ggThreadStats = 1;
1,776✔
1236
        AC.FinalStats = AM.gFinalStats = AM.ggFinalStats = 1;
1,776✔
1237
        AC.StatsFlag = AM.gStatsFlag = AM.ggStatsFlag = 1;
1,776✔
1238
        AC.ThreadsFlag = AM.gThreadsFlag = AM.ggThreadsFlag = 1;
1,776✔
1239
        AC.ThreadBalancing = AM.gThreadBalancing = AM.ggThreadBalancing = 1;
1,776✔
1240
        AC.ThreadSortFileSynch = AM.gThreadSortFileSynch = AM.ggThreadSortFileSynch = 0;
1,776✔
1241
        AC.ProcessStats = AM.gProcessStats = AM.ggProcessStats = 1;
1,776✔
1242
        AC.OldParallelStats = AM.gOldParallelStats = AM.ggOldParallelStats = 0;
1,776✔
1243
        AC.OldFactArgFlag = AM.gOldFactArgFlag = AM.ggOldFactArgFlag = NEWFACTARG;
1,776✔
1244
        AC.OldGCDflag = AM.gOldGCDflag = AM.ggOldGCDflag = 1;
1,776✔
1245
        AC.WTimeStatsFlag = AM.gWTimeStatsFlag = AM.ggWTimeStatsFlag = 0;
1,776✔
1246
        AM.gcNumDollars = AP.DollarList.num;
1,776✔
1247
        AC.SizeCommuteInSet = AM.gSizeCommuteInSet = 0;
1,776✔
1248
#ifdef WITHFLOAT
1249
        AC.MaxWeight = AM.gMaxWeight = AM.ggMaxWeight = MAXWEIGHT;
1,776✔
1250
        AC.DefaultPrecision = AM.gDefaultPrecision = AM.ggDefaultPrecision = DEFAULTPRECISION;
1,776✔
1251
#endif
1252
        AC.CommuteInSet = 0;
1,776✔
1253

1254
        AM.PrintTotalSize = 0;
1,776✔
1255

1256
        AO.NoSpacesInNumbers = AM.gNoSpacesInNumbers = AM.ggNoSpacesInNumbers = 0;
1,776✔
1257
        AO.IndentSpace = AM.gIndentSpace = AM.ggIndentSpace = INDENTSPACE;
1,776✔
1258
        AO.BlockSpaces = 0;
1,776✔
1259
        AO.OptimizationLevel = 0;
1,776✔
1260
        PUTZERO(AS.MaxExprSize);
1,776✔
1261
        PUTZERO(AC.StoreFileSize);
1,776✔
1262

1263
#ifdef WITHPTHREADS
1264
        AC.inputnumbers = 0;
524✔
1265
        AC.pfirstnum = 0;
524✔
1266
        AC.numpfirstnum = AC.sizepfirstnum = 0;
524✔
1267
#endif
1268
        AC.MemDebugFlag = 1;
1,776✔
1269

1270
#ifdef WITHEXTERNALCHANNEL
1271
        AX.currentExternalChannel=0;
1,776✔
1272
        AX.killSignal=SIGKILL;
1,776✔
1273
        AX.killWholeGroup=1;
1,776✔
1274
        AX.daemonize=1;
1,776✔
1275
        AX.currentPrompt=0;
1,776✔
1276
        AX.timeout=1000;/*One second to initialize preset channels*/
1,776✔
1277
        AX.shellname=strDup1((UBYTE *)"/bin/sh -c","external channel shellname");
1,776✔
1278
        AX.stderrname=strDup1((UBYTE *)"/dev/null","external channel stderrname");
1,776✔
1279
#endif
1280
}
1,776✔
1281

1282
/*
1283
                 #] StartVariables : 
1284
                 #[ StartMore :
1285
*/
1286

1287
VOID StartMore(VOID)
1,776✔
1288
{
1289
#ifdef WITHEXTERNALCHANNEL
1290
        /*If env.variable "FORM_PIPES" is defined, we have to initialize 
1291
                corresponding pre-set external channels, see file extcmd.c.*/
1292
        /*This line must be after all setup settings: in future, timeout
1293
                could be changed at setup.*/
1294
        if(AX.timeout>=0)/*if AX.timeout<0, this was done by cmdline option -pipe*/
1,776✔
1295
                initPresetExternalChannels((UBYTE*)getenv("FORM_PIPES"),AX.timeout);
1,776✔
1296
#endif
1297

1298
#ifdef WITHMPI
1299
/*
1300
        Define preprocessor variable PARALLELTASK_ as a process number, 0 is the master
1301
        Define preprocessor variable NPARALLELTASKS_ as a total number of processes
1302
*/
1303
        {
1304
                UBYTE buf[32];
989✔
1305
                snprintf((char*)buf,32,"%d",PF.me);
989✔
1306
                PutPreVar((UBYTE *)"PARALLELTASK_",buf,0,0);
989✔
1307
                snprintf((char*)buf,32,"%d",PF.numtasks);
989✔
1308
                PutPreVar((UBYTE *)"NPARALLELTASKS_",buf,0,0);
989✔
1309
        }
1310
#else
1311
        PutPreVar((UBYTE *)"PARALLELTASK_",(UBYTE *)"0",0,0);
787✔
1312
        PutPreVar((UBYTE *)"NPARALLELTASKS_",(UBYTE *)"1",0,0);
787✔
1313
#endif
1314

1315
        PutPreVar((UBYTE *)"NAME_",AM.InputFileName ? AM.InputFileName : (UBYTE *)"STDIN",0,0);
3,552✔
1316
}
1,776✔
1317

1318
/*
1319
                 #] StartMore : 
1320
                 #[ IniVars :
1321

1322
                This routine initializes the parameters that may change during the run.
1323
*/
1324

1325
WORD IniVars(VOID)
1,776✔
1326
{
1327
#ifdef WITHPTHREADS
1328
        GETIDENTITY
524✔
1329
#else
1330
        WORD *t;
1,252✔
1331
#endif
1332
        WORD *fi, i, one = 1;
1,776✔
1333
        CBUF *C = cbuf+AC.cbufnum;
1,776✔
1334

1335
#ifdef WITHPTHREADS
1336
        UBYTE buf[32];
524✔
1337
        snprintf((char*)buf,32,"%d",AM.totalnumberofthreads);
524✔
1338
        PutPreVar((UBYTE *)"NTHREADS_",buf,0,1);
524✔
1339
#else
1340
        PutPreVar((UBYTE *)"NTHREADS_",(UBYTE *)"1",0,1);
1,252✔
1341
#endif
1342

1343
        AC.ShortStats = 0;
1,776✔
1344
        AC.WarnFlag = 1;
1,776✔
1345
        AR.SortType = AC.SortType = AC.lSortType = AM.gSortType;
1,776✔
1346
        AC.OutputMode = 72;
1,776✔
1347
        AC.OutputSpaces = NORMALFORMAT;
1,776✔
1348
        AR.Eside = 0;
1,776✔
1349
        AC.DumNum = 0;
1,776✔
1350
        AC.ncmod = AM.gncmod = 0;
1,776✔
1351
        AC.modmode = AM.gmodmode = 0;
1,776✔
1352
        AC.npowmod = AM.gnpowmod = 0;
1,776✔
1353
        AC.halfmod = 0; AC.nhalfmod = 0;
1,776✔
1354
        AC.modinverses = 0;
1,776✔
1355
        AC.lPolyFun = AM.gPolyFun = 0;
1,776✔
1356
        AC.lPolyFunInv = AM.gPolyFunInv = 0;
1,776✔
1357
        AC.lPolyFunType = AM.gPolyFunType = 0;
1,776✔
1358
        AC.lPolyFunExp = AM.gPolyFunExp = 0;
1,776✔
1359
        AC.lPolyFunVar = AM.gPolyFunVar = 0;
1,776✔
1360
        AC.lPolyFunPow = AM.gPolyFunPow = 0;
1,776✔
1361
        AC.DirtPow = 0;
1,776✔
1362
        AC.lDefDim = AM.gDefDim = 4;
1,776✔
1363
        AC.lDefDim4 = AM.gDefDim4 = 0;
1,776✔
1364
        AC.lUnitTrace = AM.gUnitTrace = 4;
1,776✔
1365
        AC.NamesFlag = AM.gNamesFlag = 0;
1,776✔
1366
        AC.CodesFlag = AM.gCodesFlag = 0;
1,776✔
1367
        AC.extrasymbols = AM.gextrasymbols = AM.ggextrasymbols = 0;
1,776✔
1368
        AC.extrasym = (UBYTE *)Malloc1(2*sizeof(UBYTE),"extrasym");
1,776✔
1369
        AM.gextrasym = (UBYTE *)Malloc1(2*sizeof(UBYTE),"extrasym");
1,776✔
1370
        AM.ggextrasym = (UBYTE *)Malloc1(2*sizeof(UBYTE),"extrasym");
1,776✔
1371
        AC.extrasym[0] = AM.gextrasym[0] = AM.ggextrasym[0] = 'Z';
1,776✔
1372
        AC.extrasym[1] = AM.gextrasym[1] = AM.ggextrasym[1] = 0;
1,776✔
1373
        AC.TokensWriteFlag = AM.gTokensWriteFlag = 0;
1,776✔
1374
        AC.SetupFlag = 0;
1,776✔
1375
        AC.LineLength = AM.gLineLength = 79;
1,776✔
1376
        AC.NwildC = 0;
1,776✔
1377
        AC.OutputMode = 0;
1,776✔
1378
        AM.gOutputMode = 0;
1,776✔
1379
        AC.OutputSpaces = NORMALFORMAT;
1,776✔
1380
        AM.gOutputSpaces = NORMALFORMAT;
1,776✔
1381
        AC.OutNumberType = RATIONALMODE;
1,776✔
1382
        AM.gOutNumberType = RATIONALMODE;
1,776✔
1383
#ifdef WITHZLIB
1384
        AR.gzipCompress = GZIPDEFAULT;
1,776✔
1385
        AR.FoStage4[0].ziobuffer = 0;
1,776✔
1386
        AR.FoStage4[1].ziobuffer = 0;
1,776✔
1387
#endif
1388
        AR.BracketOn = 0;
1,776✔
1389
        AC.bracketindexflag = 0;
1,776✔
1390
        AT.bracketindexflag = 0;
1,776✔
1391
        AT.bracketinfo = 0;
1,776✔
1392
        AO.IsBracket = 0;
1,776✔
1393
        AM.gfunpowers = AC.funpowers = COMFUNPOWERS;
1,776✔
1394
        AC.parallelflag = AM.gparallelflag;
1,776✔
1395
        AC.properorderflag = AM.gproperorderflag = PROPERORDERFLAG;
1,776✔
1396
        AC.ProcessBucketSize = AC.mProcessBucketSize = AM.gProcessBucketSize;
1,776✔
1397
    AC.ThreadBucketSize = AM.gThreadBucketSize;
1,776✔
1398
        AC.ShortStatsMax = 0;
1,776✔
1399
        AM.gShortStatsMax = 0;
1,776✔
1400
        AM.ggShortStatsMax = 0;
1,776✔
1401

1402
        GlobalSymbols     = NumSymbols;
1,776✔
1403
        GlobalIndices     = NumIndices;
1,776✔
1404
        GlobalVectors     = NumVectors;
1,776✔
1405
        GlobalFunctions   = NumFunctions;
1,776✔
1406
        GlobalSets        = NumSets;
1,776✔
1407
        GlobalSetElements = NumSetElements;
1,776✔
1408
        AC.modpowers = (UWORD *)0;
1,776✔
1409

1410
        i = AM.OffsetIndex;
1,776✔
1411
        fi = AC.FixIndices;
1,776✔
1412
        if ( i > 0 ) do { *fi++ = one; } while ( --i >= 0 );
232,656✔
1413
        AR.sLevel = -1;
1,776✔
1414
        AM.Ordering[0] = 5;
1,776✔
1415
        AM.Ordering[1] = 6;
1,776✔
1416
        AM.Ordering[2] = 7;
1,776✔
1417
        AM.Ordering[3] = 0;
1,776✔
1418
        AM.Ordering[4] = 1;
1,776✔
1419
        AM.Ordering[5] = 2;
1,776✔
1420
        AM.Ordering[6] = 3;
1,776✔
1421
        AM.Ordering[7] = 4;
1,776✔
1422
        for ( i = 8; i < 15; i++ ) AM.Ordering[i] = i;
14,208✔
1423
        AM.gUniTrace[0] = 
1,776✔
1424
        AC.lUniTrace[0] = SNUMBER;
1,776✔
1425
        AM.gUniTrace[1] = 
1,776✔
1426
        AC.lUniTrace[1] = 
1,776✔
1427
        AM.gUniTrace[2] = 
1,776✔
1428
        AC.lUniTrace[2] = 4;
1,776✔
1429
        AM.gUniTrace[3] = 
1,776✔
1430
        AC.lUniTrace[3] = 1;
1,776✔
1431
#ifdef WITHPTHREADS
1432
        AS.Balancing = 0;
524✔
1433
#else
1434
        AT.MinVecArg[0] = 7+ARGHEAD;
1,252✔
1435
        AT.MinVecArg[ARGHEAD] = 7;
1,252✔
1436
        AT.MinVecArg[1+ARGHEAD] = INDEX;
1,252✔
1437
        AT.MinVecArg[2+ARGHEAD] = 3;
1,252✔
1438
        AT.MinVecArg[3+ARGHEAD] = 0;
1,252✔
1439
        AT.MinVecArg[4+ARGHEAD] = 1;
1,252✔
1440
        AT.MinVecArg[5+ARGHEAD] = 1;
1,252✔
1441
        AT.MinVecArg[6+ARGHEAD] = -3;
1,252✔
1442
        t = AT.FunArg;
1,252✔
1443
        *t++ = 4+ARGHEAD+FUNHEAD;
1,252✔
1444
        for ( i = 1; i < ARGHEAD; i++ ) *t++ = 0;
2,504✔
1445
        *t++ = 4+FUNHEAD;
1,252✔
1446
        *t++ = 0;
1,252✔
1447
        *t++ = FUNHEAD;
1,252✔
1448
        for ( i = 2; i < FUNHEAD; i++ ) *t++ = 0;
2,504✔
1449
        *t++ = 1; *t++ = 1; *t++ = 3;
1,252✔
1450

1451
#ifdef WITHMPI
1452
        AS.printflag = 0;
989✔
1453
#endif
1454

1455
        AT.comsym[0] = 8;
1,252✔
1456
        AT.comsym[1] = SYMBOL;
1,252✔
1457
        AT.comsym[2] = 4;
1,252✔
1458
        AT.comsym[3] = 0;
1,252✔
1459
        AT.comsym[4] = 1;
1,252✔
1460
        AT.comsym[5] = 1;
1,252✔
1461
        AT.comsym[6] = 1;
1,252✔
1462
        AT.comsym[7] = 3;
1,252✔
1463
        AT.comnum[0] = 4;
1,252✔
1464
        AT.comnum[1] = 1;
1,252✔
1465
        AT.comnum[2] = 1;
1,252✔
1466
        AT.comnum[3] = 3;
1,252✔
1467
        AT.comfun[0] = FUNHEAD+4;
1,252✔
1468
        AT.comfun[1] = FUNCTION;
1,252✔
1469
        AT.comfun[2] = FUNHEAD;
1,252✔
1470
        AT.comfun[3] = 0;
1,252✔
1471
#if FUNHEAD == 4
1472
        AT.comfun[4] = 0;
1473
#endif
1474
        AT.comfun[FUNHEAD+1] = 1;
1,252✔
1475
        AT.comfun[FUNHEAD+2] = 1;
1,252✔
1476
        AT.comfun[FUNHEAD+3] = 3;
1,252✔
1477
        AT.comind[0] = 7;
1,252✔
1478
        AT.comind[1] = INDEX;
1,252✔
1479
        AT.comind[2] = 3;
1,252✔
1480
        AT.comind[3] = 0;
1,252✔
1481
        AT.comind[4] = 1;
1,252✔
1482
        AT.comind[5] = 1;
1,252✔
1483
        AT.comind[6] = 3;
1,252✔
1484
        AT.locwildvalue[0] = SUBEXPRESSION;
1,252✔
1485
        AT.locwildvalue[1] = SUBEXPSIZE;
1,252✔
1486
        for ( i = 2; i < SUBEXPSIZE; i++ ) AT.locwildvalue[i] = 0;
5,008✔
1487
        AT.mulpat[0] = TYPEMULT;
1,252✔
1488
        AT.mulpat[1] = SUBEXPSIZE+3;
1,252✔
1489
        AT.mulpat[2] = 0;
1,252✔
1490
        AT.mulpat[3] = SUBEXPRESSION;
1,252✔
1491
        AT.mulpat[4] = SUBEXPSIZE;
1,252✔
1492
        AT.mulpat[5] = 0;
1,252✔
1493
        AT.mulpat[6] = 1;
1,252✔
1494
        for ( i = 7; i < SUBEXPSIZE+5; i++ ) AT.mulpat[i] = 0;
5,008✔
1495
        AT.proexp[0] = SUBEXPSIZE+4;
1,252✔
1496
        AT.proexp[1] = EXPRESSION;
1,252✔
1497
        AT.proexp[2] = SUBEXPSIZE;
1,252✔
1498
        AT.proexp[3] = -1;
1,252✔
1499
        AT.proexp[4] = 1;
1,252✔
1500
        for ( i = 5; i < SUBEXPSIZE+1; i++ ) AT.proexp[i] = 0;
2,504✔
1501
        AT.proexp[SUBEXPSIZE+1] = 1;
1,252✔
1502
        AT.proexp[SUBEXPSIZE+2] = 1;
1,252✔
1503
        AT.proexp[SUBEXPSIZE+3] = 3;
1,252✔
1504
        AT.proexp[SUBEXPSIZE+4] = 0;
1,252✔
1505
        AT.dummysubexp[0] = SUBEXPRESSION;
1,252✔
1506
        AT.dummysubexp[1] = SUBEXPSIZE+4;
1,252✔
1507
        for ( i = 2; i < SUBEXPSIZE; i++ ) AT.dummysubexp[i] = 0;
5,008✔
1508
        AT.dummysubexp[SUBEXPSIZE] = WILDDUMMY;
1,252✔
1509
        AT.dummysubexp[SUBEXPSIZE+1] = 4;
1,252✔
1510
        AT.dummysubexp[SUBEXPSIZE+2] = 0;
1,252✔
1511
        AT.dummysubexp[SUBEXPSIZE+3] = 0;
1,252✔
1512

1513
        AT.inprimelist = -1;
1,252✔
1514
        AT.sizeprimelist = 0;
1,252✔
1515
        AT.primelist = 0;
1,252✔
1516
        AT.LeaveNegative = 0;
1,252✔
1517
        AT.TrimPower = 0;
1,252✔
1518
        AN.SplitScratch = 0;
1,252✔
1519
        AN.SplitScratchSize = AN.InScratch = 0;
1,252✔
1520
        AN.SplitScratch1 = 0;
1,252✔
1521
        AN.SplitScratchSize1 = AN.InScratch1 = 0;
1,252✔
1522
        AN.idfunctionflag = 0;
1,252✔
1523
#endif
1524
        AO.OutputLine = AO.OutFill = BufferForOutput;
1,776✔
1525
        AO.FactorMode = 0;
1,776✔
1526
        C->Pointer = C->Buffer;
1,776✔
1527

1528
        AP.PreOut = 0;
1,776✔
1529
        AP.ComChar = AP.cComChar;
1,776✔
1530
        AC.cbufnum = AM.rbufnum;                /* Select the default compiler buffer */
1,776✔
1531
        AC.HideLevel = 0;
1,776✔
1532
        AP.PreAssignFlag = 0;
1,776✔
1533
        return(0);
1,776✔
1534
}
1535

1536
/*
1537
                 #] IniVars : 
1538
                 #[ Signal handlers :
1539
*/
1540
/*[28apr2004 mt]:*/
1541
#ifdef TRAPSIGNALS
1542

1543
static int exitInProgress = 0;
1544
static int trappedTerminate = 0;
1545

1546
/*INTSIGHANDLER : some systems require a signal handler to return an integer,
1547
  so define the macro INTSIGHANDLER if compiler fails:*/
1548
#ifdef INTSIGHANDLER
1549
static int onErrSig(int i)
1550
#else
1551
static VOID onErrSig(int i)
99✔
1552
#endif
1553
{
1554
        if (exitInProgress){
99✔
1555
                signal(i,SIG_DFL);/* Use default behaviour*/
×
1556
                raise (i);/*reproduce trapped signal*/
×
1557
#ifdef INTSIGHANDLER
1558
                return(i);
1559
#else
1560
                return;
×
1561
#endif
1562
        }
1563
        trappedTerminate = 1;
99✔
1564
        /*[13jul2005 mt]*//*TerminateImpl(-1) on signal is here:*/
UNCOV
1565
        Terminate(-1);
×
1566
}
1567

1568
#ifdef INTSIGHANDLER
1569
static VOID setNewSig(int i, int (*handler)(int))
1570
#else
1571
static VOID setNewSig(int i, void (*handler)(int))
26,640✔
1572
#endif
1573
{
1574
        if(! (i<NSIG) )/* Invalid signal -- see comments in the file */
26,640✔
1575
                return;
1576
        if ( signal(i,SIG_IGN) !=SIG_IGN)
23,088✔
1577
        /* if compiler fails here, try to define INTSIGHANDLER):*/
1578
                signal(i,handler);
23,088✔
1579
}
1580

1581
VOID setSignalHandlers(VOID)
1,776✔
1582
{
1583
        /* Reset various unrecoverable error signals:*/
1584
        setNewSig(SIGSEGV,onErrSig);
1,776✔
1585
        setNewSig(SIGFPE,onErrSig);
1,776✔
1586
        setNewSig(SIGILL,onErrSig);
1,776✔
1587
        setNewSig(SIGEMT,onErrSig);
1,776✔
1588
        setNewSig(SIGSYS,onErrSig);
1,776✔
1589
        setNewSig(SIGPIPE,onErrSig);
1,776✔
1590
        setNewSig(SIGLOST,onErrSig);
1,776✔
1591
        setNewSig(SIGXCPU,onErrSig);
1,776✔
1592
        setNewSig(SIGXFSZ,onErrSig);
1,776✔
1593

1594
        /* Reset interrupt signals:*/
1595
        setNewSig(SIGTERM,onErrSig);
1,776✔
1596
        setNewSig(SIGINT,onErrSig);
1,776✔
1597
        setNewSig(SIGQUIT,onErrSig);
1,776✔
1598
        setNewSig(SIGHUP,onErrSig);
1,776✔
1599
        setNewSig(SIGALRM,onErrSig);
1,776✔
1600
        setNewSig(SIGVTALRM,onErrSig);
1,776✔
1601
/*        setNewSig(SIGPROF,onErrSig); */  /* Why did Tentukov forbid profilers?? */
1602
}
1,776✔
1603

1604
#endif
1605
/*:[28apr2004 mt]*/
1606
/*
1607
                 #] Signal handlers : 
1608
                 #[ main :
1609
*/
1610

1611
#ifdef WITHPTHREADS
1612
ALLPRIVATES *ABdummy[10];
1613
#endif
1614

1615
int main(int argc, char **argv)
1,776✔
1616
{
1617
        int retval;
1,776✔
1618
        bzero((VOID *)(&A),sizeof(A)); /* make sure A is initialized at zero */
1,776✔
1619
        iniTools();
1,776✔
1620
#ifdef TRAPSIGNALS
1621
        setSignalHandlers();
1,776✔
1622
#endif
1623

1624
#ifdef WITHPTHREADS
1625
        AB = ABdummy;
524✔
1626
        StartHandleLock();
524✔
1627
        BeginIdentities();
524✔
1628
#else
1629
        AM.SumTime = TimeCPU(0);
1,252✔
1630
        TimeWallClock(0);
1,252✔
1631
#endif
1632

1633
#ifdef WITHMPI
1634
        if ( PF_Init(&argc,&argv) ) exit(-1);
989✔
1635
#endif
1636

1637
        StartFiles();
1,776✔
1638
        StartVariables();
1,776✔
1639
#ifdef WITHMPI
1640
        /*
1641
         * Here MesPrint() is ready. We turn on AS.printflag to print possible
1642
         * errors occurring on slaves in the initialization. With AS.printflag = -1
1643
         * MesPrint() does not use the synchronized output. This may lead broken
1644
         * texts in the output somewhat, but it is safer to implement in this way
1645
         * for the situation in which some of MesPrint() calls use MLOCK()-MUNLOCK()
1646
         * and some do not. In future if we set AS.printflag = 1 and modify the
1647
         * source code such that all MesPrint() calls are sandwiched by MLOCK()-
1648
         * MUNLOCK(), we need also to modify the code for the master to catch
1649
         * messages corresponding to MUNLOCK() calls at some point.
1650
         *
1651
         * AS.printflag will be set to 0 in IniVars() to prevent slaves from
1652
         * printing redundant errors in the preprocessor and compiler (e.g., syntax
1653
         * errors).
1654
         */
1655
        AS.printflag = -1;
989✔
1656
#endif
1657

1658
        if ( ( retval = DoTail(argc,(UBYTE **)argv) ) != 0 ) {
1,776✔
1659
                if ( retval > 0 ) Terminate(0);
×
1660
                else              Terminate(-1);
×
1661
        }
1662
        if ( DoSetups() ) Terminate(-2);
1,776✔
1663
#ifdef WITHMPI
1664
        /* It is messy if all errors in OpenInput() on slaves are printed. */
1665
        AS.printflag = 0;
989✔
1666
#endif
1667
        if ( OpenInput() ) Terminate(-3);
1,776✔
1668
#ifdef WITHMPI
1669
        AS.printflag = -1;
989✔
1670
#endif
1671
        if ( TryEnvironment() ) Terminate(-2);
1,776✔
1672
        if ( TryFileSetups() ) Terminate(-2);
1,776✔
1673
        if ( MakeSetupAllocs() ) Terminate(-2);
1,776✔
1674
        StartMore();
1,776✔
1675
        InitRecovery();
1,776✔
1676
        CheckRecoveryFile();
1,776✔
1677
        if ( AM.totalnumberofthreads == 0 ) AM.totalnumberofthreads = 1;
1,776✔
1678
        AS.MultiThreaded = 0;
1,776✔
1679
#ifdef WITHPTHREADS
1680
        if ( AM.totalnumberofthreads > 1 ) AS.MultiThreaded = 1;
524✔
1681
        ReserveTempFiles(1);
524✔
1682
        StartAllThreads(AM.totalnumberofthreads);
524✔
1683
        IniFbufs();
524✔
1684
#else
1685
        ReserveTempFiles(0);
1,252✔
1686
        IniFbuffer(AT.fbufnum);
1,252✔
1687
#endif
1688
        if ( !AM.FromStdin ) PrintHeader(1);
1,776✔
1689
        IniVars();
1,776✔
1690
        Globalize(1);
1,776✔
1691
#ifdef WITH_ALARM
1692
        if ( AM.TimeLimit > 0 ) alarm(AM.TimeLimit);
1,776✔
1693
#endif
1694
        TimeCPU(0);
1,776✔
1695
        TimeChildren(0);
1,776✔
1696
        TimeWallClock(0);
1,776✔
1697
        PreProcessor();
1,776✔
1698
        Terminate(0);
×
1699
        return(0);
1700
}
1701
/*
1702
                 #] main : 
1703
                 #[ CleanUp :
1704

1705
                if par < 0 we have to keep the storage file.
1706
                when par > 0 we ran into a .clear statement.
1707
                In that case we keep the zero level input and the log file.
1708

1709
*/
1710

1711
VOID CleanUp(WORD par)
1,776✔
1712
{
1713
        GETIDENTITY
524✔
1714
        int i;
1,776✔
1715

1716
        if ( FG.fname ) {
1,776✔
1717
        CleanUpSort(0);
1,776✔
1718
        for ( i = 0; i < 3; i++ ) {
8,880✔
1719
                if ( AR.Fscr[i].handle >= 0 ) {
5,328✔
1720
                        if ( AR.Fscr[i].name ) {
×
1721
/*
1722
                                If there are more threads referring to the same file
1723
                                only the one with the name is the owner of the file.
1724
*/
1725
                                CloseFile(AR.Fscr[i].handle);
×
1726
                                remove(AR.Fscr[i].name);
×
1727
                        }
1728
                        AR.Fscr[i].handle = - 1;
×
1729
                        AR.Fscr[i].POfill = 0;
×
1730
                }
1731
        }
1732
        if ( par > 0 ) {
1,776✔
1733
/*
1734
        Close all input levels above the lowest?
1735
*/
1736
        }
1,776✔
1737
        if ( AC.StoreHandle >= 0 && par <= 0 ) {
1,776✔
1738
#ifdef TRAPSIGNALS
1739
                if ( trappedTerminate ) { /* We don't throw .str if it has contents */
1,776✔
1740
                        POSITION pos;
96✔
1741
                        PUTZERO(pos);
96✔
1742
                        SeekFile(AC.StoreHandle,&pos,SEEK_END);
96✔
1743
                        if ( ISNOTZEROPOS(pos) ) {
96✔
1744
                                CloseFile(AC.StoreHandle);
7✔
1745
                                goto dontremove;
7✔
1746
                        }
1747
                }
1748
                CloseFile(AC.StoreHandle);
1,769✔
1749
                if ( par >= 0 || AR.StoreData.Handle < 0 || AM.ClearStore ) {
1,769✔
1750
                        remove(FG.fname);
1,769✔
1751
                }
1752
dontremove:;
×
1753
#else
1754
                CloseFile(AC.StoreHandle);
1755
                if ( par >= 0 || AR.StoreData.Handle < 0 || AM.ClearStore > 0 ) {
1756
                        remove(FG.fname);
1757
                }
1758
#endif
1759
        }
1760
        }
1761
        ClearSpectators(CLEARMODULE);
1,776✔
1762
/*
1763
        Remove recovery file on exit if everything went well
1764
*/
1765
        if ( par == 0 ) {
1,776✔
1766
                DeleteRecoveryFile();
1,680✔
1767
        }
1768
/*
1769
        Now the final message concerning the total time
1770
*/
1771
        if ( AC.LogHandle >= 0 && par <= 0 ) {
1,776✔
1772
                WORD lh = AC.LogHandle;
×
1773
                AC.LogHandle = -1;
×
1774
#ifdef WITHMPI
1775
                if ( PF.me == MASTER )  /* Only the master opened the real file. */
1776
#endif
1777
                CloseFile(lh);
×
1778
        }
1779
}
1,776✔
1780

1781
/*
1782
                 #] CleanUp : 
1783
                 #[ TerminateImpl :
1784
*/
1785

1786
static int firstterminate = 1;
1787

1788
VOID TerminateImpl(int errorcode, const char* file, int line, const char* function)
1,872✔
1789
{
1790
        if ( errorcode && firstterminate ) {
1,872✔
1791
                firstterminate = 0;
96✔
1792

1793
                MLOCK(ErrorMessageLock);
96✔
1794
#ifdef WITHPTHREADS
1795
                MesPrint("Program terminating in thread %w at &");
40✔
1796
#elif defined(WITHMPI)
1797
                MesPrint("Program terminating in process %w at &");
36✔
1798
#else
1799
                MesPrint("Program terminating at &");
20✔
1800
#endif
1801
                MesPrint("Terminate called from %s:%d (%s)", file, line, function);
96✔
1802

1803
#ifdef ENABLE_BACKTRACE
1804
                void *stack[64];
96✔
1805
                int stacksize, stop = 0;
96✔
1806
                stacksize = backtrace(stack, sizeof(stack)/sizeof(stack[0]));
96✔
1807

1808
                /* First check whether eu-addr2line is available */
1809
                if ( !system("command -v eu-addr2line > /dev/null 2>&1") ) {
96✔
NEW
1810
                        MesPrint("Backtrace:");
×
NEW
1811
                        for (int i = 0; i < stacksize && !stop; i++) {
×
NEW
1812
                                FILE *fp;
×
NEW
1813
                                char cmd[512];
×
1814
                                // Leave an initial space
NEW
1815
                                cmd[0] = ' ';
×
NEW
1816
                                MesPrint("%#%2d:%", i);
×
NEW
1817
                                snprintf(cmd+1, sizeof(cmd)-1, "eu-addr2line -s --pretty-print -f -i '%p' --pid=%d\n", stack[i], getpid());
×
NEW
1818
                                fp = popen(cmd+1, "r");
×
NEW
1819
                                while ( fgets(cmd+1, sizeof(cmd)-1, fp) != NULL ) {
×
NEW
1820
                                        MesPrint("%s", cmd);
×
1821
                                        /* Don't show functions lower than "main" (or thread equivalent) */
NEW
1822
                                        if ( strstr(cmd, " main ") || strstr(cmd, " RunThread ") || strstr(cmd, " RunSortBot ") ) {
×
NEW
1823
                                                stop = 1;
×
1824
                                        }
1825
                                }
NEW
1826
                                pclose(fp);
×
1827
                        }
1828
                }
1829
#ifdef LINUX
1830
                else if ( !system("command -v addr2line > /dev/null 2>&1") ) {
96✔
1831
                        /* Get the executable path. */
1832
                        char exe_path[PATH_MAX];
96✔
1833
                        {
1834
                                ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
96✔
1835
                                if ( len != -1 ) {
96✔
1836
                                        exe_path[len] = '\0';
96✔
1837
                                }
1838
                                else {
NEW
1839
                                        goto backtrace_fallback;
×
1840
                                }
1841
                        }
1842
                        /* Assume PIE binary and get the base address. */
1843
                        uintptr_t base_address = 0;
96✔
1844
                        {
1845
                                char line[256];
96✔
1846
                                FILE *maps = fopen("/proc/self/maps", "r");
96✔
1847
                                if ( !maps ) {
96✔
NEW
1848
                                        goto backtrace_fallback;
×
1849
                                }
1850
                                /* See the format used by nommu_region_show() in fs/proc/nommu.c of the Linux source. */
1851
                                if ( fgets(line, sizeof(line), maps) ) {
96✔
1852
                                        sscanf(line, "%" SCNxPTR "-", &base_address);
96✔
1853
                                }
1854
                                else {
NEW
1855
                                        fclose(maps);
×
NEW
1856
                                        goto backtrace_fallback;
×
1857
                                }
1858
                                fclose(maps);
96✔
1859
                        }
1860
                        char **strings;
96✔
1861
                        strings = backtrace_symbols(stack, stacksize);
96✔
1862
                        MesPrint("Backtrace:");
96✔
1863
                        for ( int i = 0; i < stacksize && !stop; i++ ) {
497✔
1864
                                FILE *fp;
401✔
1865
                                char cmd[PATH_MAX + 512];
401✔
1866
                                // Leave an initial space
1867
                                cmd[0] = ' ';
401✔
1868
                                uintptr_t addr = (uintptr_t)stack[i] - base_address;
401✔
1869
                                MesPrint("%#%2d:%", i);
401✔
1870
                                snprintf(cmd+1, sizeof(cmd)-1, "addr2line -e \"%s\" -i -p -s -f -C 0x%" PRIxPTR, exe_path, addr);
401✔
1871
                                fp = popen(cmd+1, "r");
401✔
1872
                                while ( fgets(cmd+1, sizeof(cmd)-1, fp) != NULL ) {
802✔
1873
                                        MesPrint("%s", cmd);
401✔
1874
                                        /* Don't show functions lower than "main" */
1875
                                        if ( strstr(cmd, " main ") || strstr(cmd, " RunThread ") || strstr(cmd, " RunSortBot ") ) {
401✔
1876
                                                stop = 1;
96✔
1877
                                        }
1878
                                }
1879
                                pclose(fp);
401✔
1880
                        }
1881
                        free(strings);
96✔
1882
                }
1883
#endif
1884
                else {
1885
                        /* eu-addr2line not found */
1886
#ifdef LINUX
NEW
1887
backtrace_fallback: ;
×
1888
#endif
NEW
1889
                        char **strings;
×
NEW
1890
                        strings = backtrace_symbols(stack, stacksize);
×
NEW
1891
                        MesPrint("Backtrace:");
×
NEW
1892
                        for ( int i = 0; i < stacksize && !stop; i++ ) {
×
NEW
1893
                                char *p = strings[i];
×
NEW
1894
                                while ( *p && *p != '(' ) p++;
×
NEW
1895
                                MesPrint("%#%2d: %s\n", i, p);
×
1896
                                /* Don't show functions lower than "main" (or thread equivalent) */
NEW
1897
                                if ( strstr(p, "(main+") || strstr(p, "(RunThread+") || strstr(p, "(RunSortBot+") ) {
×
NEW
1898
                                        stop = 1;
×
1899
                                }
1900
                        }
1901
#ifdef LINUX
NEW
1902
                        MesPrint("Please install addr2line or eu-addr2line for readable stack information.");
×
1903
#else
1904
                        MesPrint("Please install eu-addr2line for readable stack information.");
1905
#endif
NEW
1906
                        free(strings);
×
1907
                }
1908
#else
1909
                MesPrint("FORM compiled without backtrace support.");
1910
#endif
1911

1912
                MUNLOCK(ErrorMessageLock);
96✔
1913

1914
                Crash();
96✔
1915
        }
1916
#ifdef TRAPSIGNALS
1917
        exitInProgress=1;
1,776✔
1918
#endif
1919
#ifdef WITHEXTERNALCHANNEL
1920
/*
1921
        This function can be called from the error handler, so it is better to
1922
        clean up all started processes before any activity:
1923
*/
1924
        closeAllExternalChannels();
1,776✔
1925
        AX.currentExternalChannel=0;
1,776✔
1926
        /*[08may2006 mt]:*/
1927
        AX.killSignal=SIGKILL;
1,776✔
1928
        AX.killWholeGroup=1;
1,776✔
1929
        AX.daemonize=1;
1,776✔
1930
        /*:[08may2006 mt]*/
1931
        if(AX.currentPrompt){
1,776✔
1932
                M_free(AX.currentPrompt,"external channel prompt");
7✔
1933
                AX.currentPrompt=0;
7✔
1934
        }
1935
        /*[08may2006 mt]:*/
1936
        if(AX.shellname){
1,776✔
1937
                M_free(AX.shellname,"external channel shellname");
1,776✔
1938
                AX.shellname=0;
1,776✔
1939
        }
1940
        if(AX.stderrname){
1,776✔
1941
                M_free(AX.stderrname,"external channel stderrname");
1,776✔
1942
                AX.stderrname=0;
1,776✔
1943
        }
1944
        /*:[08may2006 mt]*/
1945
#endif
1946
#ifdef WITHPTHREADS
1947
        if ( !WhoAmI() && !errorcode ) {
524✔
1948
                TerminateAllThreads();
484✔
1949
        }
1950
#endif
1951
        if ( AC.FinalStats ) {
1,776✔
1952
                if ( AM.PrintTotalSize ) {
1,765✔
1953
                        MesPrint("Max. space for expressions: %19p bytes",&(AS.MaxExprSize));
×
1954
                }
1955
                PrintRunningTime();
1,765✔
1956
        }
1957
#ifdef WITHMPI
1958
        if ( AM.HoldFlag && PF.me == MASTER ) {
989✔
1959
                WriteFile(AM.StdOut,(UBYTE *)("Hit any key "),12);
1960
                PF_FlushStdOutBuffer();
1961
                getchar();
1962
        }
1963
#else
1964
        if ( AM.HoldFlag ) {
787✔
1965
                WriteFile(AM.StdOut,(UBYTE *)("Hit any key "),12);
1966
                getchar();
1967
        }
1968
#endif
1969
#ifdef WITHMPI
1970
        PF_Terminate(errorcode);
989✔
1971
#endif
1972
        CleanUp(errorcode);
1,776✔
1973
        M_print();
1,776✔
1974
#ifdef VMS
1975
        P_term(errorcode? 0: 1);
1976
#else
1977
        P_term(errorcode);
1,776✔
1978
#endif
1979
}
1980

1981
/*
1982
                 #] TerminateImpl : 
1983
                 #[ PrintRunningTime :
1984
*/
1985

1986
VOID PrintRunningTime(VOID)
1,821✔
1987
{
1988
#if (defined(WITHPTHREADS) && (defined(WITHPOSIXCLOCK) || defined(WINDOWS))) || defined(WITHMPI)
1989
        LONG mastertime;
1,552✔
1990
        LONG workertime;
1,552✔
1991
        LONG wallclocktime;
1,552✔
1992
        LONG totaltime;
1,552✔
1993
#if defined(WITHPTHREADS)
1994
        if ( AB[0] != 0 ) {
536✔
1995
                workertime = GetWorkerTimes();
536✔
1996
#else
1997
        workertime = PF_GetSlaveTimes();  /* must be called on all processors */
1,016✔
1998
        if ( PF.me == MASTER ) {
1,016✔
1999
#endif
2000
                mastertime = AM.SumTime + TimeCPU(1);
790✔
2001
                wallclocktime = TimeWallClock(1);
790✔
2002
                totaltime = mastertime+workertime;
790✔
2003
                if ( !AM.silent ) {
790✔
2004
                MesPrint("  %l.%2i sec + %l.%2i sec: %l.%2i sec out of %l.%2i sec",
790✔
2005
                        mastertime/1000,(WORD)((mastertime%1000)/10),
790✔
2006
                        workertime/1000,(WORD)((workertime%1000)/10),
790✔
2007
                        totaltime/1000,(WORD)((totaltime%1000)/10),
790✔
2008
                        wallclocktime/100,(WORD)(wallclocktime%100));
790✔
2009
                }
2010
        }
2011
#else
2012
        LONG mastertime = AM.SumTime + TimeCPU(1);
269✔
2013
        LONG wallclocktime = TimeWallClock(1);
269✔
2014
        if ( !AM.silent ) {
269✔
2015
        MesPrint("  %l.%2i sec out of %l.%2i sec",
269✔
2016
                mastertime/1000,(WORD)((mastertime%1000)/10),
269✔
2017
                wallclocktime/100,(WORD)(wallclocktime%100));
269✔
2018
        }
2019
#endif
2020
}
1,821✔
2021

2022
/*
2023
                 #] PrintRunningTime : 
2024
                 #[ GetRunningTime :
2025
*/
2026

2027
LONG GetRunningTime(VOID)
1,776✔
2028
{
2029
#if defined(WITHPTHREADS) && (defined(WITHPOSIXCLOCK) || defined(WINDOWS))
2030
        LONG mastertime;
524✔
2031
        if ( AB[0] != 0 ) {
524✔
2032
/* 
2033
#if ( defined(APPLE64) || defined(APPLE32) )
2034
                mastertime = AM.SumTime + TimeCPU(1);
2035
                return(mastertime);
2036
#else
2037
*/
2038
                LONG workertime = GetWorkerTimes();
524✔
2039
                mastertime = AM.SumTime + TimeCPU(1);
524✔
2040
                return(mastertime+workertime);
524✔
2041
/*
2042
#endif
2043
*/
2044
        }
2045
        else {
2046
                return(AM.SumTime + TimeCPU(1));
2047
        }
2048
#elif defined(WITHMPI)
2049
        LONG mastertime, t = 0;
989✔
2050
        LONG workertime = PF_GetSlaveTimes();  /* must be called on all processors */
989✔
2051
        if ( PF.me == MASTER ) {
989✔
2052
                mastertime = AM.SumTime + TimeCPU(1);
248✔
2053
                t = mastertime + workertime;
248✔
2054
        }
2055
        return PF_BroadcastNumber(t);  /* must be called on all processors */
989✔
2056
#else
2057
        return(AM.SumTime + TimeCPU(1));
263✔
2058
#endif
2059
}
2060

2061
/*
2062
                 #] GetRunningTime : 
2063
*/
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc