FORM  4.3
checkpoint.c
Go to the documentation of this file.
1 /*
2  #[ Explanations :
3 */
52 /*
53  #] Explanations :
54  #[ License :
55  *
56  * Copyright (C) 1984-2022 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 
104 #ifdef WITHMPI
105 #define BASENAME_FMT "%c%04dFORMrecv"
106 
111 static char BaseName[] = BASENAME_FMT;
112 #else
113 static char *BaseName = "FORMrecv";
114 #endif
115 
118 static char *recoveryfile = 0;
124 static char *intermedfile = 0;
128 static char *sortfile = 0;
132 static char *hidefile = 0;
136 static char *storefile = 0;
137 
142 static int done_snapshot = 0;
143 
144 #ifdef WITHMPI
145 
149 static int PF_fmt_pos;
150 
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 
191 #ifdef WITHMPI
192 
198 static int PF_CheckRecoveryFile()
199 {
200  int i,ret=0;
201  FILE *fd;
202  /* Check if the recovery file for the master exists. */
203  if ( PF.me == MASTER ) {
204  if ( (fd = fopen(recoveryfile, "r")) ) {
205  fclose(fd);
207  }
208  else {
210  return 0;
211  }
212  }
213  else {
214  if ( !PF_BroadcastNumber(0) )
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 
279 {
280  int ret = 0;
281 #ifdef WITHMPI
282  ret = PF_CheckRecoveryFile();
283 #else
284  FILE *fd;
285  if ( (fd = fopen(recoveryfile, "r")) ) {
286  fclose(fd);
287  ret = 1;
288  }
289 #endif
290  if ( ret < 0 ){/*In ParFORM CheckRecoveryFile() may return a fatal error.*/
291  MesPrint("Fail checking recovery file");
292  Terminate(-1);
293  }
294  else if ( ret > 0 ) {
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 ) {
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);
322 }
323 
324 /*
325  #] CheckRecoveryFile :
326  #[ DeleteRecoveryFile :
327 */
328 
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 
365 {
366  return(recoveryfile);
367 }
368 
369 /*
370  #] RecoveryFilename :
371  #[ InitRecovery :
372 */
373 
377 static char *InitName(char *str, char *ext)
378 {
379  char *s, *d = str;
380  if ( AM.TempDir ) {
381  s = (char*)AM.TempDir;
382  while ( *s ) { *d++ = *s++; }
383  *d++ = SEPARATOR;
384  }
385  s = BaseName;
386  while ( *s ) { *d++ = *s++; }
387  *d++ = '.';
388  s = ext;
389  while ( *s ) { *d++ = *s++; }
390  *d++ = 0;
391  return d;
392 }
393 
400 {
401  int lenpath = AM.TempDir ? strlen((char*)AM.TempDir)+1 : 0;
402 #ifdef WITHMPI
403  sprintf(BaseName,BASENAME_FMT,(PF.me == MASTER)?'m':'s',PF.me);
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;
407 #endif
408  recoveryfile = (char*)Malloc1(5*(lenpath+strlen(BaseName)+4+1),"InitRecovery");
409  intermedfile = InitName(recoveryfile, "tmp");
410  sortfile = InitName(intermedfile, "XXX");
411  hidefile = InitName(sortfile, "out");
412  storefile = InitName(hidefile, "hid");
413  InitName(storefile, "str");
414 }
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 
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 doesn't
2347  end up executing Process() before it uses the AR.CompressPointer,
2348  so we need to explicitely 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 
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 
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 */
UBYTE * pointer
Definition: structs.h:692
WORD bufferssize
Definition: structs.h:378
void DeleteRecoveryFile()
Definition: checkpoint.c:333
LONG * NumTerms
Definition: structs.h:945
WORD * buffers
Definition: structs.h:364
int value
Definition: structs.h:297
char * RecoveryFilename()
Definition: checkpoint.c:364
LONG reserved
Definition: structs.h:366
UBYTE * name
Definition: structs.h:793
LONG totind
Definition: structs.h:365
int numclear
Definition: structs.h:212
WORD left
Definition: structs.h:249
LONG clearnamefill
Definition: structs.h:279
int parent
Definition: structs.h:294
UBYTE * dollarname
Definition: structs.h:853
int prototypeSize
Definition: structs.h:369
UBYTE * buffer
Definition: structs.h:691
int right
Definition: structs.h:296
LONG namefill
Definition: structs.h:273
WORD type
Definition: structs.h:252
NAMENODE * namenode
Definition: structs.h:265
WORD * pattern
Definition: structs.h:356
WORD * bracketbuffer
Definition: structs.h:330
int left
Definition: structs.h:295
UBYTE * name
Definition: structs.h:850
Definition: structs.h:633
VARRENUM indi
Definition: structs.h:181
int sparse
Definition: structs.h:373
int DoRecovery(int *moduletype)
Definition: checkpoint.c:1401
struct TaBlEs * spare
Definition: structs.h:363
VARRENUM vect
Definition: structs.h:182
int size
Definition: structs.h:209
WORD number
Definition: structs.h:253
LONG nodefill
Definition: structs.h:271
LONG nodesize
Definition: structs.h:270
WORD ** lhs
Definition: structs.h:942
int numind
Definition: structs.h:370
int numglobal
Definition: structs.h:210
LONG globalnodefill
Definition: structs.h:278
LONG globalnamefill
Definition: structs.h:276
int num
Definition: structs.h:207
Definition: structs.h:938
WORD parent
Definition: structs.h:248
Definition: structs.h:293
WORD * vecnum
Definition: structs.h:187
int PF_SendFile(int to, FILE *fd)
Definition: parallel.c:4207
UBYTE * FoldName
Definition: structs.h:694
LONG name
Definition: structs.h:247
WORD * symnum
Definition: structs.h:185
WORD * renumlists
Definition: structs.h:397
int blnce
Definition: structs.h:298
int wildarg
Definition: structs.h:797
LONG TimeWallClock(WORD)
Definition: tools.c:3476
WORD * tablepointers
Definition: structs.h:350
int CopyFile(char *, char *)
Definition: tools.c:1101
LONG PF_BroadcastNumber(LONG x)
Definition: parallel.c:2083
void * lijst
Definition: structs.h:205
UBYTE * argtail
Definition: structs.h:361
UBYTE * name
Definition: structs.h:695
WORD balance
Definition: structs.h:251
WORD ** rhs
Definition: structs.h:943
char * message
Definition: structs.h:206
WORD * hi
Definition: structs.h:168
int MaxTreeSize
Definition: structs.h:376
WORD * numdum
Definition: structs.h:946
int numtemp
Definition: structs.h:211
int maxnum
Definition: structs.h:208
COMPTREE * boomlijst
Definition: structs.h:948
MINMAX * mm
Definition: structs.h:358
BRACKETINDEX * indexbuffer
Definition: structs.h:329
COMPTREE * boomlijst
Definition: structs.h:360
WORD * prototype
Definition: structs.h:355
LONG namesize
Definition: structs.h:272
LONG oldnamefill
Definition: structs.h:274
LONG oldnodefill
Definition: structs.h:275
WORD * Buffer
Definition: structs.h:939
WORD * start
Definition: structs.h:166
LONG BufferSize
Definition: structs.h:949
Definition: structs.h:204
WORD * indnum
Definition: structs.h:186
struct StreaM STREAM
int nargs
Definition: structs.h:796
UBYTE * namebuffer
Definition: structs.h:267
UBYTE * pname
Definition: structs.h:696
WORD right
Definition: structs.h:250
PRELOAD p
Definition: structs.h:849
WORD headnode
Definition: structs.h:281
VARRENUM func
Definition: structs.h:183
UBYTE * value
Definition: structs.h:794
void InitRecovery()
Definition: checkpoint.c:399
LONG TimeCPU(WORD)
Definition: tools.c:3550
UBYTE * argnames
Definition: structs.h:795
int PF_RecvFile(int from, FILE *fd)
Definition: parallel.c:4245
int CheckRecoveryFile()
Definition: checkpoint.c:278
WORD * flags
Definition: structs.h:359
LONG clearnodefill
Definition: structs.h:280
VARRENUM symb
Definition: structs.h:180
LONG * CanCommu
Definition: structs.h:944
void DoCheckpoint(int moduletype)
Definition: checkpoint.c:3108
WORD * funnum
Definition: structs.h:188
WORD * lo
Definition: structs.h:167