FORM  4.2
checkpoint.c
Go to the documentation of this file.
1 /*
2  #[ Explanations :
3 */
52 /*
53  #] Explanations :
54  #[ License :
55  *
56  * Copyright (C) 1984-2017 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("%%%% END M_const");
842 /* fflush(0); */
843 }
844 
845 static void print_P()
846 {
847  int i;
848  MesPrint("%%%% P_const");
849  print_LIST(&AP.DollarList);
850  for ( i=0; i<AP.DollarList.num; ++i ) {
851  print_DOLLARS(&(Dollars[i]));
852  }
853  MesPrint("--MARK 1");
854  print_LIST(&AP.PreVarList);
855  for ( i=0; i<AP.PreVarList.num; ++i ) {
856  print_PREVAR(&(PreVar[i]));
857  }
858  MesPrint("--MARK 2");
859  print_LIST(&AP.LoopList);
860  for ( i=0; i<AP.LoopList.num; ++i ) {
861  print_DOLOOP(&(DoLoops[i]));
862  }
863  MesPrint("--MARK 3");
864  print_LIST(&AP.ProcList);
865  for ( i=0; i<AP.ProcList.num; ++i ) {
866  print_PROCEDURE(&(Procedures[i]));
867  }
868  MesPrint("--MARK 4");
869  for ( i=0; i<=AP.PreSwitchLevel; ++i ) {
870  print_STR(AP.PreSwitchStrings[i]);
871  }
872  MesPrint("%l", AP.preStop-AP.preStart);
873  if ( AP.preFill ) MesPrint("%l", AP.preFill-AP.preStart);
874  print_CHARS(AP.preStart, AP.pSize);
875  MesPrint("%s", AP.procedureExtension);
876  MesPrint("%s", AP.cprocedureExtension);
877  print_INTV(AP.PreIfStack, AP.MaxPreIfLevel);
878  print_INTV(AP.PreSwitchModes, AP.NumPreSwitchStrings+1);
879  print_INTV(AP.PreTypes, AP.NumPreTypes+1);
880  MesPrint("%d", AP.PreAssignFlag);
881  MesPrint("--MARK 5");
882  MesPrint("%d", AP.PreContinuation);
883  MesPrint("%l", AP.InOutBuf);
884  MesPrint("%l", AP.pSize);
885  MesPrint("%d", AP.PreproFlag);
886  MesPrint("%d", AP.iBufError);
887  MesPrint("%d", AP.PreOut);
888  MesPrint("%d", AP.PreSwitchLevel);
889  MesPrint("%d", AP.NumPreSwitchStrings);
890  MesPrint("%d", AP.MaxPreTypes);
891  MesPrint("--MARK 6");
892  MesPrint("%d", AP.NumPreTypes);
893  MesPrint("%d", AP.DelayPrevar);
894  MesPrint("%d", AP.AllowDelay);
895  MesPrint("%d", AP.lhdollarerror);
896  MesPrint("%d", AP.eat);
897  MesPrint("%d", AP.gNumPre);
898  MesPrint("%d", AP.PreDebug);
899  MesPrint("--MARK 7");
900  MesPrint("%d", AP.DebugFlag);
901  MesPrint("%d", AP.preError);
902  MesPrint("%C", 1, &(AP.ComChar));
903  MesPrint("%C", 1, &(AP.cComChar));
904  MesPrint("%%%% END P_const");
905 /* fflush(0); */
906 }
907 
908 static void print_C()
909 {
910  int i;
911  UBYTE buf[40], *t;
912  MesPrint("%%%% C_const");
913  for ( i=0; i<32; ++i ) {
914  t = buf;
915  t = NumCopy((WORD)(AC.separators[i].bit_7),t);
916  t = NumCopy((WORD)(AC.separators[i].bit_6),t);
917  t = NumCopy((WORD)(AC.separators[i].bit_5),t);
918  t = NumCopy((WORD)(AC.separators[i].bit_4),t);
919  t = NumCopy((WORD)(AC.separators[i].bit_3),t);
920  t = NumCopy((WORD)(AC.separators[i].bit_2),t);
921  t = NumCopy((WORD)(AC.separators[i].bit_1),t);
922  t = NumCopy((WORD)(AC.separators[i].bit_0),t);
923  MesPrint("%s ",buf);
924  }
925  print_NAMETREE(AC.dollarnames);
926  print_NAMETREE(AC.exprnames);
927  print_NAMETREE(AC.varnames);
928  MesPrint("--MARK 1");
929  print_LIST(&AC.ChannelList);
930  for ( i=0; i<AC.ChannelList.num; ++i ) {
931  MesPrint("%s %d", channels[i].name, channels[i].handle);
932  }
933  MesPrint("--MARK 2");
934  print_LIST(&AC.DubiousList);
935  MesPrint("--MARK 3");
936  print_LIST(&AC.FunctionList);
937  for ( i=0; i<AC.FunctionList.num; ++i ) {
938  if ( functions[i].tabl ) {
939 
940  }
941  MesPrint("%l", functions[i].symminfo);
942  MesPrint("%l", functions[i].name);
943  MesPrint("%d", functions[i].namesize);
944  }
945  MesPrint("--MARK 4");
946  print_LIST(&AC.ExpressionList);
947  print_LIST(&AC.IndexList);
948  print_LIST(&AC.SetElementList);
949  print_LIST(&AC.SetList);
950  MesPrint("--MARK 5");
951  print_LIST(&AC.SymbolList);
952  print_LIST(&AC.VectorList);
953  print_LIST(&AC.PotModDolList);
954  print_LIST(&AC.ModOptDolList);
955  print_LIST(&AC.TableBaseList);
956 
957 /*
958  print_LIST(&AC.cbufList);
959  for ( i=0; i<AC.cbufList.num; ++i ) {
960  MesPrint("cbufList.num == %d", i);
961  print_CBUF(cbuf+i);
962  }
963  MesPrint("%d", AC.cbufnum);
964 */
965  MesPrint("--MARK 6");
966 
967  print_LIST(&AC.AutoSymbolList);
968  print_LIST(&AC.AutoIndexList);
969  print_LIST(&AC.AutoVectorList);
970  print_LIST(&AC.AutoFunctionList);
971 
972  print_NAMETREE(AC.autonames);
973  MesPrint("--MARK 7");
974 
975  print_LIST(AC.Symbols);
976  print_LIST(AC.Indices);
977  print_LIST(AC.Vectors);
978  print_LIST(AC.Functions);
979  MesPrint("--MARK 8");
980 
981  print_NAMETREE(*AC.activenames);
982 
983  MesPrint("--MARK 9");
984 
985  MesPrint("%d", AC.AutoDeclareFlag);
986 
987  for ( i=0; i<AC.NumStreams; ++i ) {
988  MesPrint("Stream %d\n", i);
989  print_STREAM(AC.Streams+i);
990  }
991  print_STREAM(AC.CurrentStream);
992  MesPrint("--MARK 10");
993 
994  print_LONGV(AC.termstack, AC.maxtermlevel);
995  print_LONGV(AC.termsortstack, AC.maxtermlevel);
996  print_VOIDP(AC.cmod, AM.MaxTal*4*sizeof(UWORD));
997  print_WORDV((WORD *)(AC.cmod), 1);
998  print_WORDV((WORD *)(AC.powmod), 1);
999  print_WORDV((WORD*)AC.modpowers, 1);
1000  print_WORDV((WORD*)AC.halfmod, 1);
1001  MesPrint("--MARK 10-2");
1002  /*
1003  print_WORDV(AC.ProtoType, AC.ProtoType[1]);
1004  print_WORDV(AC.WildC, 1);
1005  */
1006 
1007  MesPrint("--MARK 11");
1008  /* IfHeap ... Labels */
1009 
1010  print_CHARS((UBYTE*)AC.tokens, AC.toptokens-AC.tokens);
1011  MesPrint("%l", AC.endoftokens-AC.tokens);
1012  print_WORDV(AC.tokenarglevel, AM.MaxParLevel);
1013  print_WORDV((WORD*)AC.modinverses, ABS(AC.ncmod));
1014 #ifdef WITHPTHREADS
1015  print_LONGV(AC.inputnumbers, AC.sizepfirstnum+AC.sizepfirstnum*sizeof(WORD)/sizeof(LONG));
1016  print_WORDV(AC.pfirstnum, 1);
1017 #endif
1018  MesPrint("--MARK 12");
1019  print_LONGV(AC.argstack, MAXNEST);
1020  print_LONGV(AC.insidestack, MAXNEST);
1021  print_LONGV(AC.inexprstack, MAXNEST);
1022  MesPrint("%l", AC.iBufferSize);
1023  MesPrint("%l", AC.TransEname);
1024  MesPrint("%l", AC.ProcessBucketSize);
1025  MesPrint("%l", AC.mProcessBucketSize);
1026  MesPrint("%l", AC.CModule);
1027  MesPrint("%l", AC.ThreadBucketSize);
1028  MesPrint("%d", AC.NoShowInput);
1029  MesPrint("%d", AC.ShortStats);
1030  MesPrint("%d", AC.compiletype);
1031  MesPrint("%d", AC.firstconstindex);
1032  MesPrint("%d", AC.insidefirst);
1033  MesPrint("%d", AC.minsidefirst);
1034  MesPrint("%d", AC.wildflag);
1035  MesPrint("%d", AC.NumLabels);
1036  MesPrint("%d", AC.MaxLabels);
1037  MesPrint("--MARK 13");
1038  MesPrint("%d", AC.lDefDim);
1039  MesPrint("%d", AC.lDefDim4);
1040  MesPrint("%d", AC.NumWildcardNames);
1041  MesPrint("%d", AC.WildcardBufferSize);
1042  MesPrint("%d", AC.MaxIf);
1043  MesPrint("%d", AC.NumStreams);
1044  MesPrint("%d", AC.MaxNumStreams);
1045  MesPrint("%d", AC.firstctypemessage);
1046  MesPrint("%d", AC.tablecheck);
1047  MesPrint("%d", AC.idoption);
1048  MesPrint("%d", AC.BottomLevel);
1049  MesPrint("%d", AC.CompileLevel);
1050  MesPrint("%d", AC.TokensWriteFlag);
1051  MesPrint("%d", AC.UnsureDollarMode);
1052  MesPrint("%d", AC.outsidefun);
1053  MesPrint("%d", AC.funpowers);
1054  MesPrint("--MARK 14");
1055  MesPrint("%d", AC.WarnFlag);
1056  MesPrint("%d", AC.StatsFlag);
1057  MesPrint("%d", AC.NamesFlag);
1058  MesPrint("%d", AC.CodesFlag);
1059  MesPrint("%d", AC.TokensWriteFlag);
1060  MesPrint("%d", AC.SetupFlag);
1061  MesPrint("%d", AC.SortType);
1062  MesPrint("%d", AC.lSortType);
1063  MesPrint("%d", AC.ThreadStats);
1064  MesPrint("%d", AC.FinalStats);
1065  MesPrint("%d", AC.ThreadsFlag);
1066  MesPrint("%d", AC.ThreadBalancing);
1067  MesPrint("%d", AC.ThreadSortFileSynch);
1068  MesPrint("%d", AC.ProcessStats);
1069  MesPrint("%d", AC.OldParallelStats);
1070  MesPrint("%d", AC.WTimeStatsFlag);
1071  MesPrint("%d", AC.BracketNormalize);
1072  MesPrint("%d", AC.maxtermlevel);
1073  MesPrint("%d", AC.dumnumflag);
1074  MesPrint("--MARK 15");
1075  MesPrint("%d", AC.bracketindexflag);
1076  MesPrint("%d", AC.parallelflag);
1077  MesPrint("%d", AC.mparallelflag);
1078  MesPrint("%d", AC.properorderflag);
1079  MesPrint("%d", AC.vetofilling);
1080  MesPrint("%d", AC.tablefilling);
1081  MesPrint("%d", AC.vetotablebasefill);
1082  MesPrint("%d", AC.exprfillwarning);
1083  MesPrint("%d", AC.lhdollarflag);
1084  MesPrint("%d", AC.NoCompress);
1085 #ifdef WITHPTHREADS
1086  MesPrint("%d", AC.numpfirstnum);
1087  MesPrint("%d", AC.sizepfirstnum);
1088 #endif
1089  MesPrint("%d", AC.RepLevel);
1090  MesPrint("%d", AC.arglevel);
1091  MesPrint("%d", AC.insidelevel);
1092  MesPrint("%d", AC.inexprlevel);
1093  MesPrint("%d", AC.termlevel);
1094  MesPrint("--MARK 16");
1095  print_WORDV(AC.argsumcheck, MAXNEST);
1096  print_WORDV(AC.insidesumcheck, MAXNEST);
1097  print_WORDV(AC.inexprsumcheck, MAXNEST);
1098  MesPrint("%d", AC.MustTestTable);
1099  MesPrint("%d", AC.DumNum);
1100  MesPrint("%d", AC.ncmod);
1101  MesPrint("%d", AC.npowmod);
1102  MesPrint("%d", AC.modmode);
1103  MesPrint("%d", AC.nhalfmod);
1104  MesPrint("%d", AC.DirtPow);
1105  MesPrint("%d", AC.lUnitTrace);
1106  MesPrint("%d", AC.NwildC);
1107  MesPrint("%d", AC.ComDefer);
1108  MesPrint("%d", AC.CollectFun);
1109  MesPrint("%d", AC.AltCollectFun);
1110  MesPrint("--MARK 17");
1111  MesPrint("%d", AC.OutputMode);
1112  MesPrint("%d", AC.Cnumpows);
1113  MesPrint("%d", AC.OutputSpaces);
1114  MesPrint("%d", AC.OutNumberType);
1115  print_WORDV(AC.lUniTrace, 4);
1116  print_WORDV(AC.RepSumCheck, MAXREPEAT);
1117  MesPrint("%d", AC.DidClean);
1118  MesPrint("%d", AC.IfLevel);
1119  MesPrint("%d", AC.WhileLevel);
1120  print_WORDV(AC.IfSumCheck, (AC.MaxIf+1));
1121  MesPrint("%d", AC.LogHandle);
1122  MesPrint("%d", AC.LineLength);
1123  MesPrint("%d", AC.StoreHandle);
1124  MesPrint("%d", AC.HideLevel);
1125  MesPrint("%d", AC.lPolyFun);
1126  MesPrint("%d", AC.lPolyFunInv);
1127  MesPrint("%d", AC.lPolyFunType);
1128  MesPrint("%d", AC.lPolyFunExp);
1129  MesPrint("%d", AC.lPolyFunVar);
1130  MesPrint("%d", AC.lPolyFunPow);
1131  MesPrint("%d", AC.SymChangeFlag);
1132  MesPrint("%d", AC.CollectPercentage);
1133  MesPrint("%d", AC.ShortStatsMax);
1134  MesPrint("--MARK 18");
1135 
1136  print_CHARS(AC.Commercial, COMMERCIALSIZE+2);
1137 
1138  MesPrint("%", AC.CheckpointFlag);
1139  MesPrint("%l", AC.CheckpointStamp);
1140  print_STR((unsigned char*)AC.CheckpointRunAfter);
1141  print_STR((unsigned char*)AC.CheckpointRunBefore);
1142  MesPrint("%l", AC.CheckpointInterval);
1143 
1144  MesPrint("%%%% END C_const");
1145 /* fflush(0); */
1146 }
1147 
1148 static void print_R()
1149 {
1150  GETIDENTITY
1151  int i;
1152  MesPrint("%%%% R_const");
1153  MesPrint("%l", (LONG)(AR.infile-AR.Fscr));
1154  MesPrint("%s", AR.infile->name);
1155  MesPrint("%l", (LONG)(AR.outfile-AR.Fscr));
1156  MesPrint("%s", AR.outfile->name);
1157  MesPrint("%l", AR.hidefile-AR.Fscr);
1158  MesPrint("%s", AR.hidefile->name);
1159  for ( i=0; i<3; ++i ) {
1160  MesPrint("FSCR %d", i);
1161  print_WORDB(AR.Fscr[i].PObuffer, AR.Fscr[i].POfull);
1162  }
1163  /* ... */
1164  MesPrint("%l", AR.OldTime);
1165  MesPrint("%l", AR.InInBuf);
1166  MesPrint("%l", AR.InHiBuf);
1167  MesPrint("%l", AR.pWorkSize);
1168  MesPrint("%l", AR.lWorkSize);
1169  MesPrint("%l", AR.posWorkSize);
1170  MesPrint("%d", AR.NoCompress);
1171  MesPrint("%d", AR.gzipCompress);
1172  MesPrint("%d", AR.Cnumlhs);
1173 #ifdef WITHPTHREADS
1174  MesPrint("%d", AR.exprtodo);
1175 #endif
1176  MesPrint("%d", AR.GetFile);
1177  MesPrint("%d", AR.KeptInHold);
1178  MesPrint("%d", AR.BracketOn);
1179  MesPrint("%d", AR.MaxBracket);
1180  MesPrint("%d", AR.CurDum);
1181  MesPrint("%d", AR.DeferFlag);
1182  MesPrint("%d", AR.TePos);
1183  MesPrint("%d", AR.sLevel);
1184  MesPrint("%d", AR.Stage4Name);
1185  MesPrint("%d", AR.GetOneFile);
1186  MesPrint("%d", AR.PolyFun);
1187  MesPrint("%d", AR.PolyFunInv);
1188  MesPrint("%d", AR.PolyFunType);
1189  MesPrint("%d", AR.PolyFunExp);
1190  MesPrint("%d", AR.PolyFunVar);
1191  MesPrint("%d", AR.PolyFunPow);
1192  MesPrint("%d", AR.Eside);
1193  MesPrint("%d", AR.MaxDum);
1194  MesPrint("%d", AR.level);
1195  MesPrint("%d", AR.expchanged);
1196  MesPrint("%d", AR.expflags);
1197  MesPrint("%d", AR.CurExpr);
1198  MesPrint("%d", AR.SortType);
1199  MesPrint("%d", AR.ShortSortCount);
1200  MesPrint("%%%% END R_const");
1201 /* fflush(0); */
1202 }
1203 
1204 #endif /* ifdef PRINTDEBUG */
1205 
1206 /*
1207  #] Debugging :
1208  #[ Cached file operation functions :
1209 */
1210 
1211 #define CACHED_SNAPSHOT
1212 
1213 #define CACHE_SIZE 4096
1214 
1215 #ifdef CACHED_SNAPSHOT
1216 unsigned char cache_buffer[CACHE_SIZE];
1217 size_t cache_fill = 0;
1218 
1219 size_t fwrite_cached(const void *ptr, size_t size, size_t nmemb, FILE *fd)
1220 {
1221  size_t fullsize = size*nmemb;
1222  if ( fullsize+cache_fill >= CACHE_SIZE ) {
1223  size_t overlap = CACHE_SIZE-cache_fill;
1224  memcpy(cache_buffer+cache_fill, (unsigned char*)ptr, overlap);
1225  if ( fwrite(cache_buffer, 1, CACHE_SIZE, fd) != CACHE_SIZE ) return 0;
1226  fullsize -= overlap;
1227  if ( fullsize >= CACHE_SIZE ) {
1228  cache_fill = fullsize % CACHE_SIZE;
1229  if ( cache_fill ) memcpy(cache_buffer, (unsigned char*)ptr+overlap+fullsize-cache_fill, cache_fill);
1230  if ( fwrite((unsigned char*)ptr+overlap, 1, fullsize-cache_fill, fd) != fullsize-cache_fill ) return 0;
1231  }
1232  else {
1233  memcpy(cache_buffer, (unsigned char*)ptr+overlap, fullsize);
1234  cache_fill = fullsize;
1235  }
1236  }
1237  else {
1238  memcpy(cache_buffer+cache_fill, (unsigned char*)ptr, fullsize);
1239  cache_fill += fullsize;
1240  }
1241  return nmemb;
1242 }
1243 
1244 size_t flush_cache(FILE *fd)
1245 {
1246  if ( cache_fill ) {
1247  size_t retval = fwrite(cache_buffer, 1, cache_fill, fd);
1248  if ( retval != cache_fill ) {
1249  cache_fill = 0;
1250  return 0;
1251  }
1252  cache_fill = 0;
1253  }
1254  return 1;
1255 }
1256 #else
1257 size_t fwrite_cached(const void *ptr, size_t size, size_t nmemb, FILE *fd)
1258 {
1259  return fwrite(ptr, size, nmemb, fd);
1260 }
1261 
1262 size_t flush_cache(FILE *fd)
1263 {
1264  DUMMYUSE(fd)
1265  return 1;
1266 }
1267 #endif
1268 
1269 /*
1270  #] Cached file operation functions :
1271  #[ Helper Macros :
1272 */
1273 
1274 /* some helper macros to streamline the code in DoSnapshot() and DoRecovery() */
1275 
1276 /* freeing memory */
1277 
1278 #define R_FREE(ARG) \
1279  if ( ARG ) M_free(ARG, #ARG);
1280 
1281 #define R_FREE_NAMETREE(ARG) \
1282  R_FREE(ARG->namenode); \
1283  R_FREE(ARG->namebuffer); \
1284  R_FREE(ARG);
1285 
1286 #define R_FREE_STREAM(ARG) \
1287  R_FREE(ARG.buffer); \
1288  R_FREE(ARG.FoldName); \
1289  R_FREE(ARG.name);
1290 
1291 /* reading a single variable */
1292 
1293 #define R_SET(VAR,TYPE) \
1294  VAR = *((TYPE*)p); p = (unsigned char*)p + sizeof(TYPE);
1295 
1296 /* general buffer */
1297 
1298 #define R_COPY_B(VAR,SIZE,CAST) \
1299  VAR = (CAST)Malloc1(SIZE,#VAR); \
1300  memcpy(VAR, p, SIZE); p = (unsigned char*)p + SIZE;
1301 
1302 #define S_WRITE_B(BUF,LEN) \
1303  if ( fwrite_cached(BUF, 1, LEN, fd) != (size_t)(LEN) ) return(__LINE__);
1304 
1305 #define S_FLUSH_B \
1306  if ( flush_cache(fd) != 1 ) return(__LINE__);
1307 
1308 /* character strings */
1309 
1310 #define R_COPY_S(VAR,CAST) \
1311  if ( VAR ) { \
1312  VAR = (CAST)Malloc1(strlen(p)+1,"R_COPY_S"); \
1313  strcpy((char*)VAR, p); p = (unsigned char*)p + strlen(p) + 1; \
1314  }
1315 
1316 #define S_WRITE_S(STR) \
1317  if ( STR ) { \
1318  l = strlen((char*)STR) + 1; \
1319  if ( fwrite_cached(STR, 1, l, fd) != (size_t)l ) return(__LINE__); \
1320  }
1321 
1322 /* LIST */
1323 
1324 #define R_COPY_LIST(ARG) \
1325  if ( ARG.maxnum ) { \
1326  R_COPY_B(ARG.lijst, ARG.size*ARG.maxnum, void*) \
1327  }
1328 
1329 #define S_WRITE_LIST(LST) \
1330  if ( LST.maxnum ) { \
1331  S_WRITE_B((char*)LST.lijst, LST.maxnum*LST.size) \
1332  }
1333 
1334 /* NAMETREE */
1335 
1336 #define R_COPY_NAMETREE(ARG) \
1337  R_COPY_B(ARG, sizeof(NAMETREE), NAMETREE*); \
1338  if ( ARG->namenode ) { \
1339  R_COPY_B(ARG->namenode, ARG->nodesize*sizeof(NAMENODE), NAMENODE*); \
1340  } \
1341  if ( ARG->namebuffer ) { \
1342  R_COPY_B(ARG->namebuffer, ARG->namesize, UBYTE*); \
1343  }
1344 
1345 #define S_WRITE_NAMETREE(ARG) \
1346  S_WRITE_B(ARG, sizeof(NAMETREE)); \
1347  if ( ARG->namenode ) { \
1348  S_WRITE_B(ARG->namenode, ARG->nodesize*sizeof(struct NaMeNode)); \
1349  } \
1350  if ( ARG->namebuffer ) { \
1351  S_WRITE_B(ARG->namebuffer, ARG->namesize); \
1352  }
1353 
1354 /* DOLLAR */
1355 
1356 #define S_WRITE_DOLLAR(ARG) \
1357  if ( ARG.size && ARG.where && ARG.where != &(AM.dollarzero) ) { \
1358  S_WRITE_B(ARG.where, ARG.size*sizeof(WORD)) \
1359  }
1360 
1361 /* Printing time marks with ANNOUNCE macro */
1362 
1363 #ifdef PRINTTIMEMARKS
1364 time_t announce_time;
1365 #define ANNOUNCE(str) time(&announce_time); MesPrint("TIMEMARK %s %s", ctime(&announce_time), #str);
1366 #else
1367 #define ANNOUNCE(str)
1368 #endif
1369 
1370 /*
1371  #] Helper Macros :
1372  #[ DoRecovery :
1373 */
1374 
1399 int DoRecovery(int *moduletype)
1400 {
1401  GETIDENTITY
1402  FILE *fd;
1403  POSITION pos;
1404  void *buf, *p;
1405  LONG size, l;
1406  int i, j;
1407  UBYTE *org;
1408  char *namebufout, *namebufhide;
1409  LONG ofs;
1410  void *oldAMdollarzero;
1411  LIST PotModDolListBackup;
1412  LIST ModOptDolListBackup;
1413  WORD oldLogHandle;
1414 
1415  MesPrint("Recovering ... %"); fflush(0);
1416 
1417  if ( !(fd = fopen(recoveryfile, "r")) ) return(__LINE__);
1418 
1419  /* load the complete recovery file into a buffer */
1420  if ( fread(&pos, sizeof(POSITION), 1, fd) != 1 ) return(__LINE__);
1421  size = BASEPOSITION(pos) - sizeof(POSITION);
1422  buf = Malloc1(size, "recovery buffer");
1423  if ( fread(buf, size, 1, fd) != 1 ) return(__LINE__);
1424 
1425  /* pointer p will go through the buffer in the following */
1426  p = buf;
1427 
1428  /* read moduletype */
1429  R_SET(*moduletype, int);
1430 
1431  /*#[ AM : */
1432 
1433  /* only certain elements will be restored. the rest of AM should have gotten
1434  * the correct values at startup. */
1435 
1436  R_SET(AM.hparallelflag, int);
1437  R_SET(AM.gparallelflag, int);
1438  R_SET(AM.gCodesFlag, int);
1439  R_SET(AM.gNamesFlag, int);
1440  R_SET(AM.gStatsFlag, int);
1441  R_SET(AM.gTokensWriteFlag, int);
1442  R_SET(AM.gNoSpacesInNumbers, int);
1443  R_SET(AM.gIndentSpace, WORD);
1444  R_SET(AM.gUnitTrace, WORD);
1445  R_SET(AM.gDefDim, int);
1446  R_SET(AM.gDefDim4, int);
1447  R_SET(AM.gncmod, WORD);
1448  R_SET(AM.gnpowmod, WORD);
1449  R_SET(AM.gmodmode, WORD);
1450  R_SET(AM.gOutputMode, WORD);
1451  R_SET(AM.gCnumpows, WORD);
1452  R_SET(AM.gOutputSpaces, WORD);
1453  R_SET(AM.gOutNumberType, WORD);
1454  R_SET(AM.gfunpowers, int);
1455  R_SET(AM.gPolyFun, WORD);
1456  R_SET(AM.gPolyFunInv, WORD);
1457  R_SET(AM.gPolyFunType, WORD);
1458  R_SET(AM.gPolyFunExp, WORD);
1459  R_SET(AM.gPolyFunVar, WORD);
1460  R_SET(AM.gPolyFunPow, WORD);
1461  R_SET(AM.gProcessBucketSize, LONG);
1462  R_SET(AM.OldChildTime, LONG);
1463  R_SET(AM.OldSecTime, LONG);
1464  R_SET(AM.OldMilliTime, LONG);
1465  R_SET(AM.gproperorderflag, int);
1466  R_SET(AM.gThreadBucketSize, LONG);
1467  R_SET(AM.gSizeCommuteInSet, int);
1468  R_SET(AM.gThreadStats, int);
1469  R_SET(AM.gFinalStats, int);
1470  R_SET(AM.gThreadsFlag, int);
1471  R_SET(AM.gThreadBalancing, int);
1472  R_SET(AM.gThreadSortFileSynch, int);
1473  R_SET(AM.gProcessStats, int);
1474  R_SET(AM.gOldParallelStats, int);
1475  R_SET(AM.gSortType, int);
1476  R_SET(AM.gShortStatsMax, WORD);
1477  R_SET(AM.gIsFortran90, int);
1478  R_SET(oldAMdollarzero, void*);
1479  R_FREE(AM.gFortran90Kind);
1480  R_SET(AM.gFortran90Kind,UBYTE *);
1481  R_COPY_S(AM.gFortran90Kind,UBYTE *);
1482 
1483  R_COPY_S(AM.gextrasym,UBYTE *);
1484  R_COPY_S(AM.ggextrasym,UBYTE *);
1485 
1486  R_SET(AM.PrintTotalSize,int);
1487  R_SET(AM.fbuffersize,int);
1488  R_SET(AM.gOldFactArgFlag,int);
1489  R_SET(AM.ggOldFactArgFlag,int);
1490 
1491  R_SET(AM.gnumextrasym,int);
1492  R_SET(AM.ggnumextrasym,int);
1493  R_SET(AM.NumSpectatorFiles,int);
1494  R_SET(AM.SizeForSpectatorFiles,int);
1495  R_SET(AM.gOldGCDflag,int);
1496  R_SET(AM.ggOldGCDflag,int);
1497  R_SET(AM.gWTimeStatsFlag, int);
1498 
1499  R_FREE(AM.Path);
1500  R_SET(AM.Path,UBYTE *);
1501  R_COPY_S(AM.Path,UBYTE *);
1502 
1503 #ifdef PRINTDEBUG
1504  print_M();
1505 #endif
1506 
1507  /*#] AM : */
1508  /*#[ AC : */
1509 
1510  /* #[ AC free pointers */
1511 
1512  /* AC will be overwritten by data from the recovery file, therefore
1513  * dynamically allocated memory must be freed first. */
1514 
1515  R_FREE_NAMETREE(AC.dollarnames);
1516  R_FREE_NAMETREE(AC.exprnames);
1517  R_FREE_NAMETREE(AC.varnames);
1518  for ( i=0; i<AC.ChannelList.num; ++i ) {
1519  R_FREE(channels[i].name);
1520  }
1521  R_FREE(AC.ChannelList.lijst);
1522  R_FREE(AC.DubiousList.lijst);
1523  for ( i=0; i<AC.FunctionList.num; ++i ) {
1524  TABLES T = functions[i].tabl;
1525  if ( T ) {
1526  R_FREE(T->buffers);
1527  R_FREE(T->mm);
1528  R_FREE(T->flags);
1529  R_FREE(T->prototype);
1530  R_FREE(T->tablepointers);
1531  if ( T->sparse ) {
1532  R_FREE(T->boomlijst);
1533  R_FREE(T->argtail);
1534  }
1535  if ( T->spare ) {
1536  R_FREE(T->spare->buffers);
1537  R_FREE(T->spare->mm);
1538  R_FREE(T->spare->flags);
1539  R_FREE(T->spare->tablepointers);
1540  if ( T->spare->sparse ) {
1541  R_FREE(T->spare->boomlijst);
1542  }
1543  R_FREE(T->spare);
1544  }
1545  R_FREE(T);
1546  }
1547  }
1548  R_FREE(AC.FunctionList.lijst);
1549  for ( i=0; i<AC.ExpressionList.num; ++i ) {
1550  if ( Expressions[i].renum ) {
1551  R_FREE(Expressions[i].renum->symb.lo);
1552  R_FREE(Expressions[i].renum);
1553  }
1554  if ( Expressions[i].bracketinfo ) {
1555  R_FREE(Expressions[i].bracketinfo->indexbuffer);
1556  R_FREE(Expressions[i].bracketinfo->bracketbuffer);
1557  R_FREE(Expressions[i].bracketinfo);
1558  }
1559  if ( Expressions[i].newbracketinfo ) {
1560  R_FREE(Expressions[i].newbracketinfo->indexbuffer);
1561  R_FREE(Expressions[i].newbracketinfo->bracketbuffer);
1562  R_FREE(Expressions[i].newbracketinfo);
1563  }
1564  if ( Expressions[i].renumlists != AN.dummyrenumlist ) {
1565  R_FREE(Expressions[i].renumlists);
1566  }
1567  R_FREE(Expressions[i].inmem);
1568  }
1569  R_FREE(AC.ExpressionList.lijst);
1570  R_FREE(AC.IndexList.lijst);
1571  R_FREE(AC.SetElementList.lijst);
1572  R_FREE(AC.SetList.lijst);
1573  R_FREE(AC.SymbolList.lijst);
1574  R_FREE(AC.VectorList.lijst);
1575  for ( i=0; i<AC.TableBaseList.num; ++i ) {
1576  R_FREE(tablebases[i].iblocks);
1577  R_FREE(tablebases[i].nblocks);
1578  R_FREE(tablebases[i].name);
1579  R_FREE(tablebases[i].fullname);
1580  R_FREE(tablebases[i].tablenames);
1581  }
1582  R_FREE(AC.TableBaseList.lijst);
1583  for ( i=0; i<AC.cbufList.num; ++i ) {
1584  R_FREE(cbuf[i].Buffer);
1585  R_FREE(cbuf[i].lhs);
1586  R_FREE(cbuf[i].rhs);
1587  R_FREE(cbuf[i].boomlijst);
1588  }
1589  R_FREE(AC.cbufList.lijst);
1590  R_FREE(AC.AutoSymbolList.lijst);
1591  R_FREE(AC.AutoIndexList.lijst);
1592  R_FREE(AC.AutoVectorList.lijst);
1593  /* Tables cannot be auto-declared, therefore no extra code here */
1594  R_FREE(AC.AutoFunctionList.lijst);
1595  R_FREE_NAMETREE(AC.autonames);
1596  for ( i=0; i<AC.NumStreams; ++i ) {
1597  R_FREE_STREAM(AC.Streams[i]);
1598  }
1599  R_FREE(AC.Streams);
1600  R_FREE(AC.termstack);
1601  R_FREE(AC.termsortstack);
1602  R_FREE(AC.cmod);
1603  R_FREE(AC.modpowers);
1604  R_FREE(AC.halfmod);
1605  R_FREE(AC.IfHeap);
1606  R_FREE(AC.IfCount);
1607  R_FREE(AC.iBuffer);
1608  for ( i=0; i<AC.NumLabels; ++i ) {
1609  R_FREE(AC.LabelNames[i]);
1610  }
1611  R_FREE(AC.LabelNames);
1612  R_FREE(AC.FixIndices);
1613  R_FREE(AC.termsumcheck);
1614  R_FREE(AC.WildcardNames);
1615  R_FREE(AC.tokens);
1616  R_FREE(AC.tokenarglevel);
1617  R_FREE(AC.modinverses);
1618  R_FREE(AC.Fortran90Kind);
1619 #ifdef WITHPTHREADS
1620  R_FREE(AC.inputnumbers);
1621 #endif
1622  R_FREE(AC.IfSumCheck);
1623  R_FREE(AC.CommuteInSet);
1624  R_FREE(AC.CheckpointRunAfter);
1625  R_FREE(AC.CheckpointRunBefore);
1626 
1627  /* #] AC free pointers */
1628 
1629  /* backup some lists in order to restore it to the initial setup */
1630  PotModDolListBackup = AC.PotModDolList;
1631  ModOptDolListBackup = AC.ModOptDolList;
1632  oldLogHandle = AC.LogHandle;
1633 
1634  /* first we copy AC as a whole and then restore the pointer structures step
1635  by step. */
1636 
1637  AC = *((struct C_const*)p); p = (unsigned char*)p + sizeof(struct C_const);
1638 
1639  R_COPY_NAMETREE(AC.dollarnames);
1640  R_COPY_NAMETREE(AC.exprnames);
1641  R_COPY_NAMETREE(AC.varnames);
1642 
1643  R_COPY_LIST(AC.ChannelList);
1644  for ( i=0; i<AC.ChannelList.num; ++i ) {
1645  R_COPY_S(channels[i].name,char*);
1646  channels[i].handle = ReOpenFile(channels[i].name);
1647  }
1648  AC.ChannelList.message = "channel buffer";
1649 
1650  AC.DubiousList.lijst = 0;
1651  AC.DubiousList.message = "ambiguous variable";
1652  AC.DubiousList.num =
1653  AC.DubiousList.maxnum =
1654  AC.DubiousList.numglobal =
1655  AC.DubiousList.numtemp =
1656  AC.DubiousList.numclear = 0;
1657 
1658  R_COPY_LIST(AC.FunctionList);
1659  for ( i=0; i<AC.FunctionList.num; ++i ) {
1660  if ( functions[i].tabl ) {
1661  TABLES tabl;
1662  R_COPY_B(tabl, sizeof(struct TaBlEs), TABLES);
1663  functions[i].tabl = tabl;
1664  if ( tabl->tablepointers ) {
1665  if ( tabl->sparse ) {
1666  R_COPY_B(tabl->tablepointers,
1667  tabl->reserved*sizeof(WORD)*(tabl->numind+TABLEEXTENSION),
1668  WORD*);
1669  }
1670  else {
1671  R_COPY_B(tabl->tablepointers,
1672  TABLEEXTENSION*sizeof(WORD)*(tabl->totind), WORD*);
1673  }
1674  }
1675  org = (UBYTE*)tabl->prototype;
1676 #ifdef WITHPTHREADS
1677  R_COPY_B(tabl->prototype, tabl->prototypeSize, WORD**);
1678  ofs = (UBYTE*)tabl->prototype - org;
1679  for ( j=0; j<AM.totalnumberofthreads; ++j ) {
1680  if ( tabl->prototype[j] ) {
1681  tabl->prototype[j] = (WORD*)((UBYTE*)tabl->prototype[j] + ofs);
1682  }
1683  }
1684  if ( tabl->pattern ) {
1685  tabl->pattern = (WORD**)((UBYTE*)tabl->pattern + ofs);
1686  for ( j=0; j<AM.totalnumberofthreads; ++j ) {
1687  if ( tabl->pattern[j] ) {
1688  tabl->pattern[j] = (WORD*)((UBYTE*)tabl->pattern[j] + ofs);
1689  }
1690  }
1691  }
1692 #else
1693  ofs = tabl->pattern - tabl->prototype;
1694  R_COPY_B(tabl->prototype, tabl->prototypeSize, WORD*);
1695  if ( tabl->pattern ) {
1696  tabl->pattern = tabl->prototype + ofs;
1697  }
1698 #endif
1699  R_COPY_B(tabl->mm, tabl->numind*(LONG)sizeof(MINMAX), MINMAX*);
1700  R_COPY_B(tabl->flags, tabl->numind*(LONG)sizeof(WORD), WORD*);
1701  if ( tabl->sparse ) {
1702  R_COPY_B(tabl->boomlijst, tabl->MaxTreeSize*(LONG)sizeof(COMPTREE), COMPTREE*);
1703  R_COPY_S(tabl->argtail,UBYTE*);
1704  }
1705  R_COPY_B(tabl->buffers, tabl->bufferssize*(LONG)sizeof(WORD), WORD*);
1706  if ( tabl->spare ) {
1707  TABLES spare;
1708  R_COPY_B(spare, sizeof(struct TaBlEs), TABLES);
1709  tabl->spare = spare;
1710  if ( spare->tablepointers ) {
1711  if ( spare->sparse ) {
1712  R_COPY_B(spare->tablepointers,
1713  spare->reserved*sizeof(WORD)*(spare->numind+TABLEEXTENSION),
1714  WORD*);
1715  }
1716  else {
1717  R_COPY_B(spare->tablepointers,
1718  TABLEEXTENSION*sizeof(WORD)*(spare->totind), WORD*);
1719  }
1720  }
1721  spare->prototype = tabl->prototype;
1722  spare->pattern = tabl->pattern;
1723  R_COPY_B(spare->mm, spare->numind*(LONG)sizeof(MINMAX), MINMAX*);
1724  R_COPY_B(spare->flags, spare->numind*(LONG)sizeof(WORD), WORD*);
1725  if ( tabl->sparse ) {
1726  R_COPY_B(spare->boomlijst, spare->MaxTreeSize*(LONG)sizeof(COMPTREE), COMPTREE*);
1727  spare->argtail = tabl->argtail;
1728  }
1729  spare->spare = tabl;
1730  R_COPY_B(spare->buffers, spare->bufferssize*(LONG)sizeof(WORD), WORD*);
1731  }
1732  }
1733  }
1734  AC.FunctionList.message = "function";
1735 
1736  R_COPY_LIST(AC.ExpressionList);
1737  for ( i=0; i<AC.ExpressionList.num; ++i ) {
1738  EXPRESSIONS ex = Expressions + i;
1739  if ( ex->renum ) {
1740  R_COPY_B(ex->renum, sizeof(struct ReNuMbEr), RENUMBER);
1741  org = (UBYTE*)ex->renum->symb.lo;
1742  R_SET(size, size_t);
1743  R_COPY_B(ex->renum->symb.lo, size, WORD*);
1744  ofs = (UBYTE*)ex->renum->symb.lo - org;
1745  ex->renum->symb.start = (WORD*)((UBYTE*)ex->renum->symb.start + ofs);
1746  ex->renum->symb.hi = (WORD*)((UBYTE*)ex->renum->symb.hi + ofs);
1747  ex->renum->indi.lo = (WORD*)((UBYTE*)ex->renum->indi.lo + ofs);
1748  ex->renum->indi.start = (WORD*)((UBYTE*)ex->renum->indi.start + ofs);
1749  ex->renum->indi.hi = (WORD*)((UBYTE*)ex->renum->indi.hi + ofs);
1750  ex->renum->vect.lo = (WORD*)((UBYTE*)ex->renum->vect.lo + ofs);
1751  ex->renum->vect.start = (WORD*)((UBYTE*)ex->renum->vect.start + ofs);
1752  ex->renum->vect.hi = (WORD*)((UBYTE*)ex->renum->vect.hi + ofs);
1753  ex->renum->func.lo = (WORD*)((UBYTE*)ex->renum->func.lo + ofs);
1754  ex->renum->func.start = (WORD*)((UBYTE*)ex->renum->func.start + ofs);
1755  ex->renum->func.hi = (WORD*)((UBYTE*)ex->renum->func.hi + ofs);
1756  ex->renum->symnum = (WORD*)((UBYTE*)ex->renum->symnum + ofs);
1757  ex->renum->indnum = (WORD*)((UBYTE*)ex->renum->indnum + ofs);
1758  ex->renum->vecnum = (WORD*)((UBYTE*)ex->renum->vecnum + ofs);
1759  ex->renum->funnum = (WORD*)((UBYTE*)ex->renum->funnum + ofs);
1760  }
1761  if ( ex->bracketinfo ) {
1762  R_COPY_B(ex->bracketinfo, sizeof(BRACKETINFO), BRACKETINFO*);
1763  R_COPY_B(ex->bracketinfo->indexbuffer, ex->bracketinfo->indexbuffersize*sizeof(BRACKETINDEX), BRACKETINDEX*);
1764  R_COPY_B(ex->bracketinfo->bracketbuffer, ex->bracketinfo->bracketbuffersize*sizeof(WORD), WORD*);
1765  }
1766  if ( ex->newbracketinfo ) {
1767  R_COPY_B(ex->newbracketinfo, sizeof(BRACKETINFO), BRACKETINFO*);
1768  R_COPY_B(ex->newbracketinfo->indexbuffer, ex->newbracketinfo->indexbuffersize*sizeof(BRACKETINDEX), BRACKETINDEX*);
1769  R_COPY_B(ex->newbracketinfo->bracketbuffer, ex->newbracketinfo->bracketbuffersize*sizeof(WORD), WORD*);
1770  }
1771 #ifdef WITHPTHREADS
1772  ex->renumlists = 0;
1773 #else
1774  ex->renumlists = AN.dummyrenumlist;
1775 #endif
1776  if ( ex->inmem ) {
1777  R_SET(size, size_t);
1778  R_COPY_B(ex->inmem, size, WORD*);
1779  }
1780  }
1781  AC.ExpressionList.message = "expression";
1782 
1783  R_COPY_LIST(AC.IndexList);
1784  AC.IndexList.message = "index";
1785  R_COPY_LIST(AC.SetElementList);
1786  AC.SetElementList.message = "set element";
1787  R_COPY_LIST(AC.SetList);
1788  AC.SetList.message = "set";
1789  R_COPY_LIST(AC.SymbolList);
1790  AC.SymbolList.message = "symbol";
1791  R_COPY_LIST(AC.VectorList);
1792  AC.VectorList.message = "vector";
1793 
1794  AC.PotModDolList = PotModDolListBackup;
1795  AC.ModOptDolList = ModOptDolListBackup;
1796 
1797  R_COPY_LIST(AC.TableBaseList);
1798  for ( i=0; i<AC.TableBaseList.num; ++i ) {
1799  if ( tablebases[i].iblocks ) {
1800  R_COPY_B(tablebases[i].iblocks, tablebases[i].info.numberofindexblocks*sizeof(INDEXBLOCK*),INDEXBLOCK**);
1801  for ( j=0; j<tablebases[i].info.numberofindexblocks; ++j ) {
1802  if ( tablebases[i].iblocks[j] ) {
1803  R_COPY_B(tablebases[i].iblocks[j], sizeof(INDEXBLOCK), INDEXBLOCK*);
1804  }
1805  }
1806  }
1807  if ( tablebases[i].nblocks ) {
1808  R_COPY_B(tablebases[i].nblocks, tablebases[i].info.numberofnamesblocks*sizeof(NAMESBLOCK*),NAMESBLOCK**);
1809  for ( j=0; j<tablebases[i].info.numberofindexblocks; ++j ) {
1810  if ( tablebases[i].nblocks[j] ) {
1811  R_COPY_B(tablebases[i].nblocks[j], sizeof(NAMESBLOCK), NAMESBLOCK*);
1812  }
1813  }
1814  }
1815  /* reopen file */
1816  if ( ( tablebases[i].handle = fopen(tablebases[i].fullname, "r+b") ) == NULL ) {
1817  MesPrint("ERROR: Could not reopen tablebase %s!",tablebases[i].name);
1818  Terminate(-1);
1819  }
1820  R_COPY_S(tablebases[i].name,char*);
1821  R_COPY_S(tablebases[i].fullname,char*);
1822  R_COPY_S(tablebases[i].tablenames,char*);
1823  }
1824  AC.TableBaseList.message = "list of tablebases";
1825 
1826  R_COPY_LIST(AC.cbufList);
1827  for ( i=0; i<AC.cbufList.num; ++i ) {
1828  org = (UBYTE*)cbuf[i].Buffer;
1829  R_COPY_B(cbuf[i].Buffer, cbuf[i].BufferSize*sizeof(WORD), WORD*);
1830  ofs = (UBYTE*)cbuf[i].Buffer - org;
1831  cbuf[i].Top = (WORD*)((UBYTE*)cbuf[i].Top + ofs);
1832  cbuf[i].Pointer = (WORD*)((UBYTE*)cbuf[i].Pointer + ofs);
1833  R_COPY_B(cbuf[i].lhs, cbuf[i].maxlhs*(LONG)sizeof(WORD*), WORD**);
1834  for ( j=1; j<=cbuf[i].numlhs; ++j ) {
1835  if ( cbuf[i].lhs[j] ) cbuf[i].lhs[j] = (WORD*)((UBYTE*)cbuf[i].lhs[j] + ofs);
1836  }
1837  org = (UBYTE*)cbuf[i].rhs;
1838  R_COPY_B(cbuf[i].rhs, cbuf[i].maxrhs*(LONG)(sizeof(WORD*)+2*sizeof(LONG)+2*sizeof(WORD)), WORD**);
1839  for ( j=1; j<=cbuf[i].numrhs; ++j ) {
1840  if ( cbuf[i].rhs[j] ) cbuf[i].rhs[j] = (WORD*)((UBYTE*)cbuf[i].rhs[j] + ofs);
1841  }
1842  ofs = (UBYTE*)cbuf[i].rhs - org;
1843  cbuf[i].CanCommu = (LONG*)((UBYTE*)cbuf[i].CanCommu + ofs);
1844  cbuf[i].NumTerms = (LONG*)((UBYTE*)cbuf[i].NumTerms + ofs);
1845  cbuf[i].numdum = (WORD*)((UBYTE*)cbuf[i].numdum + ofs);
1846  cbuf[i].dimension = (WORD*)((UBYTE*)cbuf[i].dimension + ofs);
1847  if ( cbuf[i].boomlijst ) {
1848  R_COPY_B(cbuf[i].boomlijst, cbuf[i].MaxTreeSize*sizeof(COMPTREE), COMPTREE*);
1849  }
1850  }
1851  AC.cbufList.message = "compiler buffer";
1852 
1853  R_COPY_LIST(AC.AutoSymbolList);
1854  AC.AutoSymbolList.message = "autosymbol";
1855  R_COPY_LIST(AC.AutoIndexList);
1856  AC.AutoIndexList.message = "autoindex";
1857  R_COPY_LIST(AC.AutoVectorList);
1858  AC.AutoVectorList.message = "autovector";
1859  R_COPY_LIST(AC.AutoFunctionList);
1860  AC.AutoFunctionList.message = "autofunction";
1861 
1862  R_COPY_NAMETREE(AC.autonames);
1863 
1864  AC.Symbols = &(AC.SymbolList);
1865  AC.Indices = &(AC.IndexList);
1866  AC.Vectors = &(AC.VectorList);
1867  AC.Functions = &(AC.FunctionList);
1868  AC.activenames = &(AC.varnames);
1869 
1870  org = (UBYTE*)AC.Streams;
1871  R_COPY_B(AC.Streams, AC.MaxNumStreams*(LONG)sizeof(STREAM), STREAM*);
1872  for ( i=0; i<AC.NumStreams; ++i ) {
1873  if ( AC.Streams[i].type != FILESTREAM ) {
1874  UBYTE *org2;
1875  org2 = AC.Streams[i].buffer;
1876  if ( AC.Streams[i].inbuffer ) {
1877  R_COPY_B(AC.Streams[i].buffer, AC.Streams[i].inbuffer, UBYTE*);
1878  }
1879  ofs = AC.Streams[i].buffer - org2;
1880  AC.Streams[i].pointer += ofs;
1881  AC.Streams[i].top += ofs;
1882  }
1883  else {
1884  p = (unsigned char*)p + AC.Streams[i].inbuffer;
1885  }
1886  AC.Streams[i].buffersize = AC.Streams[i].inbuffer;
1887  R_COPY_S(AC.Streams[i].FoldName,UBYTE*);
1888  R_COPY_S(AC.Streams[i].name,UBYTE*);
1889  if ( AC.Streams[i].type == PREVARSTREAM || AC.Streams[i].type == DOLLARSTREAM ) {
1890  AC.Streams[i].pname = AC.Streams[i].name;
1891  }
1892  else if ( AC.Streams[i].type == FILESTREAM ) {
1893  UBYTE *org2;
1894  org2 = AC.Streams[i].buffer;
1895  AC.Streams[i].buffer = (UBYTE*)Malloc1(AC.Streams[i].buffersize, "buffer");
1896  ofs = AC.Streams[i].buffer - org2;
1897  AC.Streams[i].pointer += ofs;
1898  AC.Streams[i].top += ofs;
1899 
1900  /* open file except for already opened main input file */
1901  if ( i ) {
1902  AC.Streams[i].handle = OpenFile((char *)(AC.Streams[i].name));
1903  if ( AC.Streams[i].handle == -1 ) {
1904  MesPrint("ERROR: Could not reopen stream %s!",AC.Streams[i].name);
1905  Terminate(-1);
1906  }
1907  }
1908 
1909  PUTZERO(pos);
1910  ADDPOS(pos, AC.Streams[i].bufferposition);
1911  SeekFile(AC.Streams[i].handle, &pos, SEEK_SET);
1912 
1913  AC.Streams[i].inbuffer = ReadFile(AC.Streams[i].handle, AC.Streams[i].buffer, AC.Streams[i].inbuffer);
1914 
1915  SETBASEPOSITION(pos, AC.Streams[i].fileposition);
1916  SeekFile(AC.Streams[i].handle, &pos, SEEK_SET);
1917  }
1918  /*
1919  * Ideally, we should check if we have a type PREREADSTREAM, PREREADSTREAM2, and
1920  * PRECALCSTREAM here. If so, we should free element name and point it
1921  * to the name element of the embracing stream's struct. In practice,
1922  * this is undoable without adding new data to STREAM. Since we create
1923  * only a small memory leak here (some few byte for each existing
1924  * stream of these types) and only once when we do a recovery, we
1925  * tolerate this leak and keep it STREAM as it is.
1926  */
1927  }
1928  ofs = (UBYTE*)AC.Streams - org;
1929  AC.CurrentStream = (STREAM*)((UBYTE*)AC.CurrentStream + ofs);
1930 
1931  if ( AC.termstack ) {
1932  R_COPY_B(AC.termstack, AC.maxtermlevel*(LONG)sizeof(LONG), LONG*);
1933  }
1934 
1935  if ( AC.termsortstack ) {
1936  R_COPY_B(AC.termsortstack, AC.maxtermlevel*(LONG)sizeof(LONG), LONG*);
1937  }
1938 
1939  /* exception: here we also change values from struct AM */
1940  R_COPY_B(AC.cmod, AM.MaxTal*4*(LONG)sizeof(UWORD), UWORD*);
1941  AM.gcmod = AC.cmod + AM.MaxTal;
1942  AC.powmod = AM.gcmod + AM.MaxTal;
1943  AM.gpowmod = AC.powmod + AM.MaxTal;
1944 
1945  AC.modpowers = 0;
1946  AC.halfmod = 0;
1947 
1948  /* we don't care about AC.ProtoType/WildC */
1949 
1950  if ( AC.IfHeap ) {
1951  ofs = AC.IfStack - AC.IfHeap;
1952  R_COPY_B(AC.IfHeap, (LONG)sizeof(LONG)*(AC.MaxIf+1), LONG*);
1953  AC.IfStack = AC.IfHeap + ofs;
1954  R_COPY_B(AC.IfCount, (LONG)sizeof(LONG)*(AC.MaxIf+1), LONG*);
1955  }
1956 
1957  org = AC.iBuffer;
1958  size = AC.iStop - AC.iBuffer + 2;
1959  R_COPY_B(AC.iBuffer, size, UBYTE*);
1960  ofs = AC.iBuffer - org;
1961  AC.iPointer += ofs;
1962  AC.iStop += ofs;
1963 
1964  if ( AC.LabelNames ) {
1965  org = (UBYTE*)AC.LabelNames;
1966  R_COPY_B(AC.LabelNames, AC.MaxLabels*(LONG)(sizeof(UBYTE*)+sizeof(WORD)), UBYTE**);
1967  for ( i=0; i<AC.NumLabels; ++i ) {
1968  R_COPY_S(AC.LabelNames[i],UBYTE*);
1969  }
1970  ofs = (UBYTE*)AC.LabelNames - org;
1971  AC.Labels = (int*)((UBYTE*)AC.Labels + ofs);
1972  }
1973 
1974  R_COPY_B(AC.FixIndices, AM.OffsetIndex*(LONG)sizeof(WORD), WORD*);
1975 
1976  if ( AC.termsumcheck ) {
1977  R_COPY_B(AC.termsumcheck, AC.maxtermlevel*(LONG)sizeof(WORD), WORD*);
1978  }
1979 
1980  R_COPY_B(AC.WildcardNames, AC.WildcardBufferSize, UBYTE*);
1981 
1982  if ( AC.tokens ) {
1983  size = AC.toptokens - AC.tokens;
1984  if ( size ) {
1985  org = (UBYTE*)AC.tokens;
1986  R_COPY_B(AC.tokens, size, SBYTE*);
1987  ofs = (UBYTE*)AC.tokens - org;
1988  AC.endoftokens += ofs;
1989  AC.toptokens += ofs;
1990  }
1991  else {
1992  AC.tokens = 0;
1993  AC.endoftokens = AC.tokens;
1994  AC.toptokens = AC.tokens;
1995  }
1996  }
1997 
1998  R_COPY_B(AC.tokenarglevel, AM.MaxParLevel*(LONG)sizeof(WORD), WORD*);
1999 
2000  AC.modinverses = 0;
2001 
2002  R_COPY_S(AC.Fortran90Kind,UBYTE *);
2003 
2004 #ifdef WITHPTHREADS
2005  if ( AC.inputnumbers ) {
2006  org = (UBYTE*)AC.inputnumbers;
2007  R_COPY_B(AC.inputnumbers, AC.sizepfirstnum*(LONG)(sizeof(WORD)+sizeof(LONG)), LONG*);
2008  ofs = (UBYTE*)AC.inputnumbers - org;
2009  AC.pfirstnum = (WORD*)((UBYTE*)AC.pfirstnum + ofs);
2010  }
2011  AC.halfmodlock = dummylock;
2012 #endif /* ifdef WITHPTHREADS */
2013 
2014  if ( AC.IfSumCheck ) {
2015  R_COPY_B(AC.IfSumCheck, (LONG)sizeof(WORD)*(AC.MaxIf+1), WORD*);
2016  }
2017  if ( AC.CommuteInSet ) {
2018  R_COPY_B(AC.CommuteInSet, (LONG)sizeof(WORD)*(AC.SizeCommuteInSet+1), WORD*);
2019  }
2020 
2021  AC.LogHandle = oldLogHandle;
2022 
2023  R_COPY_S(AC.CheckpointRunAfter,char*);
2024  R_COPY_S(AC.CheckpointRunBefore,char*);
2025 
2026  R_COPY_S(AC.extrasym,UBYTE *);
2027 
2028 #ifdef PRINTDEBUG
2029  print_C();
2030 #endif
2031 
2032  /*#] AC : */
2033  /*#[ AP : */
2034 
2035  /* #[ AP free pointers */
2036 
2037  /* AP will be overwritten by data from the recovery file, therefore
2038  * dynamically allocated memory must be freed first. */
2039 
2040  for ( i=0; i<AP.DollarList.num; ++i ) {
2041  if ( Dollars[i].size ) {
2042  R_FREE(Dollars[i].where);
2043  }
2044  CleanDollarFactors(Dollars+i);
2045  }
2046  R_FREE(AP.DollarList.lijst);
2047 
2048  for ( i=0; i<AP.PreVarList.num; ++i ) {
2049  R_FREE(PreVar[i].name);
2050  }
2051  R_FREE(AP.PreVarList.lijst);
2052 
2053  for ( i=0; i<AP.LoopList.num; ++i ) {
2054  R_FREE(DoLoops[i].p.buffer);
2055  if ( DoLoops[i].dollarname ) {
2056  R_FREE(DoLoops[i].dollarname);
2057  }
2058  }
2059  R_FREE(AP.LoopList.lijst);
2060 
2061  for ( i=0; i<AP.ProcList.num; ++i ) {
2062  R_FREE(Procedures[i].p.buffer);
2063  R_FREE(Procedures[i].name);
2064  }
2065  R_FREE(AP.ProcList.lijst);
2066 
2067  for ( i=1; i<=AP.PreSwitchLevel; ++i ) {
2068  R_FREE(AP.PreSwitchStrings[i]);
2069  }
2070  R_FREE(AP.PreSwitchStrings);
2071  R_FREE(AP.preStart);
2072  R_FREE(AP.procedureExtension);
2073  R_FREE(AP.cprocedureExtension);
2074  R_FREE(AP.PreIfStack);
2075  R_FREE(AP.PreSwitchModes);
2076  R_FREE(AP.PreTypes);
2077 
2078  /* #] AP free pointers */
2079 
2080  /* first we copy AP as a whole and then restore the pointer structures step
2081  by step. */
2082 
2083  AP = *((struct P_const*)p); p = (unsigned char*)p + sizeof(struct P_const);
2084 #ifdef WITHPTHREADS
2085  AP.PreVarLock = dummylock;
2086 #endif
2087 
2088  R_COPY_LIST(AP.DollarList);
2089  for ( i=0; i<AP.DollarList.num; ++i ) {
2090  DOLLARS d = Dollars + i;
2091  size = d->size * sizeof(WORD);
2092  if ( size && d->where && d->where != oldAMdollarzero ) {
2093  R_COPY_B(d->where, size, void*);
2094  }
2095 #ifdef WITHPTHREADS
2096  d->pthreadslockread = dummylock;
2097  d->pthreadslockwrite = dummylock;
2098 #endif
2099  if ( d->nfactors > 1 ) {
2100  R_COPY_B(d->factors,sizeof(FACDOLLAR)*d->nfactors,FACDOLLAR*);
2101  for ( j = 0; j < d->nfactors; j++ ) {
2102  if ( d->factors[j].size > 0 ) {
2103  R_COPY_B(d->factors[i].where,sizeof(WORD)*(d->factors[j].size+1),WORD*);
2104  }
2105  }
2106  }
2107  }
2108  AP.DollarList.message = "$-variable";
2109 
2110  R_COPY_LIST(AP.PreVarList);
2111  for ( i=0; i<AP.PreVarList.num; ++i ) {
2112  R_SET(size, size_t);
2113  org = PreVar[i].name;
2114  R_COPY_B(PreVar[i].name, size, UBYTE*);
2115  ofs = PreVar[i].name - org;
2116  if ( PreVar[i].value ) PreVar[i].value += ofs;
2117  if ( PreVar[i].argnames ) PreVar[i].argnames += ofs;
2118  }
2119  AP.PreVarList.message = "PreVariable";
2120 
2121  R_COPY_LIST(AP.LoopList);
2122  for ( i=0; i<AP.LoopList.num; ++i ) {
2123  org = DoLoops[i].p.buffer;
2124  R_COPY_B(DoLoops[i].p.buffer, DoLoops[i].p.size, UBYTE*);
2125  ofs = DoLoops[i].p.buffer - org;
2126  if ( DoLoops[i].name ) DoLoops[i].name += ofs;
2127  if ( DoLoops[i].vars ) DoLoops[i].vars += ofs;
2128  if ( DoLoops[i].contents ) DoLoops[i].contents += ofs;
2129  if ( DoLoops[i].type == ONEEXPRESSION ) {
2130  R_COPY_S(DoLoops[i].dollarname,UBYTE*);
2131  }
2132  }
2133  AP.LoopList.message = "doloop";
2134 
2135  R_COPY_LIST(AP.ProcList);
2136  for ( i=0; i<AP.ProcList.num; ++i ) {
2137  if ( Procedures[i].p.size ) {
2138  if ( Procedures[i].loadmode != 1 ) {
2139  R_COPY_B(Procedures[i].p.buffer, Procedures[i].p.size, UBYTE*);
2140  }
2141  else {
2142  R_SET(j, int);
2143  Procedures[i].p.buffer = Procedures[j].p.buffer;
2144  }
2145  }
2146  R_COPY_S(Procedures[i].name,UBYTE*);
2147  }
2148  AP.ProcList.message = "procedure";
2149 
2150  size = (AP.NumPreSwitchStrings+1)*(LONG)sizeof(UBYTE*);
2151  R_COPY_B(AP.PreSwitchStrings, size, UBYTE**);
2152  for ( i=1; i<=AP.PreSwitchLevel; ++i ) {
2153  R_COPY_S(AP.PreSwitchStrings[i],UBYTE*);
2154  }
2155 
2156  org = AP.preStart;
2157  R_COPY_B(AP.preStart, AP.pSize, UBYTE*);
2158  ofs = AP.preStart - org;
2159  if ( AP.preFill ) AP.preFill += ofs;
2160  if ( AP.preStop ) AP.preStop += ofs;
2161 
2162  R_COPY_S(AP.procedureExtension,UBYTE*);
2163  R_COPY_S(AP.cprocedureExtension,UBYTE*);
2164 
2165  R_COPY_B(AP.PreAssignStack,AP.MaxPreAssignLevel*(LONG)sizeof(LONG),LONG*);
2166  R_COPY_B(AP.PreIfStack, AP.MaxPreIfLevel*(LONG)sizeof(int), int*);
2167  R_COPY_B(AP.PreSwitchModes, (AP.NumPreSwitchStrings+1)*(LONG)sizeof(int), int*);
2168  R_COPY_B(AP.PreTypes, (AP.MaxPreTypes+1)*(LONG)sizeof(int), int*);
2169 
2170 #ifdef PRINTDEBUG
2171  print_P();
2172 #endif
2173 
2174  /*#] AP : */
2175  /*#[ AR : */
2176 
2177  R_SET(ofs,LONG);
2178  if ( ofs ) {
2179  AR.infile = AR.Fscr+1;
2180  AR.outfile = AR.Fscr;
2181  AR.hidefile = AR.Fscr+2;
2182  }
2183  else {
2184  AR.infile = AR.Fscr;
2185  AR.outfile = AR.Fscr+1;
2186  AR.hidefile = AR.Fscr+2;
2187  }
2188 
2189  /* #[ AR free pointers */
2190 
2191  /* Parts of AR will be overwritten by data from the recovery file, therefore
2192  * dynamically allocated memory must be freed first. */
2193 
2194  namebufout = AR.outfile->name;
2195  namebufhide = AR.hidefile->name;
2196  R_FREE(AR.outfile->PObuffer);
2197 #ifdef WITHZLIB
2198  R_FREE(AR.outfile->zsp);
2199  R_FREE(AR.outfile->ziobuffer);
2200 #endif
2201  namebufhide = AR.hidefile->name;
2202  R_FREE(AR.hidefile->PObuffer);
2203 #ifdef WITHZLIB
2204  R_FREE(AR.hidefile->zsp);
2205  R_FREE(AR.hidefile->ziobuffer);
2206 #endif
2207  /* no files should be opened -> nothing to do with handle */
2208 
2209  /* #] AR free pointers */
2210 
2211  /* outfile */
2212  R_SET(*AR.outfile, FILEHANDLE);
2213  org = (UBYTE*)AR.outfile->PObuffer;
2214  size = AR.outfile->POfull - AR.outfile->PObuffer;
2215  AR.outfile->PObuffer = (WORD*)Malloc1(AR.outfile->POsize, "PObuffer");
2216  if ( size ) {
2217  memcpy(AR.outfile->PObuffer, p, size*sizeof(WORD));
2218  p = (unsigned char*)p + size*sizeof(WORD);
2219  }
2220  ofs = (UBYTE*)AR.outfile->PObuffer - org;
2221  AR.outfile->POstop = (WORD*)((UBYTE*)AR.outfile->POstop + ofs);
2222  AR.outfile->POfill = (WORD*)((UBYTE*)AR.outfile->POfill + ofs);
2223  AR.outfile->POfull = (WORD*)((UBYTE*)AR.outfile->POfull + ofs);
2224  AR.outfile->name = namebufout;
2225 #ifdef WITHPTHREADS
2226  AR.outfile->wPObuffer = AR.outfile->PObuffer;
2227  AR.outfile->wPOstop = AR.outfile->POstop;
2228  AR.outfile->wPOfill = AR.outfile->POfill;
2229  AR.outfile->wPOfull = AR.outfile->POfull;
2230 #endif
2231 #ifdef WITHZLIB
2232  /* zsp and ziobuffer will be allocated when used */
2233  AR.outfile->zsp = 0;
2234  AR.outfile->ziobuffer = 0;
2235 #endif
2236  /* reopen old outfile */
2237 #ifdef WITHMPI
2238  if(PF.me==MASTER)
2239 #endif
2240  if ( AR.outfile->handle >= 0 ) {
2241  if ( CopyFile(sortfile, AR.outfile->name) ) {
2242  MesPrint("ERROR: Could not copy old output sort file %s!",sortfile);
2243  Terminate(-1);
2244  }
2245  AR.outfile->handle = ReOpenFile(AR.outfile->name);
2246  if ( AR.outfile->handle == -1 ) {
2247  MesPrint("ERROR: Could not reopen output sort file %s!",AR.outfile->name);
2248  Terminate(-1);
2249  }
2250  SeekFile(AR.outfile->handle, &AR.outfile->POposition, SEEK_SET);
2251  }
2252 
2253  /* hidefile */
2254  R_SET(*AR.hidefile, FILEHANDLE);
2255  AR.hidefile->name = namebufhide;
2256  if ( AR.hidefile->PObuffer ) {
2257  org = (UBYTE*)AR.hidefile->PObuffer;
2258  size = AR.hidefile->POfull - AR.hidefile->PObuffer;
2259  AR.hidefile->PObuffer = (WORD*)Malloc1(AR.hidefile->POsize, "PObuffer");
2260  if ( size ) {
2261  memcpy(AR.hidefile->PObuffer, p, size*sizeof(WORD));
2262  p = (unsigned char*)p + size*sizeof(WORD);
2263  }
2264  ofs = (UBYTE*)AR.hidefile->PObuffer - org;
2265  AR.hidefile->POstop = (WORD*)((UBYTE*)AR.hidefile->POstop + ofs);
2266  AR.hidefile->POfill = (WORD*)((UBYTE*)AR.hidefile->POfill + ofs);
2267  AR.hidefile->POfull = (WORD*)((UBYTE*)AR.hidefile->POfull + ofs);
2268 #ifdef WITHPTHREADS
2269  AR.hidefile->wPObuffer = AR.hidefile->PObuffer;
2270  AR.hidefile->wPOstop = AR.hidefile->POstop;
2271  AR.hidefile->wPOfill = AR.hidefile->POfill;
2272  AR.hidefile->wPOfull = AR.hidefile->POfull;
2273 #endif
2274  }
2275 #ifdef WITHZLIB
2276  /* zsp and ziobuffer will be allocated when used */
2277  AR.hidefile->zsp = 0;
2278  AR.hidefile->ziobuffer = 0;
2279 #endif
2280  /* reopen old hidefile */
2281  if ( AR.hidefile->handle >= 0 ) {
2282  if ( CopyFile(hidefile, AR.hidefile->name) ) {
2283  MesPrint("ERROR: Could not copy old hide file %s!",hidefile);
2284  Terminate(-1);
2285  }
2286  AR.hidefile->handle = ReOpenFile(AR.hidefile->name);
2287  if ( AR.hidefile->handle == -1 ) {
2288  MesPrint("ERROR: Could not reopen hide file %s!",AR.hidefile->name);
2289  Terminate(-1);
2290  }
2291  SeekFile(AR.hidefile->handle, &AR.hidefile->POposition, SEEK_SET);
2292  }
2293 
2294  /* store file */
2295  R_SET(pos, POSITION);
2296  if ( ISNOTZEROPOS(pos) ) {
2297  CloseFile(AR.StoreData.Handle);
2298  R_SET(AR.StoreData, FILEDATA);
2299  if ( CopyFile(storefile, FG.fname) ) {
2300  MesPrint("ERROR: Could not copy old store file %s!",storefile);
2301  Terminate(-1);
2302  }
2303  AR.StoreData.Handle = (WORD)ReOpenFile(FG.fname);
2304  SeekFile(AR.StoreData.Handle, &AR.StoreData.Position, SEEK_SET);
2305  }
2306 
2307  R_SET(AR.DefPosition, POSITION);
2308  R_SET(AR.OldTime, LONG);
2309  R_SET(AR.InInBuf, LONG);
2310  R_SET(AR.InHiBuf, LONG);
2311 
2312  R_SET(AR.NoCompress, int);
2313  R_SET(AR.gzipCompress, int);
2314 
2315  R_SET(AR.outtohide, int);
2316 
2317  R_SET(AR.GetFile, WORD);
2318  R_SET(AR.KeptInHold, WORD);
2319  R_SET(AR.BracketOn, WORD);
2320  R_SET(AR.MaxBracket, WORD);
2321  R_SET(AR.CurDum, WORD);
2322  R_SET(AR.DeferFlag, WORD);
2323  R_SET(AR.TePos, WORD);
2324  R_SET(AR.sLevel, WORD);
2325  R_SET(AR.Stage4Name, WORD);
2326  R_SET(AR.GetOneFile, WORD);
2327  R_SET(AR.PolyFun, WORD);
2328  R_SET(AR.PolyFunInv, WORD);
2329  R_SET(AR.PolyFunType, WORD);
2330  R_SET(AR.PolyFunExp, WORD);
2331  R_SET(AR.PolyFunVar, WORD);
2332  R_SET(AR.PolyFunPow, WORD);
2333  R_SET(AR.Eside, WORD);
2334  R_SET(AR.MaxDum, WORD);
2335  R_SET(AR.level, WORD);
2336  R_SET(AR.expchanged, WORD);
2337  R_SET(AR.expflags, WORD);
2338  R_SET(AR.CurExpr, WORD);
2339  R_SET(AR.SortType, WORD);
2340  R_SET(AR.ShortSortCount, WORD);
2341 
2342  /* this is usually done in Process(), but sometimes FORM doesn't
2343  end up executing Process() before it uses the AR.CompressPointer,
2344  so we need to explicitely set it here. */
2345  AR.CompressPointer = AR.CompressBuffer;
2346 
2347 #ifdef WITHPTHREADS
2348  for ( j = 0; j < AM.totalnumberofthreads; j++ ) {
2349  R_SET(AB[j]->R.wranfnpair1, int);
2350  R_SET(AB[j]->R.wranfnpair2, int);
2351  R_SET(AB[j]->R.wranfcall, int);
2352  R_SET(AB[j]->R.wranfseed, ULONG);
2353  R_SET(AB[j]->R.wranfia,ULONG*);
2354  if ( AB[j]->R.wranfia ) {
2355  R_COPY_B(AB[j]->R.wranfia, sizeof(ULONG)*AB[j]->R.wranfnpair2, ULONG*);
2356  }
2357  }
2358 #else
2359  R_SET(AR.wranfnpair1, int);
2360  R_SET(AR.wranfnpair2, int);
2361  R_SET(AR.wranfcall, int);
2362  R_SET(AR.wranfseed, ULONG);
2363  R_SET(AR.wranfia,ULONG*);
2364  if ( AR.wranfia ) {
2365  R_COPY_B(AR.wranfia, sizeof(ULONG)*AR.wranfnpair2, ULONG*);
2366  }
2367 #endif
2368 
2369 #ifdef PRINTDEBUG
2370  print_R();
2371 #endif
2372 
2373  /*#] AR : */
2374  /*#[ AO :*/
2375 /*
2376  We copy all non-pointer variables.
2377 */
2378  l = sizeof(A.O) - ((UBYTE *)(&(A.O.NumInBrack))-(UBYTE *)(&A.O));
2379  memcpy(&(A.O.NumInBrack), p, l); p = (unsigned char*)p + l;
2380 /*
2381  Now the variables in OptimizeResult
2382 */
2383  memcpy(&(A.O.OptimizeResult),p,sizeof(OPTIMIZERESULT));
2384  p = (unsigned char*)p + sizeof(OPTIMIZERESULT);
2385 
2386  if ( A.O.OptimizeResult.codesize > 0 ) {
2387  R_COPY_B(A.O.OptimizeResult.code,A.O.OptimizeResult.codesize*sizeof(WORD),WORD *);
2388  }
2389  R_COPY_S(A.O.OptimizeResult.nameofexpr,UBYTE *);
2390 /*
2391  And now the dictionaries. We know how many there are. We also know
2392  how many elements the array AO.Dictionaries should have.
2393 */
2394  if ( AO.SizeDictionaries > 0 ) {
2395  AO.Dictionaries = (DICTIONARY **)Malloc1(AO.SizeDictionaries*sizeof(DICTIONARY *),
2396  "Dictionaries");
2397  for ( i = 0; i < AO.NumDictionaries; i++ ) {
2398  R_SET(l,LONG)
2399  AO.Dictionaries[i] = DictFromBytes(p);
2400  p = (char *)p + l;
2401  }
2402  }
2403  /*#] AO :*/
2404 #ifdef WITHMPI
2405  /*#[ PF : */
2406  {/*Block*/
2407  int numtasks;
2408  R_SET(numtasks, int);
2409  if(numtasks!=PF.numtasks){
2410  MesPrint("%d number of tasks expected instead of %d; use mpirun -np %d",
2411  numtasks,PF.numtasks,numtasks);
2412  if(PF.me!=MASTER)
2413  remove(RecoveryFilename());
2414  Terminate(-1);
2415  }
2416  }/*Block*/
2417  R_SET(PF.rhsInParallel, int);
2418  R_SET(PF.exprbufsize, int);
2419  R_SET(PF.log, int);
2420  /*#] PF : */
2421 #endif
2422 
2423 #ifdef WITHPTHREADS
2424  /* read timing information of individual threads */
2425  R_SET(i, int);
2426  for ( j=1; j<AM.totalnumberofthreads; ++j ) {
2427  /* ... and correcting OldTime */
2428  AB[j]->R.OldTime = -(*((LONG*)p+j));
2429  }
2430  WriteTimerInfo((LONG*)p,(LONG *)((unsigned char*)p + i*(LONG)sizeof(LONG)));
2431  p = (unsigned char*)p + 2*i*(LONG)sizeof(LONG);
2432 #endif /* ifdef WITHPTHREADS */
2433 
2434  if ( fclose(fd) ) return(__LINE__);
2435 
2436  M_free(buf,"recovery buffer");
2437 
2438  /* cares about data in S_const */
2439  UpdatePositions();
2440  AT.SS = AT.S0;
2441 /*
2442  Set the checkpoint parameter right for the next checkpoint.
2443 */
2444  AC.CheckpointStamp = TimeWallClock(1);
2445 
2446  done_snapshot = 1;
2447  MesPrint("done."); fflush(0);
2448 
2449  return(0);
2450 }
2451 
2452 /*
2453  #] DoRecovery :
2454  #[ DoSnapshot :
2455 */
2456 
2472 static int DoSnapshot(int moduletype)
2473 {
2474  GETIDENTITY
2475  FILE *fd;
2476  POSITION pos;
2477  int i, j;
2478  LONG l;
2479  WORD *w;
2480  void *adr;
2481 #ifdef WITHPTHREADS
2482  LONG *longp,*longpp;
2483 #endif /* ifdef WITHPTHREADS */
2484 
2485  MesPrint("Saving recovery point ... %"); fflush(0);
2486 #ifdef PRINTTIMEMARKS
2487  MesPrint("\n");
2488 #endif
2489 
2490  if ( !(fd = fopen(intermedfile, "wb")) ) return(__LINE__);
2491 
2492  /* reserve space in the file for a length field */
2493  if ( fwrite(&pos, 1, sizeof(POSITION), fd) != sizeof(POSITION) ) return(__LINE__);
2494 
2495  /* write moduletype */
2496  if ( fwrite(&moduletype, 1, sizeof(int), fd) != sizeof(int) ) return(__LINE__);
2497 
2498  /*#[ AM :*/
2499 
2500  /* since most values don't change during execution, AM doesn't need to be
2501  * written as a whole. all values will be correctly set when starting up
2502  * anyway. only the exceptions need to be taken care of. see MakeGlobal()
2503  * and PopVariables() in execute.c. */
2504 
2505  ANNOUNCE(AM)
2506  S_WRITE_B(&AM.hparallelflag, sizeof(int));
2507  S_WRITE_B(&AM.gparallelflag, sizeof(int));
2508  S_WRITE_B(&AM.gCodesFlag, sizeof(int));
2509  S_WRITE_B(&AM.gNamesFlag, sizeof(int));
2510  S_WRITE_B(&AM.gStatsFlag, sizeof(int));
2511  S_WRITE_B(&AM.gTokensWriteFlag, sizeof(int));
2512  S_WRITE_B(&AM.gNoSpacesInNumbers, sizeof(int));
2513  S_WRITE_B(&AM.gIndentSpace, sizeof(WORD));
2514  S_WRITE_B(&AM.gUnitTrace, sizeof(WORD));
2515  S_WRITE_B(&AM.gDefDim, sizeof(int));
2516  S_WRITE_B(&AM.gDefDim4, sizeof(int));
2517  S_WRITE_B(&AM.gncmod, sizeof(WORD));
2518  S_WRITE_B(&AM.gnpowmod, sizeof(WORD));
2519  S_WRITE_B(&AM.gmodmode, sizeof(WORD));
2520  S_WRITE_B(&AM.gOutputMode, sizeof(WORD));
2521  S_WRITE_B(&AM.gCnumpows, sizeof(WORD));
2522  S_WRITE_B(&AM.gOutputSpaces, sizeof(WORD));
2523  S_WRITE_B(&AM.gOutNumberType, sizeof(WORD));
2524  S_WRITE_B(&AM.gfunpowers, sizeof(int));
2525  S_WRITE_B(&AM.gPolyFun, sizeof(WORD));
2526  S_WRITE_B(&AM.gPolyFunInv, sizeof(WORD));
2527  S_WRITE_B(&AM.gPolyFunType, sizeof(WORD));
2528  S_WRITE_B(&AM.gPolyFunExp, sizeof(WORD));
2529  S_WRITE_B(&AM.gPolyFunVar, sizeof(WORD));
2530  S_WRITE_B(&AM.gPolyFunPow, sizeof(WORD));
2531  S_WRITE_B(&AM.gProcessBucketSize, sizeof(LONG));
2532  S_WRITE_B(&AM.OldChildTime, sizeof(LONG));
2533  S_WRITE_B(&AM.OldSecTime, sizeof(LONG));
2534  S_WRITE_B(&AM.OldMilliTime, sizeof(LONG));
2535  S_WRITE_B(&AM.gproperorderflag, sizeof(int));
2536  S_WRITE_B(&AM.gThreadBucketSize, sizeof(LONG));
2537  S_WRITE_B(&AM.gSizeCommuteInSet, sizeof(int));
2538  S_WRITE_B(&AM.gThreadStats, sizeof(int));
2539  S_WRITE_B(&AM.gFinalStats, sizeof(int));
2540  S_WRITE_B(&AM.gThreadsFlag, sizeof(int));
2541  S_WRITE_B(&AM.gThreadBalancing, sizeof(int));
2542  S_WRITE_B(&AM.gThreadSortFileSynch, sizeof(int));
2543  S_WRITE_B(&AM.gProcessStats, sizeof(int));
2544  S_WRITE_B(&AM.gOldParallelStats, sizeof(int));
2545  S_WRITE_B(&AM.gSortType, sizeof(int));
2546  S_WRITE_B(&AM.gShortStatsMax, sizeof(WORD));
2547  S_WRITE_B(&AM.gIsFortran90, sizeof(int));
2548  adr = &AM.dollarzero;
2549  S_WRITE_B(&adr, sizeof(void*));
2550  S_WRITE_B(&AM.gFortran90Kind,sizeof(UBYTE *));
2551  S_WRITE_S(AM.gFortran90Kind);
2552 
2553  S_WRITE_S(AM.gextrasym);
2554  S_WRITE_S(AM.ggextrasym);
2555 
2556  S_WRITE_B(&AM.PrintTotalSize,sizeof(int));
2557  S_WRITE_B(&AM.fbuffersize,sizeof(int));
2558  S_WRITE_B(&AM.gOldFactArgFlag,sizeof(int));
2559  S_WRITE_B(&AM.ggOldFactArgFlag,sizeof(int));
2560 
2561  S_WRITE_B(&AM.gnumextrasym,sizeof(int));
2562  S_WRITE_B(&AM.ggnumextrasym,sizeof(int));
2563  S_WRITE_B(&AM.NumSpectatorFiles,sizeof(int));
2564  S_WRITE_B(&AM.SizeForSpectatorFiles,sizeof(int));
2565  S_WRITE_B(&AM.gOldGCDflag,sizeof(int));
2566  S_WRITE_B(&AM.ggOldGCDflag,sizeof(int));
2567  S_WRITE_B(&AM.gWTimeStatsFlag, sizeof(int));
2568 
2569  S_WRITE_B(&AM.Path,sizeof(UBYTE *));
2570  S_WRITE_S(AM.Path);
2571 
2572  /*#] AM :*/
2573  /*#[ AC :*/
2574 
2575  /* we write AC as a whole and then write all additional data step by step.
2576  * AC.DubiousList doesn't need to be treated, because it should be empty. */
2577 
2578  ANNOUNCE(AC)
2579  S_WRITE_B(&AC, sizeof(struct C_const));
2580 
2581  S_WRITE_NAMETREE(AC.dollarnames);
2582  S_WRITE_NAMETREE(AC.exprnames);
2583  S_WRITE_NAMETREE(AC.varnames);
2584 
2585  S_WRITE_LIST(AC.ChannelList);
2586  for ( i=0; i<AC.ChannelList.num; ++i ) {
2587  S_WRITE_S(channels[i].name);
2588  }
2589 
2590  ANNOUNCE(AC.FunctionList)
2591  S_WRITE_LIST(AC.FunctionList);
2592  for ( i=0; i<AC.FunctionList.num; ++i ) {
2593  /* if the function is a table */
2594  if ( functions[i].tabl ) {
2595  TABLES tabl = functions[i].tabl;
2596  S_WRITE_B(tabl, sizeof(struct TaBlEs));
2597  if ( tabl->tablepointers ) {
2598  if ( tabl->sparse ) {
2599  /* sparse tables. reserved holds number of allocated
2600  * elements. the size of an element is numind plus
2601  * TABLEEXTENSION times the size of WORD. */
2602  S_WRITE_B(tabl->tablepointers,
2603  tabl->reserved*sizeof(WORD)*(tabl->numind+TABLEEXTENSION));
2604  }
2605  else {
2606  /* matrix like tables. */
2607  S_WRITE_B(tabl->tablepointers,
2608  TABLEEXTENSION*sizeof(WORD)*(tabl->totind));
2609  }
2610  }
2611  S_WRITE_B(tabl->prototype, tabl->prototypeSize);
2612  S_WRITE_B(tabl->mm, tabl->numind*(LONG)sizeof(MINMAX));
2613  S_WRITE_B(tabl->flags, tabl->numind*(LONG)sizeof(WORD));
2614  if ( tabl->sparse ) {
2615  S_WRITE_B(tabl->boomlijst, tabl->MaxTreeSize*(LONG)sizeof(COMPTREE));
2616  S_WRITE_S(tabl->argtail);
2617  }
2618  S_WRITE_B(tabl->buffers, tabl->bufferssize*(LONG)sizeof(WORD));
2619  if ( tabl->spare ) {
2620  TABLES spare = tabl->spare;
2621  S_WRITE_B(spare, sizeof(struct TaBlEs));
2622  if ( spare->tablepointers ) {
2623  if ( spare->sparse ) {
2624  /* sparse tables */
2625  S_WRITE_B(spare->tablepointers,
2626  spare->reserved*sizeof(WORD)*(spare->numind+TABLEEXTENSION));
2627  }
2628  else {
2629  /* matrix like tables */
2630  S_WRITE_B(spare->tablepointers,
2631  TABLEEXTENSION*sizeof(WORD)*(spare->totind));
2632  }
2633  }
2634  S_WRITE_B(spare->mm, spare->numind*(LONG)sizeof(MINMAX));
2635  S_WRITE_B(spare->flags, spare->numind*(LONG)sizeof(WORD));
2636  if ( spare->sparse ) {
2637  S_WRITE_B(spare->boomlijst, spare->MaxTreeSize*(LONG)sizeof(COMPTREE));
2638  }
2639  S_WRITE_B(spare->buffers, spare->bufferssize*(LONG)sizeof(WORD));
2640  }
2641  }
2642  }
2643 
2644  ANNOUNCE(AC.ExpressionList)
2645  S_WRITE_LIST(AC.ExpressionList);
2646  for ( i=0; i<AC.ExpressionList.num; ++i ) {
2647  EXPRESSIONS ex = Expressions + i;
2648  if ( ex->renum ) {
2649  S_WRITE_B(ex->renum, sizeof(struct ReNuMbEr));
2650  /* there is one dynamically allocated buffer for struct ReNuMbEr and
2651  * symb.lo points to its beginning. the size of the buffer is not
2652  * stored anywhere but we know it is 2*sizeof(WORD)*N, where N is
2653  * the number of all vectors, indices, functions and symbols. since
2654  * funum points into the buffer at a distance 2N-[Number of
2655  * functions] from symb.lo (see GetTable() in store.c), we can
2656  * calculate the buffer size by some pointer arithmetic. the size is
2657  * then written to the file. */
2658  l = ex->renum->funnum - ex->renum->symb.lo;
2659  l += ex->renum->funnum - ex->renum->func.lo;
2660  S_WRITE_B(&l, sizeof(size_t));
2661  S_WRITE_B(ex->renum->symb.lo, l);
2662  }
2663  if ( ex->bracketinfo ) {
2664  S_WRITE_B(ex->bracketinfo, sizeof(BRACKETINFO));
2665  S_WRITE_B(ex->bracketinfo->indexbuffer, ex->bracketinfo->indexbuffersize*sizeof(BRACKETINDEX));
2666  S_WRITE_B(ex->bracketinfo->bracketbuffer, ex->bracketinfo->bracketbuffersize*sizeof(WORD));
2667  }
2668  if ( ex->newbracketinfo ) {
2669  S_WRITE_B(ex->newbracketinfo, sizeof(BRACKETINFO));
2670  S_WRITE_B(ex->newbracketinfo->indexbuffer, ex->newbracketinfo->indexbuffersize*sizeof(BRACKETINDEX));
2671  S_WRITE_B(ex->newbracketinfo->bracketbuffer, ex->newbracketinfo->bracketbuffersize*sizeof(WORD));
2672  }
2673  /* don't need to write ex->renumlists */
2674  if ( ex->inmem ) {
2675  /* size of the inmem buffer has to be determined. we use the fact
2676  * that the end of an expression is marked by a zero. */
2677  w = ex->inmem;
2678  while ( *w++ ) ;
2679  l = w - ex->inmem;
2680  S_WRITE_B(&l, sizeof(size_t));
2681  S_WRITE_B(ex->inmem, l);
2682  }
2683  }
2684 
2685  ANNOUNCE(AC.IndexList)
2686  S_WRITE_LIST(AC.IndexList);
2687  S_WRITE_LIST(AC.SetElementList);
2688  S_WRITE_LIST(AC.SetList);
2689  S_WRITE_LIST(AC.SymbolList);
2690  S_WRITE_LIST(AC.VectorList);
2691 
2692  ANNOUNCE(AC.TableBaseList)
2693  S_WRITE_LIST(AC.TableBaseList);
2694  for ( i=0; i<AC.TableBaseList.num; ++i ) {
2695  /* see struct dbase in minos.h */
2696  if ( tablebases[i].iblocks ) {
2697  S_WRITE_B(tablebases[i].iblocks, tablebases[i].info.numberofindexblocks * sizeof(INDEXBLOCK*));
2698  for ( j=0; j<tablebases[i].info.numberofindexblocks; ++j ) {
2699  if ( tablebases[i].iblocks[j] ) {
2700  S_WRITE_B(tablebases[i].iblocks[j], sizeof(INDEXBLOCK));
2701  }
2702  }
2703  }
2704  if ( tablebases[i].nblocks ) {
2705  S_WRITE_B(tablebases[i].nblocks, tablebases[i].info.numberofnamesblocks * sizeof(NAMESBLOCK*));
2706  for ( j=0; j<tablebases[i].info.numberofnamesblocks; ++j ) {
2707  if ( tablebases[i].nblocks[j] ) {
2708  S_WRITE_B(tablebases[i].nblocks[j], sizeof(NAMESBLOCK));
2709  }
2710  }
2711  }
2712  S_WRITE_S(tablebases[i].name);
2713  S_WRITE_S(tablebases[i].fullname);
2714  S_WRITE_S(tablebases[i].tablenames);
2715  }
2716 
2717  ANNOUNCE(AC.cbufList)
2718  S_WRITE_LIST(AC.cbufList);
2719  for ( i=0; i<AC.cbufList.num; ++i ) {
2720  S_WRITE_B(cbuf[i].Buffer, cbuf[i].BufferSize*sizeof(WORD));
2721  /* see inicbufs in comtool.c */
2722  S_WRITE_B(cbuf[i].lhs, cbuf[i].maxlhs*(LONG)sizeof(WORD*));
2723  S_WRITE_B(cbuf[i].rhs, cbuf[i].maxrhs*(LONG)(sizeof(WORD*)+2*sizeof(LONG)+2*sizeof(WORD)));
2724  if ( cbuf[i].boomlijst ) {
2725  S_WRITE_B(cbuf[i].boomlijst, cbuf[i].MaxTreeSize*(LONG)sizeof(COMPTREE));
2726  }
2727  }
2728 
2729  S_WRITE_LIST(AC.AutoSymbolList);
2730  S_WRITE_LIST(AC.AutoIndexList);
2731  S_WRITE_LIST(AC.AutoVectorList);
2732  S_WRITE_LIST(AC.AutoFunctionList);
2733 
2734  S_WRITE_NAMETREE(AC.autonames);
2735 
2736  ANNOUNCE(AC.Streams)
2737  S_WRITE_B(AC.Streams, AC.MaxNumStreams*(LONG)sizeof(STREAM));
2738  for ( i=0; i<AC.NumStreams; ++i ) {
2739  if ( AC.Streams[i].inbuffer ) {
2740  S_WRITE_B(AC.Streams[i].buffer, AC.Streams[i].inbuffer);
2741  }
2742  S_WRITE_S(AC.Streams[i].FoldName);
2743  S_WRITE_S(AC.Streams[i].name);
2744  }
2745 
2746  if ( AC.termstack ) {
2747  S_WRITE_B(AC.termstack, AC.maxtermlevel*(LONG)sizeof(LONG));
2748  }
2749 
2750  if ( AC.termsortstack ) {
2751  S_WRITE_B(AC.termsortstack, AC.maxtermlevel*(LONG)sizeof(LONG));
2752  }
2753 
2754  S_WRITE_B(AC.cmod, AM.MaxTal*4*(LONG)sizeof(UWORD));
2755 
2756  if ( AC.IfHeap ) {
2757  S_WRITE_B(AC.IfHeap, (LONG)sizeof(LONG)*(AC.MaxIf+1));
2758  S_WRITE_B(AC.IfCount, (LONG)sizeof(LONG)*(AC.MaxIf+1));
2759  }
2760 
2761  l = AC.iStop - AC.iBuffer + 2;
2762  S_WRITE_B(AC.iBuffer, l);
2763 
2764  if ( AC.LabelNames ) {
2765  S_WRITE_B(AC.LabelNames, AC.MaxLabels*(LONG)(sizeof(UBYTE*)+sizeof(WORD)));
2766  for ( i=0; i<AC.NumLabels; ++i ) {
2767  S_WRITE_S(AC.LabelNames[i]);
2768  }
2769  }
2770 
2771  S_WRITE_B(AC.FixIndices, AM.OffsetIndex*(LONG)sizeof(WORD));
2772 
2773  if ( AC.termsumcheck ) {
2774  S_WRITE_B(AC.termsumcheck, AC.maxtermlevel*(LONG)sizeof(WORD));
2775  }
2776 
2777  S_WRITE_B(AC.WildcardNames, AC.WildcardBufferSize);
2778 
2779  if ( AC.tokens ) {
2780  l = AC.toptokens - AC.tokens;
2781  if ( l ) {
2782  S_WRITE_B(AC.tokens, l);
2783  }
2784  }
2785 
2786  S_WRITE_B(AC.tokenarglevel, AM.MaxParLevel*(LONG)sizeof(WORD));
2787 
2788  S_WRITE_S(AC.Fortran90Kind);
2789 
2790 #ifdef WITHPTHREADS
2791  if ( AC.inputnumbers ) {
2792  S_WRITE_B(AC.inputnumbers, AC.sizepfirstnum*(LONG)(sizeof(WORD)+sizeof(LONG)));
2793  }
2794 #endif /* ifdef WITHPTHREADS */
2795 
2796  if ( AC.IfSumCheck ) {
2797  S_WRITE_B(AC.IfSumCheck, (LONG)sizeof(WORD)*(AC.MaxIf+1));
2798  }
2799  if ( AC.CommuteInSet ) {
2800  S_WRITE_B(AC.CommuteInSet, (LONG)sizeof(WORD)*(AC.SizeCommuteInSet+1));
2801  }
2802 
2803  S_WRITE_S(AC.CheckpointRunAfter);
2804  S_WRITE_S(AC.CheckpointRunBefore);
2805 
2806  S_WRITE_S(AC.extrasym);
2807 
2808  /*#] AC :*/
2809  /*#[ AP :*/
2810 
2811  /* we write AP as a whole and then write all additional data step by step. */
2812 
2813  ANNOUNCE(AP)
2814  S_WRITE_B(&AP, sizeof(struct P_const));
2815 
2816  S_WRITE_LIST(AP.DollarList);
2817  for ( i=0; i<AP.DollarList.num; ++i ) {
2818  DOLLARS d = Dollars + i;
2819  S_WRITE_DOLLAR(Dollars[i]);
2820  if ( d->nfactors > 1 ) {
2821  S_WRITE_B(&(d->factors),sizeof(FACDOLLAR)*d->nfactors);
2822  for ( j = 0; j < d->nfactors; j++ ) {
2823  if ( d->factors[j].size > 0 ) {
2824  S_WRITE_B(&(d->factors[i].where),sizeof(WORD)*(d->factors[j].size+1));
2825  }
2826  }
2827  }
2828  }
2829 
2830  S_WRITE_LIST(AP.PreVarList);
2831  for ( i=0; i<AP.PreVarList.num; ++i ) {
2832  /* there is one dynamically allocated buffer in struct pReVaR holding
2833  * the strings name, value and several argnames. the size of the buffer
2834  * can be calculated by adding up their string lengths. */
2835  l = strlen((char*)PreVar[i].name) + 1;
2836  if ( PreVar[i].value ) {
2837  l += strlen((char*)(PreVar[i].name+l)) + 1;
2838  }
2839  for ( j=0; j<PreVar[i].nargs; ++j ) {
2840  l += strlen((char*)(PreVar[i].name+l)) + 1;
2841  }
2842  S_WRITE_B(&l, sizeof(size_t));
2843  S_WRITE_B(PreVar[i].name, l);
2844  }
2845 
2846  ANNOUNCE(AP.LoopList)
2847  S_WRITE_LIST(AP.LoopList);
2848  for ( i=0; i<AP.LoopList.num; ++i ) {
2849  S_WRITE_B(DoLoops[i].p.buffer, DoLoops[i].p.size);
2850  if ( DoLoops[i].type == ONEEXPRESSION ) {
2851  /* do loops with an expression keep this expression in a dynamically
2852  * allocated buffer in dollarname */
2853  S_WRITE_S(DoLoops[i].dollarname);
2854  }
2855  }
2856 
2857  S_WRITE_LIST(AP.ProcList);
2858  for ( i=0; i<AP.ProcList.num; ++i ) {
2859  if ( Procedures[i].p.size ) {
2860  if ( Procedures[i].loadmode != 1 ) {
2861  S_WRITE_B(Procedures[i].p.buffer, Procedures[i].p.size);
2862  }
2863  else {
2864  for ( j=0; j<AP.ProcList.num; ++j ) {
2865  if ( Procedures[i].p.buffer == Procedures[j].p.buffer ) {
2866  break;
2867  }
2868  }
2869  if ( j == AP.ProcList.num ) {
2870  MesPrint("Error writing procedures to recovery file!");
2871  }
2872  S_WRITE_B(&j, sizeof(int));
2873  }
2874  }
2875  S_WRITE_S(Procedures[i].name);
2876  }
2877 
2878  S_WRITE_B(AP.PreSwitchStrings, (AP.NumPreSwitchStrings+1)*(LONG)sizeof(UBYTE*));
2879  for ( i=1; i<=AP.PreSwitchLevel; ++i ) {
2880  S_WRITE_S(AP.PreSwitchStrings[i]);
2881  }
2882 
2883  S_WRITE_B(AP.preStart, AP.pSize);
2884 
2885  S_WRITE_S(AP.procedureExtension);
2886  S_WRITE_S(AP.cprocedureExtension);
2887 
2888  S_WRITE_B(AP.PreAssignStack, AP.MaxPreAssignLevel*(LONG)sizeof(LONG));
2889  S_WRITE_B(AP.PreIfStack, AP.MaxPreIfLevel*(LONG)sizeof(int));
2890  S_WRITE_B(AP.PreSwitchModes, (AP.NumPreSwitchStrings+1)*(LONG)sizeof(int));
2891  S_WRITE_B(AP.PreTypes, (AP.MaxPreTypes+1)*(LONG)sizeof(int));
2892 
2893  /*#] AP :*/
2894  /*#[ AR :*/
2895 
2896  ANNOUNCE(AR)
2897  /* to remember which entry in AR.Fscr corresponds to the infile */
2898  l = AR.infile - AR.Fscr;
2899  S_WRITE_B(&l, sizeof(LONG));
2900 
2901  /* write the FILEHANDLEs */
2902  S_WRITE_B(AR.outfile, sizeof(FILEHANDLE));
2903  l = AR.outfile->POfull - AR.outfile->PObuffer;
2904  if ( l ) {
2905  S_WRITE_B(AR.outfile->PObuffer, l*sizeof(WORD));
2906  }
2907  S_WRITE_B(AR.hidefile, sizeof(FILEHANDLE));
2908  l = AR.hidefile->POfull - AR.hidefile->PObuffer;
2909  if ( l ) {
2910  S_WRITE_B(AR.hidefile->PObuffer, l*sizeof(WORD));
2911  }
2912 
2913  S_WRITE_B(&AR.StoreData.Fill, sizeof(POSITION));
2914  if ( ISNOTZEROPOS(AR.StoreData.Fill) ) {
2915  S_WRITE_B(&AR.StoreData, sizeof(FILEDATA));
2916  }
2917 
2918  S_WRITE_B(&AR.DefPosition, sizeof(POSITION));
2919 
2920  l = TimeCPU(1); l = -l;
2921  S_WRITE_B(&l, sizeof(LONG));
2922 
2923  ANNOUNCE(AR.InInBuf)
2924  S_WRITE_B(&AR.InInBuf, sizeof(LONG));
2925  S_WRITE_B(&AR.InHiBuf, sizeof(LONG));
2926 
2927  S_WRITE_B(&AR.NoCompress, sizeof(int));
2928  S_WRITE_B(&AR.gzipCompress, sizeof(int));
2929 
2930  S_WRITE_B(&AR.outtohide, sizeof(int));
2931 
2932  S_WRITE_B(&AR.GetFile, sizeof(WORD));
2933  S_WRITE_B(&AR.KeptInHold, sizeof(WORD));
2934  S_WRITE_B(&AR.BracketOn, sizeof(WORD));
2935  S_WRITE_B(&AR.MaxBracket, sizeof(WORD));
2936  S_WRITE_B(&AR.CurDum, sizeof(WORD));
2937  S_WRITE_B(&AR.DeferFlag, sizeof(WORD));
2938  S_WRITE_B(&AR.TePos, sizeof(WORD));
2939  S_WRITE_B(&AR.sLevel, sizeof(WORD));
2940  S_WRITE_B(&AR.Stage4Name, sizeof(WORD));
2941  S_WRITE_B(&AR.GetOneFile, sizeof(WORD));
2942  S_WRITE_B(&AR.PolyFun, sizeof(WORD));
2943  S_WRITE_B(&AR.PolyFunInv, sizeof(WORD));
2944  S_WRITE_B(&AR.PolyFunType, sizeof(WORD));
2945  S_WRITE_B(&AR.PolyFunExp, sizeof(WORD));
2946  S_WRITE_B(&AR.PolyFunVar, sizeof(WORD));
2947  S_WRITE_B(&AR.PolyFunPow, sizeof(WORD));
2948  S_WRITE_B(&AR.Eside, sizeof(WORD));
2949  S_WRITE_B(&AR.MaxDum, sizeof(WORD));
2950  S_WRITE_B(&AR.level, sizeof(WORD));
2951  S_WRITE_B(&AR.expchanged, sizeof(WORD));
2952  S_WRITE_B(&AR.expflags, sizeof(WORD));
2953  S_WRITE_B(&AR.CurExpr, sizeof(WORD));
2954  S_WRITE_B(&AR.SortType, sizeof(WORD));
2955  S_WRITE_B(&AR.ShortSortCount, sizeof(WORD));
2956 
2957 #ifdef WITHPTHREADS
2958  for ( j = 0; j < AM.totalnumberofthreads; j++ ) {
2959  S_WRITE_B(&(AB[j]->R.wranfnpair1), sizeof(int));
2960  S_WRITE_B(&(AB[j]->R.wranfnpair2), sizeof(int));
2961  S_WRITE_B(&(AB[j]->R.wranfcall), sizeof(int));
2962  S_WRITE_B(&(AB[j]->R.wranfseed), sizeof(ULONG));
2963  S_WRITE_B(&(AB[j]->R.wranfia),sizeof(ULONG *));
2964  if ( AB[j]->R.wranfia ) {
2965  S_WRITE_B(AB[j]->R.wranfia, sizeof(ULONG)*AB[j]->R.wranfnpair2);
2966  }
2967  }
2968 #else
2969  S_WRITE_B(&(AR.wranfnpair1), sizeof(int));
2970  S_WRITE_B(&(AR.wranfnpair2), sizeof(int));
2971  S_WRITE_B(&(AR.wranfcall), sizeof(int));
2972  S_WRITE_B(&(AR.wranfseed), sizeof(ULONG));
2973  S_WRITE_B(&(AR.wranfia),sizeof(ULONG *));
2974  if ( AR.wranfia ) {
2975  S_WRITE_B(AR.wranfia, sizeof(ULONG)*AR.wranfnpair2);
2976  }
2977 #endif
2978 
2979  /*#] AR :*/
2980  /*#[ AO :*/
2981 /*
2982  We copy all non-pointer variables.
2983 */
2984  ANNOUNCE(AO)
2985  l = sizeof(A.O) - ((UBYTE *)(&(A.O.NumInBrack))-(UBYTE *)(&A.O));
2986  S_WRITE_B(&(A.O.NumInBrack),l);
2987 /*
2988  Now the variables in OptimizeResult
2989 */
2990  S_WRITE_B(&(A.O.OptimizeResult),sizeof(OPTIMIZERESULT));
2991  if ( A.O.OptimizeResult.codesize > 0 ) {
2992  S_WRITE_B(A.O.OptimizeResult.code,A.O.OptimizeResult.codesize*sizeof(WORD));
2993  }
2994  S_WRITE_S(A.O.OptimizeResult.nameofexpr);
2995 /*
2996  And now the dictionaries.
2997  We write each dictionary to a buffer and get the size of that buffer.
2998  Then we write the size and the buffer.
2999 */
3000  for ( i = 0; i < AO.NumDictionaries; i++ ) {
3001  l = DictToBytes(AO.Dictionaries[i],(UBYTE *)(AT.WorkPointer));
3002  S_WRITE_B(&l,sizeof(LONG));
3003  S_WRITE_B(AT.WorkPointer,l);
3004  }
3005 
3006  /*#] AO :*/
3007  /*#[ PF :*/
3008 #ifdef WITHMPI
3009  S_WRITE_B(&PF.numtasks, sizeof(int));
3010  S_WRITE_B(&PF.rhsInParallel, sizeof(int));
3011  S_WRITE_B(&PF.exprbufsize, sizeof(int));
3012  S_WRITE_B(&PF.log, sizeof(int));
3013 #endif
3014  /*#] PF :*/
3015 
3016 #ifdef WITHPTHREADS
3017 
3018  ANNOUNCE(GetTimerInfo)
3019 /*
3020  write timing information of individual threads
3021 */
3022  i = GetTimerInfo(&longp,&longpp);
3023  S_WRITE_B(&i, sizeof(int));
3024  S_WRITE_B(longp, i*(LONG)sizeof(LONG));
3025  S_WRITE_B(&i, sizeof(int));
3026  S_WRITE_B(longpp, i*(LONG)sizeof(LONG));
3027 
3028 #endif
3029 
3030  S_FLUSH_B /* because we will call fwrite() directly in the following code */
3031 
3032  /* save length of data at the beginning of the file */
3033  ANNOUNCE(file length)
3034  SETBASEPOSITION(pos, (ftell(fd)));
3035  fseek(fd, 0, SEEK_SET);
3036  if ( fwrite(&pos, 1, sizeof(POSITION), fd) != sizeof(POSITION) ) return(__LINE__);
3037  fseek(fd, BASEPOSITION(pos), SEEK_SET);
3038 
3039  ANNOUNCE(file close)
3040  if ( fclose(fd) ) return(__LINE__);
3041 #ifdef WITHMPI
3042  if ( PF.me == MASTER ) {
3043 #endif
3044 /*
3045  copy store file if necessary
3046 */
3047  ANNOUNCE(copy store file)
3048  if ( ISNOTZEROPOS(AR.StoreData.Fill) ) {
3049  if ( CopyFile(FG.fname, storefile) ) return(__LINE__);
3050  }
3051 /*
3052  copy sort file if necessary
3053 */
3054  ANNOUNCE(copy sort file)
3055  if ( AR.outfile->handle >= 0 ) {
3056  if ( CopyFile(AR.outfile->name, sortfile) ) return(__LINE__);
3057  }
3058 /*
3059  copy hide file if necessary
3060 */
3061  ANNOUNCE(copy hide file)
3062  if ( AR.hidefile->handle >= 0 ) {
3063  if ( CopyFile(AR.hidefile->name, hidefile) ) return(__LINE__);
3064  }
3065 #ifdef WITHMPI
3066  }
3067  /*
3068  * For ParFORM, the renaming will be performed after the master got
3069  * all recovery files from the slaves.
3070  */
3071 #else
3072 /*
3073  make the intermediate file the recovery file
3074 */
3075  ANNOUNCE(rename intermediate file)
3076  if ( rename(intermedfile, recoveryfile) ) return(__LINE__);
3077 
3078  done_snapshot = 1;
3079 
3080  MesPrint("done."); fflush(0);
3081 #endif
3082 
3083 #ifdef PRINTDEBUG
3084  print_M();
3085  print_C();
3086  print_P();
3087  print_R();
3088 #endif
3089 
3090  return(0);
3091 }
3092 
3093 /*
3094  #] DoSnapshot :
3095  #[ DoCheckpoint :
3096 */
3097 
3102 void DoCheckpoint(int moduletype)
3103 {
3104  int error;
3105  LONG timestamp = TimeWallClock(1);
3106 #ifdef WITHMPI
3107  if(PF.me == MASTER){
3108 #endif
3109  if ( timestamp - AC.CheckpointStamp >= AC.CheckpointInterval ) {
3110  char argbuf[20];
3111  int retvalue = 0;
3112  if ( AC.CheckpointRunBefore ) {
3113  size_t l, l2;
3114  char *str;
3115  l = strlen(AC.CheckpointRunBefore);
3116  NumToStr((UBYTE*)argbuf, AC.CModule);
3117  l2 = strlen(argbuf);
3118  str = (char*)Malloc1(l+l2+2, "callbefore");
3119  strcpy(str, AC.CheckpointRunBefore);
3120  *(str+l) = ' ';
3121  strcpy(str+l+1, argbuf);
3122  retvalue = system(str);
3123  M_free(str, "callbefore");
3124  if ( retvalue ) {
3125  MesPrint("Script returned error -> no recovery file will be created.");
3126  }
3127  }
3128 #ifdef WITHMPI
3129  /* Confirm slaves to make snapshots. */
3130  PF_BroadcastNumber(retvalue == 0);
3131 #endif
3132  if ( retvalue == 0 ) {
3133  if ( (error = DoSnapshot(moduletype)) ) {
3134  MesPrint("Error creating recovery files: %d", error);
3135  }
3136 #ifdef WITHMPI
3137  {
3138  int i;
3139  /*get recovery files from slaves:*/
3140  for(i=1; i<PF.numtasks;i++){
3141  FILE *fd;
3142  const char *tmpnam = PF_recoveryfile('m', i, 1);
3143  fd = fopen(tmpnam, "w");
3144  if(fd == NULL){
3145  MesPrint("Error opening recovery file for slave %d",i);
3146  Terminate(-1);
3147  }/*if(fd == NULL)*/
3148  retvalue=PF_RecvFile(i,fd);
3149  if(retvalue<=0){
3150  MesPrint("Error receiving recovery file from slave %d",i);
3151  Terminate(-1);
3152  }/*if(retvalue<=0)*/
3153  fclose(fd);
3154  }/*for(i=0; i<PF.numtasks;i++)*/
3155  /*
3156  * Make the intermediate files the recovery files.
3157  */
3158  ANNOUNCE(rename intermediate file)
3159  for ( i = 0; i < PF.numtasks; i++ ) {
3160  const char *src = PF_recoveryfile('m', i, 1);
3161  const char *dst = PF_recoveryfile('m', i, 0);
3162  if ( rename(src, dst) ) {
3163  MesPrint("Error renaming recovery file %s -> %s", src, dst);
3164  }
3165  }
3166  done_snapshot = 1;
3167  MesPrint("done."); fflush(0);
3168  }
3169 #endif
3170  }
3171  if ( AC.CheckpointRunAfter ) {
3172  size_t l, l2;
3173  char *str;
3174  l = strlen(AC.CheckpointRunAfter);
3175  NumToStr((UBYTE*)argbuf, AC.CModule);
3176  l2 = strlen(argbuf);
3177  str = (char*)Malloc1(l+l2+2, "callafter");
3178  strcpy(str, AC.CheckpointRunAfter);
3179  *(str+l) = ' ';
3180  strcpy(str+l+1, argbuf);
3181  retvalue = system(str);
3182  M_free(str, "callafter");
3183  if ( retvalue ) {
3184  MesPrint("Error calling script after recovery.");
3185  }
3186  }
3187  AC.CheckpointStamp = TimeWallClock(1);
3188  }
3189 #ifdef WITHMPI
3190  else{/* timestamp - AC.CheckpointStamp < AC.CheckpointInterval*/
3191  /* The slaves don't need to make snapshots. */
3192  PF_BroadcastNumber(0);
3193  }
3194  }/*if(PF.me == MASTER)*/
3195  else{/*Slave*/
3196  int i;
3197  /* Check if the slave needs to make a snapshot. */
3198  if ( PF_BroadcastNumber(0) ) {
3199  error = DoSnapshot(moduletype);
3200  if(error == 0){
3201  FILE *fd;
3202  /*
3203  * Send the recovery file to the master. Note that no renaming
3204  * has been performed and what we have to send is actually sitting
3205  * in the intermediate file.
3206  */
3207  fd = fopen(intermedfile, "r");
3208  i=PF_SendFile(MASTER, fd);/*if fd==NULL, PF_SendFile seds to a slave the failure tag*/
3209  if(fd == NULL)
3210  Terminate(-1);
3211  fclose(fd);
3212  if(i<=0)
3213  Terminate(-1);
3214  /*Now the slave need not the recovery file so remove it:*/
3215  remove(intermedfile);
3216  }
3217  else{
3218  /*send the error tag to the master:*/
3219  PF_SendFile(MASTER,NULL);/*if fd==NULL, PF_SendFile seds to a slave the failure tag*/
3220  Terminate(-1);
3221  }
3222  done_snapshot = 1;
3223  }/*if(tag=PF_DATA_MSGTAG)*/
3224  }/*if(PF.me != MASTER)*/
3225 #endif
3226 }
3227 
3228 /*
3229  #] DoCheckpoint :
3230 */
UBYTE * pointer
Definition: structs.h:679
WORD bufferssize
Definition: structs.h:366
void DeleteRecoveryFile()
Definition: checkpoint.c:333
LONG * NumTerms
Definition: structs.h:928
WORD * buffers
Definition: structs.h:352
int value
Definition: structs.h:285
char * RecoveryFilename()
Definition: checkpoint.c:364
LONG reserved
Definition: structs.h:354
UBYTE * name
Definition: structs.h:780
LONG totind
Definition: structs.h:353
int numclear
Definition: structs.h:212
WORD left
Definition: structs.h:237
LONG clearnamefill
Definition: structs.h:267
int parent
Definition: structs.h:282
UBYTE * dollarname
Definition: structs.h:840
int prototypeSize
Definition: structs.h:357
UBYTE * buffer
Definition: structs.h:678
int right
Definition: structs.h:284
LONG namefill
Definition: structs.h:261
WORD type
Definition: structs.h:240
NAMENODE * namenode
Definition: structs.h:253
WORD * pattern
Definition: structs.h:344
WORD * bracketbuffer
Definition: structs.h:318
int left
Definition: structs.h:283
UBYTE * name
Definition: structs.h:837
Definition: structs.h:620
VARRENUM indi
Definition: structs.h:181
int sparse
Definition: structs.h:361
int DoRecovery(int *moduletype)
Definition: checkpoint.c:1399
struct TaBlEs * spare
Definition: structs.h:351
VARRENUM vect
Definition: structs.h:182
int size
Definition: structs.h:209
WORD number
Definition: structs.h:241
LONG nodefill
Definition: structs.h:259
LONG nodesize
Definition: structs.h:258
WORD ** lhs
Definition: structs.h:925
int numind
Definition: structs.h:358
int numglobal
Definition: structs.h:210
LONG globalnodefill
Definition: structs.h:266
LONG globalnamefill
Definition: structs.h:264
int num
Definition: structs.h:207
Definition: structs.h:921
WORD parent
Definition: structs.h:236
Definition: structs.h:281
WORD * vecnum
Definition: structs.h:187
int PF_SendFile(int to, FILE *fd)
Definition: parallel.c:4207
UBYTE * FoldName
Definition: structs.h:681
LONG name
Definition: structs.h:235
WORD * symnum
Definition: structs.h:185
WORD * renumlists
Definition: structs.h:385
int blnce
Definition: structs.h:286
int wildarg
Definition: structs.h:784
LONG TimeWallClock(WORD)
Definition: tools.c:3377
WORD * tablepointers
Definition: structs.h:338
int CopyFile(char *, char *)
Definition: tools.c:1029
LONG PF_BroadcastNumber(LONG x)
Definition: parallel.c:2083
void * lijst
Definition: structs.h:205
UBYTE * argtail
Definition: structs.h:349
UBYTE * name
Definition: structs.h:682
WORD balance
Definition: structs.h:239
WORD ** rhs
Definition: structs.h:926
char * message
Definition: structs.h:206
WORD * hi
Definition: structs.h:168
int MaxTreeSize
Definition: structs.h:364
WORD * numdum
Definition: structs.h:929
int numtemp
Definition: structs.h:211
int maxnum
Definition: structs.h:208
COMPTREE * boomlijst
Definition: structs.h:931
MINMAX * mm
Definition: structs.h:346
BRACKETINDEX * indexbuffer
Definition: structs.h:317
COMPTREE * boomlijst
Definition: structs.h:348
WORD * prototype
Definition: structs.h:343
LONG namesize
Definition: structs.h:260
LONG oldnamefill
Definition: structs.h:262
LONG oldnodefill
Definition: structs.h:263
WORD * Buffer
Definition: structs.h:922
WORD * start
Definition: structs.h:166
LONG BufferSize
Definition: structs.h:932
Definition: structs.h:204
WORD * indnum
Definition: structs.h:186
struct StreaM STREAM
int nargs
Definition: structs.h:783
UBYTE * namebuffer
Definition: structs.h:255
UBYTE * pname
Definition: structs.h:683
WORD right
Definition: structs.h:238
PRELOAD p
Definition: structs.h:836
WORD headnode
Definition: structs.h:269
VARRENUM func
Definition: structs.h:183
UBYTE * value
Definition: structs.h:781
void InitRecovery()
Definition: checkpoint.c:399
LONG TimeCPU(WORD)
Definition: tools.c:3418
UBYTE * argnames
Definition: structs.h:782
int PF_RecvFile(int from, FILE *fd)
Definition: parallel.c:4245
int CheckRecoveryFile()
Definition: checkpoint.c:278
WORD * flags
Definition: structs.h:347
LONG clearnodefill
Definition: structs.h:268
VARRENUM symb
Definition: structs.h:180
LONG * CanCommu
Definition: structs.h:927
void DoCheckpoint(int moduletype)
Definition: checkpoint.c:3102
WORD * funnum
Definition: structs.h:188
WORD * lo
Definition: structs.h:167