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

tueda / form / 12516247166

27 Dec 2024 12:47PM UTC coverage: 50.678% (-0.05%) from 50.724%
12516247166

push

github

tueda
debug

42035 of 82946 relevant lines covered (50.68%)

1401654.15 hits per line

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

3.57
/sources/checkpoint.c
1
/*
2
          #[ Explanations :
3
*/
4
/** @file checkpoint.c
5
 * 
6
 *  Contains all functions that deal with the recovery mechanism controlled and
7
 *  activated by the On Checkpoint switch.
8
 *
9
 *  The main function are DoCheckpoint, DoRecovery, and DoSnapshot. If the
10
 *  checkpoints are activated DoCheckpoint is called every time a module is
11
 *  finished executing. If the conditions for the creation of a recovery
12
 *  snapshot are met DoCheckpoint calls DoSnapshot. DoRecovery is called once
13
 *  when FORM starts up with the command line argument -R. Most of the other
14
 *  code contains debugging facilities that are only compiled if the macro
15
 *  PRINTDEBUG is defined.
16
 *
17
 *  The recovery mechanism is atomic, i.e. only if everything went well, the
18
 *  final recovery file is created (and the older one overwritten) in a single
19
 *  step (copying). If some errors occur, a warning is issued and the program
20
 *  continues without having created a new recovery file. The only situation in
21
 *  which the creation of the recovery data leads to a termination of the
22
 *  running program is if not enough disk or memory space is left.
23
 *
24
 *  For ParFORM each slave creates its own recovery file, sends it to the 
25
 *  master and then it deletes the recovery file. The master stores all the 
26
 *  recovery files and on recovery it feeds these files to the slaves. It is
27
 *  nearly impossible to recover after some MPI fault so ParFORM terminates 
28
 *  on any recovery failure.
29
 *
30
 *  DoRecovery and DoSnapshot do the loading and saving of the recovery data,
31
 *  respectively. Every change in one functions needs to be accompanied by the
32
 *  appropriate change in the other function. The structure of both functions is
33
 *  quite similar. They handle the relevant global structs one after the other
34
 *  and then care about the copying of the hide and scratch files.
35
 *
36
 *  The names of the recovery, scratch and hide files are hard-coded in the
37
 *  variables in fold "filenames and system commands".
38
 *
39
 *  If the global structs AM,AP,AC,AR are changed, DoRecovery and DoSnapshot
40
 *  usually also have to be changed. Some structs are read/written as a whole
41
 *  (AP,AC), some are read/written only partly as a selection of their
42
 *  individual elements (AM,AR). If AM or AR have been changed by adding or
43
 *  removing an element that is important for the runtime status, then the
44
 *  reading/writing statements have to be added to or removed from DoRecovery
45
 *  and DoSnapshot. If AP or AC are changed, then for non-pointer variables (in
46
 *  the case of a struct it also means that none of its elements is a pointer)
47
 *  nothing has to be changed in the functions here. If pointers are involved,
48
 *  extra code has to be added (or removed). See the comments of DoRecovery and
49
 *  DoSnapshot.
50
 *
51
 */
52
/*
53
          #] Explanations : 
54
          #[ License :
55
 *
56
 *   Copyright (C) 1984-2023 J.A.M. Vermaseren
57
 *   When using this file you are requested to refer to the publication
58
 *   J.A.M.Vermaseren "New features of FORM" math-ph/0010025
59
 *   This is considered a matter of courtesy as the development was paid
60
 *   for by FOM the Dutch physics granting agency and we would like to
61
 *   be able to track its scientific use to convince FOM of its value
62
 *   for the community.
63
 *
64
 *   This file is part of FORM.
65
 *
66
 *   FORM is free software: you can redistribute it and/or modify it under the
67
 *   terms of the GNU General Public License as published by the Free Software
68
 *   Foundation, either version 3 of the License, or (at your option) any later
69
 *   version.
70
 *
71
 *   FORM is distributed in the hope that it will be useful, but WITHOUT ANY
72
 *   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
73
 *   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
74
 *   details.
75
 *
76
 *   You should have received a copy of the GNU General Public License along
77
 *   with FORM.  If not, see <http://www.gnu.org/licenses/>.
78
 */
79
/*
80
          #] License : 
81
          #[ Includes :
82
*/
83

84
#include "form3.h"
85

86
#include <errno.h>
87

88
/*
89
#define PRINTDEBUG
90
*/
91

92
/*
93
#define PRINTTIMEMARKS
94
*/
95

96
/*
97
          #] Includes : 
98
          #[ filenames and system commands :
99
*/
100

101
/**
102
 *  BaseName of recovery files
103
 */
104
#ifdef WITHMPI
105
#define BASENAME_FMT "%c%04dFORMrecv"
106
/**
107
 * The basenames for ParFORM will be created from BASENAME_FMT by means of 
108
 * sprintf(BaseName,BASENAME_FMT,(PF.me == MASTER)?'m':'s',PF.me);
109
 * in InitRecovery(). Here just reserve the space:
110
 */
111
static char BaseName[] = BASENAME_FMT;
112
#else
113
static char *BaseName = "FORMrecv";
114
#endif
115
/**
116
 *  filename for the recovery file
117
 */
118
static char *recoveryfile = 0;
119
/**
120
 *  filename for the intermediate recovery file. only if the write is
121
 *  completely successful, this file will be moved/renamed to the one
122
 *  named by recoveryfile. this offers atomicity for the snapshot generation.
123
 */
124
static char *intermedfile = 0;
125
/**
126
 *  filename of sort file copy
127
 */
128
static char *sortfile = 0;
129
/**
130
 *  filename of hide file copy
131
 */
132
static char *hidefile = 0;
133
/**
134
 *  filename of store file copy
135
 */
136
static char *storefile = 0;
137

138
/**
139
 *  >0 if at least once the respective file has been created.
140
 *  Checked by DeleteRecoveryFile().
141
 */
142
static int done_snapshot = 0;
143

144
#ifdef WITHMPI
145
/**
146
 *  The position at which BASENAME_FMT should be applied.
147
 *  Initialized in InitRecovery().
148
 */
149
static int PF_fmt_pos;
150

151
/**
152
 *  Returns the contents of recoveryfile or intermedfile but with the renaming
153
 *  specified by the arguments.
154
 */
155
static const char *PF_recoveryfile(char prefix, int id, int intermed)
156
{
157
        /*
158
         * Assume that InitRecovery() has been already called, namely
159
         * recoveryfile, intermedfile and PF_fmt_pos are already initialized.
160
         */
161
        static char *tmp_recovery = NULL;
162
        static char *tmp_intermed  = NULL;
163
        char *tmp, c;
164
        if ( tmp_recovery == NULL ) {
165
                if ( PF.numtasks > 9999 ) {  /* see BASENAME_FMT */
166
                        MesPrint("Checkpoint: too many number of processors.");
167
                        Terminate(-1);
168
                }
169
                tmp_recovery = (char *)Malloc1(strlen(recoveryfile) + strlen(intermedfile) + 2, "PF_recoveryfile");
170
                tmp_intermed = tmp_recovery + strlen(recoveryfile) + 1;
171
                strcpy(tmp_recovery, recoveryfile);
172
                strcpy(tmp_intermed, intermedfile);
173
        }
174
        tmp = intermed ? tmp_intermed : tmp_recovery;
175
        c = tmp[PF_fmt_pos + 13];  /* The magic number 13 comes from BASENAME_FMT. */
176
        sprintf(tmp + PF_fmt_pos, BASENAME_FMT, prefix, id);
177
        tmp[PF_fmt_pos + 13] = c;
178
        return tmp;
179
}
180
#endif
181

182
/*
183
          #] filenames and system commands : 
184
          #[ CheckRecoveryFile :
185
*/
186

187
/**
188
 *  Checks whether a snapshot/recovery file exists.
189
 *  Returns 1 if it exists, 0 otherwise.
190
 */
191
#ifdef WITHMPI
192

193
/**
194
 * The master has all the recovery files. It checks whether these files
195
 * exist and sends proper files to slaves. On any error PF_CheckRecoveryFile()
196
 * returns -1 which leads to the program termination.
197
 */
198
static int PF_CheckRecoveryFile()
1,041✔
199
{
200
        int i,ret=0;
1,041✔
201
        FILE *fd;
1,041✔
202
        /* Check if the recovery file for the master exists. */
203
        if ( PF.me == MASTER ) {
1,041✔
204
                if ( (fd = fopen(recoveryfile, "r")) ) {
261✔
205
                        fclose(fd);
206
                        PF_BroadcastNumber(1);
207
                }
208
                else {
209
                        PF_BroadcastNumber(0);
261✔
210
                        return 0;
261✔
211
                }
212
        }
213
        else {
214
                if ( !PF_BroadcastNumber(0) )
780✔
215
                        return 0;
216
        }
217
        /* Now the main part. */
218
        if (PF.me == MASTER){
219
                /*We have to have recovery files for the master and all the slaves:*/
220
                for(i=1; i<PF.numtasks;i++){
221
                        const char *tmpnam = PF_recoveryfile('m', i, 0);
222
                        if ( (fd = fopen(tmpnam, "r")) )
223
                                fclose(fd);
224
                        else
225
                                break;
226
                }/*for(i=0; i<PF.numtasks;i++)*/
227
                if(i!=PF.numtasks){/*some files are absent*/
228
                        int j;
229
                        /*Send all slaves failure*/
230
                        for(j=1; j<PF.numtasks;j++){
231
                                ret=PF_SendFile(j, NULL);
232
                                if(ret<0)
233
                                        return(-1);
234
                        }
235
                        if(i==0)
236
                                return(0);/*Ok, no recovery files at all.*/
237
                        /*The master recovery file exists but some slave files are absent*/
238
                        MesPrint("The file %s exists but some of the slave recovery files are absent.",
239
                                                        RecoveryFilename());
240
                        return(-1);
241
                }/*if(i!=PF.numtasks)*/
242
                /*All the files are here.*/
243
                /*Send all slaves success and files:*/
244
                for(i=1; i<PF.numtasks;i++){
245
                        const char *tmpnam = PF_recoveryfile('m', i, 0);
246
                        fd = fopen(tmpnam, "r");
247
                        ret=PF_SendFile(i, fd);/*if fd==NULL, PF_SendFile seds to a slave the failure tag*/
248
                        if(fd == NULL)
249
                                return(-1);
250
                        else
251
                                fclose(fd);
252
                        if(ret<0)
253
                                return(-1);
254
                }/*for(i=0; i<PF.numtasks;i++)*/
255
                return(1);                
256
        }/*if (PF.me == MASTER)*/
257
        /*Slave:*/
258
        /*Get the answer from the master:*/
259
        fd=fopen(recoveryfile,"w");
260
        if(fd == NULL) {
261
                MesPrint("Failed to open %s in write mode in process %w", recoveryfile);
262
                return(-1);
263
        }
264
        ret=PF_RecvFile(MASTER,fd);
265
        if(ret<0)
266
                return(-1);
267
        fclose(fd);
268
        if(ret==0){
269
                /*Nothing is found by the master*/
270
                remove(recoveryfile);
271
                return(0);
272
        }
273
        /*Recovery file is successfully transferred*/
274
        return(1);
275
}
276
#endif
277

278
int CheckRecoveryFile(VOID)
1,903✔
279
{
280
        int ret = 0;
1,903✔
281
#ifdef WITHMPI
282
        ret = PF_CheckRecoveryFile();
1,041✔
283
#else
284
        FILE *fd;
862✔
285
        if ( (fd = fopen(recoveryfile, "r")) ) {
862✔
286
                fclose(fd);
287
                ret = 1;
288
        }
289
#endif
290
        if ( ret < 0 ){/*In ParFORM CheckRecoveryFile() may return a fatal error.*/
1,903✔
291
                MesPrint("Fail checking recovery file");
292
                Terminate(-1);
293
        }
294
        else if  ( ret > 0 ) {
1,903✔
295
                if ( AC.CheckpointFlag != -1 ) {
×
296
                        /* recovery file exists but recovery option is not given */
297
#ifdef WITHMPI
298
                        if ( PF.me == MASTER ) {
299
#endif
300
                        MesPrint("The recovery file %s exists, but the recovery option -R has not been given!", RecoveryFilename());
×
301
                        MesPrint("FORM will be terminated to avoid unintentional loss of data.");
×
302
                        MesPrint("Delete the recovery file manually, if you want to start FORM without recovery.");
×
303
#ifdef WITHMPI
304
                        }
305
                        if(PF.me != MASTER)
306
                                remove(RecoveryFilename());
307
#endif
308
                        Terminate(-1);
×
309
                }
310
        }
311
        else {
312
                if ( AC.CheckpointFlag == -1 ) {
1,903✔
313
                        /* recovery option given but recovery file does not exist */
314
#ifdef WITHMPI
315
                        if ( PF.me == MASTER )
316
#endif
317
                        MesPrint("Option -R for recovery has been given, but the recovery file %s does not exist!", RecoveryFilename());
×
318
                        Terminate(-1);
×
319
                }
320
        }
321
        return(ret);
1,903✔
322
}
323

324
/*
325
          #] CheckRecoveryFile : 
326
          #[ DeleteRecoveryFile :
327
*/
328

329
/**
330
 *  Deletes the recovery files. It is called by CleanUp() in the case of a
331
 *  successful completion.
332
 */
333
void DeleteRecoveryFile(VOID)
×
334
{
335
        if ( done_snapshot ) {
×
336
                remove(recoveryfile);
×
337
#ifdef WITHMPI
338
                if( PF.me == MASTER){
339
                        int i;
340
                        for(i=1; i<PF.numtasks;i++){
341
                                const char *tmpnam = PF_recoveryfile('m', i, 0);
342
                                remove(tmpnam);
343
                        }/*for(i=1; i<PF.numtasks;i++)*/
344
                        remove(storefile);
345
                        remove(sortfile);
346
                        remove(hidefile);
347
                }/*if( PF.me == MASTER)*/
348
#else
349
                remove(storefile);
350
                remove(sortfile);
351
                remove(hidefile);
352
#endif
353
        }
354
}
×
355

356
/*
357
          #] DeleteRecoveryFile : 
358
          #[ RecoveryFilename :
359
*/
360

361
/**
362
 *  Returns pointer to recovery filename. 
363
 */
364
char *RecoveryFilename(VOID)
×
365
{
366
        return(recoveryfile);
×
367
}
368

369
/*
370
          #] RecoveryFilename : 
371
          #[ InitRecovery :
372
*/
373

374
/**
375
 *  Utility function for InitRecovery().
376
 */
377
static char *InitName(char *str, char *ext)
9,515✔
378
{
379
        char *s, *d = str;
9,515✔
380
        if ( AM.TempDir ) {
9,515✔
381
                s = (char*)AM.TempDir;
382
                while ( *s ) { *d++ = *s++; }
×
383
                *d++ = SEPARATOR;
×
384
        }
385
        s = BaseName;
4,310✔
386
        while ( *s ) { *d++ = *s++; }
111,660✔
387
        *d++ = '.';
9,515✔
388
        s = ext;
9,515✔
389
        while ( *s ) { *d++ = *s++; }
38,060✔
390
        *d++ = 0;
9,515✔
391
        return d;
9,515✔
392
}
393

394
/**
395
 *  Sets up the strings for the filenames of the recovery files.
396
 *  This functions should only be called once to avoid memory leaks and after
397
 *  AM.TempDir has been initialized.
398
 */
399
void InitRecovery(VOID)
1,903✔
400
{
401
        int lenpath = AM.TempDir ? strlen((char*)AM.TempDir)+1 : 0;
1,903✔
402
#ifdef WITHMPI
403
        sprintf(BaseName,BASENAME_FMT,(PF.me == MASTER)?'m':'s',PF.me);
1,041✔
404
        /*Now BaseName has a form ?XXXXFORMrecv where ? == 'm' for master and 's' for slave,
405
                XXXX is a zero - padded PF.me*/
406
        PF_fmt_pos = lenpath;
1,041✔
407
#endif        
408
        recoveryfile = (char*)Malloc1(5*(lenpath+strlen(BaseName)+4+1),"InitRecovery");
1,903✔
409
        intermedfile = InitName(recoveryfile, "tmp");
1,903✔
410
        sortfile     = InitName(intermedfile, "XXX");
1,903✔
411
        hidefile     = InitName(sortfile, "out");
1,903✔
412
        storefile    = InitName(hidefile, "hid");
1,903✔
413
                       InitName(storefile, "str");
1,903✔
414
}
1,903✔
415

416
/*
417
          #] InitRecovery : 
418
          #[ Debugging :
419
*/
420

421
#ifdef PRINTDEBUG
422

423
void print_BYTE(void *p)
424
{
425
        UBYTE h = (UBYTE)(*((UBYTE*)p) >> 4);
426
        UBYTE l = (UBYTE)(*((UBYTE*)p) & 0x0F);
427
        if ( h > 9 ) h += 55; else h += 48;
428
        if ( l > 9 ) l += 55; else l += 48;
429
        printf("%c%c ", h, l);
430
}
431

432
static void print_STR(UBYTE *p)
433
{
434
        if ( p ) {
435
                MesPrint("%s", (char*)p);
436
        }
437
        else {
438
                MesPrint("NULL");
439
        }
440
}
441

442
static void print_WORDB(WORD *buf, WORD *top)
443
{
444
        LONG size = top-buf;
445
        int i;
446
        while ( size > 0 ) {
447
                if ( size > MAXPOSITIVE ) i = MAXPOSITIVE;
448
                else i = size;
449
                size -= i;
450
                MesPrint("%a",i,buf);
451
                buf += i;
452
        }
453
}
454

455
static void print_VOIDP(void *p, size_t size)
456
{
457
        int i;
458
        if ( p ) {
459
                while ( size > 0 ) {
460
                        if ( size > MAXPOSITIVE ) i = MAXPOSITIVE;
461
                        else i = size;
462
                        size -= i;
463
                        MesPrint("%b",i,(UBYTE *)p);
464
                        p = ((UBYTE *)p)+i;
465
                }
466
        }
467
        else {
468
                MesPrint("NULL");
469
        }
470
}
471

472
static void print_CHARS(UBYTE *p, size_t size)
473
{
474
        int i;
475
        while ( size > 0 ) {
476
                if ( size > MAXPOSITIVE ) i = MAXPOSITIVE;
477
                else i = size;
478
                size -= i;
479
                MesPrint("%C",i,(char *)p);
480
                p += i;
481
        }
482
}
483

484
static void print_WORDV(WORD *p, size_t size)
485
{
486
        int i;
487
        if ( p ) {
488
                while ( size > 0 ) {
489
                        if ( size > MAXPOSITIVE ) i = MAXPOSITIVE;
490
                        else i = size;
491
                        size -= i;
492
                        MesPrint("%a",i,p);
493
                        p += i;
494
                }
495
        }
496
        else {
497
                MesPrint("NULL");
498
        }
499
}
500

501
static void print_INTV(int *p, size_t size)
502
{
503
        int iarray[8];
504
        WORD i = 0;
505
        if ( p ) {
506
                while ( size > 0 ) {
507
                        if ( i >= 8 ) {
508
                                MesPrint("%I",i,iarray);
509
                                i = 0;
510
                        }
511
                        iarray[i++] = *p++;
512
                        size--;
513
                }
514
                if ( i > 0 ) MesPrint("%I",i,iarray);
515
        }
516
        else {
517
                MesPrint("NULL");
518
        }
519
}
520

521
static void print_LONGV(LONG *p, size_t size)
522
{
523
        LONG larray[8];
524
        WORD i = 0;
525
        if ( p ) {
526
                while ( size > 0 ) {
527
                        if ( i >= 8 ) {
528
                                MesPrint("%I",i,larray);
529
                                i = 0;
530
                        }
531
                        larray[i++] = *p++;
532
                        size--;
533
                }
534
                if ( i > 0 ) MesPrint("%I",i,larray);
535
        }
536
        else {
537
                MesPrint("NULL");
538
        }
539
}
540

541
static void print_PRELOAD(PRELOAD *l)
542
{
543
        if ( l->size ) {
544
                print_CHARS(l->buffer, l->size);
545
        }
546
        MesPrint("%ld", l->size);
547
}
548

549
static void print_PREVAR(PREVAR *l)
550
{
551
        MesPrint("%s", l->name);
552
        print_STR(l->value);
553
        if ( l->nargs ) print_STR(l->argnames);
554
        MesPrint("%d", l->nargs);
555
        MesPrint("%d", l->wildarg);
556
}
557

558
static void print_DOLLARS(DOLLARS l)
559
{
560
        print_VOIDP(l->where, l->size);
561
        MesPrint("%ld", l->size);
562
        MesPrint("%ld", l->name);
563
        MesPrint("%s", AC.dollarnames->namebuffer+l->name);
564
        MesPrint("%d", l->type);
565
        MesPrint("%d", l->node);
566
        MesPrint("%d", l->index);
567
        MesPrint("%d", l->zero);
568
        MesPrint("%d", l->numdummies);
569
        MesPrint("%d", l->nfactors);
570
}
571

572
static void print_LIST(LIST *l)
573
{
574
        print_VOIDP(l->lijst, l->size);
575
        MesPrint("%s", l->message);
576
        MesPrint("%d", l->num);
577
        MesPrint("%d", l->maxnum);
578
        MesPrint("%d", l->size);
579
        MesPrint("%d", l->numglobal);
580
        MesPrint("%d", l->numtemp);
581
        MesPrint("%d", l->numclear);
582
}
583

584
static void print_DOLOOP(DOLOOP *l)
585
{
586
        print_PRELOAD(&(l->p));
587
        print_STR(l->name);
588
        if ( l->type != NUMERICALLOOP ) {
589
                print_STR(l->vars);
590
        }
591
        print_STR(l->contents);
592
        if ( l->type != LISTEDLOOP && l->type != NUMERICALLOOP ) {
593
                print_STR(l->dollarname);
594
        }
595
        MesPrint("%l", l->startlinenumber);
596
        MesPrint("%l", l->firstnum);
597
        MesPrint("%l", l->lastnum);
598
        MesPrint("%l", l->incnum);
599
        MesPrint("%d", l->type);
600
        MesPrint("%d", l->NoShowInput);
601
        MesPrint("%d", l->errorsinloop);
602
        MesPrint("%d", l->firstloopcall);
603
}
604

605
static void print_PROCEDURE(PROCEDURE *l)
606
{
607
        if ( l->loadmode != 1 ) {
608
                print_PRELOAD(&(l->p));
609
        }
610
        print_STR(l->name);
611
        MesPrint("%d", l->loadmode);
612
}
613

614
static void print_NAMETREE(NAMETREE *t)
615
{
616
        int i;
617
        for ( i=0; i<t->nodefill; ++i ) {
618
                MesPrint("%l %d %d %d %d %d %d\n", t->namenode[i].name,
619
                         t->namenode[i].parent, t->namenode[i].left, t->namenode[i].right,
620
                         t->namenode[i].balance, t->namenode[i].type, t->namenode[i].number );
621
        }
622
        print_CHARS(t->namebuffer, t->namefill);
623
        MesPrint("%l", t->namesize);
624
        MesPrint("%l", t->namefill);
625
        MesPrint("%l", t->nodesize);
626
        MesPrint("%l", t->nodefill);
627
        MesPrint("%l", t->oldnamefill);
628
        MesPrint("%l", t->oldnodefill);
629
        MesPrint("%l", t->globalnamefill);
630
        MesPrint("%l", t->globalnodefill);
631
        MesPrint("%l", t->clearnamefill);
632
        MesPrint("%l", t->clearnodefill);
633
        MesPrint("%d", t->headnode);
634
}
635

636
void print_CBUF(CBUF *c)
637
{
638
        int i;
639
        print_WORDV(c->Buffer, c->BufferSize);
640
        /*
641
        MesPrint("%x", c->Buffer);
642
        MesPrint("%x", c->lhs);
643
        MesPrint("%x", c->rhs);
644
        */
645
        for ( i=0; i<c->numlhs; ++i ) {
646
                if ( c->lhs[i]) MesPrint("%d", *(c->lhs[i]));
647
        }
648
        for ( i=0; i<c->numrhs; ++i ) {
649
                if ( c->rhs[i]) MesPrint("%d", *(c->rhs[i]));
650
        }
651
        MesPrint("%l", *c->CanCommu);
652
        MesPrint("%l", *c->NumTerms);
653
        MesPrint("%d", *c->numdum);
654
        for ( i=0; i<c->MaxTreeSize; ++i ) {
655
                MesPrint("%d %d %d %d %d", c->boomlijst[i].parent, c->boomlijst[i].left, c->boomlijst[i].right,
656
                                c->boomlijst[i].value, c->boomlijst[i].blnce);
657
        }
658
}
659

660
static void print_STREAM(STREAM *t)
661
{
662
        print_CHARS(t->buffer, t->inbuffer);
663
        MesPrint("%l", (LONG)(t->pointer-t->buffer));
664
        print_STR(t->FoldName);
665
        print_STR(t->name);
666
        if ( t->type == PREVARSTREAM || t->type == DOLLARSTREAM ) {
667
                print_STR(t->pname);
668
        }
669
        MesPrint("%l", (LONG)t->fileposition);
670
        MesPrint("%l", (LONG)t->linenumber);
671
        MesPrint("%l", (LONG)t->prevline);
672
        MesPrint("%l", t->buffersize);
673
        MesPrint("%l", t->bufferposition);
674
        MesPrint("%l", t->inbuffer);
675
        MesPrint("%d", t->previous);
676
        MesPrint("%d", t->handle);
677
        switch ( t->type ) {
678
                case FILESTREAM: MesPrint("%d == FILESTREAM", t->type); break;
679
                case PREVARSTREAM: MesPrint("%d == PREVARSTREAM", t->type); break;
680
                case PREREADSTREAM: MesPrint("%d == PREREADSTREAM", t->type); break;
681
                case PIPESTREAM: MesPrint("%d == PIPESTREAM", t->type); break;
682
                case PRECALCSTREAM: MesPrint("%d == PRECALCSTREAM", t->type); break;
683
                case DOLLARSTREAM: MesPrint("%d == DOLLARSTREAM", t->type); break;
684
                case PREREADSTREAM2: MesPrint("%d == PREREADSTREAM2", t->type); break;
685
                case EXTERNALCHANNELSTREAM: MesPrint("%d == EXTERNALCHANNELSTREAM", t->type); break;
686
                case PREREADSTREAM3: MesPrint("%d == PREREADSTREAM3", t->type); break;
687
                default: MesPrint("%d == UNKNOWN", t->type);
688
        }
689
}
690

691
static void print_M()
692
{
693
        MesPrint("%%%% M_const");
694
        MesPrint("%d", *AM.gcmod);
695
        MesPrint("%d", *AM.gpowmod);
696
        print_STR(AM.TempDir);
697
        print_STR(AM.TempSortDir);
698
        print_STR(AM.IncDir);
699
        print_STR(AM.InputFileName);
700
        print_STR(AM.LogFileName);
701
        print_STR(AM.OutBuffer);
702
        print_STR(AM.Path);
703
        print_STR(AM.SetupDir);
704
        print_STR(AM.SetupFile);
705
        MesPrint("--MARK  1");
706
        MesPrint("%l", (LONG)BASEPOSITION(AM.zeropos));
707
#ifdef WITHPTHREADS
708
        MesPrint("%l", AM.ThreadScratSize);
709
        MesPrint("%l", AM.ThreadScratOutSize);
710
#endif
711
        MesPrint("%l", AM.MaxTer);
712
        MesPrint("%l", AM.CompressSize);
713
        MesPrint("%l", AM.ScratSize);
714
        MesPrint("%l", AM.SizeStoreCache);
715
        MesPrint("%l", AM.MaxStreamSize);
716
        MesPrint("%l", AM.SIOsize);
717
        MesPrint("%l", AM.SLargeSize);
718
        MesPrint("%l", AM.SSmallEsize);
719
        MesPrint("%l", AM.SSmallSize);
720
        MesPrint("--MARK  2");
721
        MesPrint("%l", AM.STermsInSmall);
722
        MesPrint("%l", AM.MaxBracketBufferSize);
723
        MesPrint("%l", AM.hProcessBucketSize);
724
        MesPrint("%l", AM.gProcessBucketSize);
725
        MesPrint("%l", AM.shmWinSize);
726
        MesPrint("%l", AM.OldChildTime);
727
        MesPrint("%l", AM.OldSecTime);
728
        MesPrint("%l", AM.OldMilliTime);
729
        MesPrint("%l", AM.WorkSize);
730
        MesPrint("%l", AM.gThreadBucketSize);
731
        MesPrint("--MARK  3");
732
        MesPrint("%l", AM.ggThreadBucketSize);
733
        MesPrint("%d", AM.FileOnlyFlag);
734
        MesPrint("%d", AM.Interact);
735
        MesPrint("%d", AM.MaxParLevel);
736
        MesPrint("%d", AM.OutBufSize);
737
        MesPrint("%d", AM.SMaxFpatches);
738
        MesPrint("%d", AM.SMaxPatches);
739
        MesPrint("%d", AM.StdOut);
740
        MesPrint("%d", AM.ginsidefirst);
741
        MesPrint("%d", AM.gDefDim);
742
        MesPrint("%d", AM.gDefDim4);
743
        MesPrint("--MARK  4");
744
        MesPrint("%d", AM.NumFixedSets);
745
        MesPrint("%d", AM.NumFixedFunctions);
746
        MesPrint("%d", AM.rbufnum);
747
        MesPrint("%d", AM.dbufnum);
748
        MesPrint("%d", AM.SkipClears);
749
        MesPrint("%d", AM.gfunpowers);
750
        MesPrint("%d", AM.gStatsFlag);
751
        MesPrint("%d", AM.gNamesFlag);
752
        MesPrint("%d", AM.gCodesFlag);
753
        MesPrint("%d", AM.gTokensWriteFlag);
754
        MesPrint("%d", AM.gSortType);
755
        MesPrint("%d", AM.gproperorderflag);
756
        MesPrint("--MARK  5");
757
        MesPrint("%d", AM.hparallelflag);
758
        MesPrint("%d", AM.gparallelflag);
759
        MesPrint("%d", AM.totalnumberofthreads);
760
        MesPrint("%d", AM.gSizeCommuteInSet);
761
        MesPrint("%d", AM.gThreadStats);
762
        MesPrint("%d", AM.ggThreadStats);
763
        MesPrint("%d", AM.gFinalStats);
764
        MesPrint("%d", AM.ggFinalStats);
765
        MesPrint("%d", AM.gThreadsFlag);
766
        MesPrint("%d", AM.ggThreadsFlag);
767
        MesPrint("%d", AM.gThreadBalancing);
768
        MesPrint("%d", AM.ggThreadBalancing);
769
        MesPrint("%d", AM.gThreadSortFileSynch);
770
        MesPrint("%d", AM.ggThreadSortFileSynch);
771
        MesPrint("%d", AM.gProcessStats);
772
        MesPrint("%d", AM.ggProcessStats);
773
        MesPrint("%d", AM.gOldParallelStats);
774
        MesPrint("%d", AM.ggOldParallelStats);
775
        MesPrint("%d", AM.gWTimeStatsFlag);
776
        MesPrint("%d", AM.ggWTimeStatsFlag);
777
        MesPrint("%d", AM.maxFlevels);
778
        MesPrint("--MARK  6");
779
        MesPrint("%d", AM.resetTimeOnClear);
780
        MesPrint("%d", AM.gcNumDollars);
781
        MesPrint("%d", AM.MultiRun);
782
        MesPrint("%d", AM.gNoSpacesInNumbers);
783
        MesPrint("%d", AM.ggNoSpacesInNumbers);
784
        MesPrint("%d", AM.MaxTal);
785
        MesPrint("%d", AM.IndDum);
786
        MesPrint("%d", AM.DumInd);
787
        MesPrint("%d", AM.WilInd);
788
        MesPrint("%d", AM.gncmod);
789
        MesPrint("%d", AM.gnpowmod);
790
        MesPrint("%d", AM.gmodmode);
791
        MesPrint("--MARK  7");
792
        MesPrint("%d", AM.gUnitTrace);
793
        MesPrint("%d", AM.gOutputMode);
794
        MesPrint("%d", AM.gCnumpows);
795
        MesPrint("%d", AM.gOutputSpaces);
796
        MesPrint("%d", AM.gOutNumberType);
797
        MesPrint("%d %d %d %d", AM.gUniTrace[0], AM.gUniTrace[1], AM.gUniTrace[2], AM.gUniTrace[3]);
798
        MesPrint("%d", AM.MaxWildcards);
799
        MesPrint("%d", AM.mTraceDum);
800
        MesPrint("%d", AM.OffsetIndex);
801
        MesPrint("%d", AM.OffsetVector);
802
        MesPrint("%d", AM.RepMax);
803
        MesPrint("%d", AM.LogType);
804
        MesPrint("%d", AM.ggStatsFlag);
805
        MesPrint("%d", AM.gLineLength);
806
        MesPrint("%d", AM.qError);
807
        MesPrint("--MARK  8");
808
        MesPrint("%d", AM.FortranCont);
809
        MesPrint("%d", AM.HoldFlag);
810
        MesPrint("%d %d %d %d %d", AM.Ordering[0], AM.Ordering[1], AM.Ordering[2], AM.Ordering[3], AM.Ordering[4]);
811
        MesPrint("%d %d %d %d %d", AM.Ordering[5], AM.Ordering[6], AM.Ordering[7], AM.Ordering[8], AM.Ordering[9]);
812
        MesPrint("%d %d %d %d %d", AM.Ordering[10], AM.Ordering[11], AM.Ordering[12], AM.Ordering[13], AM.Ordering[14]);
813
        MesPrint("%d", AM.silent);
814
        MesPrint("%d", AM.tracebackflag);
815
        MesPrint("%d", AM.expnum);
816
        MesPrint("%d", AM.denomnum);
817
        MesPrint("%d", AM.facnum);
818
        MesPrint("%d", AM.invfacnum);
819
        MesPrint("%d", AM.sumnum);
820
        MesPrint("%d", AM.sumpnum);
821
        MesPrint("--MARK  9");
822
        MesPrint("%d", AM.OldOrderFlag);
823
        MesPrint("%d", AM.termfunnum);
824
        MesPrint("%d", AM.matchfunnum);
825
        MesPrint("%d", AM.countfunnum);
826
        MesPrint("%d", AM.gPolyFun);
827
        MesPrint("%d", AM.gPolyFunInv);
828
        MesPrint("%d", AM.gPolyFunType);
829
        MesPrint("%d", AM.gPolyFunExp);
830
        MesPrint("%d", AM.gPolyFunVar);
831
        MesPrint("%d", AM.gPolyFunPow);
832
        MesPrint("--MARK 10");
833
        MesPrint("%d", AM.dollarzero);
834
        MesPrint("%d", AM.atstartup);
835
        MesPrint("%d", AM.exitflag);
836
        MesPrint("%d", AM.NumStoreCaches);
837
        MesPrint("%d", AM.gIndentSpace);
838
        MesPrint("%d", AM.ggIndentSpace);
839
        MesPrint("%d", AM.gShortStatsMax);
840
        MesPrint("%d", AM.ggShortStatsMax);
841
        MesPrint("--MARK 11");
842
        MesPrint("%d", AM.FromStdin);
843
        MesPrint("%%%% END M_const");
844
/*        fflush(0); */
845
}
846

847
static void print_P()
848
{
849
        int i;
850
        MesPrint("%%%% P_const");
851
        print_LIST(&AP.DollarList);
852
        for ( i=0; i<AP.DollarList.num; ++i ) {
853
                print_DOLLARS(&(Dollars[i]));
854
        }
855
        MesPrint("--MARK  1");
856
        print_LIST(&AP.PreVarList);
857
        for ( i=0; i<AP.PreVarList.num; ++i ) {
858
                print_PREVAR(&(PreVar[i]));
859
        }
860
        MesPrint("--MARK  2");
861
        print_LIST(&AP.LoopList);
862
        for ( i=0; i<AP.LoopList.num; ++i ) {
863
                print_DOLOOP(&(DoLoops[i]));
864
        }
865
        MesPrint("--MARK  3");
866
        print_LIST(&AP.ProcList);
867
        for ( i=0; i<AP.ProcList.num; ++i ) {
868
                print_PROCEDURE(&(Procedures[i]));
869
        }
870
        MesPrint("--MARK  4");
871
        for ( i=0; i<=AP.PreSwitchLevel; ++i ) {
872
                print_STR(AP.PreSwitchStrings[i]);
873
        }
874
        MesPrint("%l", AP.preStop-AP.preStart);
875
        if ( AP.preFill ) MesPrint("%l", AP.preFill-AP.preStart);
876
        print_CHARS(AP.preStart, AP.pSize);
877
        MesPrint("%s", AP.procedureExtension);
878
        MesPrint("%s", AP.cprocedureExtension);
879
        print_INTV(AP.PreIfStack, AP.MaxPreIfLevel);
880
        print_INTV(AP.PreSwitchModes, AP.NumPreSwitchStrings+1);
881
        print_INTV(AP.PreTypes, AP.NumPreTypes+1);
882
        MesPrint("%d", AP.PreAssignFlag);
883
        MesPrint("--MARK  5");
884
        MesPrint("%d", AP.PreContinuation);
885
        MesPrint("%l", AP.InOutBuf);
886
        MesPrint("%l", AP.pSize);
887
        MesPrint("%d", AP.PreproFlag);
888
        MesPrint("%d", AP.iBufError);
889
        MesPrint("%d", AP.PreOut);
890
        MesPrint("%d", AP.PreSwitchLevel);
891
        MesPrint("%d", AP.NumPreSwitchStrings);
892
        MesPrint("%d", AP.MaxPreTypes);
893
        MesPrint("--MARK  6");
894
        MesPrint("%d", AP.NumPreTypes);
895
        MesPrint("%d", AP.DelayPrevar);
896
        MesPrint("%d", AP.AllowDelay);
897
        MesPrint("%d", AP.lhdollarerror);
898
        MesPrint("%d", AP.eat);
899
        MesPrint("%d", AP.gNumPre);
900
        MesPrint("%d", AP.PreDebug);
901
        MesPrint("--MARK  7");
902
        MesPrint("%d", AP.DebugFlag);
903
        MesPrint("%d", AP.preError);
904
        MesPrint("%C", 1, &(AP.ComChar));
905
        MesPrint("%C", 1, &(AP.cComChar));
906
        MesPrint("%%%% END P_const");
907
/*        fflush(0); */
908
}
909

910
static void print_C()
911
{
912
        int i;
913
        UBYTE buf[40], *t;
914
        MesPrint("%%%% C_const");
915
        for ( i=0; i<32; ++i ) {
916
                t = buf;
917
                t = NumCopy((WORD)(AC.separators[i].bit_7),t);
918
                t = NumCopy((WORD)(AC.separators[i].bit_6),t);
919
                t = NumCopy((WORD)(AC.separators[i].bit_5),t);
920
                t = NumCopy((WORD)(AC.separators[i].bit_4),t);
921
                t = NumCopy((WORD)(AC.separators[i].bit_3),t);
922
                t = NumCopy((WORD)(AC.separators[i].bit_2),t);
923
                t = NumCopy((WORD)(AC.separators[i].bit_1),t);
924
                t = NumCopy((WORD)(AC.separators[i].bit_0),t);
925
                MesPrint("%s ",buf);
926
        }
927
        print_NAMETREE(AC.dollarnames);
928
        print_NAMETREE(AC.exprnames);
929
        print_NAMETREE(AC.varnames);
930
        MesPrint("--MARK  1");
931
        print_LIST(&AC.ChannelList);
932
        for ( i=0; i<AC.ChannelList.num; ++i ) {
933
                MesPrint("%s %d", channels[i].name, channels[i].handle);
934
        }
935
        MesPrint("--MARK  2");
936
        print_LIST(&AC.DubiousList);
937
        MesPrint("--MARK  3");
938
        print_LIST(&AC.FunctionList);
939
        for ( i=0; i<AC.FunctionList.num; ++i ) {
940
                if ( functions[i].tabl ) {
941

942
                }
943
                MesPrint("%l", functions[i].symminfo);
944
                MesPrint("%l", functions[i].name);
945
                MesPrint("%d", functions[i].namesize);
946
        }
947
        MesPrint("--MARK  4");
948
        print_LIST(&AC.ExpressionList);
949
        print_LIST(&AC.IndexList);
950
        print_LIST(&AC.SetElementList);
951
        print_LIST(&AC.SetList);
952
        MesPrint("--MARK  5");
953
        print_LIST(&AC.SymbolList);
954
        print_LIST(&AC.VectorList);
955
        print_LIST(&AC.PotModDolList);
956
        print_LIST(&AC.ModOptDolList);
957
        print_LIST(&AC.TableBaseList);
958

959
/*
960
        print_LIST(&AC.cbufList);
961
        for ( i=0; i<AC.cbufList.num; ++i ) {
962
                MesPrint("cbufList.num == %d", i);
963
                print_CBUF(cbuf+i);
964
        }
965
        MesPrint("%d", AC.cbufnum);
966
*/
967
        MesPrint("--MARK  6");
968

969
        print_LIST(&AC.AutoSymbolList);
970
        print_LIST(&AC.AutoIndexList);
971
        print_LIST(&AC.AutoVectorList);
972
        print_LIST(&AC.AutoFunctionList);
973

974
        print_NAMETREE(AC.autonames);
975
        MesPrint("--MARK  7");
976

977
        print_LIST(AC.Symbols);
978
        print_LIST(AC.Indices);
979
        print_LIST(AC.Vectors);
980
        print_LIST(AC.Functions);
981
        MesPrint("--MARK  8");
982

983
        print_NAMETREE(*AC.activenames);
984
        
985
        MesPrint("--MARK  9");
986

987
        MesPrint("%d", AC.AutoDeclareFlag);
988

989
        for ( i=0; i<AC.NumStreams; ++i ) {
990
                MesPrint("Stream %d\n", i);
991
                print_STREAM(AC.Streams+i);
992
        }
993
        print_STREAM(AC.CurrentStream);
994
        MesPrint("--MARK 10");
995

996
        print_LONGV(AC.termstack, AC.maxtermlevel);
997
        print_LONGV(AC.termsortstack, AC.maxtermlevel);
998
        print_VOIDP(AC.cmod, AM.MaxTal*4*sizeof(UWORD));
999
        print_WORDV((WORD *)(AC.cmod), 1);
1000
        print_WORDV((WORD *)(AC.powmod), 1);
1001
        print_WORDV((WORD*)AC.modpowers, 1);
1002
        print_WORDV((WORD*)AC.halfmod, 1);
1003
        MesPrint("--MARK 10-2");
1004
        /*
1005
        print_WORDV(AC.ProtoType, AC.ProtoType[1]);
1006
        print_WORDV(AC.WildC, 1);
1007
        */
1008

1009
        MesPrint("--MARK 11");
1010
        /* IfHeap ... Labels */
1011

1012
        print_CHARS((UBYTE*)AC.tokens, AC.toptokens-AC.tokens);
1013
        MesPrint("%l", AC.endoftokens-AC.tokens);
1014
        print_WORDV(AC.tokenarglevel, AM.MaxParLevel);
1015
        print_WORDV((WORD*)AC.modinverses, ABS(AC.ncmod));
1016
#ifdef WITHPTHREADS
1017
        print_LONGV(AC.inputnumbers, AC.sizepfirstnum+AC.sizepfirstnum*sizeof(WORD)/sizeof(LONG));
1018
        print_WORDV(AC.pfirstnum, 1);
1019
#endif
1020
        MesPrint("--MARK 12");
1021
    print_LONGV(AC.argstack, MAXNEST);
1022
    print_LONGV(AC.insidestack, MAXNEST);
1023
    print_LONGV(AC.inexprstack, MAXNEST);
1024
        MesPrint("%l", AC.iBufferSize);
1025
        MesPrint("%l", AC.TransEname);
1026
        MesPrint("%l", AC.ProcessBucketSize);
1027
        MesPrint("%l", AC.mProcessBucketSize);
1028
        MesPrint("%l", AC.CModule);
1029
        MesPrint("%l", AC.ThreadBucketSize);
1030
        MesPrint("%d", AC.NoShowInput);
1031
        MesPrint("%d", AC.ShortStats);
1032
        MesPrint("%d", AC.compiletype);
1033
        MesPrint("%d", AC.firstconstindex);
1034
        MesPrint("%d", AC.insidefirst);
1035
        MesPrint("%d", AC.minsidefirst);
1036
        MesPrint("%d", AC.wildflag);
1037
        MesPrint("%d", AC.NumLabels);
1038
        MesPrint("%d", AC.MaxLabels);
1039
        MesPrint("--MARK 13");
1040
        MesPrint("%d", AC.lDefDim);
1041
        MesPrint("%d", AC.lDefDim4);
1042
        MesPrint("%d", AC.NumWildcardNames);
1043
        MesPrint("%d", AC.WildcardBufferSize);
1044
        MesPrint("%d", AC.MaxIf);
1045
        MesPrint("%d", AC.NumStreams);
1046
        MesPrint("%d", AC.MaxNumStreams);
1047
        MesPrint("%d", AC.firstctypemessage);
1048
        MesPrint("%d", AC.tablecheck);
1049
        MesPrint("%d", AC.idoption);
1050
        MesPrint("%d", AC.BottomLevel);
1051
        MesPrint("%d", AC.CompileLevel);
1052
        MesPrint("%d", AC.TokensWriteFlag);
1053
        MesPrint("%d", AC.UnsureDollarMode);
1054
        MesPrint("%d", AC.outsidefun);
1055
        MesPrint("%d", AC.funpowers);
1056
        MesPrint("--MARK 14");
1057
        MesPrint("%d", AC.WarnFlag);
1058
        MesPrint("%d", AC.StatsFlag);
1059
        MesPrint("%d", AC.NamesFlag);
1060
        MesPrint("%d", AC.CodesFlag);
1061
        MesPrint("%d", AC.TokensWriteFlag);
1062
        MesPrint("%d", AC.SetupFlag);
1063
        MesPrint("%d", AC.SortType);
1064
        MesPrint("%d", AC.lSortType);
1065
        MesPrint("%d", AC.ThreadStats);
1066
        MesPrint("%d", AC.FinalStats);
1067
        MesPrint("%d", AC.ThreadsFlag);
1068
        MesPrint("%d", AC.ThreadBalancing);
1069
        MesPrint("%d", AC.ThreadSortFileSynch);
1070
        MesPrint("%d", AC.ProcessStats);
1071
        MesPrint("%d", AC.OldParallelStats);
1072
        MesPrint("%d", AC.WTimeStatsFlag);
1073
        MesPrint("%d", AC.BracketNormalize);
1074
        MesPrint("%d", AC.maxtermlevel);
1075
        MesPrint("%d", AC.dumnumflag);
1076
        MesPrint("--MARK 15");
1077
        MesPrint("%d", AC.bracketindexflag);
1078
        MesPrint("%d", AC.parallelflag);
1079
        MesPrint("%d", AC.mparallelflag);
1080
        MesPrint("%d", AC.properorderflag);
1081
        MesPrint("%d", AC.vetofilling);
1082
        MesPrint("%d", AC.tablefilling);
1083
        MesPrint("%d", AC.vetotablebasefill);
1084
        MesPrint("%d", AC.exprfillwarning);
1085
        MesPrint("%d", AC.lhdollarflag);
1086
        MesPrint("%d", AC.NoCompress);
1087
#ifdef WITHPTHREADS
1088
        MesPrint("%d", AC.numpfirstnum);
1089
        MesPrint("%d", AC.sizepfirstnum);
1090
#endif
1091
        MesPrint("%d", AC.RepLevel);
1092
        MesPrint("%d", AC.arglevel);
1093
        MesPrint("%d", AC.insidelevel);
1094
        MesPrint("%d", AC.inexprlevel);
1095
        MesPrint("%d", AC.termlevel);
1096
        MesPrint("--MARK 16");
1097
        print_WORDV(AC.argsumcheck, MAXNEST);
1098
        print_WORDV(AC.insidesumcheck, MAXNEST);
1099
        print_WORDV(AC.inexprsumcheck, MAXNEST);
1100
        MesPrint("%d", AC.MustTestTable);
1101
        MesPrint("%d", AC.DumNum);
1102
        MesPrint("%d", AC.ncmod);
1103
        MesPrint("%d", AC.npowmod);
1104
        MesPrint("%d", AC.modmode);
1105
        MesPrint("%d", AC.nhalfmod);
1106
        MesPrint("%d", AC.DirtPow);
1107
        MesPrint("%d", AC.lUnitTrace);
1108
        MesPrint("%d", AC.NwildC);
1109
        MesPrint("%d", AC.ComDefer);
1110
        MesPrint("%d", AC.CollectFun);
1111
        MesPrint("%d", AC.AltCollectFun);
1112
        MesPrint("--MARK 17");
1113
        MesPrint("%d", AC.OutputMode);
1114
        MesPrint("%d", AC.Cnumpows);
1115
        MesPrint("%d", AC.OutputSpaces);
1116
        MesPrint("%d", AC.OutNumberType);
1117
        print_WORDV(AC.lUniTrace, 4);
1118
        print_WORDV(AC.RepSumCheck, MAXREPEAT);
1119
        MesPrint("%d", AC.DidClean);
1120
        MesPrint("%d", AC.IfLevel);
1121
        MesPrint("%d", AC.WhileLevel);
1122
        print_WORDV(AC.IfSumCheck, (AC.MaxIf+1));
1123
        MesPrint("%d", AC.LogHandle);
1124
        MesPrint("%d", AC.LineLength);
1125
        MesPrint("%d", AC.StoreHandle);
1126
        MesPrint("%d", AC.HideLevel);
1127
        MesPrint("%d", AC.lPolyFun);
1128
        MesPrint("%d", AC.lPolyFunInv);
1129
        MesPrint("%d", AC.lPolyFunType);
1130
        MesPrint("%d", AC.lPolyFunExp);
1131
        MesPrint("%d", AC.lPolyFunVar);
1132
        MesPrint("%d", AC.lPolyFunPow);
1133
        MesPrint("%d", AC.SymChangeFlag);
1134
        MesPrint("%d", AC.CollectPercentage);
1135
        MesPrint("%d", AC.ShortStatsMax);
1136
        MesPrint("--MARK 18");
1137

1138
        print_CHARS(AC.Commercial, COMMERCIALSIZE+2);
1139

1140
        MesPrint("%", AC.CheckpointFlag);
1141
        MesPrint("%l", AC.CheckpointStamp);
1142
        print_STR((unsigned char*)AC.CheckpointRunAfter);
1143
        print_STR((unsigned char*)AC.CheckpointRunBefore);
1144
        MesPrint("%l", AC.CheckpointInterval);
1145

1146
        MesPrint("%%%% END C_const");
1147
/*        fflush(0); */
1148
}
1149

1150
static void print_R()
1151
{
1152
        GETIDENTITY
1153
        int i;
1154
        MesPrint("%%%% R_const");
1155
        MesPrint("%l", (LONG)(AR.infile-AR.Fscr));
1156
        MesPrint("%s", AR.infile->name);
1157
        MesPrint("%l", (LONG)(AR.outfile-AR.Fscr));
1158
        MesPrint("%s", AR.outfile->name);
1159
        MesPrint("%l", AR.hidefile-AR.Fscr);
1160
        MesPrint("%s", AR.hidefile->name);
1161
        for ( i=0; i<3; ++i ) {
1162
                MesPrint("FSCR %d", i);
1163
                print_WORDB(AR.Fscr[i].PObuffer, AR.Fscr[i].POfull);
1164
        }
1165
        /* ... */
1166
        MesPrint("%l", AR.OldTime);
1167
        MesPrint("%l", AR.InInBuf);
1168
        MesPrint("%l", AR.InHiBuf);
1169
        MesPrint("%l", AR.pWorkSize);
1170
        MesPrint("%l", AR.lWorkSize);
1171
        MesPrint("%l", AR.posWorkSize);
1172
        MesPrint("%d", AR.NoCompress);
1173
        MesPrint("%d", AR.gzipCompress);
1174
        MesPrint("%d", AR.Cnumlhs);
1175
#ifdef WITHPTHREADS
1176
        MesPrint("%d", AR.exprtodo);
1177
#endif
1178
        MesPrint("%d", AR.GetFile);
1179
        MesPrint("%d", AR.KeptInHold);
1180
        MesPrint("%d", AR.BracketOn);
1181
        MesPrint("%d", AR.MaxBracket);
1182
        MesPrint("%d", AR.CurDum);
1183
        MesPrint("%d", AR.DeferFlag);
1184
        MesPrint("%d", AR.TePos);
1185
        MesPrint("%d", AR.sLevel);
1186
        MesPrint("%d", AR.Stage4Name);
1187
        MesPrint("%d", AR.GetOneFile);
1188
        MesPrint("%d", AR.PolyFun);
1189
        MesPrint("%d", AR.PolyFunInv);
1190
        MesPrint("%d", AR.PolyFunType);
1191
        MesPrint("%d", AR.PolyFunExp);
1192
        MesPrint("%d", AR.PolyFunVar);
1193
        MesPrint("%d", AR.PolyFunPow);
1194
        MesPrint("%d", AR.Eside);
1195
        MesPrint("%d", AR.MaxDum);
1196
        MesPrint("%d", AR.level);
1197
        MesPrint("%d", AR.expchanged);
1198
        MesPrint("%d", AR.expflags);
1199
        MesPrint("%d", AR.CurExpr);
1200
        MesPrint("%d", AR.SortType);
1201
        MesPrint("%d", AR.ShortSortCount);
1202
        MesPrint("%%%% END R_const");
1203
/*        fflush(0); */
1204
}
1205

1206
#endif /* ifdef PRINTDEBUG */
1207

1208
/*
1209
          #] Debugging : 
1210
          #[ Cached file operation functions :
1211
*/
1212

1213
#define CACHED_SNAPSHOT
1214

1215
#define CACHE_SIZE 4096
1216

1217
#ifdef CACHED_SNAPSHOT
1218
unsigned char cache_buffer[CACHE_SIZE];
1219
size_t cache_fill = 0;
1220

1221
size_t fwrite_cached(const void *ptr, size_t size, size_t nmemb, FILE *fd)
×
1222
{
1223
        size_t fullsize = size*nmemb;
×
1224
        if ( fullsize+cache_fill >= CACHE_SIZE ) {
×
1225
                size_t overlap = CACHE_SIZE-cache_fill;
×
1226
                memcpy(cache_buffer+cache_fill, (unsigned char*)ptr, overlap);
×
1227
                if ( fwrite(cache_buffer, 1, CACHE_SIZE, fd) != CACHE_SIZE ) return 0;
×
1228
                fullsize -= overlap;
×
1229
                if ( fullsize >= CACHE_SIZE ) {
×
1230
                        cache_fill = fullsize % CACHE_SIZE;
×
1231
                        if ( cache_fill ) memcpy(cache_buffer, (unsigned char*)ptr+overlap+fullsize-cache_fill, cache_fill);
×
1232
                        if ( fwrite((unsigned char*)ptr+overlap, 1, fullsize-cache_fill, fd) != fullsize-cache_fill ) return 0;
×
1233
                }
1234
                else {
1235
                        memcpy(cache_buffer, (unsigned char*)ptr+overlap, fullsize);
×
1236
                        cache_fill = fullsize;
×
1237
                }
1238
        }
1239
        else {
1240
                memcpy(cache_buffer+cache_fill, (unsigned char*)ptr, fullsize);
×
1241
                cache_fill += fullsize;
×
1242
        }
1243
        return nmemb;
1244
}
1245

1246
size_t flush_cache(FILE *fd)
×
1247
{
1248
        if ( cache_fill ) {
×
1249
                size_t retval = fwrite(cache_buffer, 1, cache_fill, fd);
×
1250
                if ( retval != cache_fill ) {
×
1251
                         cache_fill = 0;
×
1252
                        return 0;
×
1253
                }
1254
                 cache_fill = 0;
×
1255
        }
1256
        return 1;
1257
}
1258
#else
1259
size_t fwrite_cached(const void *ptr, size_t size, size_t nmemb, FILE *fd)
1260
{
1261
        return fwrite(ptr, size, nmemb, fd);
1262
}
1263

1264
size_t flush_cache(FILE *fd)
1265
{
1266
        DUMMYUSE(fd)
1267
        return 1;
1268
}
1269
#endif
1270

1271
/*
1272
          #] Cached file operation functions : 
1273
          #[ Helper Macros :
1274
*/
1275

1276
/* some helper macros to streamline the code in DoSnapshot() and DoRecovery() */
1277

1278
/* freeing memory */
1279

1280
#define R_FREE(ARG) \
1281
        if ( ARG ) M_free(ARG, #ARG);
1282

1283
#define R_FREE_NAMETREE(ARG) \
1284
        R_FREE(ARG->namenode); \
1285
        R_FREE(ARG->namebuffer); \
1286
        R_FREE(ARG);
1287

1288
#define R_FREE_STREAM(ARG) \
1289
        R_FREE(ARG.buffer); \
1290
        R_FREE(ARG.FoldName); \
1291
        R_FREE(ARG.name);
1292

1293
/* reading a single variable */
1294

1295
#define R_SET(VAR,TYPE) \
1296
        VAR = *((TYPE*)p); p = (unsigned char*)p + sizeof(TYPE);
1297

1298
/* general buffer */
1299

1300
#define R_COPY_B(VAR,SIZE,CAST) \
1301
        VAR = (CAST)Malloc1(SIZE,#VAR); \
1302
        memcpy(VAR, p, SIZE); p = (unsigned char*)p + SIZE;
1303

1304
#define S_WRITE_B(BUF,LEN) \
1305
        if ( fwrite_cached(BUF, 1, LEN, fd) != (size_t)(LEN) ) return(__LINE__);
1306

1307
#define S_FLUSH_B \
1308
        if ( flush_cache(fd) != 1 ) return(__LINE__);
1309

1310
/* character strings */
1311

1312
#define R_COPY_S(VAR,CAST) \
1313
        if ( VAR ) { \
1314
                VAR = (CAST)Malloc1(strlen(p)+1,"R_COPY_S"); \
1315
                strcpy((char*)VAR, p); p = (unsigned char*)p + strlen(p) + 1; \
1316
        }
1317

1318
#define S_WRITE_S(STR) \
1319
        if ( STR ) { \
1320
                l = strlen((char*)STR) + 1; \
1321
                if ( fwrite_cached(STR, 1, l, fd) != (size_t)l ) return(__LINE__); \
1322
        }
1323

1324
/* LIST */
1325

1326
#define R_COPY_LIST(ARG) \
1327
        if ( ARG.maxnum ) { \
1328
                R_COPY_B(ARG.lijst, ARG.size*ARG.maxnum, void*) \
1329
        }
1330

1331
#define S_WRITE_LIST(LST) \
1332
        if ( LST.maxnum ) { \
1333
                S_WRITE_B((char*)LST.lijst, LST.maxnum*LST.size) \
1334
        }
1335

1336
/* NAMETREE */
1337

1338
#define R_COPY_NAMETREE(ARG) \
1339
        R_COPY_B(ARG, sizeof(NAMETREE), NAMETREE*); \
1340
        if ( ARG->namenode ) { \
1341
                R_COPY_B(ARG->namenode, ARG->nodesize*sizeof(NAMENODE), NAMENODE*); \
1342
        } \
1343
        if ( ARG->namebuffer ) { \
1344
                R_COPY_B(ARG->namebuffer, ARG->namesize, UBYTE*); \
1345
        }
1346

1347
#define S_WRITE_NAMETREE(ARG) \
1348
        S_WRITE_B(ARG, sizeof(NAMETREE)); \
1349
        if ( ARG->namenode ) { \
1350
                S_WRITE_B(ARG->namenode, ARG->nodesize*sizeof(struct NaMeNode)); \
1351
        } \
1352
        if ( ARG->namebuffer ) { \
1353
                S_WRITE_B(ARG->namebuffer, ARG->namesize); \
1354
        }
1355

1356
/* DOLLAR */
1357

1358
#define S_WRITE_DOLLAR(ARG) \
1359
        if ( ARG.size && ARG.where && ARG.where != &(AM.dollarzero) ) { \
1360
                S_WRITE_B(ARG.where, ARG.size*sizeof(WORD)) \
1361
        }
1362

1363
/* Printing time marks with ANNOUNCE macro */
1364

1365
#ifdef PRINTTIMEMARKS
1366
time_t announce_time;
1367
#define ANNOUNCE(str) time(&announce_time); MesPrint("TIMEMARK %s  %s", ctime(&announce_time), #str);
1368
#else
1369
#define ANNOUNCE(str)
1370
#endif
1371

1372
/*
1373
          #] Helper Macros : 
1374
          #[ DoRecovery :
1375
*/
1376

1377
/**
1378
 *  Reads from the recovery file and restores all necessary variables and
1379
 *  states in FORM, so that the execution can recommence in preprocessor() as
1380
 *  if no restart of FORM had occurred.
1381
 *
1382
 *  The recovery file is read into memory as a whole. The pointer p then points
1383
 *  into this memory at the next non-processed data. The macros by which
1384
 *  variables are restored, like R_SET, automatically increase p appropriately.
1385
 *
1386
 *  If something goes wrong, the function returns with a non-zero value.
1387
 *
1388
 *  Allocated memory that would be lost when overwriting the global structs with
1389
 *  data from the file is freed first. A major part of the code deals with the
1390
 *  restoration of pointers. The idiom we use is to memorize the original
1391
 *  pointer value (org), allocate new memory and copy the data from the file
1392
 *  into this memory, calculate the offset between the old pointer value
1393
 *  and the new allocated memory position (ofs), and then correct all affected
1394
 *  pointers (+=ofs).
1395
 *
1396
 *  We rely on the fact that several variables (especially in AM) are already
1397
 *  assigned the correct values by the startup functions. That means, in
1398
 *  principle, that a change in the setup files between snapshot creation and
1399
 *  recovery will be noticed.
1400
 */
1401
int DoRecovery(int *moduletype)
×
1402
{
1403
        GETIDENTITY
1404
        FILE *fd;
×
1405
        POSITION pos;
×
1406
        void *buf, *p;
×
1407
        LONG size, l;
×
1408
        int i, j;
×
1409
        UBYTE *org;
×
1410
        char *namebufout, *namebufhide;
×
1411
        LONG ofs;
×
1412
        void *oldAMdollarzero;
×
1413
        LIST PotModDolListBackup;
×
1414
        LIST ModOptDolListBackup;
×
1415
        WORD oldLogHandle;
×
1416

1417
        MesPrint("Recovering ... %"); fflush(0);
×
1418

1419
        if ( !(fd = fopen(recoveryfile, "r")) ) return(__LINE__);
×
1420

1421
        /* load the complete recovery file into a buffer */
1422
        if ( fread(&pos, sizeof(POSITION), 1, fd) != 1 ) return(__LINE__);
×
1423
        size = BASEPOSITION(pos) - sizeof(POSITION);
×
1424
        buf = Malloc1(size, "recovery buffer");
×
1425
        if ( fread(buf, size, 1, fd) != 1 ) return(__LINE__);
×
1426

1427
        /* pointer p will go through the buffer in the following */
1428
        p = buf;
×
1429

1430
        /* read moduletype */
1431
        R_SET(*moduletype, int);
×
1432

1433
        /*#[ AM : */
1434

1435
        /* only certain elements will be restored. the rest of AM should have gotten
1436
         * the correct values at startup. */
1437

1438
        R_SET(AM.hparallelflag, int);
×
1439
        R_SET(AM.gparallelflag, int);
×
1440
        R_SET(AM.gCodesFlag, int);
×
1441
        R_SET(AM.gNamesFlag, int);
×
1442
        R_SET(AM.gStatsFlag, int);
×
1443
        R_SET(AM.gTokensWriteFlag, int);
×
1444
        R_SET(AM.gNoSpacesInNumbers, int);
×
1445
        R_SET(AM.gIndentSpace, WORD);
×
1446
        R_SET(AM.gUnitTrace, WORD);
×
1447
        R_SET(AM.gDefDim, int);
×
1448
        R_SET(AM.gDefDim4, int);
×
1449
        R_SET(AM.gncmod, WORD);
×
1450
        R_SET(AM.gnpowmod, WORD);
×
1451
        R_SET(AM.gmodmode, WORD);
×
1452
        R_SET(AM.gOutputMode, WORD);
×
1453
        R_SET(AM.gCnumpows, WORD);
×
1454
        R_SET(AM.gOutputSpaces, WORD);
×
1455
        R_SET(AM.gOutNumberType, WORD);
×
1456
        R_SET(AM.gfunpowers, int);
×
1457
        R_SET(AM.gPolyFun, WORD);
×
1458
        R_SET(AM.gPolyFunInv, WORD);
×
1459
        R_SET(AM.gPolyFunType, WORD);
×
1460
        R_SET(AM.gPolyFunExp, WORD);
×
1461
        R_SET(AM.gPolyFunVar, WORD);
×
1462
        R_SET(AM.gPolyFunPow, WORD);
×
1463
        R_SET(AM.gProcessBucketSize, LONG);
×
1464
        R_SET(AM.OldChildTime, LONG);
×
1465
        R_SET(AM.OldSecTime, LONG);
×
1466
        R_SET(AM.OldMilliTime, LONG);
×
1467
        R_SET(AM.gproperorderflag, int);
×
1468
        R_SET(AM.gThreadBucketSize, LONG);
×
1469
        R_SET(AM.gSizeCommuteInSet, int);
×
1470
        R_SET(AM.gThreadStats, int);
×
1471
        R_SET(AM.gFinalStats, int);
×
1472
        R_SET(AM.gThreadsFlag, int);
×
1473
        R_SET(AM.gThreadBalancing, int);
×
1474
        R_SET(AM.gThreadSortFileSynch, int);
×
1475
        R_SET(AM.gProcessStats, int);
×
1476
        R_SET(AM.gOldParallelStats, int);
×
1477
        R_SET(AM.gSortType, int);
×
1478
        R_SET(AM.gShortStatsMax, WORD);
×
1479
        R_SET(AM.gIsFortran90, int);
×
1480
        R_SET(oldAMdollarzero, void*);
×
1481
        R_FREE(AM.gFortran90Kind);
×
1482
        R_SET(AM.gFortran90Kind,UBYTE *);
×
1483
        R_COPY_S(AM.gFortran90Kind,UBYTE *);
×
1484

1485
        R_COPY_S(AM.gextrasym,UBYTE *);
×
1486
        R_COPY_S(AM.ggextrasym,UBYTE *);
×
1487

1488
        R_SET(AM.PrintTotalSize,int);
×
1489
        R_SET(AM.fbuffersize,int);
×
1490
        R_SET(AM.gOldFactArgFlag,int);
×
1491
        R_SET(AM.ggOldFactArgFlag,int);
×
1492

1493
    R_SET(AM.gnumextrasym,int);
×
1494
    R_SET(AM.ggnumextrasym,int);
×
1495
        R_SET(AM.NumSpectatorFiles,int);
×
1496
        R_SET(AM.SizeForSpectatorFiles,int);
×
1497
    R_SET(AM.gOldGCDflag,int);
×
1498
    R_SET(AM.ggOldGCDflag,int);
×
1499
        R_SET(AM.gWTimeStatsFlag, int);
×
1500

1501
        R_FREE(AM.Path);
×
1502
        R_SET(AM.Path,UBYTE *);
×
1503
        R_COPY_S(AM.Path,UBYTE *);
×
1504

1505
        R_SET(AM.FromStdin, BOOL);
×
1506

1507
#ifdef PRINTDEBUG
1508
        print_M();
1509
#endif
1510

1511
        /*#] AM : */ 
1512
        /*#[ AC : */
1513

1514
        /* #[ AC free pointers */
1515

1516
        /* AC will be overwritten by data from the recovery file, therefore
1517
         * dynamically allocated memory must be freed first. */
1518

1519
        R_FREE_NAMETREE(AC.dollarnames);
×
1520
        R_FREE_NAMETREE(AC.exprnames);
×
1521
        R_FREE_NAMETREE(AC.varnames);
×
1522
        for ( i=0; i<AC.ChannelList.num; ++i ) {
×
1523
                R_FREE(channels[i].name);
×
1524
        }
1525
        R_FREE(AC.ChannelList.lijst);
×
1526
        R_FREE(AC.DubiousList.lijst);
×
1527
        for ( i=0; i<AC.FunctionList.num; ++i ) {
×
1528
                TABLES T = functions[i].tabl;
×
1529
                if ( T ) {
×
1530
                        R_FREE(T->buffers);
×
1531
                        R_FREE(T->mm);
×
1532
                        R_FREE(T->flags);
×
1533
                        R_FREE(T->prototype);
×
1534
                        R_FREE(T->tablepointers);
×
1535
                        if ( T->sparse ) {
×
1536
                                R_FREE(T->boomlijst);
×
1537
                                R_FREE(T->argtail);
×
1538
                        }
1539
                        if ( T->spare ) {
×
1540
                                R_FREE(T->spare->buffers);
×
1541
                                R_FREE(T->spare->mm);
×
1542
                                R_FREE(T->spare->flags);
×
1543
                                R_FREE(T->spare->tablepointers);
×
1544
                                if ( T->spare->sparse ) {
×
1545
                                        R_FREE(T->spare->boomlijst);
×
1546
                                }
1547
                                R_FREE(T->spare);
×
1548
                        }
1549
                        R_FREE(T);
×
1550
                }
1551
        }
1552
        R_FREE(AC.FunctionList.lijst);
×
1553
        for ( i=0; i<AC.ExpressionList.num; ++i ) {
×
1554
                if ( Expressions[i].renum ) {
×
1555
                        R_FREE(Expressions[i].renum->symb.lo);
×
1556
                        R_FREE(Expressions[i].renum);
×
1557
                }
1558
                if ( Expressions[i].bracketinfo ) {
×
1559
                        R_FREE(Expressions[i].bracketinfo->indexbuffer);
×
1560
                        R_FREE(Expressions[i].bracketinfo->bracketbuffer);
×
1561
                        R_FREE(Expressions[i].bracketinfo);
×
1562
                }
1563
                if ( Expressions[i].newbracketinfo ) {
×
1564
                        R_FREE(Expressions[i].newbracketinfo->indexbuffer);
×
1565
                        R_FREE(Expressions[i].newbracketinfo->bracketbuffer);
×
1566
                        R_FREE(Expressions[i].newbracketinfo);
×
1567
                }
1568
                if ( Expressions[i].renumlists != AN.dummyrenumlist ) { 
×
1569
                        R_FREE(Expressions[i].renumlists);
×
1570
                }
1571
                R_FREE(Expressions[i].inmem);
×
1572
        }
1573
        R_FREE(AC.ExpressionList.lijst);
×
1574
        R_FREE(AC.IndexList.lijst);
×
1575
        R_FREE(AC.SetElementList.lijst);
×
1576
        R_FREE(AC.SetList.lijst);
×
1577
        R_FREE(AC.SymbolList.lijst);
×
1578
        R_FREE(AC.VectorList.lijst);
×
1579
        for ( i=0; i<AC.TableBaseList.num; ++i ) {
×
1580
                R_FREE(tablebases[i].iblocks);
×
1581
                R_FREE(tablebases[i].nblocks);
×
1582
                R_FREE(tablebases[i].name);
×
1583
                R_FREE(tablebases[i].fullname);
×
1584
                R_FREE(tablebases[i].tablenames);
×
1585
        }
1586
        R_FREE(AC.TableBaseList.lijst);
×
1587
        for ( i=0; i<AC.cbufList.num; ++i ) {
×
1588
                R_FREE(cbuf[i].Buffer);
×
1589
                R_FREE(cbuf[i].lhs);
×
1590
                R_FREE(cbuf[i].rhs);
×
1591
                R_FREE(cbuf[i].boomlijst);
×
1592
        }
1593
        R_FREE(AC.cbufList.lijst);
×
1594
        R_FREE(AC.AutoSymbolList.lijst);
×
1595
        R_FREE(AC.AutoIndexList.lijst);
×
1596
        R_FREE(AC.AutoVectorList.lijst);
×
1597
        /* Tables cannot be auto-declared, therefore no extra code here */
1598
        R_FREE(AC.AutoFunctionList.lijst);
×
1599
        R_FREE_NAMETREE(AC.autonames);
×
1600
        for ( i=0; i<AC.NumStreams; ++i ) {
×
1601
                R_FREE_STREAM(AC.Streams[i]);
×
1602
        }
1603
        R_FREE(AC.Streams);
×
1604
        R_FREE(AC.termstack);
×
1605
        R_FREE(AC.termsortstack);
×
1606
        R_FREE(AC.cmod);
×
1607
        R_FREE(AC.modpowers);
×
1608
        R_FREE(AC.halfmod);
×
1609
        R_FREE(AC.IfHeap);
×
1610
        R_FREE(AC.IfCount);
×
1611
        R_FREE(AC.iBuffer);
×
1612
        for ( i=0; i<AC.NumLabels; ++i ) {
×
1613
                R_FREE(AC.LabelNames[i]);
×
1614
        }
1615
        R_FREE(AC.LabelNames);
×
1616
        R_FREE(AC.FixIndices);
×
1617
        R_FREE(AC.termsumcheck);
×
1618
        R_FREE(AC.WildcardNames);
×
1619
        R_FREE(AC.tokens);
×
1620
        R_FREE(AC.tokenarglevel);
×
1621
        R_FREE(AC.modinverses);
×
1622
        R_FREE(AC.Fortran90Kind);
×
1623
#ifdef WITHPTHREADS
1624
        R_FREE(AC.inputnumbers);
1625
#endif
1626
        R_FREE(AC.IfSumCheck);
×
1627
        R_FREE(AC.CommuteInSet);
×
1628
        R_FREE(AC.CheckpointRunAfter);
×
1629
        R_FREE(AC.CheckpointRunBefore);
×
1630

1631
        /* #] AC free pointers */
1632

1633
        /* backup some lists in order to restore it to the initial setup */
1634
        PotModDolListBackup = AC.PotModDolList;
×
1635
        ModOptDolListBackup = AC.ModOptDolList;
×
1636
        oldLogHandle = AC.LogHandle;
×
1637

1638
        /* first we copy AC as a whole and then restore the pointer structures step
1639
           by step. */
1640

1641
        AC = *((struct C_const*)p); p = (unsigned char*)p + sizeof(struct C_const);
×
1642
        
1643
        R_COPY_NAMETREE(AC.dollarnames);
×
1644
        R_COPY_NAMETREE(AC.exprnames);
×
1645
        R_COPY_NAMETREE(AC.varnames);
×
1646

1647
        R_COPY_LIST(AC.ChannelList);
×
1648
        for ( i=0; i<AC.ChannelList.num; ++i ) {
×
1649
                R_COPY_S(channels[i].name,char*);
×
1650
                channels[i].handle = ReOpenFile(channels[i].name);
×
1651
        }
1652
        AC.ChannelList.message = "channel buffer";
×
1653

1654
        AC.DubiousList.lijst = 0;
×
1655
        AC.DubiousList.message = "ambiguous variable";
×
1656
        AC.DubiousList.num =
×
1657
        AC.DubiousList.maxnum =
×
1658
        AC.DubiousList.numglobal =
×
1659
        AC.DubiousList.numtemp =
×
1660
        AC.DubiousList.numclear = 0;
×
1661

1662
        R_COPY_LIST(AC.FunctionList);
×
1663
        for ( i=0; i<AC.FunctionList.num; ++i ) {
×
1664
                if ( functions[i].tabl ) {
×
1665
                        TABLES tabl;
×
1666
                        R_COPY_B(tabl, sizeof(struct TaBlEs), TABLES);
×
1667
                        functions[i].tabl = tabl;
×
1668
                        if ( tabl->tablepointers ) {
×
1669
                                if ( tabl->sparse ) {
×
1670
                                        R_COPY_B(tabl->tablepointers,
×
1671
                                                tabl->reserved*sizeof(WORD)*(tabl->numind+TABLEEXTENSION),
1672
                                                WORD*);
×
1673
                                }
1674
                                else {
1675
                                        R_COPY_B(tabl->tablepointers, 
×
1676
                                                TABLEEXTENSION*sizeof(WORD)*(tabl->totind), WORD*);
×
1677
                                }
1678
                        }
1679
                        org = (UBYTE*)tabl->prototype;
×
1680
#ifdef WITHPTHREADS
1681
                        R_COPY_B(tabl->prototype, tabl->prototypeSize, WORD**);
1682
                        ofs = (UBYTE*)tabl->prototype - org;
1683
                        for ( j=0; j<AM.totalnumberofthreads; ++j ) {
1684
                                if ( tabl->prototype[j] ) {
1685
                                        tabl->prototype[j] = (WORD*)((UBYTE*)tabl->prototype[j] + ofs);
1686
                                }
1687
                        }
1688
                        if ( tabl->pattern ) {
1689
                                tabl->pattern = (WORD**)((UBYTE*)tabl->pattern + ofs);
1690
                                for ( j=0; j<AM.totalnumberofthreads; ++j ) {
1691
                                        if ( tabl->pattern[j] ) {
1692
                                                tabl->pattern[j] = (WORD*)((UBYTE*)tabl->pattern[j] + ofs);
1693
                                        }
1694
                                }
1695
                        }
1696
#else
1697
                        ofs = tabl->pattern - tabl->prototype;
1698
                        R_COPY_B(tabl->prototype, tabl->prototypeSize, WORD*);
1699
                        if ( tabl->pattern ) {
1700
                                tabl->pattern = tabl->prototype + ofs;
1701
                        }
1702
#endif
1703
                        R_COPY_B(tabl->mm, tabl->numind*(LONG)sizeof(MINMAX), MINMAX*);
×
1704
                        R_COPY_B(tabl->flags, tabl->numind*(LONG)sizeof(WORD), WORD*);
×
1705
                        if ( tabl->sparse ) {
×
1706
                                R_COPY_B(tabl->boomlijst, tabl->MaxTreeSize*(LONG)sizeof(COMPTREE), COMPTREE*);
×
1707
                                R_COPY_S(tabl->argtail,UBYTE*);
×
1708
                        }
1709
                        R_COPY_B(tabl->buffers, tabl->bufferssize*(LONG)sizeof(WORD), WORD*);
×
1710
                        if ( tabl->spare ) {
×
1711
                                TABLES spare;
×
1712
                                R_COPY_B(spare, sizeof(struct TaBlEs), TABLES);
×
1713
                                tabl->spare = spare;
×
1714
                                if ( spare->tablepointers ) {
×
1715
                                        if ( spare->sparse ) {
×
1716
                                                R_COPY_B(spare->tablepointers,
×
1717
                                                        spare->reserved*sizeof(WORD)*(spare->numind+TABLEEXTENSION),
1718
                                                        WORD*);
×
1719
                                        }
1720
                                        else {
1721
                                                R_COPY_B(spare->tablepointers,
×
1722
                                                        TABLEEXTENSION*sizeof(WORD)*(spare->totind), WORD*);
×
1723
                                        }
1724
                                }
1725
                                spare->prototype = tabl->prototype;
×
1726
                                spare->pattern = tabl->pattern;
×
1727
                                R_COPY_B(spare->mm, spare->numind*(LONG)sizeof(MINMAX), MINMAX*);
×
1728
                                R_COPY_B(spare->flags, spare->numind*(LONG)sizeof(WORD), WORD*);
×
1729
                                if ( tabl->sparse ) {
×
1730
                                        R_COPY_B(spare->boomlijst, spare->MaxTreeSize*(LONG)sizeof(COMPTREE), COMPTREE*);
×
1731
                                        spare->argtail = tabl->argtail;
×
1732
                                }
1733
                                spare->spare = tabl;
×
1734
                                R_COPY_B(spare->buffers, spare->bufferssize*(LONG)sizeof(WORD), WORD*);
×
1735
                        }
1736
                }
1737
        }
1738
        AC.FunctionList.message = "function";
×
1739

1740
        R_COPY_LIST(AC.ExpressionList);
×
1741
        for ( i=0; i<AC.ExpressionList.num; ++i ) {
×
1742
                EXPRESSIONS ex = Expressions + i;
×
1743
                if ( ex->renum ) {
×
1744
                        R_COPY_B(ex->renum, sizeof(struct ReNuMbEr), RENUMBER);
×
1745
                        org = (UBYTE*)ex->renum->symb.lo;
×
1746
                        R_SET(size, size_t);
×
1747
                        R_COPY_B(ex->renum->symb.lo, size, WORD*);
×
1748
                        ofs = (UBYTE*)ex->renum->symb.lo - org;
×
1749
                        ex->renum->symb.start = (WORD*)((UBYTE*)ex->renum->symb.start + ofs);
×
1750
                        ex->renum->symb.hi = (WORD*)((UBYTE*)ex->renum->symb.hi + ofs);
×
1751
                        ex->renum->indi.lo = (WORD*)((UBYTE*)ex->renum->indi.lo + ofs);
×
1752
                        ex->renum->indi.start = (WORD*)((UBYTE*)ex->renum->indi.start + ofs);
×
1753
                        ex->renum->indi.hi = (WORD*)((UBYTE*)ex->renum->indi.hi + ofs);
×
1754
                        ex->renum->vect.lo = (WORD*)((UBYTE*)ex->renum->vect.lo + ofs);
×
1755
                        ex->renum->vect.start = (WORD*)((UBYTE*)ex->renum->vect.start + ofs);
×
1756
                        ex->renum->vect.hi = (WORD*)((UBYTE*)ex->renum->vect.hi + ofs);
×
1757
                        ex->renum->func.lo = (WORD*)((UBYTE*)ex->renum->func.lo + ofs);
×
1758
                        ex->renum->func.start = (WORD*)((UBYTE*)ex->renum->func.start + ofs);
×
1759
                        ex->renum->func.hi = (WORD*)((UBYTE*)ex->renum->func.hi + ofs);
×
1760
                        ex->renum->symnum = (WORD*)((UBYTE*)ex->renum->symnum + ofs);
×
1761
                        ex->renum->indnum = (WORD*)((UBYTE*)ex->renum->indnum + ofs);
×
1762
                        ex->renum->vecnum = (WORD*)((UBYTE*)ex->renum->vecnum + ofs);
×
1763
                        ex->renum->funnum = (WORD*)((UBYTE*)ex->renum->funnum + ofs);
×
1764
                }
1765
                if ( ex->bracketinfo ) {
×
1766
                        R_COPY_B(ex->bracketinfo, sizeof(BRACKETINFO), BRACKETINFO*);
×
1767
                        R_COPY_B(ex->bracketinfo->indexbuffer, ex->bracketinfo->indexbuffersize*sizeof(BRACKETINDEX), BRACKETINDEX*);
×
1768
                        R_COPY_B(ex->bracketinfo->bracketbuffer, ex->bracketinfo->bracketbuffersize*sizeof(WORD), WORD*);
×
1769
                }
1770
                if ( ex->newbracketinfo ) {
×
1771
                        R_COPY_B(ex->newbracketinfo, sizeof(BRACKETINFO), BRACKETINFO*);
×
1772
                        R_COPY_B(ex->newbracketinfo->indexbuffer, ex->newbracketinfo->indexbuffersize*sizeof(BRACKETINDEX), BRACKETINDEX*);
×
1773
                        R_COPY_B(ex->newbracketinfo->bracketbuffer, ex->newbracketinfo->bracketbuffersize*sizeof(WORD), WORD*);
×
1774
                }
1775
#ifdef WITHPTHREADS
1776
                ex->renumlists = 0;
1777
#else
1778
                ex->renumlists = AN.dummyrenumlist;
1779
#endif
1780
                if ( ex->inmem ) {
×
1781
                        R_SET(size, size_t);
×
1782
                        R_COPY_B(ex->inmem, size, WORD*);
×
1783
                }
1784
        }
1785
        AC.ExpressionList.message = "expression";
×
1786

1787
        R_COPY_LIST(AC.IndexList);
×
1788
        AC.IndexList.message = "index";
×
1789
        R_COPY_LIST(AC.SetElementList);
×
1790
        AC.SetElementList.message = "set element";
×
1791
        R_COPY_LIST(AC.SetList);
×
1792
        AC.SetList.message = "set";
×
1793
        R_COPY_LIST(AC.SymbolList);
×
1794
        AC.SymbolList.message = "symbol";
×
1795
        R_COPY_LIST(AC.VectorList);
×
1796
        AC.VectorList.message = "vector";
×
1797

1798
        AC.PotModDolList = PotModDolListBackup;
×
1799
        AC.ModOptDolList = ModOptDolListBackup;
×
1800

1801
        R_COPY_LIST(AC.TableBaseList);
×
1802
        for ( i=0; i<AC.TableBaseList.num; ++i ) {
×
1803
                if ( tablebases[i].iblocks ) {
×
1804
                        R_COPY_B(tablebases[i].iblocks, tablebases[i].info.numberofindexblocks*sizeof(INDEXBLOCK*),INDEXBLOCK**);
×
1805
                        for ( j=0; j<tablebases[i].info.numberofindexblocks; ++j ) {
×
1806
                                if ( tablebases[i].iblocks[j] ) {
×
1807
                                        R_COPY_B(tablebases[i].iblocks[j], sizeof(INDEXBLOCK), INDEXBLOCK*);
×
1808
                                }
1809
                        }
1810
                }
1811
                if ( tablebases[i].nblocks ) {
×
1812
                        R_COPY_B(tablebases[i].nblocks, tablebases[i].info.numberofnamesblocks*sizeof(NAMESBLOCK*),NAMESBLOCK**);
×
1813
                        for ( j=0; j<tablebases[i].info.numberofindexblocks; ++j ) {
×
1814
                                if ( tablebases[i].nblocks[j] ) {
×
1815
                                        R_COPY_B(tablebases[i].nblocks[j], sizeof(NAMESBLOCK), NAMESBLOCK*);
×
1816
                                }
1817
                        }
1818
                }
1819
                /* reopen file */
1820
                if ( ( tablebases[i].handle = fopen(tablebases[i].fullname, "r+b") ) == NULL ) {
×
1821
                        MesPrint("ERROR: Could not reopen tablebase %s!",tablebases[i].name);
×
1822
                        Terminate(-1);
×
1823
                }
1824
                R_COPY_S(tablebases[i].name,char*);
×
1825
                R_COPY_S(tablebases[i].fullname,char*);
×
1826
                R_COPY_S(tablebases[i].tablenames,char*);
×
1827
        }
1828
        AC.TableBaseList.message = "list of tablebases";
×
1829

1830
        R_COPY_LIST(AC.cbufList);
×
1831
        for ( i=0; i<AC.cbufList.num; ++i ) {
×
1832
                org = (UBYTE*)cbuf[i].Buffer;
×
1833
                R_COPY_B(cbuf[i].Buffer, cbuf[i].BufferSize*sizeof(WORD), WORD*);
×
1834
                ofs = (UBYTE*)cbuf[i].Buffer - org;
×
1835
                cbuf[i].Top = (WORD*)((UBYTE*)cbuf[i].Top + ofs);
×
1836
                cbuf[i].Pointer = (WORD*)((UBYTE*)cbuf[i].Pointer + ofs);
×
1837
                R_COPY_B(cbuf[i].lhs, cbuf[i].maxlhs*(LONG)sizeof(WORD*), WORD**);
×
1838
                for ( j=1; j<=cbuf[i].numlhs; ++j ) {
×
1839
                        if ( cbuf[i].lhs[j] ) cbuf[i].lhs[j] = (WORD*)((UBYTE*)cbuf[i].lhs[j] + ofs);
×
1840
                }
1841
                org = (UBYTE*)cbuf[i].rhs;
×
1842
                R_COPY_B(cbuf[i].rhs, cbuf[i].maxrhs*(LONG)(sizeof(WORD*)+2*sizeof(LONG)+2*sizeof(WORD)), WORD**);
×
1843
                for ( j=1; j<=cbuf[i].numrhs; ++j ) {
×
1844
                        if ( cbuf[i].rhs[j] ) cbuf[i].rhs[j] = (WORD*)((UBYTE*)cbuf[i].rhs[j] + ofs);
×
1845
                }
1846
                ofs = (UBYTE*)cbuf[i].rhs - org;
×
1847
                cbuf[i].CanCommu = (LONG*)((UBYTE*)cbuf[i].CanCommu + ofs);
×
1848
                cbuf[i].NumTerms = (LONG*)((UBYTE*)cbuf[i].NumTerms + ofs);
×
1849
                cbuf[i].numdum = (WORD*)((UBYTE*)cbuf[i].numdum + ofs);
×
1850
                cbuf[i].dimension = (WORD*)((UBYTE*)cbuf[i].dimension + ofs);
×
1851
                if ( cbuf[i].boomlijst ) {
×
1852
                        R_COPY_B(cbuf[i].boomlijst, cbuf[i].MaxTreeSize*sizeof(COMPTREE), COMPTREE*);
×
1853
                }
1854
        }
1855
        AC.cbufList.message = "compiler buffer";
×
1856

1857
        R_COPY_LIST(AC.AutoSymbolList);
×
1858
        AC.AutoSymbolList.message = "autosymbol";
×
1859
        R_COPY_LIST(AC.AutoIndexList);
×
1860
        AC.AutoIndexList.message = "autoindex";
×
1861
        R_COPY_LIST(AC.AutoVectorList);
×
1862
        AC.AutoVectorList.message = "autovector";
×
1863
        R_COPY_LIST(AC.AutoFunctionList);
×
1864
        AC.AutoFunctionList.message = "autofunction";
×
1865

1866
        R_COPY_NAMETREE(AC.autonames);
×
1867

1868
        AC.Symbols = &(AC.SymbolList);
×
1869
        AC.Indices = &(AC.IndexList);
×
1870
        AC.Vectors = &(AC.VectorList);
×
1871
        AC.Functions = &(AC.FunctionList);
×
1872
        AC.activenames = &(AC.varnames);
×
1873

1874
        org = (UBYTE*)AC.Streams;
×
1875
        R_COPY_B(AC.Streams, AC.MaxNumStreams*(LONG)sizeof(STREAM), STREAM*);
×
1876
        for ( i=0; i<AC.NumStreams; ++i ) {
×
1877
                if ( AC.Streams[i].type != FILESTREAM ) {
×
1878
                        UBYTE *org2;
×
1879
                        org2 = AC.Streams[i].buffer;
×
1880
                        if ( AC.Streams[i].inbuffer ) {
×
1881
                                R_COPY_B(AC.Streams[i].buffer, AC.Streams[i].inbuffer, UBYTE*);
×
1882
                        }
1883
                        ofs = AC.Streams[i].buffer - org2;
×
1884
                        AC.Streams[i].pointer += ofs;
×
1885
                        AC.Streams[i].top += ofs;
×
1886
                }
1887
                else {
1888
                        p = (unsigned char*)p + AC.Streams[i].inbuffer;
×
1889
                }
1890
                AC.Streams[i].buffersize = AC.Streams[i].inbuffer;
×
1891
                R_COPY_S(AC.Streams[i].FoldName,UBYTE*);
×
1892
                R_COPY_S(AC.Streams[i].name,UBYTE*);
×
1893
                if ( AC.Streams[i].type == PREVARSTREAM || AC.Streams[i].type == DOLLARSTREAM ) {
×
1894
                        AC.Streams[i].pname = AC.Streams[i].name;
×
1895
                }
1896
                else if ( AC.Streams[i].type == FILESTREAM ) {
×
1897
                        UBYTE *org2;
×
1898
                        org2 = AC.Streams[i].buffer;
×
1899
                        AC.Streams[i].buffer = (UBYTE*)Malloc1(AC.Streams[i].buffersize, "buffer");
×
1900
                        ofs = AC.Streams[i].buffer - org2;
×
1901
                        AC.Streams[i].pointer += ofs;
×
1902
                        AC.Streams[i].top += ofs;
×
1903

1904
                        /* open file except for already opened main input file */
1905
                        if ( i ) {
×
1906
                                AC.Streams[i].handle = OpenFile((char *)(AC.Streams[i].name));
×
1907
                                if ( AC.Streams[i].handle == -1 ) {
×
1908
                                        MesPrint("ERROR: Could not reopen stream %s!",AC.Streams[i].name);
×
1909
                                        Terminate(-1);
×
1910
                                }
1911
                        }
1912
                        
1913
                        PUTZERO(pos);
×
1914
                        ADDPOS(pos, AC.Streams[i].bufferposition);
×
1915
                        SeekFile(AC.Streams[i].handle, &pos, SEEK_SET);
×
1916

1917
                        AC.Streams[i].inbuffer = ReadFile(AC.Streams[i].handle, AC.Streams[i].buffer, AC.Streams[i].inbuffer);
×
1918

1919
                        SETBASEPOSITION(pos, AC.Streams[i].fileposition);
×
1920
                        SeekFile(AC.Streams[i].handle, &pos, SEEK_SET);
×
1921
                }
1922
                /* 
1923
                 * Ideally, we should check if we have a type PREREADSTREAM, PREREADSTREAM2, and
1924
                 * PRECALCSTREAM here. If so, we should free element name and point it
1925
                 * to the name element of the embracing stream's struct. In practice,
1926
                 * this is undoable without adding new data to STREAM. Since we create
1927
                 * only a small memory leak here (some few byte for each existing
1928
                 * stream of these types) and only once when we do a recovery, we
1929
                 * tolerate this leak and keep it STREAM as it is.
1930
                 */
1931
        }
1932
        ofs = (UBYTE*)AC.Streams - org;
×
1933
        AC.CurrentStream = (STREAM*)((UBYTE*)AC.CurrentStream + ofs);
×
1934

1935
        if ( AC.termstack ) {
×
1936
                R_COPY_B(AC.termstack, AC.maxtermlevel*(LONG)sizeof(LONG), LONG*);
×
1937
        }
1938

1939
        if ( AC.termsortstack ) {
×
1940
                R_COPY_B(AC.termsortstack, AC.maxtermlevel*(LONG)sizeof(LONG), LONG*);
×
1941
        }
1942

1943
        /* exception: here we also change values from struct AM */
1944
        R_COPY_B(AC.cmod, AM.MaxTal*4*(LONG)sizeof(UWORD), UWORD*);
×
1945
        AM.gcmod = AC.cmod + AM.MaxTal;
×
1946
        AC.powmod = AM.gcmod + AM.MaxTal;
×
1947
        AM.gpowmod = AC.powmod + AM.MaxTal;
×
1948

1949
        AC.modpowers = 0;
×
1950
        AC.halfmod = 0;
×
1951

1952
        /* we don't care about AC.ProtoType/WildC */
1953

1954
        if ( AC.IfHeap ) {
×
1955
                ofs = AC.IfStack - AC.IfHeap;
×
1956
                R_COPY_B(AC.IfHeap, (LONG)sizeof(LONG)*(AC.MaxIf+1), LONG*);
×
1957
                AC.IfStack = AC.IfHeap + ofs;
×
1958
                R_COPY_B(AC.IfCount, (LONG)sizeof(LONG)*(AC.MaxIf+1), LONG*);
×
1959
        }
1960

1961
        org = AC.iBuffer;
×
1962
        size = AC.iStop - AC.iBuffer + 2;
×
1963
        R_COPY_B(AC.iBuffer, size, UBYTE*);
×
1964
        ofs = AC.iBuffer - org;
×
1965
        AC.iPointer += ofs;
×
1966
        AC.iStop += ofs;
×
1967

1968
        if ( AC.LabelNames ) {
×
1969
                org = (UBYTE*)AC.LabelNames;
×
1970
                R_COPY_B(AC.LabelNames, AC.MaxLabels*(LONG)(sizeof(UBYTE*)+sizeof(WORD)), UBYTE**);
×
1971
                for ( i=0; i<AC.NumLabels; ++i ) {
×
1972
                        R_COPY_S(AC.LabelNames[i],UBYTE*);
×
1973
                }
1974
                ofs = (UBYTE*)AC.LabelNames - org;
×
1975
                AC.Labels = (int*)((UBYTE*)AC.Labels + ofs);
×
1976
        }
1977
        
1978
        R_COPY_B(AC.FixIndices, AM.OffsetIndex*(LONG)sizeof(WORD), WORD*);
×
1979

1980
        if ( AC.termsumcheck ) {
×
1981
                R_COPY_B(AC.termsumcheck, AC.maxtermlevel*(LONG)sizeof(WORD), WORD*);
×
1982
        }
1983

1984
        R_COPY_B(AC.WildcardNames, AC.WildcardBufferSize, UBYTE*);
×
1985

1986
        if ( AC.tokens ) {
×
1987
                size = AC.toptokens - AC.tokens;
×
1988
                if ( size ) {
×
1989
                        org = (UBYTE*)AC.tokens;
×
1990
                        R_COPY_B(AC.tokens, size, SBYTE*);
×
1991
                        ofs = (UBYTE*)AC.tokens - org;
×
1992
                        AC.endoftokens += ofs;
×
1993
                        AC.toptokens += ofs;
×
1994
                }
1995
                else {
1996
                        AC.tokens = 0;
×
1997
                        AC.endoftokens = AC.tokens;
×
1998
                        AC.toptokens = AC.tokens;
×
1999
                }
2000
        }
2001

2002
        R_COPY_B(AC.tokenarglevel, AM.MaxParLevel*(LONG)sizeof(WORD), WORD*);
×
2003

2004
        AC.modinverses = 0;
×
2005

2006
        R_COPY_S(AC.Fortran90Kind,UBYTE *);
×
2007

2008
#ifdef WITHPTHREADS
2009
        if ( AC.inputnumbers ) {
2010
                org = (UBYTE*)AC.inputnumbers;
2011
                R_COPY_B(AC.inputnumbers, AC.sizepfirstnum*(LONG)(sizeof(WORD)+sizeof(LONG)), LONG*);
2012
                ofs = (UBYTE*)AC.inputnumbers - org;
2013
                AC.pfirstnum = (WORD*)((UBYTE*)AC.pfirstnum + ofs);
2014
        }
2015
        AC.halfmodlock = dummylock;
2016
#endif /* ifdef WITHPTHREADS */
2017

2018
        if ( AC.IfSumCheck ) {
×
2019
                R_COPY_B(AC.IfSumCheck, (LONG)sizeof(WORD)*(AC.MaxIf+1), WORD*);
×
2020
        }
2021
        if ( AC.CommuteInSet ) {
×
2022
                R_COPY_B(AC.CommuteInSet, (LONG)sizeof(WORD)*(AC.SizeCommuteInSet+1), WORD*);
×
2023
        }
2024

2025
        AC.LogHandle = oldLogHandle;
×
2026

2027
        R_COPY_S(AC.CheckpointRunAfter,char*);
×
2028
        R_COPY_S(AC.CheckpointRunBefore,char*);
×
2029

2030
        R_COPY_S(AC.extrasym,UBYTE *);
×
2031

2032
#ifdef PRINTDEBUG
2033
        print_C();
2034
#endif
2035

2036
        /*#] AC : */ 
2037
        /*#[ AP : */
2038

2039
        /* #[ AP free pointers */
2040

2041
        /* AP will be overwritten by data from the recovery file, therefore
2042
         * dynamically allocated memory must be freed first. */
2043

2044
        for ( i=0; i<AP.DollarList.num; ++i ) {
×
2045
                if ( Dollars[i].size ) {
×
2046
                        R_FREE(Dollars[i].where);
×
2047
                }
2048
                CleanDollarFactors(Dollars+i);
×
2049
        }
2050
        R_FREE(AP.DollarList.lijst);
×
2051

2052
        for ( i=0; i<AP.PreVarList.num; ++i ) {
×
2053
                R_FREE(PreVar[i].name);
×
2054
        }
2055
        R_FREE(AP.PreVarList.lijst);
×
2056

2057
        for ( i=0; i<AP.LoopList.num; ++i ) {
×
2058
                R_FREE(DoLoops[i].p.buffer);
×
2059
                if ( DoLoops[i].dollarname ) {
×
2060
                        R_FREE(DoLoops[i].dollarname);
×
2061
                }
2062
        }
2063
        R_FREE(AP.LoopList.lijst);
×
2064
        
2065
        for ( i=0; i<AP.ProcList.num; ++i ) {
×
2066
                R_FREE(Procedures[i].p.buffer);
×
2067
                R_FREE(Procedures[i].name);
×
2068
        }
2069
        R_FREE(AP.ProcList.lijst);
×
2070

2071
        for ( i=1; i<=AP.PreSwitchLevel; ++i ) {
×
2072
                R_FREE(AP.PreSwitchStrings[i]);
×
2073
        }
2074
        R_FREE(AP.PreSwitchStrings);
×
2075
        R_FREE(AP.preStart);
×
2076
        R_FREE(AP.procedureExtension);
×
2077
        R_FREE(AP.cprocedureExtension);
×
2078
        R_FREE(AP.PreIfStack);
×
2079
        R_FREE(AP.PreSwitchModes);
×
2080
        R_FREE(AP.PreTypes);
×
2081

2082
        /* #] AP free pointers */
2083
        
2084
        /* first we copy AP as a whole and then restore the pointer structures step
2085
           by step. */
2086

2087
        AP = *((struct P_const*)p); p = (unsigned char*)p + sizeof(struct P_const);
×
2088
#ifdef WITHPTHREADS
2089
        AP.PreVarLock = dummylock;
2090
#endif
2091

2092
        R_COPY_LIST(AP.DollarList);
×
2093
        for ( i=0; i<AP.DollarList.num; ++i ) {
×
2094
                DOLLARS d = Dollars + i;
×
2095
                size = d->size * sizeof(WORD);
×
2096
                if ( size && d->where && d->where != oldAMdollarzero ) {
×
2097
                        R_COPY_B(d->where, size, void*);
×
2098
                }
2099
#ifdef WITHPTHREADS
2100
                d->pthreadslockread = dummylock;
2101
                d->pthreadslockwrite = dummylock;
2102
#endif
2103
                if ( d->nfactors > 1 ) {
×
2104
                        R_COPY_B(d->factors,sizeof(FACDOLLAR)*d->nfactors,FACDOLLAR*);
×
2105
                        for ( j = 0; j < d->nfactors; j++ ) {
×
2106
                                if ( d->factors[j].size > 0 ) {
×
2107
                                        R_COPY_B(d->factors[i].where,sizeof(WORD)*(d->factors[j].size+1),WORD*);
×
2108
                                }
2109
                        }
2110
                }
2111
        }
2112
        AP.DollarList.message = "$-variable";
×
2113

2114
        R_COPY_LIST(AP.PreVarList);
×
2115
        for ( i=0; i<AP.PreVarList.num; ++i ) {
×
2116
                R_SET(size, size_t);
×
2117
                org = PreVar[i].name;
×
2118
                R_COPY_B(PreVar[i].name, size, UBYTE*);
×
2119
                ofs = PreVar[i].name - org;
×
2120
                if ( PreVar[i].value ) PreVar[i].value += ofs;
×
2121
                if ( PreVar[i].argnames ) PreVar[i].argnames += ofs;
×
2122
        }
2123
        AP.PreVarList.message = "PreVariable";
×
2124

2125
        R_COPY_LIST(AP.LoopList);
×
2126
        for ( i=0; i<AP.LoopList.num; ++i ) {
×
2127
                org = DoLoops[i].p.buffer;
×
2128
                R_COPY_B(DoLoops[i].p.buffer, DoLoops[i].p.size, UBYTE*);
×
2129
                ofs = DoLoops[i].p.buffer - org;
×
2130
                if ( DoLoops[i].name ) DoLoops[i].name += ofs;
×
2131
                if ( DoLoops[i].vars ) DoLoops[i].vars += ofs;
×
2132
                if ( DoLoops[i].contents ) DoLoops[i].contents += ofs;
×
2133
                if ( DoLoops[i].type == ONEEXPRESSION ) {
×
2134
                        R_COPY_S(DoLoops[i].dollarname,UBYTE*);
×
2135
                }
2136
        }
2137
        AP.LoopList.message = "doloop";
×
2138

2139
        R_COPY_LIST(AP.ProcList);
×
2140
        for ( i=0; i<AP.ProcList.num; ++i ) {
×
2141
                if ( Procedures[i].p.size ) {
×
2142
                        if ( Procedures[i].loadmode != 1 ) {
×
2143
                                R_COPY_B(Procedures[i].p.buffer, Procedures[i].p.size, UBYTE*);
×
2144
                        }
2145
                        else {
2146
                                R_SET(j, int);
×
2147
                                Procedures[i].p.buffer = Procedures[j].p.buffer;
×
2148
                        }
2149
                }
2150
                R_COPY_S(Procedures[i].name,UBYTE*);
×
2151
        }
2152
        AP.ProcList.message = "procedure";
×
2153

2154
        size = (AP.NumPreSwitchStrings+1)*(LONG)sizeof(UBYTE*);
×
2155
        R_COPY_B(AP.PreSwitchStrings, size, UBYTE**);
×
2156
        for ( i=1; i<=AP.PreSwitchLevel; ++i ) {
×
2157
                R_COPY_S(AP.PreSwitchStrings[i],UBYTE*);
×
2158
        }
2159

2160
        org = AP.preStart;
×
2161
        R_COPY_B(AP.preStart, AP.pSize, UBYTE*);
×
2162
        ofs = AP.preStart - org;
×
2163
        if ( AP.preFill ) AP.preFill += ofs;
×
2164
        if ( AP.preStop ) AP.preStop += ofs;
×
2165

2166
        R_COPY_S(AP.procedureExtension,UBYTE*);
×
2167
        R_COPY_S(AP.cprocedureExtension,UBYTE*);
×
2168

2169
        R_COPY_B(AP.PreAssignStack,AP.MaxPreAssignLevel*(LONG)sizeof(LONG),LONG*);
×
2170
        R_COPY_B(AP.PreIfStack, AP.MaxPreIfLevel*(LONG)sizeof(int), int*);
×
2171
        R_COPY_B(AP.PreSwitchModes, (AP.NumPreSwitchStrings+1)*(LONG)sizeof(int), int*);
×
2172
        R_COPY_B(AP.PreTypes, (AP.MaxPreTypes+1)*(LONG)sizeof(int), int*);
×
2173

2174
#ifdef PRINTDEBUG
2175
        print_P();
2176
#endif
2177

2178
        /*#] AP : */ 
2179
        /*#[ AR : */
2180

2181
        R_SET(ofs,LONG);
×
2182
        if ( ofs ) {
×
2183
                AR.infile = AR.Fscr+1;
×
2184
                AR.outfile = AR.Fscr;
×
2185
                AR.hidefile = AR.Fscr+2;
×
2186
        }
2187
        else {
2188
                AR.infile = AR.Fscr;
×
2189
                AR.outfile = AR.Fscr+1;
×
2190
                AR.hidefile = AR.Fscr+2;
×
2191
        }
2192

2193
        /* #[ AR free pointers */
2194

2195
        /* Parts of AR will be overwritten by data from the recovery file, therefore
2196
         * dynamically allocated memory must be freed first. */
2197

2198
        namebufout = AR.outfile->name;
×
2199
        namebufhide = AR.hidefile->name;
×
2200
        R_FREE(AR.outfile->PObuffer);
×
2201
#ifdef WITHZLIB
2202
        R_FREE(AR.outfile->zsp);
×
2203
        R_FREE(AR.outfile->ziobuffer);
×
2204
#endif
2205
        namebufhide = AR.hidefile->name;
×
2206
        R_FREE(AR.hidefile->PObuffer);
×
2207
#ifdef WITHZLIB
2208
        R_FREE(AR.hidefile->zsp);
×
2209
        R_FREE(AR.hidefile->ziobuffer);
×
2210
#endif
2211
        /* no files should be opened -> nothing to do with handle */
2212

2213
        /* #] AR free pointers */
2214
        
2215
        /* outfile */
2216
        R_SET(*AR.outfile, FILEHANDLE);
×
2217
        org = (UBYTE*)AR.outfile->PObuffer;
×
2218
        size = AR.outfile->POfull - AR.outfile->PObuffer;
×
2219
        AR.outfile->PObuffer = (WORD*)Malloc1(AR.outfile->POsize, "PObuffer");
×
2220
        if ( size ) {
×
2221
                memcpy(AR.outfile->PObuffer, p, size*sizeof(WORD));
×
2222
                p = (unsigned char*)p + size*sizeof(WORD);
×
2223
        }
2224
        ofs = (UBYTE*)AR.outfile->PObuffer - org;
×
2225
        AR.outfile->POstop = (WORD*)((UBYTE*)AR.outfile->POstop + ofs);
×
2226
        AR.outfile->POfill = (WORD*)((UBYTE*)AR.outfile->POfill + ofs);
×
2227
        AR.outfile->POfull = (WORD*)((UBYTE*)AR.outfile->POfull + ofs);
×
2228
        AR.outfile->name = namebufout;
×
2229
#ifdef WITHPTHREADS
2230
        AR.outfile->wPObuffer = AR.outfile->PObuffer;
2231
        AR.outfile->wPOstop = AR.outfile->POstop;
2232
        AR.outfile->wPOfill = AR.outfile->POfill;
2233
        AR.outfile->wPOfull = AR.outfile->POfull;
2234
#endif
2235
#ifdef WITHZLIB
2236
        /* zsp and ziobuffer will be allocated when used */
2237
        AR.outfile->zsp = 0;
×
2238
        AR.outfile->ziobuffer = 0;
×
2239
#endif
2240
        /* reopen old outfile */
2241
#ifdef WITHMPI
2242
        if(PF.me==MASTER)
2243
#endif
2244
        if ( AR.outfile->handle >= 0 ) {
×
2245
                if ( CopyFile(sortfile, AR.outfile->name) ) {
×
2246
                        MesPrint("ERROR: Could not copy old output sort file %s!",sortfile);
×
2247
                        Terminate(-1);
×
2248
                }
2249
                AR.outfile->handle = ReOpenFile(AR.outfile->name);
×
2250
                if ( AR.outfile->handle == -1 ) {
×
2251
                        MesPrint("ERROR: Could not reopen output sort file %s!",AR.outfile->name);
×
2252
                        Terminate(-1);
×
2253
                }
2254
                SeekFile(AR.outfile->handle, &AR.outfile->POposition, SEEK_SET);
×
2255
        }
2256

2257
        /* hidefile */
2258
        R_SET(*AR.hidefile, FILEHANDLE);
×
2259
        AR.hidefile->name = namebufhide;
×
2260
        if ( AR.hidefile->PObuffer ) {
×
2261
                org = (UBYTE*)AR.hidefile->PObuffer;
×
2262
                size = AR.hidefile->POfull - AR.hidefile->PObuffer;
×
2263
                AR.hidefile->PObuffer = (WORD*)Malloc1(AR.hidefile->POsize, "PObuffer");
×
2264
                if ( size ) {
×
2265
                        memcpy(AR.hidefile->PObuffer, p, size*sizeof(WORD));
×
2266
                        p = (unsigned char*)p + size*sizeof(WORD);
×
2267
                }
2268
                ofs = (UBYTE*)AR.hidefile->PObuffer - org;
×
2269
                AR.hidefile->POstop = (WORD*)((UBYTE*)AR.hidefile->POstop + ofs);
×
2270
                AR.hidefile->POfill = (WORD*)((UBYTE*)AR.hidefile->POfill + ofs);
×
2271
                AR.hidefile->POfull = (WORD*)((UBYTE*)AR.hidefile->POfull + ofs);
×
2272
#ifdef WITHPTHREADS
2273
                AR.hidefile->wPObuffer = AR.hidefile->PObuffer;
2274
                AR.hidefile->wPOstop = AR.hidefile->POstop;
2275
                AR.hidefile->wPOfill = AR.hidefile->POfill;
2276
                AR.hidefile->wPOfull = AR.hidefile->POfull;
2277
#endif
2278
        }
2279
#ifdef WITHZLIB
2280
                /* zsp and ziobuffer will be allocated when used */
2281
                AR.hidefile->zsp = 0;
×
2282
                AR.hidefile->ziobuffer = 0;
×
2283
#endif
2284
        /* reopen old hidefile */
2285
        if ( AR.hidefile->handle >= 0 ) {
×
2286
                if ( CopyFile(hidefile, AR.hidefile->name) ) {
×
2287
                        MesPrint("ERROR: Could not copy old hide file %s!",hidefile);
×
2288
                        Terminate(-1);
×
2289
                }
2290
                AR.hidefile->handle = ReOpenFile(AR.hidefile->name);
×
2291
                if ( AR.hidefile->handle == -1 ) {
×
2292
                        MesPrint("ERROR: Could not reopen hide file %s!",AR.hidefile->name);
×
2293
                        Terminate(-1);
×
2294
                }
2295
                SeekFile(AR.hidefile->handle, &AR.hidefile->POposition, SEEK_SET);
×
2296
        }
2297

2298
        /* store file */
2299
        R_SET(pos, POSITION);
×
2300
        if ( ISNOTZEROPOS(pos) ) {
×
2301
                CloseFile(AR.StoreData.Handle);
×
2302
                R_SET(AR.StoreData, FILEDATA);
×
2303
                if ( CopyFile(storefile, FG.fname) ) {
×
2304
                        MesPrint("ERROR: Could not copy old store file %s!",storefile);
×
2305
                        Terminate(-1);
×
2306
                }
2307
                AR.StoreData.Handle = (WORD)ReOpenFile(FG.fname);
×
2308
                SeekFile(AR.StoreData.Handle, &AR.StoreData.Position, SEEK_SET);
×
2309
        }
2310

2311
        R_SET(AR.DefPosition, POSITION);
×
2312
        R_SET(AR.OldTime, LONG);
×
2313
        R_SET(AR.InInBuf, LONG);
×
2314
        R_SET(AR.InHiBuf, LONG);
×
2315

2316
        R_SET(AR.NoCompress, int);
×
2317
        R_SET(AR.gzipCompress, int);
×
2318

2319
        R_SET(AR.outtohide, int);
×
2320

2321
        R_SET(AR.GetFile, WORD);
×
2322
        R_SET(AR.KeptInHold, WORD);
×
2323
        R_SET(AR.BracketOn, WORD);
×
2324
        R_SET(AR.MaxBracket, WORD);
×
2325
        R_SET(AR.CurDum, WORD);
×
2326
        R_SET(AR.DeferFlag, WORD);
×
2327
        R_SET(AR.TePos, WORD);
×
2328
        R_SET(AR.sLevel, WORD);
×
2329
        R_SET(AR.Stage4Name, WORD);
×
2330
        R_SET(AR.GetOneFile, WORD);
×
2331
        R_SET(AR.PolyFun, WORD);
×
2332
        R_SET(AR.PolyFunInv, WORD);
×
2333
        R_SET(AR.PolyFunType, WORD);
×
2334
        R_SET(AR.PolyFunExp, WORD);
×
2335
        R_SET(AR.PolyFunVar, WORD);
×
2336
        R_SET(AR.PolyFunPow, WORD);
×
2337
        R_SET(AR.Eside, WORD);
×
2338
        R_SET(AR.MaxDum, WORD);
×
2339
        R_SET(AR.level, WORD);
×
2340
        R_SET(AR.expchanged, WORD);
×
2341
        R_SET(AR.expflags, WORD);
×
2342
        R_SET(AR.CurExpr, WORD);
×
2343
        R_SET(AR.SortType, WORD);
×
2344
        R_SET(AR.ShortSortCount, WORD);
×
2345

2346
        /* this is usually done in Process(), but sometimes FORM does not
2347
           end up executing Process() before it uses the AR.CompressPointer,
2348
           so we need to explicitly set it here. */
2349
        AR.CompressPointer = AR.CompressBuffer;
×
2350

2351
#ifdef WITHPTHREADS
2352
        for ( j = 0; j < AM.totalnumberofthreads; j++ ) {
2353
                R_SET(AB[j]->R.wranfnpair1, int);
2354
                R_SET(AB[j]->R.wranfnpair2, int);
2355
                R_SET(AB[j]->R.wranfcall, int);
2356
                R_SET(AB[j]->R.wranfseed, ULONG);
2357
                R_SET(AB[j]->R.wranfia,ULONG*);
2358
                if ( AB[j]->R.wranfia ) {
2359
                        R_COPY_B(AB[j]->R.wranfia, sizeof(ULONG)*AB[j]->R.wranfnpair2, ULONG*);
2360
                }
2361
        }
2362
#else
2363
        R_SET(AR.wranfnpair1, int);
2364
        R_SET(AR.wranfnpair2, int);
2365
        R_SET(AR.wranfcall, int);
2366
        R_SET(AR.wranfseed, ULONG);
2367
        R_SET(AR.wranfia,ULONG*);
2368
        if ( AR.wranfia ) {
2369
                R_COPY_B(AR.wranfia, sizeof(ULONG)*AR.wranfnpair2, ULONG*);
2370
        }
2371
#endif
2372

2373
#ifdef PRINTDEBUG
2374
        print_R();
2375
#endif
2376

2377
        /*#] AR : */ 
2378
        /*#[ AO :*/
2379
/*
2380
        We copy all non-pointer variables.
2381
*/
2382
        l = sizeof(A.O) - ((UBYTE *)(&(A.O.NumInBrack))-(UBYTE *)(&A.O));
×
2383
        memcpy(&(A.O.NumInBrack), p, l); p = (unsigned char*)p + l;
×
2384
/*
2385
        Now the variables in OptimizeResult
2386
*/
2387
        memcpy(&(A.O.OptimizeResult),p,sizeof(OPTIMIZERESULT));
×
2388
                p = (unsigned char*)p + sizeof(OPTIMIZERESULT);
×
2389

2390
        if ( A.O.OptimizeResult.codesize > 0 ) {
×
2391
                R_COPY_B(A.O.OptimizeResult.code,A.O.OptimizeResult.codesize*sizeof(WORD),WORD *);
×
2392
        }
2393
        R_COPY_S(A.O.OptimizeResult.nameofexpr,UBYTE *);
×
2394
/*
2395
        And now the dictionaries. We know how many there are. We also know
2396
        how many elements the array AO.Dictionaries should have.
2397
*/
2398
        if ( AO.SizeDictionaries > 0 ) {
×
2399
                AO.Dictionaries = (DICTIONARY **)Malloc1(AO.SizeDictionaries*sizeof(DICTIONARY *),
×
2400
                                        "Dictionaries");
2401
                for ( i = 0; i < AO.NumDictionaries; i++ ) {
×
2402
                        R_SET(l,LONG)
×
2403
                        AO.Dictionaries[i] = DictFromBytes(p);
×
2404
                        p = (char *)p + l;
×
2405
                }
2406
        }
2407
        /*#] AO :*/ 
2408
#ifdef WITHMPI
2409
        /*#[ PF : */
2410
        {/*Block*/
2411
                int numtasks;
2412
                R_SET(numtasks, int);
2413
                if(numtasks!=PF.numtasks){
2414
                        MesPrint("%d number of tasks expected instead of %d; use mpirun -np %d",
2415
                                                        numtasks,PF.numtasks,numtasks);
2416
                        if(PF.me!=MASTER)
2417
                                remove(RecoveryFilename());
2418
                        Terminate(-1);
2419
                }
2420
        }/*Block*/
2421
        R_SET(PF.rhsInParallel, int);
2422
        R_SET(PF.exprbufsize, int);
2423
        R_SET(PF.log, int);
2424
        /*#] PF : */ 
2425
#endif
2426

2427
#ifdef WITHPTHREADS
2428
        /* read timing information of individual threads */
2429
        R_SET(i, int);
2430
        for ( j=1; j<AM.totalnumberofthreads; ++j ) {
2431
                /* ... and correcting OldTime */
2432
                AB[j]->R.OldTime = -(*((LONG*)p+j));
2433
        }
2434
        WriteTimerInfo((LONG*)p,(LONG *)((unsigned char*)p + i*(LONG)sizeof(LONG)));
2435
        p = (unsigned char*)p + 2*i*(LONG)sizeof(LONG);
2436
#endif /* ifdef WITHPTHREADS */
2437

2438
        if ( fclose(fd) ) return(__LINE__);
×
2439

2440
        M_free(buf,"recovery buffer");
×
2441

2442
        /* cares about data in S_const */
2443
        UpdatePositions();
×
2444
        AT.SS = AT.S0;
×
2445
/*
2446
        Set the checkpoint parameter right for the next checkpoint.
2447
*/
2448
        AC.CheckpointStamp = TimeWallClock(1);
×
2449
        
2450
        done_snapshot = 1;
×
2451
        MesPrint("done."); fflush(0);
×
2452

2453
        return(0);
×
2454
}
2455

2456
/*
2457
          #] DoRecovery : 
2458
          #[ DoSnapshot :
2459
*/
2460

2461
/**
2462
 *  Writes all relevant information for a recovery to the recovery file. It
2463
 *  writes first to an intermediate file and then only if everything went well
2464
 *  it renames this intermediate file to the final recovery file. Then it copies
2465
 *  the sort and store files if necessary.
2466
 *
2467
 *  The data is directly written to file from the structs or struct element.
2468
 *
2469
 *  No data is changed in the global structs and this function should never crash.
2470
 *  Honorably exception might be: not enough memory for the allocation of the
2471
 *  command strings (usually less than 100 bytes), or not enough disk space for
2472
 *  the recovery file and the copies of the hide/scratch/store files.
2473
 *
2474
 *  If something goes wrong, the function returns with a non-zero value.
2475
 */
2476
static int DoSnapshot(int moduletype)
×
2477
{
2478
        GETIDENTITY
2479
        FILE *fd;
×
2480
        POSITION pos;
×
2481
        int i, j;
×
2482
        LONG l;
×
2483
        WORD *w;
×
2484
        void *adr;
×
2485
#ifdef WITHPTHREADS
2486
        LONG *longp,*longpp;
2487
#endif /* ifdef WITHPTHREADS */
2488

2489
        MesPrint("Saving recovery point ... %"); fflush(0);
×
2490
#ifdef PRINTTIMEMARKS
2491
        MesPrint("\n");
2492
#endif
2493

2494
        if ( !(fd = fopen(intermedfile, "wb")) ) return(__LINE__);
×
2495

2496
        /* reserve space in the file for a length field */
2497
        if ( fwrite(&pos, 1, sizeof(POSITION), fd) != sizeof(POSITION) ) return(__LINE__);
×
2498

2499
        /* write moduletype */
2500
        if ( fwrite(&moduletype, 1, sizeof(int), fd) != sizeof(int) ) return(__LINE__);
×
2501

2502
        /*#[ AM :*/
2503

2504
        /* since most values don't change during execution, AM doesn't need to be
2505
         * written as a whole. all values will be correctly set when starting up
2506
         * anyway. only the exceptions need to be taken care of. see MakeGlobal()
2507
         * and PopVariables() in execute.c. */
2508

2509
        ANNOUNCE(AM)
2510
        S_WRITE_B(&AM.hparallelflag, sizeof(int));
×
2511
        S_WRITE_B(&AM.gparallelflag, sizeof(int));
×
2512
        S_WRITE_B(&AM.gCodesFlag, sizeof(int));
×
2513
        S_WRITE_B(&AM.gNamesFlag, sizeof(int));
×
2514
        S_WRITE_B(&AM.gStatsFlag, sizeof(int));
×
2515
        S_WRITE_B(&AM.gTokensWriteFlag, sizeof(int));
×
2516
        S_WRITE_B(&AM.gNoSpacesInNumbers, sizeof(int));
×
2517
        S_WRITE_B(&AM.gIndentSpace, sizeof(WORD));
×
2518
        S_WRITE_B(&AM.gUnitTrace, sizeof(WORD));
×
2519
        S_WRITE_B(&AM.gDefDim, sizeof(int));
×
2520
        S_WRITE_B(&AM.gDefDim4, sizeof(int));
×
2521
        S_WRITE_B(&AM.gncmod, sizeof(WORD));
×
2522
        S_WRITE_B(&AM.gnpowmod, sizeof(WORD));
×
2523
        S_WRITE_B(&AM.gmodmode, sizeof(WORD));
×
2524
        S_WRITE_B(&AM.gOutputMode, sizeof(WORD));
×
2525
        S_WRITE_B(&AM.gCnumpows, sizeof(WORD));
×
2526
        S_WRITE_B(&AM.gOutputSpaces, sizeof(WORD));
×
2527
        S_WRITE_B(&AM.gOutNumberType, sizeof(WORD));
×
2528
        S_WRITE_B(&AM.gfunpowers, sizeof(int));
×
2529
        S_WRITE_B(&AM.gPolyFun, sizeof(WORD));
×
2530
        S_WRITE_B(&AM.gPolyFunInv, sizeof(WORD));
×
2531
        S_WRITE_B(&AM.gPolyFunType, sizeof(WORD));
×
2532
        S_WRITE_B(&AM.gPolyFunExp, sizeof(WORD));
×
2533
        S_WRITE_B(&AM.gPolyFunVar, sizeof(WORD));
×
2534
        S_WRITE_B(&AM.gPolyFunPow, sizeof(WORD));
×
2535
        S_WRITE_B(&AM.gProcessBucketSize, sizeof(LONG));
×
2536
        S_WRITE_B(&AM.OldChildTime, sizeof(LONG));
×
2537
        S_WRITE_B(&AM.OldSecTime, sizeof(LONG));
×
2538
        S_WRITE_B(&AM.OldMilliTime, sizeof(LONG));
×
2539
        S_WRITE_B(&AM.gproperorderflag, sizeof(int));
×
2540
        S_WRITE_B(&AM.gThreadBucketSize, sizeof(LONG));
×
2541
        S_WRITE_B(&AM.gSizeCommuteInSet, sizeof(int));
×
2542
        S_WRITE_B(&AM.gThreadStats, sizeof(int));
×
2543
        S_WRITE_B(&AM.gFinalStats, sizeof(int));
×
2544
        S_WRITE_B(&AM.gThreadsFlag, sizeof(int));
×
2545
        S_WRITE_B(&AM.gThreadBalancing, sizeof(int));
×
2546
        S_WRITE_B(&AM.gThreadSortFileSynch, sizeof(int));
×
2547
        S_WRITE_B(&AM.gProcessStats, sizeof(int));
×
2548
        S_WRITE_B(&AM.gOldParallelStats, sizeof(int));
×
2549
        S_WRITE_B(&AM.gSortType, sizeof(int));
×
2550
        S_WRITE_B(&AM.gShortStatsMax, sizeof(WORD));
×
2551
        S_WRITE_B(&AM.gIsFortran90, sizeof(int));
×
2552
        adr = &AM.dollarzero;
×
2553
        S_WRITE_B(&adr, sizeof(void*));
×
2554
        S_WRITE_B(&AM.gFortran90Kind,sizeof(UBYTE *));
×
2555
        S_WRITE_S(AM.gFortran90Kind);
×
2556

2557
        S_WRITE_S(AM.gextrasym);
×
2558
        S_WRITE_S(AM.ggextrasym);
×
2559

2560
        S_WRITE_B(&AM.PrintTotalSize,sizeof(int));
×
2561
        S_WRITE_B(&AM.fbuffersize,sizeof(int));
×
2562
        S_WRITE_B(&AM.gOldFactArgFlag,sizeof(int));
×
2563
        S_WRITE_B(&AM.ggOldFactArgFlag,sizeof(int));
×
2564

2565
    S_WRITE_B(&AM.gnumextrasym,sizeof(int));
×
2566
    S_WRITE_B(&AM.ggnumextrasym,sizeof(int));
×
2567
        S_WRITE_B(&AM.NumSpectatorFiles,sizeof(int));
×
2568
        S_WRITE_B(&AM.SizeForSpectatorFiles,sizeof(int));
×
2569
    S_WRITE_B(&AM.gOldGCDflag,sizeof(int));
×
2570
    S_WRITE_B(&AM.ggOldGCDflag,sizeof(int));
×
2571
        S_WRITE_B(&AM.gWTimeStatsFlag, sizeof(int));
×
2572

2573
        S_WRITE_B(&AM.Path,sizeof(UBYTE *));
×
2574
        S_WRITE_S(AM.Path);
×
2575

2576
        S_WRITE_B(&AM.FromStdin,sizeof(BOOL));
×
2577

2578
        /*#] AM :*/ 
2579
        /*#[ AC :*/
2580

2581
        /* we write AC as a whole and then write all additional data step by step.
2582
         * AC.DubiousList doesn't need to be treated, because it should be empty. */
2583

2584
        ANNOUNCE(AC)
2585
        S_WRITE_B(&AC, sizeof(struct C_const));
×
2586

2587
        S_WRITE_NAMETREE(AC.dollarnames);
×
2588
        S_WRITE_NAMETREE(AC.exprnames);
×
2589
        S_WRITE_NAMETREE(AC.varnames);
×
2590
        
2591
        S_WRITE_LIST(AC.ChannelList);
×
2592
        for ( i=0; i<AC.ChannelList.num; ++i ) {
×
2593
                S_WRITE_S(channels[i].name);
×
2594
        }
2595

2596
        ANNOUNCE(AC.FunctionList)
2597
        S_WRITE_LIST(AC.FunctionList);
×
2598
        for ( i=0; i<AC.FunctionList.num; ++i ) {
×
2599
                /* if the function is a table */
2600
                if ( functions[i].tabl ) {
×
2601
                        TABLES tabl = functions[i].tabl;
×
2602
                        S_WRITE_B(tabl, sizeof(struct TaBlEs));
×
2603
                        if ( tabl->tablepointers ) {
×
2604
                                if ( tabl->sparse ) {
×
2605
                                        /* sparse tables. reserved holds number of allocated
2606
                                         * elements. the size of an element is numind plus
2607
                                         * TABLEEXTENSION times the size of WORD. */
2608
                                        S_WRITE_B(tabl->tablepointers,
×
2609
                                                tabl->reserved*sizeof(WORD)*(tabl->numind+TABLEEXTENSION));
2610
                                }
2611
                                else {
2612
                                        /* matrix like tables. */
2613
                                        S_WRITE_B(tabl->tablepointers,
×
2614
                                                TABLEEXTENSION*sizeof(WORD)*(tabl->totind));
×
2615
                                }
2616
                        }
2617
                        S_WRITE_B(tabl->prototype, tabl->prototypeSize);
×
2618
                        S_WRITE_B(tabl->mm, tabl->numind*(LONG)sizeof(MINMAX));
×
2619
                        S_WRITE_B(tabl->flags, tabl->numind*(LONG)sizeof(WORD));
×
2620
                        if ( tabl->sparse ) {
×
2621
                                S_WRITE_B(tabl->boomlijst, tabl->MaxTreeSize*(LONG)sizeof(COMPTREE));
×
2622
                                S_WRITE_S(tabl->argtail);
×
2623
                        }
2624
                        S_WRITE_B(tabl->buffers, tabl->bufferssize*(LONG)sizeof(WORD));
×
2625
                        if ( tabl->spare ) {
×
2626
                                TABLES spare = tabl->spare;
×
2627
                                S_WRITE_B(spare, sizeof(struct TaBlEs));
×
2628
                                if ( spare->tablepointers ) {
×
2629
                                        if ( spare->sparse ) {
×
2630
                                                /* sparse tables */
2631
                                                S_WRITE_B(spare->tablepointers,
×
2632
                                                        spare->reserved*sizeof(WORD)*(spare->numind+TABLEEXTENSION));
2633
                                        }
2634
                                        else {
2635
                                                /* matrix like tables */
2636
                                                S_WRITE_B(spare->tablepointers,
×
2637
                                                        TABLEEXTENSION*sizeof(WORD)*(spare->totind));
×
2638
                                        }
2639
                                }
2640
                                S_WRITE_B(spare->mm, spare->numind*(LONG)sizeof(MINMAX));
×
2641
                                S_WRITE_B(spare->flags, spare->numind*(LONG)sizeof(WORD));
×
2642
                                if ( spare->sparse ) {
×
2643
                                        S_WRITE_B(spare->boomlijst, spare->MaxTreeSize*(LONG)sizeof(COMPTREE));
×
2644
                                }
2645
                                S_WRITE_B(spare->buffers, spare->bufferssize*(LONG)sizeof(WORD));
×
2646
                        }
2647
                }
2648
        }
2649

2650
        ANNOUNCE(AC.ExpressionList)
2651
        S_WRITE_LIST(AC.ExpressionList);
×
2652
        for ( i=0; i<AC.ExpressionList.num; ++i ) {
×
2653
                EXPRESSIONS ex = Expressions + i;
×
2654
                if ( ex->renum ) {
×
2655
                        S_WRITE_B(ex->renum, sizeof(struct ReNuMbEr));
×
2656
                        /* there is one dynamically allocated buffer for struct ReNuMbEr and
2657
                         * symb.lo points to its beginning. the size of the buffer is not
2658
                         * stored anywhere but we know it is 2*sizeof(WORD)*N, where N is
2659
                         * the number of all vectors, indices, functions and symbols. since
2660
                         * funum points into the buffer at a distance 2N-[Number of
2661
                         * functions] from symb.lo (see GetTable() in store.c), we can
2662
                         * calculate the buffer size by some pointer arithmetic. the size is
2663
                         * then written to the file. */
2664
                        l = ex->renum->funnum - ex->renum->symb.lo;
×
2665
                        l += ex->renum->funnum - ex->renum->func.lo;
×
2666
                        S_WRITE_B(&l, sizeof(size_t));
×
2667
                        S_WRITE_B(ex->renum->symb.lo, l);
×
2668
                }
2669
                if ( ex->bracketinfo ) {
×
2670
                        S_WRITE_B(ex->bracketinfo, sizeof(BRACKETINFO));
×
2671
                        S_WRITE_B(ex->bracketinfo->indexbuffer, ex->bracketinfo->indexbuffersize*sizeof(BRACKETINDEX));
×
2672
                        S_WRITE_B(ex->bracketinfo->bracketbuffer, ex->bracketinfo->bracketbuffersize*sizeof(WORD));
×
2673
                }
2674
                if ( ex->newbracketinfo ) {
×
2675
                        S_WRITE_B(ex->newbracketinfo, sizeof(BRACKETINFO));
×
2676
                        S_WRITE_B(ex->newbracketinfo->indexbuffer, ex->newbracketinfo->indexbuffersize*sizeof(BRACKETINDEX));
×
2677
                        S_WRITE_B(ex->newbracketinfo->bracketbuffer, ex->newbracketinfo->bracketbuffersize*sizeof(WORD));
×
2678
                }
2679
                /* don't need to write ex->renumlists */
2680
                if ( ex->inmem ) {
×
2681
                        /* size of the inmem buffer has to be determined. we use the fact
2682
                         * that the end of an expression is marked by a zero. */
2683
                        w = ex->inmem;
2684
                        while ( *w++ ) ;
×
2685
                        l = w - ex->inmem;
×
2686
                        S_WRITE_B(&l, sizeof(size_t));
×
2687
                        S_WRITE_B(ex->inmem, l);
×
2688
                }
2689
        }
2690
        
2691
        ANNOUNCE(AC.IndexList)
2692
        S_WRITE_LIST(AC.IndexList);
×
2693
        S_WRITE_LIST(AC.SetElementList);
×
2694
        S_WRITE_LIST(AC.SetList);
×
2695
        S_WRITE_LIST(AC.SymbolList);
×
2696
        S_WRITE_LIST(AC.VectorList);
×
2697

2698
        ANNOUNCE(AC.TableBaseList)
2699
        S_WRITE_LIST(AC.TableBaseList);
×
2700
        for ( i=0; i<AC.TableBaseList.num; ++i ) {
×
2701
                /* see struct dbase in minos.h */
2702
                if ( tablebases[i].iblocks ) {
×
2703
                        S_WRITE_B(tablebases[i].iblocks, tablebases[i].info.numberofindexblocks * sizeof(INDEXBLOCK*));
×
2704
                        for ( j=0; j<tablebases[i].info.numberofindexblocks; ++j ) {
×
2705
                                if ( tablebases[i].iblocks[j] ) {
×
2706
                                        S_WRITE_B(tablebases[i].iblocks[j], sizeof(INDEXBLOCK));
×
2707
                                }
2708
                        }
2709
                }
2710
                if ( tablebases[i].nblocks ) {
×
2711
                        S_WRITE_B(tablebases[i].nblocks, tablebases[i].info.numberofnamesblocks * sizeof(NAMESBLOCK*));
×
2712
                        for ( j=0; j<tablebases[i].info.numberofnamesblocks; ++j ) {
×
2713
                                if ( tablebases[i].nblocks[j] ) {
×
2714
                                        S_WRITE_B(tablebases[i].nblocks[j], sizeof(NAMESBLOCK));
×
2715
                                }
2716
                        }
2717
                }
2718
                S_WRITE_S(tablebases[i].name);
×
2719
                S_WRITE_S(tablebases[i].fullname);
×
2720
                S_WRITE_S(tablebases[i].tablenames);
×
2721
        }
2722

2723
        ANNOUNCE(AC.cbufList)
2724
        S_WRITE_LIST(AC.cbufList);
×
2725
        for ( i=0; i<AC.cbufList.num; ++i ) {
×
2726
                S_WRITE_B(cbuf[i].Buffer, cbuf[i].BufferSize*sizeof(WORD));
×
2727
                /* see inicbufs in comtool.c */
2728
                S_WRITE_B(cbuf[i].lhs, cbuf[i].maxlhs*(LONG)sizeof(WORD*));
×
2729
                S_WRITE_B(cbuf[i].rhs, cbuf[i].maxrhs*(LONG)(sizeof(WORD*)+2*sizeof(LONG)+2*sizeof(WORD)));
×
2730
                if ( cbuf[i].boomlijst ) {
×
2731
                        S_WRITE_B(cbuf[i].boomlijst, cbuf[i].MaxTreeSize*(LONG)sizeof(COMPTREE));
×
2732
                }
2733
        }
2734

2735
        S_WRITE_LIST(AC.AutoSymbolList);
×
2736
        S_WRITE_LIST(AC.AutoIndexList);
×
2737
        S_WRITE_LIST(AC.AutoVectorList);
×
2738
        S_WRITE_LIST(AC.AutoFunctionList);
×
2739

2740
        S_WRITE_NAMETREE(AC.autonames);
×
2741

2742
        ANNOUNCE(AC.Streams)
2743
        S_WRITE_B(AC.Streams, AC.MaxNumStreams*(LONG)sizeof(STREAM));
×
2744
        for ( i=0; i<AC.NumStreams; ++i ) {
×
2745
                if ( AC.Streams[i].inbuffer ) {
×
2746
                        S_WRITE_B(AC.Streams[i].buffer, AC.Streams[i].inbuffer);
×
2747
                }
2748
                S_WRITE_S(AC.Streams[i].FoldName);
×
2749
                S_WRITE_S(AC.Streams[i].name);
×
2750
        }
2751

2752
        if ( AC.termstack ) {
×
2753
                S_WRITE_B(AC.termstack, AC.maxtermlevel*(LONG)sizeof(LONG));
×
2754
        }
2755

2756
        if ( AC.termsortstack ) {
×
2757
                S_WRITE_B(AC.termsortstack, AC.maxtermlevel*(LONG)sizeof(LONG));
×
2758
        }
2759

2760
        S_WRITE_B(AC.cmod, AM.MaxTal*4*(LONG)sizeof(UWORD));
×
2761

2762
        if ( AC.IfHeap ) {
×
2763
                S_WRITE_B(AC.IfHeap, (LONG)sizeof(LONG)*(AC.MaxIf+1));
×
2764
                S_WRITE_B(AC.IfCount, (LONG)sizeof(LONG)*(AC.MaxIf+1));
×
2765
        }
2766

2767
        l = AC.iStop - AC.iBuffer + 2;
×
2768
        S_WRITE_B(AC.iBuffer, l);
×
2769

2770
        if ( AC.LabelNames ) {
×
2771
                S_WRITE_B(AC.LabelNames, AC.MaxLabels*(LONG)(sizeof(UBYTE*)+sizeof(WORD)));
×
2772
                for ( i=0; i<AC.NumLabels; ++i ) {
×
2773
                        S_WRITE_S(AC.LabelNames[i]);
×
2774
                }
2775
        }
2776

2777
        S_WRITE_B(AC.FixIndices, AM.OffsetIndex*(LONG)sizeof(WORD));
×
2778

2779
        if ( AC.termsumcheck ) {
×
2780
                S_WRITE_B(AC.termsumcheck, AC.maxtermlevel*(LONG)sizeof(WORD));
×
2781
        }
2782

2783
        S_WRITE_B(AC.WildcardNames, AC.WildcardBufferSize);
×
2784

2785
        if ( AC.tokens ) {
×
2786
                l = AC.toptokens - AC.tokens;
×
2787
                if ( l ) {
×
2788
                        S_WRITE_B(AC.tokens, l);
×
2789
                }
2790
        }
2791

2792
        S_WRITE_B(AC.tokenarglevel, AM.MaxParLevel*(LONG)sizeof(WORD));
×
2793

2794
        S_WRITE_S(AC.Fortran90Kind);
×
2795
        
2796
#ifdef WITHPTHREADS
2797
        if ( AC.inputnumbers ) {
2798
                S_WRITE_B(AC.inputnumbers, AC.sizepfirstnum*(LONG)(sizeof(WORD)+sizeof(LONG)));
2799
        }
2800
#endif /* ifdef WITHPTHREADS */
2801

2802
        if ( AC.IfSumCheck ) {
×
2803
                S_WRITE_B(AC.IfSumCheck, (LONG)sizeof(WORD)*(AC.MaxIf+1));
×
2804
        }
2805
        if ( AC.CommuteInSet ) {
×
2806
                S_WRITE_B(AC.CommuteInSet, (LONG)sizeof(WORD)*(AC.SizeCommuteInSet+1));
×
2807
        }
2808

2809
        S_WRITE_S(AC.CheckpointRunAfter);
×
2810
        S_WRITE_S(AC.CheckpointRunBefore);
×
2811

2812
        S_WRITE_S(AC.extrasym);
×
2813

2814
        /*#] AC :*/ 
2815
        /*#[ AP :*/
2816

2817
        /* we write AP as a whole and then write all additional data step by step. */
2818

2819
        ANNOUNCE(AP)
2820
        S_WRITE_B(&AP, sizeof(struct P_const));
×
2821

2822
        S_WRITE_LIST(AP.DollarList);
×
2823
        for ( i=0; i<AP.DollarList.num; ++i ) {
×
2824
                DOLLARS d = Dollars + i;
×
2825
                S_WRITE_DOLLAR(Dollars[i]);
×
2826
                if ( d->nfactors > 1 ) {
×
2827
                        S_WRITE_B(&(d->factors),sizeof(FACDOLLAR)*d->nfactors);
×
2828
                        for ( j = 0; j < d->nfactors; j++ ) {
×
2829
                                if ( d->factors[j].size > 0 ) {
×
2830
                                        S_WRITE_B(&(d->factors[i].where),sizeof(WORD)*(d->factors[j].size+1));
×
2831
                                }
2832
                        }
2833
                }
2834
        }
2835

2836
        S_WRITE_LIST(AP.PreVarList);
×
2837
        for ( i=0; i<AP.PreVarList.num; ++i ) {
×
2838
                /* there is one dynamically allocated buffer in struct pReVaR holding
2839
                 * the strings name, value and several argnames. the size of the buffer
2840
                 * can be calculated by adding up their string lengths. */
2841
                l = strlen((char*)PreVar[i].name) + 1;
×
2842
                if ( PreVar[i].value ) {
×
2843
                        l += strlen((char*)(PreVar[i].name+l)) + 1;
×
2844
                }
2845
                for ( j=0; j<PreVar[i].nargs; ++j ) {
×
2846
                        l += strlen((char*)(PreVar[i].name+l)) + 1;
×
2847
                }
2848
                S_WRITE_B(&l, sizeof(size_t));
×
2849
                S_WRITE_B(PreVar[i].name, l);
×
2850
        }
2851

2852
        ANNOUNCE(AP.LoopList)
2853
        S_WRITE_LIST(AP.LoopList);
×
2854
        for ( i=0; i<AP.LoopList.num; ++i ) {
×
2855
                S_WRITE_B(DoLoops[i].p.buffer, DoLoops[i].p.size);
×
2856
                if ( DoLoops[i].type == ONEEXPRESSION ) {
×
2857
                        /* do loops with an expression keep this expression in a dynamically
2858
                         * allocated buffer in dollarname */
2859
                        S_WRITE_S(DoLoops[i].dollarname);
×
2860
                }
2861
        }
2862

2863
        S_WRITE_LIST(AP.ProcList);
×
2864
        for ( i=0; i<AP.ProcList.num; ++i ) {
×
2865
                if ( Procedures[i].p.size ) {
×
2866
                        if ( Procedures[i].loadmode != 1 ) {
×
2867
                                S_WRITE_B(Procedures[i].p.buffer, Procedures[i].p.size);
×
2868
                        }
2869
                        else {
2870
                                for ( j=0; j<AP.ProcList.num; ++j ) {
×
2871
                                        if ( Procedures[i].p.buffer == Procedures[j].p.buffer ) {
×
2872
                                                break;
2873
                                        }
2874
                                }
2875
                                if ( j == AP.ProcList.num ) {
×
2876
                                        MesPrint("Error writing procedures to recovery file!");
×
2877
                                }
2878
                                S_WRITE_B(&j, sizeof(int));
×
2879
                        }
2880
                }
2881
                S_WRITE_S(Procedures[i].name);
×
2882
        }
2883

2884
        S_WRITE_B(AP.PreSwitchStrings, (AP.NumPreSwitchStrings+1)*(LONG)sizeof(UBYTE*));
×
2885
        for ( i=1; i<=AP.PreSwitchLevel; ++i ) {
×
2886
                S_WRITE_S(AP.PreSwitchStrings[i]);
×
2887
        }
2888

2889
        S_WRITE_B(AP.preStart, AP.pSize);
×
2890
        
2891
        S_WRITE_S(AP.procedureExtension);
×
2892
        S_WRITE_S(AP.cprocedureExtension);
×
2893

2894
        S_WRITE_B(AP.PreAssignStack, AP.MaxPreAssignLevel*(LONG)sizeof(LONG));
×
2895
        S_WRITE_B(AP.PreIfStack, AP.MaxPreIfLevel*(LONG)sizeof(int));
×
2896
        S_WRITE_B(AP.PreSwitchModes, (AP.NumPreSwitchStrings+1)*(LONG)sizeof(int));
×
2897
        S_WRITE_B(AP.PreTypes, (AP.MaxPreTypes+1)*(LONG)sizeof(int));
×
2898

2899
        /*#] AP :*/ 
2900
        /*#[ AR :*/
2901

2902
        ANNOUNCE(AR)
2903
        /* to remember which entry in AR.Fscr corresponds to the infile */
2904
        l = AR.infile - AR.Fscr;
×
2905
        S_WRITE_B(&l, sizeof(LONG));
×
2906
        
2907
        /* write the FILEHANDLEs */
2908
        S_WRITE_B(AR.outfile, sizeof(FILEHANDLE));
×
2909
        l = AR.outfile->POfull - AR.outfile->PObuffer;
×
2910
        if ( l ) {
×
2911
                S_WRITE_B(AR.outfile->PObuffer, l*sizeof(WORD));
×
2912
        }
2913
        S_WRITE_B(AR.hidefile, sizeof(FILEHANDLE));
×
2914
        l = AR.hidefile->POfull - AR.hidefile->PObuffer;
×
2915
        if ( l ) {
×
2916
                S_WRITE_B(AR.hidefile->PObuffer, l*sizeof(WORD));
×
2917
        }
2918

2919
        S_WRITE_B(&AR.StoreData.Fill, sizeof(POSITION));
×
2920
        if ( ISNOTZEROPOS(AR.StoreData.Fill) ) {
×
2921
                S_WRITE_B(&AR.StoreData, sizeof(FILEDATA));
×
2922
        }
2923

2924
        S_WRITE_B(&AR.DefPosition, sizeof(POSITION));
×
2925

2926
        l = TimeCPU(1); l = -l;
×
2927
        S_WRITE_B(&l, sizeof(LONG));
×
2928

2929
        ANNOUNCE(AR.InInBuf)
2930
        S_WRITE_B(&AR.InInBuf, sizeof(LONG));
×
2931
        S_WRITE_B(&AR.InHiBuf, sizeof(LONG));
×
2932
        
2933
        S_WRITE_B(&AR.NoCompress, sizeof(int));
×
2934
        S_WRITE_B(&AR.gzipCompress, sizeof(int));
×
2935
        
2936
        S_WRITE_B(&AR.outtohide, sizeof(int));
×
2937

2938
        S_WRITE_B(&AR.GetFile, sizeof(WORD));
×
2939
        S_WRITE_B(&AR.KeptInHold, sizeof(WORD));
×
2940
        S_WRITE_B(&AR.BracketOn, sizeof(WORD));
×
2941
        S_WRITE_B(&AR.MaxBracket, sizeof(WORD));
×
2942
        S_WRITE_B(&AR.CurDum, sizeof(WORD));
×
2943
        S_WRITE_B(&AR.DeferFlag, sizeof(WORD));
×
2944
        S_WRITE_B(&AR.TePos, sizeof(WORD));
×
2945
        S_WRITE_B(&AR.sLevel, sizeof(WORD));
×
2946
        S_WRITE_B(&AR.Stage4Name, sizeof(WORD));
×
2947
        S_WRITE_B(&AR.GetOneFile, sizeof(WORD));
×
2948
        S_WRITE_B(&AR.PolyFun, sizeof(WORD));
×
2949
        S_WRITE_B(&AR.PolyFunInv, sizeof(WORD));
×
2950
        S_WRITE_B(&AR.PolyFunType, sizeof(WORD));
×
2951
        S_WRITE_B(&AR.PolyFunExp, sizeof(WORD));
×
2952
        S_WRITE_B(&AR.PolyFunVar, sizeof(WORD));
×
2953
        S_WRITE_B(&AR.PolyFunPow, sizeof(WORD));
×
2954
        S_WRITE_B(&AR.Eside, sizeof(WORD));
×
2955
        S_WRITE_B(&AR.MaxDum, sizeof(WORD));
×
2956
        S_WRITE_B(&AR.level, sizeof(WORD));
×
2957
        S_WRITE_B(&AR.expchanged, sizeof(WORD));
×
2958
        S_WRITE_B(&AR.expflags, sizeof(WORD));
×
2959
        S_WRITE_B(&AR.CurExpr, sizeof(WORD));
×
2960
        S_WRITE_B(&AR.SortType, sizeof(WORD));
×
2961
        S_WRITE_B(&AR.ShortSortCount, sizeof(WORD));
×
2962

2963
#ifdef WITHPTHREADS
2964
        for ( j = 0; j < AM.totalnumberofthreads; j++ ) {
2965
                S_WRITE_B(&(AB[j]->R.wranfnpair1), sizeof(int));
2966
                S_WRITE_B(&(AB[j]->R.wranfnpair2), sizeof(int));
2967
                S_WRITE_B(&(AB[j]->R.wranfcall), sizeof(int));
2968
                S_WRITE_B(&(AB[j]->R.wranfseed), sizeof(ULONG));
2969
                S_WRITE_B(&(AB[j]->R.wranfia),sizeof(ULONG *));
2970
                if ( AB[j]->R.wranfia ) {
2971
                        S_WRITE_B(AB[j]->R.wranfia, sizeof(ULONG)*AB[j]->R.wranfnpair2);
2972
                }
2973
        }
2974
#else
2975
        S_WRITE_B(&(AR.wranfnpair1), sizeof(int));
2976
        S_WRITE_B(&(AR.wranfnpair2), sizeof(int));
2977
        S_WRITE_B(&(AR.wranfcall), sizeof(int));
2978
        S_WRITE_B(&(AR.wranfseed), sizeof(ULONG));
2979
        S_WRITE_B(&(AR.wranfia),sizeof(ULONG *));
2980
        if ( AR.wranfia ) {
2981
                S_WRITE_B(AR.wranfia, sizeof(ULONG)*AR.wranfnpair2);
2982
        }
2983
#endif
2984

2985
        /*#] AR :*/ 
2986
        /*#[ AO :*/
2987
/*
2988
        We copy all non-pointer variables.
2989
*/
2990
        ANNOUNCE(AO)
2991
        l = sizeof(A.O) - ((UBYTE *)(&(A.O.NumInBrack))-(UBYTE *)(&A.O));
×
2992
        S_WRITE_B(&(A.O.NumInBrack),l);
×
2993
/*
2994
        Now the variables in OptimizeResult
2995
*/
2996
        S_WRITE_B(&(A.O.OptimizeResult),sizeof(OPTIMIZERESULT));
×
2997
        if ( A.O.OptimizeResult.codesize > 0 ) {
×
2998
                S_WRITE_B(A.O.OptimizeResult.code,A.O.OptimizeResult.codesize*sizeof(WORD));
×
2999
        }
3000
        S_WRITE_S(A.O.OptimizeResult.nameofexpr);
×
3001
/*
3002
        And now the dictionaries.
3003
        We write each dictionary to a buffer and get the size of that buffer.
3004
        Then we write the size and the buffer.
3005
*/
3006
        for ( i = 0; i < AO.NumDictionaries; i++ ) {
×
3007
                l = DictToBytes(AO.Dictionaries[i],(UBYTE *)(AT.WorkPointer));
×
3008
                S_WRITE_B(&l,sizeof(LONG));
×
3009
                S_WRITE_B(AT.WorkPointer,l);
×
3010
        }
3011

3012
        /*#] AO :*/ 
3013
        /*#[ PF :*/
3014
#ifdef WITHMPI
3015
        S_WRITE_B(&PF.numtasks, sizeof(int));
3016
        S_WRITE_B(&PF.rhsInParallel, sizeof(int));
3017
        S_WRITE_B(&PF.exprbufsize, sizeof(int));
3018
        S_WRITE_B(&PF.log, sizeof(int));
3019
#endif
3020
        /*#] PF :*/ 
3021

3022
#ifdef WITHPTHREADS
3023

3024
        ANNOUNCE(GetTimerInfo)
3025
/*
3026
        write timing information of individual threads
3027
*/
3028
        i = GetTimerInfo(&longp,&longpp);
3029
        S_WRITE_B(&i, sizeof(int));
3030
        S_WRITE_B(longp, i*(LONG)sizeof(LONG));
3031
        S_WRITE_B(&i, sizeof(int));
3032
        S_WRITE_B(longpp, i*(LONG)sizeof(LONG));
3033

3034
#endif
3035

3036
        S_FLUSH_B /* because we will call fwrite() directly in the following code */
×
3037

3038
        /* save length of data at the beginning of the file */
3039
        ANNOUNCE(file length)
3040
        SETBASEPOSITION(pos, (ftell(fd)));
×
3041
        fseek(fd, 0, SEEK_SET);
×
3042
        if ( fwrite(&pos, 1, sizeof(POSITION), fd) != sizeof(POSITION) ) return(__LINE__);
×
3043
        fseek(fd, BASEPOSITION(pos), SEEK_SET);
×
3044

3045
        ANNOUNCE(file close)
3046
        if ( fclose(fd) ) return(__LINE__);
×
3047
#ifdef WITHMPI
3048
        if ( PF.me == MASTER ) {
3049
#endif
3050
/*
3051
                copy store file if necessary
3052
*/
3053
                ANNOUNCE(copy store file)
3054
                if ( ISNOTZEROPOS(AR.StoreData.Fill) ) {
×
3055
                        if ( CopyFile(FG.fname, storefile) ) return(__LINE__);
×
3056
                }
3057
/*
3058
                copy sort file if necessary
3059
*/
3060
                ANNOUNCE(copy sort file)
3061
                if ( AR.outfile->handle >= 0 ) {
×
3062
                        if ( CopyFile(AR.outfile->name, sortfile) ) return(__LINE__);
×
3063
                }
3064
/*
3065
                copy hide file if necessary
3066
*/
3067
                ANNOUNCE(copy hide file)
3068
                if ( AR.hidefile->handle >= 0 ) {
×
3069
                        if ( CopyFile(AR.hidefile->name, hidefile) ) return(__LINE__);
×
3070
                }
3071
#ifdef WITHMPI
3072
        }
3073
        /*
3074
         * For ParFORM, the renaming will be performed after the master got
3075
         * all recovery files from the slaves.
3076
         */
3077
#else
3078
/*
3079
        make the intermediate file the recovery file
3080
*/
3081
        ANNOUNCE(rename intermediate file)
3082
        if ( rename(intermedfile, recoveryfile) ) return(__LINE__);
3083

3084
        done_snapshot = 1;
3085

3086
        MesPrint("done."); fflush(0);
3087
#endif
3088

3089
#ifdef PRINTDEBUG
3090
        print_M();
3091
        print_C();
3092
        print_P();
3093
        print_R();
3094
#endif
3095

3096
        return(0);
3097
}
3098

3099
/*
3100
          #] DoSnapshot : 
3101
          #[ DoCheckpoint :
3102
*/
3103

3104
/**
3105
 *  Checks whether a snapshot should be done. Calls DoSnapshot() to create the
3106
 *  snapshot.
3107
 */
3108
void DoCheckpoint(int moduletype)
×
3109
{
3110
        int error;
×
3111
        LONG timestamp = TimeWallClock(1);
×
3112
#ifdef WITHMPI
3113
        if(PF.me == MASTER){
3114
#endif
3115
        if ( timestamp - AC.CheckpointStamp >= AC.CheckpointInterval ) {
×
3116
                char argbuf[20];
×
3117
                int retvalue = 0;
×
3118
                if ( AC.CheckpointRunBefore ) {
×
3119
                        size_t l, l2;
×
3120
                        char *str;
×
3121
                        l = strlen(AC.CheckpointRunBefore);
×
3122
                        NumToStr((UBYTE*)argbuf, AC.CModule);
×
3123
                        l2 = strlen(argbuf);
×
3124
                        str = (char*)Malloc1(l+l2+2, "callbefore");
×
3125
                        strcpy(str, AC.CheckpointRunBefore);
×
3126
                        *(str+l) = ' ';
×
3127
                        strcpy(str+l+1, argbuf);
×
3128
                        retvalue = system(str);
×
3129
                        M_free(str, "callbefore");
×
3130
                        if ( retvalue ) {
×
3131
                                MesPrint("Script returned error -> no recovery file will be created.");
×
3132
                        }
3133
                }
3134
#ifdef WITHMPI
3135
                /* Confirm slaves to make snapshots. */
3136
                PF_BroadcastNumber(retvalue == 0);
3137
#endif
3138
                if ( retvalue == 0 ) {
×
3139
                        if ( (error = DoSnapshot(moduletype)) ) {
×
3140
                                MesPrint("Error creating recovery files: %d", error);
×
3141
                        }
3142
#ifdef WITHMPI
3143
                        {
3144
                        int i;
3145
                        /*get recovery files from slaves:*/
3146
                        for(i=1; i<PF.numtasks;i++){
3147
                                FILE *fd;
3148
                                const char *tmpnam = PF_recoveryfile('m', i, 1);
3149
                                fd = fopen(tmpnam, "w");
3150
                                if(fd == NULL){
3151
                                        MesPrint("Error opening recovery file for slave %d",i);
3152
                                        Terminate(-1);
3153
                                }/*if(fd == NULL)*/
3154
                                retvalue=PF_RecvFile(i,fd);
3155
                                if(retvalue<=0){
3156
                                        MesPrint("Error receiving recovery file from slave %d",i);
3157
                                        Terminate(-1);
3158
                                }/*if(retvalue<=0)*/
3159
                                fclose(fd);
3160
                        }/*for(i=0; i<PF.numtasks;i++)*/
3161
                        /*
3162
                         * Make the intermediate files the recovery files.
3163
                         */
3164
                        ANNOUNCE(rename intermediate file)
3165
                        for ( i = 0; i < PF.numtasks; i++ ) {
3166
                                const char *src = PF_recoveryfile('m', i, 1);
3167
                                const char *dst = PF_recoveryfile('m', i, 0);
3168
                                if ( rename(src, dst) ) {
3169
                                        MesPrint("Error renaming recovery file %s -> %s", src, dst);
3170
                                }
3171
                        }
3172
                        done_snapshot = 1;
3173
                        MesPrint("done."); fflush(0);
3174
                        }
3175
#endif
3176
                }
3177
                if ( AC.CheckpointRunAfter ) {
×
3178
                        size_t l, l2;
×
3179
                        char *str;
×
3180
                        l = strlen(AC.CheckpointRunAfter);
×
3181
                        NumToStr((UBYTE*)argbuf, AC.CModule);
×
3182
                        l2 = strlen(argbuf);
×
3183
                        str = (char*)Malloc1(l+l2+2, "callafter");
×
3184
                        strcpy(str, AC.CheckpointRunAfter);
×
3185
                        *(str+l) = ' ';
×
3186
                        strcpy(str+l+1, argbuf);
×
3187
                        retvalue = system(str);
×
3188
                        M_free(str, "callafter");
×
3189
                        if ( retvalue ) {
×
3190
                                MesPrint("Error calling script after recovery.");
×
3191
                        }
3192
                }
3193
                AC.CheckpointStamp = TimeWallClock(1);
×
3194
        }
3195
#ifdef WITHMPI
3196
        else{/* timestamp - AC.CheckpointStamp < AC.CheckpointInterval*/
3197
                /* The slaves don't need to make snapshots. */
3198
                PF_BroadcastNumber(0);
3199
        }
3200
        }/*if(PF.me == MASTER)*/
3201
        else{/*Slave*/
3202
                int i;
3203
                /* Check if the slave needs to make a snapshot. */
3204
                if ( PF_BroadcastNumber(0) ) {
3205
                        error = DoSnapshot(moduletype);
3206
                        if(error == 0){
3207
                                FILE *fd;
3208
                                /*
3209
                                 * Send the recovery file to the master. Note that no renaming
3210
                                 * has been performed and what we have to send is actually sitting
3211
                                 * in the intermediate file.
3212
                                 */
3213
                                fd = fopen(intermedfile, "r");
3214
                                i=PF_SendFile(MASTER, fd);/*if fd==NULL, PF_SendFile seds to a slave the failure tag*/
3215
                                if(fd == NULL)
3216
                                        Terminate(-1);
3217
                                fclose(fd);
3218
                                if(i<=0)
3219
                                        Terminate(-1);
3220
                                /*Now the slave need not the recovery file so remove it:*/
3221
                                remove(intermedfile);
3222
                        }
3223
                        else{
3224
                                /*send the error tag to the master:*/
3225
                                PF_SendFile(MASTER,NULL);/*if fd==NULL, PF_SendFile seds to a slave the failure tag*/
3226
                                Terminate(-1);
3227
                        }
3228
                        done_snapshot = 1;
3229
                }/*if(tag=PF_DATA_MSGTAG)*/
3230
        }/*if(PF.me != MASTER)*/
3231
#endif
3232
}
×
3233

3234
/*
3235
          #] DoCheckpoint : 
3236
*/
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