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