FORM  4.1
store.c
Go to the documentation of this file.
1 
6 /* #[ License : */
7 /*
8  * Copyright (C) 1984-2013 J.A.M. Vermaseren
9  * When using this file you are requested to refer to the publication
10  * J.A.M.Vermaseren "New features of FORM" math-ph/0010025
11  * This is considered a matter of courtesy as the development was paid
12  * for by FOM the Dutch physics granting agency and we would like to
13  * be able to track its scientific use to convince FOM of its value
14  * for the community.
15  *
16  * This file is part of FORM.
17  *
18  * FORM is free software: you can redistribute it and/or modify it under the
19  * terms of the GNU General Public License as published by the Free Software
20  * Foundation, either version 3 of the License, or (at your option) any later
21  * version.
22  *
23  * FORM is distributed in the hope that it will be useful, but WITHOUT ANY
24  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
25  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
26  * details.
27  *
28  * You should have received a copy of the GNU General Public License along
29  * with FORM. If not, see <http://www.gnu.org/licenses/>.
30  */
31 /* #] License : */
32 /*
33 #define HIDEDEBUG
34  #[ Includes : store.c
35 */
36 
37 #include "form3.h"
38 
39 /*
40  #] Includes :
41  #[ StoreExpressions :
42  #[ OpenTemp :
43 
44  Opens the scratch files for the input -> output operations.
45 
46 */
47 
48 WORD OpenTemp()
49 {
50  GETIDENTITY
51  if ( AR.outfile->handle >= 0 ) {
52  SeekFile(AR.outfile->handle,&(AR.outfile->filesize),SEEK_SET);
53  AR.outfile->POposition = AR.outfile->filesize;
54  AR.outfile->POfill = AR.outfile->PObuffer;
55  }
56  return(0);
57 }
58 
59 /*
60  #] OpenTemp :
61  #[ SeekScratch :
62 */
63 
64 VOID SeekScratch(FILEHANDLE *fi, POSITION *pos)
65 {
66  *pos = fi->POposition;
67  ADDPOS(*pos,(TOLONG(fi->POfill)-TOLONG(fi->PObuffer)));
68 }
69 
70 /*
71  #] SeekScratch :
72  #[ SetEndScratch :
73 */
74 
75 VOID SetEndScratch(FILEHANDLE *f, POSITION *position)
76 {
77  if ( f->handle < 0 ) {
78  SETBASEPOSITION(*position,(f->POfull-f->PObuffer)*sizeof(WORD));
79  }
80  else *position = f->filesize;
81  SetScratch(f,position);
82 }
83 
84 /*
85  #] SetEndScratch :
86  #[ SetEndHScratch :
87 */
88 
89 VOID SetEndHScratch(FILEHANDLE *f, POSITION *position)
90 {
91  if ( f->handle < 0 ) {
92  SETBASEPOSITION(*position,(f->POfull-f->PObuffer)*sizeof(WORD));
93  f->POfill = f->POfull;
94  }
95  else {
96 #ifdef HIDEDEBUG
97  POSITION possize;
98  PUTZERO(possize);
99  SeekFile(f->handle,&possize,SEEK_END);
100  MesPrint("SetEndHScratch: filesize(th) = %12p, filesize(ex) = %12p",&(f->filesize),
101  &(possize));
102 #endif
103  *position = f->filesize;
104  f->POposition = f->filesize;
105  f->POfill = f->POfull = f->PObuffer;
106  }
107 /* SetScratch(f,position); */
108 }
109 
110 /*
111  #] SetEndHScratch :
112  #[ SetScratch :
113 */
114 
115 VOID SetScratch(FILEHANDLE *f, POSITION *position)
116 {
117  GETIDENTITY
118  POSITION possize;
119  LONG size, *whichInInBuf;
120  if ( f == AR.hidefile ) whichInInBuf = &(AR.InHiBuf);
121  else whichInInBuf = &(AR.InInBuf);
122 #ifdef HIDEDEBUG
123  if ( f == AR.hidefile ) MesPrint("In the hide file");
124  else MesPrint("In the input file");
125  MesPrint("SetScratch to position %15p",position);
126  MesPrint("POposition = %15p, full = %l, fill = %l"
127  ,&(f->POposition),(f->POfull-f->PObuffer)*sizeof(WORD)
128  ,(f->POfill-f->PObuffer)*sizeof(WORD));
129 #endif
130  if ( ISLESSPOS(*position,f->POposition) ||
131  ISGEPOSINC(*position,f->POposition,(f->POfull-f->PObuffer)*sizeof(WORD)) ) {
132  if ( f->handle < 0 ) {
133  if ( ISEQUALPOSINC(*position,f->POposition,
134  (f->POfull-f->PObuffer)*sizeof(WORD)) ) goto endpos;
135  MesPrint("Illegal position in SetScratch");
136  Terminate(-1);
137  }
138  possize = *position;
139  LOCK(AS.inputslock);
140  SeekFile(f->handle,&possize,SEEK_SET);
141  if ( ISNOTEQUALPOS(possize,*position) ) {
142  UNLOCK(AS.inputslock);
143  MesPrint("Cannot position file in SetScratch");
144  Terminate(-1);
145  }
146 #ifdef HIDEDEBUG
147  MesPrint("SetScratch1(%w): position = %12p, size = %l, address = %x",position,f->POsize,f->PObuffer);
148 #endif
149  if ( ( size = ReadFile(f->handle,(UBYTE *)(f->PObuffer),f->POsize) ) < 0
150  || ( size & 1 ) != 0 ) {
151  UNLOCK(AS.inputslock);
152  MesPrint("Read error in SetScratch");
153  Terminate(-1);
154  }
155  UNLOCK(AS.inputslock);
156  if ( size == 0 ) {
157  f->PObuffer[0] = 0;
158  }
159  f->POfill = f->PObuffer;
160  f->POposition = *position;
161 #ifdef WORD2
162  *whichInInBuf = size >> 1;
163 #else
164  *whichInInBuf = size / TABLESIZE(WORD,UBYTE);
165 #endif
166  f->POfull = f->PObuffer + *whichInInBuf;
167 #ifdef HIDEDEBUG
168  MesPrint("SetScratch2: size = %l, InInBuf = %l, fill = %l, full = %l"
169  ,size,*whichInInBuf,(f->POfill-f->PObuffer)*sizeof(WORD)
170  ,(f->POfull-f->PObuffer)*sizeof(WORD));
171 #endif
172  }
173  else {
174 endpos:
175  DIFPOS(possize,*position,f->POposition);
176  f->POfill = (WORD *)(BASEPOSITION(possize)+(UBYTE *)(f->PObuffer));
177  *whichInInBuf = f->POfull-f->POfill;
178  }
179 }
180 
181 /*
182  #] SetScratch :
183  #[ RevertScratch :
184 
185  Reverts the input/output directions. This way input comes
186  always from AR.infile
187 
188 */
189 
190 WORD RevertScratch()
191 {
192  GETIDENTITY
193  FILEHANDLE *f;
194  if ( AR.infile->handle >= 0 && AR.infile->handle != AR.outfile->handle ) {
195  CloseFile(AR.infile->handle);
196  AR.infile->handle = -1;
197  remove(AR.infile->name);
198  }
199  f = AR.infile; AR.infile = AR.outfile; AR.outfile = f;
200  AR.infile->POfull = AR.infile->POfill;
201  AR.infile->POfill = AR.infile->PObuffer;
202  if ( AR.infile->handle >= 0 ) {
203  POSITION scrpos;
204  PUTZERO(scrpos);
205  SeekFile(AR.infile->handle,&scrpos,SEEK_SET);
206  if ( ISNOTZEROPOS(scrpos) ) {
207  return(MesPrint("Error with scratch output."));
208  }
209  if ( ( AR.InInBuf = ReadFile(AR.infile->handle,(UBYTE *)(AR.infile->PObuffer)
210  ,AR.infile->POsize) ) < 0 || AR.InInBuf & 1 ) {
211  return(MesPrint("Error while reading from scratch file"));
212  }
213  else {
214  AR.InInBuf /= TABLESIZE(WORD,UBYTE);
215  }
216  AR.infile->POfull = AR.infile->PObuffer + AR.InInBuf;
217  }
218  PUTZERO(AR.infile->POposition);
219  AR.outfile->POfill = AR.outfile->POfull = AR.outfile->PObuffer;
220  PUTZERO(AR.outfile->POposition);
221  PUTZERO(AR.outfile->filesize);
222  return(0);
223 }
224 
225 /*
226  #] RevertScratch :
227  #[ ResetScratch :
228 
229  Resets the output scratch file to its beginning in such a way
230  that the write routines can read it. The output buffers are
231  left untouched as they may still be needed for extra declarations.
232 
233 */
234 
235 WORD ResetScratch()
236 {
237  GETIDENTITY
238  FILEHANDLE *f;
239  if ( AR.infile->handle >= 0 ) {
240  CloseFile(AR.infile->handle); AR.infile->handle = -1;
241  remove(AR.infile->name);
242  PUTZERO(AR.infile->POposition);
243  AR.infile->POfill = AR.infile->POfull = AR.infile->PObuffer;
244  }
245  if ( AR.outfile->handle >= 0 ) {
246  POSITION scrpos;
247  PUTZERO(scrpos);
248  SeekFile(AR.outfile->handle,&scrpos,SEEK_SET);
249  if ( ISNOTZEROPOS(scrpos) ) {
250  return(MesPrint("Error with scratch output."));
251  }
252  if ( ( AR.InInBuf = ReadFile(AR.outfile->handle,(UBYTE *)(AR.outfile->PObuffer)
253  ,AR.outfile->POsize) ) < 0 || AR.InInBuf & 1 ) {
254  return(MesPrint("Error while reading from scratch file"));
255  }
256  else AR.InInBuf /= TABLESIZE(WORD,UBYTE);
257  AR.outfile->POfull = AR.outfile->PObuffer + AR.InInBuf;
258  }
259  else AR.outfile->POfull = AR.outfile->POfill;
260  AR.outfile->POfill = AR.outfile->PObuffer;
261  PUTZERO(AR.outfile->POposition);
262  f = AR.outfile; AR.outfile = AR.infile; AR.infile = f;
263  return(0);
264 }
265 
266 /*
267  #] ResetScratch :
268  #[ CoSave :
269 
270  The syntax of the save statement is:
271 
272  save filename
273  save filename expr1 expr2
274 
275 */
276 
277 int CoSave(UBYTE *inp)
278 {
279  GETIDENTITY
280  UBYTE *p, c;
281  WORD n = 0, i;
282  WORD error = 0, type, number;
283  LONG RetCode = 0, wSize;
284  EXPRESSIONS e;
285  INDEXENTRY *ind;
286  INDEXENTRY *indold;
287  WORD TMproto[SUBEXPSIZE];
288  POSITION scrpos, scrpos1, filesize;
289  int ii, j = sizeof(FILEINDEX)/(sizeof(LONG));
290  LONG *lo;
291  while ( *inp == ',' ) inp++;
292  p = inp;
293 
294 #ifdef WITHMPI
295  if( PF.me != MASTER) return(0);
296 #endif
297 
298  if ( !*p ) return(MesPrint("No filename in save statement"));
299  if ( FG.cTable[*p] && ( *p != SEPARATOR ) && ( *p != ALTSEPARATOR ) )
300  return(MesPrint("Illegal filename"));
301  while ( *++p && *p != ',' ) {}
302  c = *p;
303  *p = 0;
304  if ( !AP.preError ) {
305  if ( ( RetCode = CreateFile((char *)inp) ) < 0 ) {
306  return(MesPrint("Cannot open file %s",inp));
307  }
308  }
309  AO.SaveData.Handle = (WORD)RetCode;
310  PUTZERO(filesize);
311 
312  e = Expressions;
313  n = NumExpressions;
314  if ( c ) { /* There follows a list of expressions */
315  *p++ = c;
316  inp = p;
317  i = (WORD)(INFILEINDEX);
318  if ( WriteStoreHeader(AO.SaveData.Handle) ) return(MesPrint("Error writing storage file header"));
319 /* PUTZERO(AO.SaveData.Index.number); */
320 /* PUTZERO(AO.SaveData.Index.next); */
321  lo = (LONG *)(&AO.SaveData.Index);
322  for ( ii = 0; ii < j; ii++ ) *lo++ = 0;
323  SETBASEPOSITION(AO.SaveData.Position,(LONG)sizeof(STOREHEADER));
324  ind = AO.SaveData.Index.expression;
325  if ( !AP.preError && WriteFile(AO.SaveData.Handle,(UBYTE *)(&(AO.SaveData.Index))
326  ,(LONG)sizeof(struct FiLeInDeX))!= (LONG)sizeof(struct FiLeInDeX) ) goto SavWrt;
327  SeekFile(AO.SaveData.Handle,&(filesize),SEEK_END);
328 /* ADDPOS(filesize,sizeof(struct FiLeInDeX)); */
329 
330  do { /* Scan the list */
331  if ( !FG.cTable[*p] || *p == '[' ) {
332  p = SkipAName(p);
333  if ( p == 0 ) return(-1);
334  }
335  c = *p; *p = 0;
336  if ( GetVar(inp,&type,&number,CEXPRESSION,NOAUTO) != NAMENOTFOUND ) {
337  if ( e[number].status == STOREDEXPRESSION ) {
338 /*
339  Here we have to locate the stored expression, copy its index entry
340  possibly after making a new fileindex and then copy the whole
341  expression.
342 */
343  if ( AP.preError ) goto NextExpr;
344  TMproto[0] = EXPRESSION;
345  TMproto[1] = SUBEXPSIZE;
346  TMproto[2] = number;
347  TMproto[3] = 1;
348  { int ie; for ( ie = 4; ie < SUBEXPSIZE; ie++ ) TMproto[ie] = 0; }
349  AT.TMaddr = TMproto;
350  if ( ( indold = FindInIndex(number,&AR.StoreData,0,0) ) != 0 ) {
351  if ( i <= 0 ) {
352 /*
353  AO.SaveData.Index.next = filesize;
354 */
355  SeekFile(AO.SaveData.Handle,&(AO.SaveData.Index.next),SEEK_END);
356  scrpos = AO.SaveData.Position;
357  SeekFile(AO.SaveData.Handle,&scrpos,SEEK_SET);
358  if ( ISNOTEQUALPOS(scrpos,AO.SaveData.Position) ) goto SavWrt;
359  if ( WriteFile(AO.SaveData.Handle,(UBYTE *)(&(AO.SaveData.Index))
360  ,(LONG)sizeof(struct FiLeInDeX)) != (LONG)sizeof(struct FiLeInDeX) )
361  goto SavWrt;
362  i = (WORD)(INFILEINDEX);
363  AO.SaveData.Position = AO.SaveData.Index.next;
364  lo = (LONG *)(&AO.SaveData.Index);
365  for ( ii = 0; ii < j; ii++ ) *lo++ = 0;
366  ind = AO.SaveData.Index.expression;
367  scrpos = AO.SaveData.Position;
368  SeekFile(AO.SaveData.Handle,&scrpos,SEEK_SET);
369  if ( ISNOTEQUALPOS(scrpos,AO.SaveData.Position) ) goto SavWrt;
370  if ( WriteFile(AO.SaveData.Handle,(UBYTE *)(&(AO.SaveData.Index))
371  ,(LONG)sizeof(struct FiLeInDeX)) != (LONG)sizeof(struct FiLeInDeX) )
372  goto SavWrt;
373  ADDPOS(filesize,sizeof(struct FiLeInDeX));
374  }
375  *ind = *indold;
376 /*
377  ind->variables = SeekFile(AO.SaveData.Handle,&(AM.zeropos),SEEK_END);
378 */
379  ind->variables = filesize;
380  ind->position = ind->variables;
381  ADDPOS(ind->position,DIFBASE(indold->position,indold->variables));
382  SeekFile(AR.StoreData.Handle,&(indold->variables),SEEK_SET);
383  wSize = TOLONG(AT.WorkTop) - TOLONG(AT.WorkPointer);
384  scrpos = ind->length;
385  ADDPOS(scrpos,DIFBASE(ind->position,ind->variables));
386  ADD2POS(filesize,scrpos);
387  SETBASEPOSITION(scrpos1,wSize);
388  do {
389  if ( ISLESSPOS(scrpos,scrpos1) ) wSize = BASEPOSITION(scrpos);
390  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,wSize)
391  != wSize ) {
392  MesPrint("ReadError");
393  error = -1;
394  goto EndSave;
395  }
396  if ( WriteFile(AO.SaveData.Handle,(UBYTE *)AT.WorkPointer,wSize)
397  != wSize ) goto SavWrt;
398  ADDPOS(scrpos,-wSize);
399  } while ( ISPOSPOS(scrpos) );
400  ADDPOS(AO.SaveData.Index.number,1);
401  ind++;
402  }
403  else error = -1;
404  i--;
405  }
406  else {
407  MesPrint("%s is not a stored expression",inp);
408  error = -1;
409  }
410 NextExpr:;
411  }
412  else {
413  MesPrint("%s is not an expression",inp);
414  error = -1;
415  }
416  *p = c;
417  if ( c != ',' && c ) {
418  MesComp("Illegal character",inp,p);
419  error = -1;
420  goto EndSave;
421  }
422  if ( c ) c = *++p;
423  inp = p;
424  } while ( c );
425  if ( !AP.preError ) {
426  scrpos = AO.SaveData.Position;
427  SeekFile(AO.SaveData.Handle,&scrpos,SEEK_SET);
428  if ( ISNOTEQUALPOS(scrpos,AO.SaveData.Position) ) goto SavWrt;
429  }
430  if ( !AP.preError &&
431  WriteFile(AO.SaveData.Handle,(UBYTE *)(&(AO.SaveData.Index))
432  ,(LONG)sizeof(struct FiLeInDeX)) != (LONG)sizeof(struct FiLeInDeX) ) goto SavWrt;
433  }
434  else if ( !AP.preError ) { /* All stored expressions should be saved. Easy */
435  if ( n > 0 ) { do {
436  if ( e->status == STOREDEXPRESSION ) break;
437  e++;
438  } while ( --n > 0 ); }
439  if ( n ) {
440  wSize = TOLONG(AT.WorkTop) - TOLONG(AT.WorkPointer);
441  PUTZERO(scrpos);
442  SeekFile(AR.StoreData.Handle,&scrpos,SEEK_SET); /* Start at the beginning */
443  scrpos = AR.StoreData.Fill; /* Number of bytes to be copied */
444  SETBASEPOSITION(scrpos1,wSize);
445  do {
446  if ( ISLESSPOS(scrpos,scrpos1) ) wSize = BASEPOSITION(scrpos);
447  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,wSize) != wSize ) {
448  MesPrint("ReadError");
449  error = -1;
450  goto EndSave;
451  }
452  if ( WriteFile(AO.SaveData.Handle,(UBYTE *)AT.WorkPointer,wSize) != wSize )
453  goto SavWrt;
454  ADDPOS(scrpos,-wSize);
455  } while ( ISPOSPOS(scrpos) );
456  }
457  }
458 EndSave:
459  if ( !AP.preError ) {
460  CloseFile(AO.SaveData.Handle);
461  AO.SaveData.Handle = -1;
462  }
463  return(error);
464 SavWrt:
465  MesPrint("WriteError");
466  error = -1;
467  goto EndSave;
468 }
469 
470 /*
471  #] CoSave :
472  #[ CoLoad :
473 */
474 
475 int CoLoad(UBYTE *inp)
476 {
477  GETIDENTITY
478  INDEXENTRY *ind;
479  LONG RetCode;
480  UBYTE *p, c;
481  WORD num, i, error = 0;
482  WORD type, number, silentload = 0;
483  WORD TMproto[SUBEXPSIZE];
484  POSITION scrpos,firstposition;
485  while ( *inp == ',' ) inp++;
486  p = inp;
487  if ( ( *p == ',' && p[1] == '-' ) || *p == '-' ) {
488  if ( *p == ',' ) p++;
489  p++;
490  if ( *p == 's' || *p == 'S' ) {
491  silentload = 1;
492  while ( *p && ( *p != ',' && *p != '-' && *p != '+'
493  && *p != SEPARATOR && *p != ALTSEPARATOR ) ) p++;
494  }
495  else if ( *p != ',' ) {
496  return(MesPrint("Illegal option in Load statement"));
497  }
498  while ( *p == ',' ) p++;
499  }
500  inp = p;
501  if ( !*p ) return(MesPrint("No filename in load statement"));
502  if ( FG.cTable[*p] && ( *p != SEPARATOR ) && ( *p != ALTSEPARATOR ) )
503  return(MesPrint("Illegal filename"));
504  while ( *++p && *p != ',' ) {}
505  c = *p;
506  *p = 0;
507  if ( ( RetCode = OpenFile((char *)inp) ) < 0 ) {
508  return(MesPrint("Cannot open file %s",inp));
509  }
510 
511  if ( SetFileIndex() ) {
512  MesCall("CoLoad");
513  SETERROR(-1)
514  }
515 
516  AO.SaveData.Handle = (WORD)(RetCode);
517 
518 #ifdef SYSDEPENDENTSAVE
519  if ( ReadFile(AO.SaveData.Handle,(UBYTE *)(&(AO.SaveData.Index)),
520  (LONG)sizeof(struct FiLeInDeX)) != (LONG)sizeof(struct FiLeInDeX) ) goto LoadRead;
521 #else
522  if ( ReadSaveHeader() ) goto LoadRead;
523  TELLFILE(AO.SaveData.Handle,&firstposition);
524  if ( ReadSaveIndex(&AO.SaveData.Index) ) goto LoadRead;
525 #endif
526  if ( c ) { /* There follows a list of expressions */
527  *p++ = c;
528  inp = p;
529 
530  do { /* Scan the list */
531  if ( !FG.cTable[*p] || *p == '[' ) {
532  p = SkipAName(p);
533  if ( p == 0 ) return(-1);
534  }
535  c = *p; *p = 0;
536  if ( GetVar(inp,&type,&number,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
537  MesPrint("Conflicting name: %s",inp);
538  error = -1;
539  }
540  else {
541  if ( ( num = EntVar(CEXPRESSION,inp,STOREDEXPRESSION,0,0,0) ) >= 0 ) {
542  TMproto[0] = EXPRESSION;
543  TMproto[1] = SUBEXPSIZE;
544  TMproto[2] = num;
545  TMproto[3] = 1;
546  { int ie; for ( ie = 4; ie < SUBEXPSIZE; ie++ ) TMproto[ie] = 0; }
547  AT.TMaddr = TMproto;
548  SeekFile(AO.SaveData.Handle,&firstposition,SEEK_SET);
549  AO.SaveData.Position = firstposition;
550  if ( ReadSaveIndex(&AO.SaveData.Index) ) goto LoadRead;
551  if ( ( ind = FindInIndex(num,&AO.SaveData,1,0) ) != 0 ) {
552  if ( !error ) {
553  if ( PutInStore(ind,num) ) error = -1;
554  else if ( !AM.silent && silentload == 0 )
555  MesPrint(" %s loaded",ind->name);
556  }
557 /*
558 !!! Added 1-feb-1998
559 */
560  Expressions[num].counter = -1;
561  }
562  else {
563  MesPrint(" %s not found",inp);
564  error = -1;
565  }
566  }
567  else error = -1;
568  }
569  *p = c;
570  if ( c != ',' && c ) {
571  MesComp("Illegal character",inp,p);
572  error = -1;
573  goto EndLoad;
574  }
575  if ( c ) c = *++p;
576  inp = p;
577  } while ( c );
578  scrpos = AR.StoreData.Position;
579  SeekFile(AR.StoreData.Handle,&scrpos,SEEK_SET);
580  if ( ISNOTEQUALPOS(scrpos,AR.StoreData.Position) ) goto LoadWrt;
581  if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&(AR.StoreData.Index))
582  ,(LONG)sizeof(struct FiLeInDeX)) != (LONG)sizeof(struct FiLeInDeX) ) goto LoadWrt;
583  }
584  else { /* All saved expressions should be stored. Easy */
585  i = (WORD)BASEPOSITION(AO.SaveData.Index.number);
586  ind = AO.SaveData.Index.expression;
587 #ifdef SYSDEPENDENTSAVE
588  if ( i > 0 ) { do {
589  if ( GetVar((UBYTE *)(ind->name),&type,&number,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
590  MesPrint("Conflicting name: %s",ind->name);
591  error = -1;
592  }
593  else {
594  if ( ( num = EntVar(CEXPRESSION,(UBYTE *)(ind->name),STOREDEXPRESSION,0,0,0) ) >= 0 ) {
595  if ( !error ) {
596  if ( PutInStore(ind,num) ) error = -1;
597  else if ( !AM.silent && silentload == 0 )
598  MesPrint(" %s loaded",ind->name);
599  }
600  }
601  else error = -1;
602  }
603  i--;
604  if ( i == 0 && ISNOTZEROPOS(AO.SaveData.Index.next) ) {
605  SeekFile(AO.SaveData.Handle,&(AO.SaveData.Index.next),SEEK_SET);
606  if ( ReadFile(AO.SaveData.Handle,(UBYTE *)(&(AO.SaveData.Index)),
607  (LONG)sizeof(struct FiLeInDeX)) != (LONG)sizeof(struct FiLeInDeX) ) goto LoadRead;
608  i = (WORD)BASEPOSITION(AO.SaveData.Index.number);
609  ind = AO.SaveData.Index.expression;
610  }
611  else ind++;
612  } while ( i > 0 ); }
613 #else
614  if ( i > 0 ) {
615  do {
616  if ( GetVar((UBYTE *)(ind->name),&type,&number,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
617  MesPrint("Conflicting name: %s",ind->name);
618  error = -1;
619  }
620  else {
621  if ( ( num = EntVar(CEXPRESSION,(UBYTE *)(ind->name),STOREDEXPRESSION,0,0,0) ) >= 0 ) {
622  if ( !error ) {
623  if ( PutInStore(ind,num) ) error = -1;
624  else if ( !AM.silent && silentload == 0 )
625  MesPrint(" %s loaded",ind->name);
626  }
627  }
628  else error = -1;
629  }
630  i--;
631  if ( i == 0 && (ISNOTZEROPOS(AO.SaveData.Index.next) || AO.bufferedInd) ) {
632  SeekFile(AO.SaveData.Handle,&(AO.SaveData.Index.next),SEEK_SET);
633  if ( ReadSaveIndex(&AO.SaveData.Index) ) goto LoadRead;
634  i = (WORD)BASEPOSITION(AO.SaveData.Index.number);
635  ind = AO.SaveData.Index.expression;
636  }
637  else ind++;
638  } while ( i > 0 );
639  }
640 #endif
641  }
642 EndLoad:
643 #ifndef SYSDEPENDENTSAVE
644  if ( AO.powerFlag ) {
645  MesPrint("WARNING: min-/maxpower had to be adjusted!");
646  }
647  if ( AO.resizeFlag ) {
648  MesPrint("ERROR: could not downsize data!");
649  return ( -2 );
650  }
651 #endif
652  CloseFile(AO.SaveData.Handle);
653  AO.SaveData.Handle = -1;
654  SeekFile(AR.StoreData.Handle,&(AC.StoreFileSize),SEEK_END);
655  return(error);
656 LoadWrt:
657  MesPrint("WriteError");
658  error = -1;
659  goto EndLoad;
660 LoadRead:
661  MesPrint("ReadError");
662  error = -1;
663  goto EndLoad;
664 }
665 
666 /*
667  #] CoLoad :
668  #[ DeleteStore :
669 
670  Routine deletes the contents of the entire storage file.
671  We close the file and recreate it.
672  If par > 0 we have to remove the expressions from the namelists.
673 */
674 
675 WORD DeleteStore(WORD par)
676 {
677  GETIDENTITY
678  char *s;
679  WORD j, n = 0;
680  EXPRESSIONS e_in, e_out;
681  WORD DidClean = 0;
682  if ( AR.StoreData.Handle >= 0 ) {
683  if ( par > 0 ) {
684  n = NumExpressions;
685  j = 0;
686  e_in = e_out = Expressions;
687  if ( n > 0 ) { do {
688  if ( e_in->status == STOREDEXPRESSION ) {
689  NAMENODE *node = GetNode(AC.exprnames,
690  AC.exprnames->namebuffer+e_in->name);
691  node->type = CDELETE;
692  DidClean = 1;
693  }
694  else {
695  if ( e_out != e_in ) {
696  NAMENODE *node;
697  node = GetNode(AC.exprnames,
698  AC.exprnames->namebuffer+e_in->name);
699  node->number = (WORD)(e_out - Expressions);
700  e_out->onfile = e_in->onfile;
701  e_out->printflag = 0;
702  e_out->status = e_in->status;
703  e_out->name = e_in->name;
704  e_out->inmem = e_in->inmem;
705  }
706  e_out++;
707  j++;
708  }
709  e_in++;
710  } while ( --n > 0 ); }
711  NumExpressions = j;
712  if ( DidClean ) CompactifyTree(AC.exprnames,EXPRNAMES);
713  }
714  AR.StoreData.Handle = -1;
715  CloseFile(AC.StoreHandle);
716  AC.StoreHandle = -1;
717  {
718 /*
719  Knock out the storage caches (25-apr-1990!)
720 */
721  STORECACHE st;
722  st = (STORECACHE)(AT.StoreCache);
723  while ( st ) {
724  SETBASEPOSITION(st->position,-1);
725  SETBASEPOSITION(st->toppos,-1);
726  st = st->next;
727  }
728 #ifdef WITHPTHREADS
729  for ( j = 1; j < AM.totalnumberofthreads; j++ ) {
730  st = (STORECACHE)(AB[j]->T.StoreCache);
731  while ( st ) {
732  SETBASEPOSITION(st->position,-1);
733  SETBASEPOSITION(st->toppos,-1);
734  st = st->next;
735  }
736  }
737 #endif
738  }
739  PUTZERO(AC.StoreFileSize);
740  s = FG.fname; while ( *s ) s++;
741 #ifdef VMS
742  *s = ';'; s[1] = '*'; s[2] = 0;
743  remove(FG.fname);
744  *s = 0;
745 #endif
746  return(AC.StoreHandle = CreateFile(FG.fname));
747  }
748  else return(0);
749 }
750 
751 /*
752  #] DeleteStore :
753  #[ PutInStore :
754 
755  Copies the expression indicated by ind from a load file to the
756  internal storage file. A return value of zero indicates that
757  everything is OK.
758 
759 */
760 
761 WORD PutInStore(INDEXENTRY *ind, WORD num)
762 {
763  GETIDENTITY
764  INDEXENTRY *newind;
765  LONG wSize;
766 #ifndef SYSDEPENDENTSAVE
767  LONG wSizeOut;
768  LONG stage;
769 #endif
770  POSITION scrpos,scrpos1;
771  newind = NextFileIndex(&(Expressions[num].onfile));
772  *newind = *ind;
773 #ifndef SYSDEPENDENTSAVE
774  SETBASEPOSITION(newind->length, 0);
775 #endif
776  newind->variables = AR.StoreData.Fill;
777  SeekFile(AR.StoreData.Handle,&(newind->variables),SEEK_SET);
778  if ( ISNOTEQUALPOS(newind->variables,AR.StoreData.Fill) ) goto PutErrS;
779  newind->position = newind->variables;
780 #ifdef SYSDEPENDENTSAVE
781  ADDPOS(newind->position,DIFBASE(ind->position,ind->variables));
782 #endif
783  /* set read position to ind->variables */
784  scrpos = ind->variables;
785  SeekFile(AO.SaveData.Handle,&scrpos,SEEK_SET);
786  if ( ISNOTEQUALPOS(scrpos,ind->variables) ) goto PutErrS;
787  /* set max size for read-in */
788  wSize = TOLONG(AT.WorkTop) - TOLONG(AT.WorkPointer);
789 #ifdef SYSDEPENDENTSAVE
790  scrpos = ind->length;
791  ADDPOS(scrpos,DIFBASE(ind->position,ind->variables));
792  ADD2POS(AR.StoreData.Fill,scrpos);
793 #endif
794  SETBASEPOSITION(scrpos1,wSize);
795 #ifndef SYSDEPENDENTSAVE
796  /* prepare look-up table for tensor functions */
797  if ( ind->nfunctions ) {
798  AO.tensorList = (UBYTE *)Malloc1(MAXSAVEFUNCTION,"PutInStore");
799  }
800  SETBASEPOSITION(scrpos, DIFBASE(ind->position,ind->variables));
801  /* copy variables first */
802  stage = -1;
803  do {
804  wSize = TOLONG(AT.WorkTop) - TOLONG(AT.WorkPointer);
805  if ( ISLESSPOS(scrpos,scrpos1) ) wSize = BASEPOSITION(scrpos);
806  wSizeOut = wSize;
807  if ( ReadSaveVariables(
808  (UBYTE *)AT.WorkPointer, (UBYTE *)AT.WorkTop, &wSize, &wSizeOut, ind, &stage) ) {
809  goto PutErrS;
810  }
811  if ( WriteFile(AR.StoreData.Handle, (UBYTE *)AT.WorkPointer, wSizeOut)
812  != wSizeOut ) goto PutErrS;
813  ADDPOS(scrpos,-wSize);
814  ADDPOS(newind->position, wSizeOut);
815  ADDPOS(AR.StoreData.Fill, wSizeOut);
816  } while ( ISPOSPOS(scrpos) );
817  /* then copy the expression itself */
818  wSize = TOLONG(AT.WorkTop) - TOLONG(AT.WorkPointer);
819  scrpos = ind->length;
820 #endif
821  do {
822  wSize = TOLONG(AT.WorkTop) - TOLONG(AT.WorkPointer);
823  if ( ISLESSPOS(scrpos,scrpos1) ) wSize = BASEPOSITION(scrpos);
824 #ifdef SYSDEPENDENTSAVE
825  if ( ReadFile(AO.SaveData.Handle,(UBYTE *)AT.WorkPointer,wSize)
826  != wSize ) goto PutErrS;
827  if ( WriteFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,wSize)
828  != wSize ) goto PutErrS;
829  ADDPOS(scrpos,-wSize);
830 #else
831  wSizeOut = wSize;
832 
833  if ( ReadSaveExpression((UBYTE *)AT.WorkPointer, (UBYTE *)AT.WorkTop, &wSize, &wSizeOut) ) {
834  goto PutErrS;
835  }
836 
837  if ( WriteFile(AR.StoreData.Handle, (UBYTE *)AT.WorkPointer, wSizeOut)
838  != wSizeOut ) goto PutErrS;
839  ADDPOS(scrpos,-wSize);
840  ADDPOS(AR.StoreData.Fill, wSizeOut);
841  ADDPOS(newind->length, wSizeOut);
842 #endif
843  } while ( ISPOSPOS(scrpos) );
844  /* free look-up table for tensor functions */
845  if ( ind->nfunctions ) {
846  M_free(AO.tensorList,"PutInStore");
847  }
848  scrpos = AR.StoreData.Position;
849  SeekFile(AR.StoreData.Handle,&scrpos,SEEK_SET);
850  if ( ISNOTEQUALPOS(scrpos,AR.StoreData.Position) ) goto PutErrS;
851  if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&AR.StoreData.Index),(LONG)sizeof(FILEINDEX))
852  == (LONG)sizeof(FILEINDEX) ) return(0);
853 PutErrS:
854  return(MesPrint("File error"));
855 }
856 
857 /*
858  #] PutInStore :
859  #[ GetTerm :
860 
861  Gets one term from input scratch stream.
862  Puts it in 'term'.
863  Returns the length of the term.
864 
865  Used by Processor (proces.c)
866  WriteAll (sch.c)
867  WriteOne (sch.c)
868  GetMoreTerms (store.c)
869  ToStorage (store.c)
870  CoFillExpression (comexpr.c)
871  FactorInExpr (factor.c)
872  LoadOpti (optim.c)
873  PF_Processor (parallel.c)
874  ThreadsProcessor (threads.c)
875  In multi thread/processor mode all calls are done by the master.
876  Note however that other routines, used by the threads, can use
877  the same file. Hence we need to be careful about SeekFile and locks.
878 */
879 
880 WORD GetTerm(PHEAD WORD *term)
881 {
882  GETBIDENTITY
883  WORD *inp, i, j = 0, len;
884  LONG InIn, *whichInInBuf;
885  WORD *r, *m, *mstop = 0, minsiz = 0, *bra = 0, *from;
886  WORD first, *start = 0, testing = 0;
887  FILEHANDLE *fi;
888  AN.deferskipped = 0;
889  if ( AR.GetFile == 2 ) {
890  fi = AR.hidefile;
891  whichInInBuf = &(AR.InHiBuf);
892  }
893  else {
894  fi = AR.infile;
895  whichInInBuf = &(AR.InInBuf);
896  }
897  InIn = *whichInInBuf;
898  from = term;
899  if ( AR.KeptInHold ) {
900  r = AR.CompressBuffer;
901  i = *r;
902  if ( i <= 0 ) { *term = 0; goto RegRet; }
903  m = term;
904  NCOPY(m,r,i);
905  AR.KeptInHold = 0;
906  goto RegRet;
907  }
908  if ( AR.DeferFlag ) {
909  m = AR.CompressBuffer;
910  if ( *m > 0 ) {
911  mstop = m + *m;
912  mstop -= ABS(mstop[-1]);
913  m++;
914  while ( m < mstop ) {
915  if ( *m == HAAKJE ) {
916  testing = 1;
917  mstop = m + m[1];
918  bra = (WORD *)(((UBYTE *)(term)) + 2*AM.MaxTer);
919  m = AR.CompressBuffer+1;
920  r = bra;
921  while ( m < mstop ) *r++ = *m++;
922  mstop = r;
923  minsiz = WORDDIF(mstop,bra);
924  goto ReStart;
925 /*
926  We have the bracket to be tested in bra till mstop
927 */
928  }
929  m += m[1];
930  }
931  }
932  bra = (WORD *)(((UBYTE *)(term)) + 2*AM.MaxTer);
933  mstop = bra+1;
934  *bra = 0;
935  minsiz = 1;
936  testing = 1;
937  }
938 ReStart:
939  first = 0;
940  r = AR.CompressBuffer;
941  if ( fi->handle >= 0 ) {
942  if ( InIn <= 0 ) {
943  ADDPOS(fi->POposition,(fi->POfull-fi->PObuffer)*sizeof(WORD));
944  LOCK(AS.inputslock);
945  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
946  InIn = ReadFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize);
947  UNLOCK(AS.inputslock);
948  if ( ( InIn < 0 ) || ( InIn & 1 ) ) {
949  goto GTerr;
950  }
951 #ifdef WORD2
952  InIn >>= 1;
953 #else
954  InIn /= TABLESIZE(WORD,UBYTE);
955 #endif
956  *whichInInBuf = InIn;
957  if ( !InIn ) { *r = 0; *from = 0; goto RegRet; }
958  fi->POfill = fi->PObuffer;
959  fi->POfull = fi->PObuffer + InIn;
960  }
961  inp = fi->POfill;
962  if ( ( len = i = *inp ) == 0 ) {
963  (*whichInInBuf)--;
964  (fi->POfill)++;
965  *r = 0;
966  *from = 0;
967  goto RegRet;
968  }
969  if ( i < 0 ) {
970  InIn--;
971  inp++;
972  r++;
973  start = term;
974  *term++ = -i + 1;
975  while ( ++i <= 0 ) *term++ = *r++;
976  if ( InIn > 0 ) {
977  i = *inp++;
978  InIn--;
979  *start += i;
980  *(AR.CompressBuffer) = len = *start;
981  }
982  else {
983  first = 1;
984  goto NewIn;
985  }
986  }
987  InIn -= i;
988  if ( InIn < 0 ) {
989  j = (WORD)(- InIn);
990  i -= j;
991  }
992  else j = 0;
993  while ( --i >= 0 ) {
994  *r++ = *term++ = *inp++;
995  }
996  if ( j ) {
997 NewIn:
998  ADDPOS(fi->POposition,(fi->POfull-fi->PObuffer)*sizeof(WORD));
999  LOCK(AS.inputslock);
1000  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
1001  InIn = ReadFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize);
1002  UNLOCK(AS.inputslock);
1003  if ( ( InIn <= 0 ) || ( InIn & 1 ) ) {
1004  goto GTerr;
1005  }
1006 #ifdef WORD2
1007  InIn >>= 1;
1008 #else
1009  InIn /= TABLESIZE(WORD,UBYTE);
1010 #endif
1011  inp = fi->PObuffer;
1012  fi->POfull = inp + InIn;
1013 
1014  if ( first ) {
1015  j = *inp++;
1016  InIn--;
1017  *start += j;
1018  *(AR.CompressBuffer) = len = *start;
1019  }
1020  InIn -= j;
1021  while ( --j >= 0 ) { *r++ = *term++ = *inp++; }
1022  }
1023  fi->POfill = inp;
1024  *whichInInBuf = InIn;
1025  AR.DefPosition = fi->POposition;
1026  ADDPOS(AR.DefPosition,((UBYTE *)(fi->POfill)-(UBYTE *)(fi->PObuffer)));
1027  }
1028  else {
1029  inp = fi->POfill;
1030  if ( inp >= fi->POfull ) { *from = 0; goto RegRet; }
1031  len = j = *inp;
1032  if ( j < 0 ) {
1033  inp++;
1034  *term++ = *r++ = len = - j + 1 + *inp;
1035  while ( ++j <= 0 ) *term++ = *r++;
1036  j = *inp++;
1037  }
1038  else if ( !j ) j = 1;
1039  while ( --j >= 0 ) { *r++ = *term++ = *inp++; }
1040  fi->POfill = inp;
1041 /*%%%%%ADDED 7-apr-2006 for Keep Brackets in bucket */
1042  SETBASEPOSITION(AR.DefPosition,((UBYTE *)(fi->POfill)-(UBYTE *)(fi->PObuffer)));
1043  if ( inp > fi->POfull ) {
1044  goto GTerr;
1045  }
1046  }
1047  if ( r >= AR.ComprTop ) {
1048  MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
1049  Terminate(-1);
1050  }
1051  AR.CompressPointer = r; *r = 0;
1052 /*
1053  The next *from is a bug fix that made the program read in forbidden
1054  territory.
1055 */
1056  if ( testing && *from != 0 ) {
1057  WORD jj;
1058  r = from;
1059  jj = *r - 1 - ABS(*(r+*r-1));
1060  if ( jj < minsiz ) goto strip;
1061  r++;
1062  m = bra;
1063  while ( m < mstop ) {
1064  if ( *m != *r ) {
1065 strip: r = from;
1066  m = r + *r;
1067  mstop = m - ABS(m[-1]);
1068  r++;
1069  while ( r < mstop ) {
1070  if ( *r == HAAKJE ) {
1071  *r++ = 1;
1072  *r++ = 1;
1073  *r++ = 3;
1074  len = WORDDIF(r,from);
1075  *from = len;
1076  goto RegRet;
1077  }
1078  r += r[1];
1079  }
1080  goto RegRet;
1081  }
1082  m++;
1083  r++;
1084  }
1085  term = from;
1086  AN.deferskipped++;
1087  goto ReStart;
1088  }
1089 RegRet:;
1090 /*
1091  #[ debug :
1092 */
1093  {
1094  UBYTE OutBuf[140];
1095 /* if ( AP.DebugFlag ) { */
1096  if ( ( AP.PreDebug & DUMPINTERMS ) == DUMPINTERMS ) {
1097  MLOCK(ErrorMessageLock);
1098  AO.OutFill = AO.OutputLine = OutBuf;
1099  AO.OutSkip = 3;
1100  FiniLine();
1101  r = from;
1102  i = *r;
1103  TokenToLine((UBYTE *)("Input: "));
1104  if ( i == 0 ) {
1105  TokenToLine((UBYTE *)"zero");
1106  }
1107  else if ( i < 0 ) {
1108  TokenToLine((UBYTE *)"negative!!");
1109  }
1110  else {
1111  while ( --i >= 0 ) {
1112  TalToLine((UWORD)(*r++)); TokenToLine((UBYTE *)" ");
1113  }
1114  }
1115  FiniLine();
1116  MUNLOCK(ErrorMessageLock);
1117  }
1118  }
1119 /*
1120  #] debug :
1121 */
1122  return(*from);
1123 GTerr:
1124  MesPrint("Error while reading scratch file in GetTerm");
1125  Terminate(-1);
1126  return(-1);
1127 }
1128 
1129 /*
1130  #] GetTerm :
1131  #[ GetOneTerm :
1132 
1133  Gets one term from stream AR.infile->handle.
1134  Puts it in 'term'.
1135  Returns the length of the term.
1136  Input is unbuffered.
1137  Compression via AR.CompressPointer
1138  par is actually in all calls a file handle
1139 
1140  Routine is called from
1141  DoOnePow Get one power of an expression
1142  Deferred Get the contents of a bracket
1143  GetFirstBracket
1144  FindBracket
1145  We should do something about the lack of buffering.
1146  Maybe a buffer of a few times AM.MaxTer (MaxTermSize*sizeof(WORD)).
1147  Each thread will need its own buffer!
1148 
1149  If par == 0 we use ReadPosFile which can fill the whole buffer.
1150  If par == 1 we use ReadFile and do actual read operations.
1151 
1152  Note: we cannot use ReadPosFile when running in the master thread.
1153 */
1154 
1155 WORD GetOneTerm(PHEAD WORD *term, FILEHANDLE *fi, POSITION *pos, int par)
1156 {
1157  GETBIDENTITY
1158  WORD i, *p;
1159  LONG j, siz;
1160  WORD *r, *rr = AR.CompressPointer;
1161  int error = 0;
1162  r = rr;
1163  if ( fi->handle >= 0 ) {
1164 #ifdef READONEBYONE
1165 #ifdef WITHPTHREADS
1166 /*
1167  This code needs some investigation.
1168  It may be that we should do this always.
1169  It may be that even for workers it is no good.
1170  We may have to make a variable like AM.ReadDirect with
1171  if ( AM.ReadDirect ) par = 1;
1172  and a user command like
1173  On ReadDirect;
1174 */
1175  if ( AT.identity > 0 ) par = 1;
1176 #endif
1177 #endif
1178 /*
1179  To be changed:
1180  1: check first whether the term lies completely inside the buffer
1181  2: if not a: use old strategy for AT.identity == 0 (master)
1182  b: for workers, position file and read buffer
1183 */
1184  if ( par == 0 ) {
1185  siz = ReadPosFile(BHEAD fi,(UBYTE *)term,1L,pos);
1186  }
1187  else {
1188  LOCK(AS.inputslock);
1189  SeekFile(fi->handle,pos,SEEK_SET);
1190  siz = ReadFile(fi->handle,(UBYTE *)term,sizeof(WORD));
1191  UNLOCK(AS.inputslock);
1192  ADDPOS(*pos,siz);
1193  }
1194  if ( siz == sizeof(WORD) ) {
1195  p = term;
1196  j = i = *term++;
1197  if ( ( i > AM.MaxTer/((WORD)sizeof(WORD)) ) || ( -i >= AM.MaxTer/((WORD)sizeof(WORD)) ) )
1198  {
1199  error = 1;
1200  goto ErrGet;
1201  }
1202  r++;
1203  if ( i < 0 ) {
1204  *p = -i + 1;
1205  while ( ++i <= 0 ) *term++ = *r++;
1206  if ( par == 0 ) {
1207  siz = ReadPosFile(BHEAD fi,(UBYTE *)term,1L,pos);
1208  }
1209  else {
1210  LOCK(AS.inputslock);
1211  SeekFile(fi->handle,pos,SEEK_SET);
1212  siz = ReadFile(fi->handle,(UBYTE *)term,sizeof(WORD));
1213  UNLOCK(AS.inputslock);
1214  ADDPOS(*pos,sizeof(WORD));
1215  }
1216  if ( siz != sizeof(WORD) ) {
1217  error = 2;
1218  goto ErrGet;
1219  }
1220  *p += *term;
1221  j = *term;
1222  if ( ( j > AM.MaxTer/((WORD)sizeof(WORD)) ) || ( j <= 0 ) )
1223  {
1224  error = 3;
1225  goto ErrGet;
1226  }
1227  *rr = *p;
1228  }
1229  else {
1230  if ( !j ) return(0);
1231  j--;
1232  }
1233  i = (WORD)j;
1234  if ( par == 0 ) {
1235  siz = ReadPosFile(BHEAD fi,(UBYTE *)term,j,pos);
1236  j *= TABLESIZE(WORD,UBYTE);
1237  }
1238  else {
1239  j *= TABLESIZE(WORD,UBYTE);
1240  LOCK(AS.inputslock);
1241  SeekFile(fi->handle,pos,SEEK_SET);
1242  siz = ReadFile(fi->handle,(UBYTE *)term,j);
1243  UNLOCK(AS.inputslock);
1244  ADDPOS(*pos,j);
1245  }
1246  if ( siz != j ) {
1247  error = 4;
1248  goto ErrGet;
1249  }
1250  while ( --i >= 0 ) *r++ = *term++;
1251  if ( r >= AR.ComprTop ) {
1252  MLOCK(ErrorMessageLock);
1253  MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
1254  MUNLOCK(ErrorMessageLock);
1255  Terminate(-1);
1256  }
1257  AR.CompressPointer = r; *r = 0;
1258  return(*p);
1259  }
1260  error = 5;
1261  }
1262  else {
1263 /*
1264  Here the whole expression is in the buffer.
1265 */
1266  fi->POfill = (WORD *)((UBYTE *)(fi->PObuffer) + BASEPOSITION(*pos));
1267  p = fi->POfill;
1268  if ( p >= fi->POfull ) { *term = 0; return(0); }
1269  j = i = *p;
1270  if ( i < 0 ) {
1271  p++;
1272  j = *r++ = *term++ = -i + 1 + *p;
1273  while ( ++i <= 0 ) *term++ = *r++;
1274  i = *p++;
1275  }
1276  if ( i == 0 ) { i = 1; *r++ = 0; *term++ = 0; }
1277  else { while ( --i >= 0 ) { *r++ = *term++ = *p++; } }
1278  fi->POfill = p;
1279  SETBASEPOSITION(*pos,(UBYTE *)(fi->POfill)-(UBYTE *)(fi->PObuffer));
1280  if ( p <= fi->POfull ) {
1281  if ( r >= AR.ComprTop ) {
1282  MLOCK(ErrorMessageLock);
1283  MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
1284  MUNLOCK(ErrorMessageLock);
1285  Terminate(-1);
1286  }
1287  AR.CompressPointer = r; *r = 0;
1288  return((WORD)j);
1289  }
1290  error = 6;
1291  }
1292 ErrGet:
1293  MLOCK(ErrorMessageLock);
1294  MesPrint("Error while reading scratch file in GetOneTerm (%d)",error);
1295  MUNLOCK(ErrorMessageLock);
1296  Terminate(-1);
1297  return(-1);
1298 }
1299 
1300 /*
1301  #] GetOneTerm :
1302  #[ GetMoreTerms :
1303  Routine collects more contents of brackets inside a function,
1304  indicated by the number in AC.CollectFun.
1305  The first term is in term already.
1306  We can keep calling GetTerm either till a bracket is finished
1307  or till it would make the term too long (> AM.MaxTer/2)
1308  In all cases this function makes that the routine GetTerm
1309  has a term in 'hold', so the AR.KeptInHold flag must be turned on.
1310 */
1311 
1312 WORD GetMoreTerms(WORD *term)
1313 {
1314  GETIDENTITY
1315  WORD *t, *r, *m, *h, *tstop, i, inc, same;
1316  WORD extra;
1317  WORD retval = 0;
1318 /*
1319  We use 23% as a quasi-random default value.
1320 */
1321  extra = ((AM.MaxTer/sizeof(WORD))*((LONG)100-AC.CollectPercentage))/100;
1322  if ( extra < 23 ) extra = 23;
1323 /*
1324  First find the bracket pointer
1325 */
1326  t = term + *term;
1327  tstop = t - ABS(t[-1]);
1328  h = term+1;
1329  while ( *h != HAAKJE && h < tstop ) h += h[1];
1330  if ( h >= tstop ) return(retval);
1331  inc = FUNHEAD+ARGHEAD+1-h[1];
1332  same = WORDDIF(h,term) + h[1] - 1;
1333  r = m = t + inc;
1334  tstop = h + h[1];
1335  while ( t > tstop ) *--r = *--t;
1336  r--;
1337  *r = WORDDIF(m,r);
1338  while ( GetTerm(BHEAD m) > 0 ) {
1339  r = m + 1;
1340  t = m + *m - 1;
1341  if ( same > ( i = ( *m - ABS(*t) -1 ) ) ) { /* Must fail */
1342  if ( AC.AltCollectFun && AS.CollectOverFlag == 2 ) AS.CollectOverFlag = 3;
1343  break;
1344  }
1345  t = term+1;
1346  i = same;
1347  while ( --i >= 0 ) {
1348  if ( *r != *t ) {
1349  if ( AC.AltCollectFun && AS.CollectOverFlag == 2 ) AS.CollectOverFlag = 3;
1350  goto FullTerm;
1351  }
1352  r++; t++;
1353  }
1354  if ( ( WORDDIF(m,term) + i + extra ) > (WORD)(AM.MaxTer/sizeof(WORD)) ) {
1355 /* 23 = 3 +20. The 20 is to have some extra for substitutions or whatever */
1356  if ( AS.CollectOverFlag == 0 && AC.AltCollectFun == 0 ) {
1357  Warning("Bracket contents too long in Collect statement");
1358  Warning("Contents spread over more than one term");
1359  Warning("If possible: increase MaxTermSize in setfile");
1360  AS.CollectOverFlag = 1;
1361  }
1362  else if ( AC.AltCollectFun ) {
1363  AS.CollectOverFlag = 2;
1364  }
1365  break;
1366  }
1367  tstop = m + *m;
1368  *m -= same;
1369  m++;
1370  while ( r < tstop ) *m++ = *r++;
1371  retval++;
1372  if ( extra == 23 ) extra = ((AM.MaxTer/sizeof(WORD))/6);
1373  }
1374 FullTerm:
1375  h[1] = WORDDIF(m,h);
1376  if ( AS.CollectOverFlag > 1 ) {
1377  *h = AC.AltCollectFun;
1378  if ( AS.CollectOverFlag == 3 ) AS.CollectOverFlag = 1;
1379  }
1380  else *h = AC.CollectFun;
1381  h[2] |= DIRTYFLAG;
1382  h[FUNHEAD] = h[1] - FUNHEAD;
1383  h[FUNHEAD+1] = 0;
1384  if ( ToFast(h+FUNHEAD,h+FUNHEAD) ) {
1385  if ( h[FUNHEAD] <= -FUNCTION ) {
1386  h[1] = FUNHEAD+1;
1387  m = h + FUNHEAD+1;
1388  }
1389  else {
1390  h[1] = FUNHEAD+2;
1391  m = h + FUNHEAD+2;
1392  }
1393  }
1394  *m++ = 1;
1395  *m++ = 1;
1396  *m++ = 3;
1397  *term = WORDDIF(m,term);
1398  AR.KeptInHold = 1;
1399  return(retval);
1400 }
1401 
1402 /*
1403  #] GetMoreTerms :
1404  #[ GetMoreFromMem :
1405 
1406 */
1407 
1408 WORD GetMoreFromMem(WORD *term, WORD **tpoin)
1409 {
1410  GETIDENTITY
1411  WORD *t, *r, *m, *h, *tstop, i, j, inc, same;
1412  LONG extra = 23;
1413 /*
1414  First find the bracket pointer
1415 */
1416  t = term + *term;
1417  tstop = t - ABS(t[-1]);
1418  h = term+1;
1419  while ( *h != HAAKJE && h < tstop ) h += h[1];
1420  if ( h >= tstop ) return(0);
1421  inc = FUNHEAD+ARGHEAD+1-h[1];
1422  same = WORDDIF(h,term) + h[1] - 1;
1423  r = m = t + inc;
1424  tstop = h + h[1];
1425  while ( t > tstop ) *--r = *--t;
1426  r--;
1427  *r = WORDDIF(m,r);
1428  while ( **tpoin ) {
1429  r = *tpoin; j = *r;
1430  for ( i = 0; i < j; i++ ) m[i] = *r++;
1431  *tpoin = r;
1432  r = m + 1;
1433  t = m + *m - 1;
1434  if ( same > ( i = ( *m - ABS(*t) -1 ) ) ) { /* Must fail */
1435  if ( AC.AltCollectFun && AS.CollectOverFlag == 2 ) AS.CollectOverFlag = 3;
1436  break;
1437  }
1438  t = term+1;
1439  i = same;
1440  while ( --i >= 0 ) {
1441  if ( *r != *t ) {
1442  if ( AC.AltCollectFun && AS.CollectOverFlag == 2 ) AS.CollectOverFlag = 3;
1443  goto FullTerm;
1444  }
1445  r++; t++;
1446  }
1447  if ( ( WORDDIF(m,term) + i + extra ) > (LONG)(AM.MaxTer/(2*sizeof(WORD))) ) {
1448 /* 23 = 3 +20. The 20 is to have some extra for substitutions or whatever */
1449  if ( AS.CollectOverFlag == 0 && AC.AltCollectFun == 0 ) {
1450  Warning("Bracket contents too long in Collect statement");
1451  Warning("Contents spread over more than one term");
1452  Warning("If possible: increase MaxTermSize in setfile");
1453  AS.CollectOverFlag = 1;
1454  }
1455  else if ( AC.AltCollectFun ) {
1456  AS.CollectOverFlag = 2;
1457  }
1458  break;
1459  }
1460  tstop = m + *m;
1461  *m -= same;
1462  m++;
1463  while ( r < tstop ) *m++ = *r++;
1464  if ( extra == 23 ) extra = ((AM.MaxTer/sizeof(WORD))/6);
1465  }
1466 FullTerm:
1467  h[1] = WORDDIF(m,h);
1468  if ( AS.CollectOverFlag > 1 ) {
1469  *h = AC.AltCollectFun;
1470  if ( AS.CollectOverFlag == 3 ) AS.CollectOverFlag = 1;
1471  }
1472  else *h = AC.CollectFun;
1473  h[2] |= DIRTYFLAG;
1474  h[FUNHEAD] = h[1] - FUNHEAD;
1475  h[FUNHEAD+1] = 0;
1476  if ( ToFast(h+FUNHEAD,h+FUNHEAD) ) {
1477  if ( h[FUNHEAD] <= -FUNCTION ) {
1478  h[1] = FUNHEAD+1;
1479  m = h + FUNHEAD+1;
1480  }
1481  else {
1482  h[1] = FUNHEAD+2;
1483  m = h + FUNHEAD+2;
1484  }
1485  }
1486  *m++ = 1;
1487  *m++ = 1;
1488  *m++ = 3;
1489  *term = WORDDIF(m,term);
1490  AR.KeptInHold = 1;
1491  return(0);
1492 }
1493 
1494 /*
1495  #] GetMoreFromMem :
1496  #[ GetFromStore :
1497 
1498  Gets a single term from the storage file at position and puts
1499  it at 'to'.
1500  The value to be returned is the number of words read.
1501  Renumbering is done also.
1502  This is controled by the renumber table, given in 'renumber'
1503 
1504  This routine should work with a number of cache buffers. The
1505  exact number should be definable in form.set.
1506  The parameters are:
1507  AM.SizeStoreCache (4096)
1508  The numbers are the proposed default values.
1509 
1510  The cache is a pure read cache.
1511 */
1512 
1513 static int gfs = 0;
1514 
1515 WORD GetFromStore(WORD *to, POSITION *position, RENUMBER renumber, WORD *InCompState, WORD nexpr)
1516 {
1517  GETIDENTITY
1518  LONG RetCode, num, first = 0;
1519  WORD *from, *m;
1520  struct StOrEcAcHe sc;
1521  STORECACHE s;
1522  STORECACHE snext, sold;
1523  WORD *r, *rr = AR.CompressPointer;
1524  r = rr;
1525  gfs++;
1526  sc.next = AT.StoreCache;
1527  sold = s = &sc;
1528  snext = s->next;
1529  while ( snext ) {
1530  sold = s;
1531  s = snext;
1532  snext = s->next;
1533  if ( BASEPOSITION(s->position) == -1 ) break;
1534  if ( ISLESSPOS(*position,s->toppos) &&
1535  ISGEPOS(*position,s->position) ) { /* Hit */
1536  if ( AT.StoreCache != s ) {
1537  sold->next = s->next;
1538  s->next = AT.StoreCache->next;
1539  AT.StoreCache = s;
1540  }
1541  from = (WORD *)(((UBYTE *)(s->buffer)) + DIFBASE(*position,s->position));
1542  num = *from;
1543  if ( !num ) { return(*to = 0); }
1544  *InCompState = (WORD)num;
1545  m = to;
1546  if ( num < 0 ) {
1547  from++;
1548  ADDPOS(*position,sizeof(WORD));
1549  *m++ = (WORD)(-num+1);
1550  r++;
1551  while ( ++num <= 0 ) *m++ = *r++;
1552  if ( ISLESSPOS(*position,s->toppos) ) {
1553  num = *from++;
1554  *to += (WORD)num;
1555  ADDPOS(*position,sizeof(WORD));
1556  *InCompState = (WORD)(num + 2);
1557  }
1558  else {
1559  first = 1;
1560  goto InNew;
1561  }
1562  }
1563 PastCon:;
1564  while ( num > 0 && ISLESSPOS(*position,s->toppos) ) {
1565  *r++ = *m++ = *from++; ADDPOS(*position,sizeof(WORD)); num--;
1566  }
1567  if ( num > 0 ) {
1568 InNew:
1569  SETBASEPOSITION(s->position,-1);
1570  SETBASEPOSITION(s->toppos,-1);
1571  LOCK(AM.storefilelock);
1572  SeekFile(AR.StoreData.Handle,position,SEEK_SET);
1573  RetCode = ReadFile(AR.StoreData.Handle,(UBYTE *)(s->buffer),AM.SizeStoreCache);
1574  UNLOCK(AM.storefilelock);
1575  if ( RetCode < 0 ) goto PastErr;
1576  if ( !RetCode ) return( *to = 0 );
1577  s->position = *position;
1578  s->toppos = *position;
1579  ADDPOS(s->toppos,RetCode);
1580  from = s->buffer;
1581  if ( first ) {
1582  num = *from++;
1583  ADDPOS(*position,sizeof(WORD));
1584  *to += (WORD)num;
1585 /* first = 0; */
1586  *InCompState = (WORD)(num + 2);
1587  }
1588  goto PastCon;
1589  }
1590  goto PastEnd;
1591  }
1592  }
1593  if ( AT.StoreCache ) { /* Fill the last buffer */
1594  s->position = *position;
1595  LOCK(AM.storefilelock);
1596  SeekFile(AR.StoreData.Handle,position,SEEK_SET);
1597  RetCode = ReadFile(AR.StoreData.Handle,(UBYTE *)(s->buffer),AM.SizeStoreCache);
1598  UNLOCK(AM.storefilelock);
1599  if ( RetCode < 0 ) goto PastErr;
1600  if ( !RetCode ) return( *to = 0 );
1601  s->toppos = *position;
1602  ADDPOS(s->toppos,RetCode);
1603  if ( AT.StoreCache != s ) {
1604  sold->next = s->next;
1605  s->next = AT.StoreCache->next;
1606  AT.StoreCache = s;
1607  }
1608  m = to;
1609  from = s->buffer;
1610  num = *from;
1611  if ( !num ) { return( *to = 0 ); }
1612  *InCompState = (WORD)num;
1613  if ( num < 0 ) {
1614  *m++ = (WORD)(-num+1);
1615  r++;
1616  from++;
1617  ADDPOS(*position,sizeof(WORD));
1618  while ( ++num <= 0 ) *m++ = *r++;
1619  num = *from++;
1620  *to += (WORD)num;
1621  ADDPOS(*position,sizeof(WORD));
1622  *InCompState = (WORD)(num+2);
1623  }
1624  goto PastCon;
1625  }
1626 /* No caching available */
1627  LOCK(AM.storefilelock);
1628  SeekFile(AR.StoreData.Handle,position,SEEK_SET);
1629  RetCode = ReadFile(AR.StoreData.Handle,(UBYTE *)to,(LONG)sizeof(WORD));
1630  SeekFile(AR.StoreData.Handle,position,SEEK_CUR);
1631  UNLOCK(AM.storefilelock);
1632  if ( RetCode != sizeof(WORD) ) {
1633  *to = 0;
1634  return((WORD)RetCode);
1635  }
1636  if ( !*to ) return(0);
1637  m = to;
1638  if ( *to < 0 ) {
1639  num = *m++;
1640  *to = *r++ = (WORD)(-num + 1);
1641  while ( ++num <= 0 ) *m++ = *r++;
1642  LOCK(AM.storefilelock);
1643  SeekFile(AR.StoreData.Handle,position,SEEK_SET);
1644  RetCode = ReadFile(AR.StoreData.Handle,(UBYTE *)m,(LONG)sizeof(WORD));
1645  SeekFile(AR.StoreData.Handle,position,SEEK_CUR);
1646  UNLOCK(AM.storefilelock);
1647  if ( RetCode != sizeof(WORD) ) {
1648  MLOCK(ErrorMessageLock);
1649  MesPrint("@Error in compression of store file");
1650  MUNLOCK(ErrorMessageLock);
1651  return(-1);
1652  }
1653  num = *m;
1654  *to += (WORD)num;
1655  *InCompState = (WORD)(num + 2);
1656  }
1657  else {
1658  *InCompState = *to;
1659  num = *to - 1; m = to + 1; r = rr + 1;
1660  }
1661  first = num;
1662  num *= wsizeof(WORD);
1663  if ( num < 0 ) {
1664  MLOCK(ErrorMessageLock);
1665  MesPrint("@Error in stored expressions file at position %9p",position);
1666  MUNLOCK(ErrorMessageLock);
1667  return(-1);
1668  }
1669  LOCK(AM.storefilelock);
1670  SeekFile(AR.StoreData.Handle,position,SEEK_SET);
1671  RetCode = ReadFile(AR.StoreData.Handle,(UBYTE *)m,num);
1672  SeekFile(AR.StoreData.Handle,position,SEEK_CUR);
1673  UNLOCK(AM.storefilelock);
1674  if ( RetCode != num ) {
1675  MLOCK(ErrorMessageLock);
1676  MesPrint("@Error in stored expressions file at position %9p",position);
1677  MUNLOCK(ErrorMessageLock);
1678  return(-1);
1679  }
1680  NCOPY(r,m,first);
1681 PastEnd:
1682  *rr = *to;
1683  if ( r >= AR.ComprTop ) {
1684  MLOCK(ErrorMessageLock);
1685  MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
1686  MUNLOCK(ErrorMessageLock);
1687  Terminate(-1);
1688  }
1689  AR.CompressPointer = r; *r = 0;
1690  if ( !TermRenumber(to,renumber,nexpr) ) {
1691  MarkDirty(to,DIRTYSYMFLAG);
1692  if ( AR.CurDum > AM.IndDum && Expressions[nexpr].numdummies > 0 )
1693  MoveDummies(BHEAD to,AR.CurDum - AM.IndDum);
1694  return((WORD)*to);
1695  }
1696 PastErr:
1697  MLOCK(ErrorMessageLock);
1698  MesCall("GetFromStore");
1699  MUNLOCK(ErrorMessageLock);
1700  SETERROR(-1)
1701 }
1702 
1703 /*
1704  #] GetFromStore :
1705  #[ DetVars : VOID DetVars(term)
1706 
1707  Determines which variables are used in term.
1708 
1709  When par = 1 we are scanning a prototype expression which involves
1710  completely different rules.
1711 
1712 */
1713 
1714 VOID DetVars(WORD *term, WORD par)
1715 {
1716  GETIDENTITY
1717  WORD *stopper;
1718  WORD *t, sym;
1719  WORD *sarg;
1720  stopper = term + *term - 1;
1721  stopper = stopper - ABS(*stopper) + 1;
1722  term++;
1723  if ( par ) { /* Prototype expression */
1724  WORD n;
1725  if ( ( n = NumSymbols ) > 0 ) {
1726  SYMBOLS tt;
1727  tt = symbols;
1728  do {
1729  (tt++)->flags = 0;
1730  } while ( --n > 0 );
1731  }
1732  if ( ( n = NumIndices ) > 0 ) {
1733  INDICES tt;
1734  tt = indices;
1735  do {
1736  (tt++)->flags = 0;
1737  } while ( --n > 0 );
1738  }
1739  if ( ( n = NumVectors ) > 0 ) {
1740  VECTORS tt;
1741  tt = vectors;
1742  do {
1743  (tt++)->flags = 0;
1744  } while ( --n > 0 );
1745  }
1746  if ( ( n = NumFunctions ) > 0 ) {
1747  FUNCTIONS tt;
1748  tt = functions;
1749  do {
1750  (tt++)->flags = 0;
1751  } while ( --n > 0 );
1752  }
1753  term += SUBEXPSIZE;
1754  while ( term < stopper ) {
1755  if ( *term == SYMTOSYM || *term == SYMTONUM ) {
1756  term += 2;
1757  AN.UsedSymbol[*term] = 1;
1758  symbols[*term].flags = 1;
1759  }
1760  else if ( *term == VECTOVEC ) {
1761  term += 2;
1762  AN.UsedVector[*term-AM.OffsetVector] = 1;
1763  vectors[*term-AM.OffsetVector].flags = 1;
1764  }
1765  else if ( *term == INDTOIND ) {
1766  term += 2;
1767  sym = indices[*term - AM.OffsetIndex].dimension;
1768  if ( sym < 0 ) AN.UsedSymbol[-sym] = 1;
1769  AN.UsedIndex[(*term) - AM.OffsetIndex] = 1;
1770  sym = indices[*term-AM.OffsetIndex].nmin4;
1771  if ( sym < -NMIN4SHIFT ) AN.UsedSymbol[-sym-NMIN4SHIFT] = 1;
1772  indices[*term-AM.OffsetIndex].flags = 1;
1773  }
1774  else if ( *term == FUNTOFUN ) {
1775  term += 2;
1776  AN.UsedFunction[*term-FUNCTION] = 1;
1777  functions[*term-FUNCTION].flags = 1;
1778  }
1779  term += 2;
1780  }
1781  }
1782  else {
1783  while ( term < stopper ) {
1784  t = term + term[1];
1785  if ( *term == SYMBOL ) {
1786  term += 2;
1787  do {
1788  AN.UsedSymbol[*term] = 1;
1789  term += 2;
1790  } while ( term < t );
1791  }
1792  else if ( *term == DOTPRODUCT ) {
1793  term += 2;
1794  do {
1795  AN.UsedVector[(*term++) - AM.OffsetVector] = 1;
1796  AN.UsedVector[(*term) - AM.OffsetVector] = 1;
1797  term += 2;
1798  } while ( term < t );
1799  }
1800  else if ( *term == VECTOR ) {
1801  term += 2;
1802  do {
1803  AN.UsedVector[(*term++) - AM.OffsetVector] = 1;
1804  if ( *term >= AM.OffsetIndex && *term < AM.DumInd ) {
1805  sym = indices[*term - AM.OffsetIndex].dimension;
1806  if ( sym < 0 ) AN.UsedSymbol[-sym] = 1;
1807  AN.UsedIndex[*term - AM.OffsetIndex] = 1;
1808  sym = indices[(*term++)-AM.OffsetIndex].nmin4;
1809  if ( sym < -NMIN4SHIFT ) AN.UsedSymbol[-sym-NMIN4SHIFT] = 1;
1810  }
1811  else term++;
1812  } while ( term < t );
1813  }
1814  else if ( *term == INDEX || *term == LEVICIVITA || *term == GAMMA
1815  || *term == DELTA ) {
1816 /*
1817 Tensors:
1818  term += 2;
1819 */
1820  if ( *term == INDEX || *term == DELTA ) term += 2;
1821  else {
1822 Tensors:
1823  term += FUNHEAD;
1824  }
1825  while ( term < t ) {
1826  if ( *term >= AM.OffsetIndex && *term < AM.DumInd ) {
1827  sym = indices[*term - AM.OffsetIndex].dimension;
1828  if ( sym < 0 ) AN.UsedSymbol[-sym] = 1;
1829  AN.UsedIndex[(*term) - AM.OffsetIndex] = 1;
1830  sym = indices[*term-AM.OffsetIndex].nmin4;
1831  if ( sym < -NMIN4SHIFT ) AN.UsedSymbol[-sym-NMIN4SHIFT] = 1;
1832  }
1833  else if ( *term < (WILDOFFSET+AM.OffsetVector) )
1834  AN.UsedVector[(*term) - AM.OffsetVector] = 1;
1835  term++;
1836  }
1837  }
1838  else if ( *term == HAAKJE ) term = t;
1839  else {
1840  if ( *term > MAXBUILTINFUNCTION )
1841  AN.UsedFunction[(*term)-FUNCTION] = 1;
1842  if ( *term >= FUNCTION && functions[*term-FUNCTION].spec
1843  >= TENSORFUNCTION && term[1] > FUNHEAD ) goto Tensors;
1844  term += FUNHEAD; /* First argument */
1845  while ( term < t ) {
1846  sarg = term;
1847  NEXTARG(sarg)
1848  if ( *term > 0 ) {
1849  sarg = term + *term; /* End of argument */
1850  term += ARGHEAD; /* First term in argument */
1851  if ( term < sarg ) { do {
1852  DetVars(term,par);
1853  term += *term;
1854  } while ( term < sarg ); }
1855  }
1856  else {
1857  if ( *term < -MAXBUILTINFUNCTION ) {
1858  AN.UsedFunction[-*term-FUNCTION] = 1;
1859  }
1860  else if ( *term == -SYMBOL ) {
1861  AN.UsedSymbol[term[1]] = 1;
1862  }
1863  else if ( *term == -INDEX ) {
1864  if ( term[1] < (WILDOFFSET+AM.OffsetVector) ) {
1865  AN.UsedVector[term[1]-AM.OffsetVector] = 1;
1866  }
1867  else if ( term[1] >= AM.OffsetIndex && term[1] < AM.DumInd ) {
1868  sym = indices[term[1] - AM.OffsetIndex].dimension;
1869  if ( sym < 0 ) AN.UsedSymbol[-sym] = 1;
1870  AN.UsedIndex[term[1] - AM.OffsetIndex] = 1;
1871  sym = indices[term[1]-AM.OffsetIndex].nmin4;
1872  if ( sym < -NMIN4SHIFT ) AN.UsedSymbol[-sym-NMIN4SHIFT] = 1;
1873  }
1874  }
1875  else if ( *term == -VECTOR || *term == -MINVECTOR ) {
1876  AN.UsedVector[term[1]-AM.OffsetVector] = 1;
1877  }
1878  }
1879  term = sarg; /* Next argument */
1880  }
1881  term = t;
1882  }
1883  }
1884  }
1885 }
1886 
1887 /*
1888  #] DetVars :
1889  #[ ToStorage :
1890 
1891  This routine takes an expression in the scratch buffer (indicated by e)
1892  and puts it in the storage file. The necessary actions are:
1893 
1894  1: determine the list of the used variables.
1895  2: make an index entry.
1896  3: write the namelists.
1897  4: copy the 'length' bytes of the expression.
1898 
1899 */
1900 
1901 WORD ToStorage(EXPRESSIONS e, POSITION *length)
1902 {
1903  GETIDENTITY
1904  WORD *w, i, j;
1905  WORD *term;
1906  INDEXENTRY *indexent;
1907  LONG size;
1908  POSITION indexpos, scrpos;
1909  FILEHANDLE *f;
1910  if ( ( indexent = NextFileIndex(&indexpos) ) == 0 ) {
1911  MesCall("ToStorage");
1912  SETERROR(-1)
1913  }
1914  indexent->CompressSize = 0; /* thus far no compression */
1915  f = AR.infile; AR.infile = AR.outfile; AR.outfile = f;
1916  if ( e->status == HIDDENGEXPRESSION ) {
1917  AR.InHiBuf = 0; f = AR.hidefile; AR.GetFile = 2;
1918  }
1919  else {
1920  AR.InInBuf = 0; f = AR.infile; AR.GetFile = 0;
1921  }
1922  if ( f->handle >= 0 ) {
1923  scrpos = e->onfile;
1924  SeekFile(f->handle,&scrpos,SEEK_SET);
1925  if ( ISNOTEQUALPOS(scrpos,e->onfile) ) {
1926  MesPrint(":::Error in Scratch file");
1927  goto ErrReturn;
1928  }
1929  f->POposition = e->onfile;
1930  f->POfull = f->PObuffer;
1931  if ( e->status == HIDDENGEXPRESSION ) AR.InHiBuf = 0;
1932  else AR.InInBuf = 0;
1933  }
1934  else {
1935  f->POfill = (WORD *)((UBYTE *)(f->PObuffer)+BASEPOSITION(e->onfile));
1936  }
1937  w = AT.WorkPointer;
1938  AN.UsedSymbol = w; w += NumSymbols;
1939  AN.UsedVector = w; w += NumVectors;
1940  AN.UsedIndex = w; w += NumIndices;
1941  AN.UsedFunction = w; w += NumFunctions;
1942  term = w;
1943  w = (WORD *)(((UBYTE *)(w)) + AM.MaxTer);
1944  if ( w > AT.WorkTop ) {
1945  MesWork();
1946  goto ErrReturn;
1947  }
1948  w = AN.UsedSymbol;
1949  i = NumSymbols + NumVectors + NumIndices + NumFunctions;
1950  do { *w++ = 0; } while ( --i > 0 );
1951  if ( GetTerm(BHEAD term) > 0 ) {
1952  DetVars(term,1);
1953  if ( GetTerm(BHEAD term) ) {
1954  do { DetVars(term,0); } while ( GetTerm(BHEAD term) > 0 );
1955  }
1956  }
1957  j = 0;
1958  w = AN.UsedSymbol;
1959  i = NumSymbols;
1960  while ( --i >= 0 ) { if ( *w++ ) j++; }
1961  indexent->nsymbols = j;
1962 /* size = j * sizeof(struct SyMbOl); */
1963  j = 0;
1964  w = AN.UsedIndex;
1965  i = NumIndices;
1966  while ( --i >= 0 ) { if ( *w++ ) j++; }
1967  indexent->nindices = j;
1968 /* size += j * sizeof(struct InDeX); */
1969  j = 0;
1970  w = AN.UsedVector;
1971  i = NumVectors;
1972  while ( --i >= 0 ) { if ( *w++ ) j++; }
1973  indexent->nvectors = j;
1974 /* size += j * sizeof(struct VeCtOr); */
1975  j = 0;
1976  w = AN.UsedFunction;
1977  i = NumFunctions;
1978  while ( --i >= 0 ) { if ( *w++ ) j++; }
1979  indexent->nfunctions = j;
1980 /* size += j * sizeof(struct FuNcTiOn); */
1981  indexent->length = *length;
1982  indexent->variables = AR.StoreData.Fill;
1983 /* indexent->position = AR.StoreData.Fill + size; */
1984  StrCopy(AC.exprnames->namebuffer+e->name,(UBYTE *)(indexent->name));
1985  SeekFile(AR.StoreData.Handle,&(AR.StoreData.Fill),SEEK_SET);
1986  AO.wlen = 100000;
1987  AO.wpos = (UBYTE *)Malloc1(AO.wlen,"AO.wpos buffer");
1988  AO.wpoin = AO.wpos;
1989  {
1990  SYMBOLS a;
1991  w = AN.UsedSymbol;
1992  a = symbols;
1993  j = 0;
1994  i = indexent->nsymbols;
1995  while ( --i >= 0 ) {
1996  while ( !*w ) { w++; a++; j++; }
1997  a->number = j;
1998  if ( VarStore((UBYTE *)a,(WORD)(sizeof(struct SyMbOl)),a->name,
1999  a->namesize) ) goto ErrToSto;
2000  w++; j++; a++;
2001  }
2002  }
2003  {
2004  INDICES a;
2005  w = AN.UsedIndex;
2006  a = indices;
2007  j = 0;
2008  i = indexent->nindices;
2009  while ( --i >= 0 ) {
2010  while ( !*w ) { w++; a++; j++; }
2011  a->number = j;
2012  if ( VarStore((UBYTE *)a,(WORD)(sizeof(struct InDeX)),a->name,
2013  a->namesize) ) goto ErrToSto;
2014  w++; j++; a++;
2015  }
2016  }
2017  {
2018  VECTORS a;
2019  w = AN.UsedVector;
2020  a = vectors;
2021  j = 0;
2022  i = indexent->nvectors;
2023  while ( --i >= 0 ) {
2024  while ( !*w ) { w++; a++; j++; }
2025  a->number = j;
2026  if ( VarStore((UBYTE *)a,(WORD)(sizeof(struct VeCtOr)),a->name,
2027  a->namesize) ) goto ErrToSto;
2028  w++; j++; a++;
2029  }
2030  }
2031  {
2032  FUNCTIONS a;
2033  w = AN.UsedFunction;
2034  a = functions;
2035  j = 0;
2036  i = indexent->nfunctions;
2037  while ( --i >= 0 ) {
2038  while ( !*w ) { w++; a++; j++; }
2039  a->number = j;
2040  if ( VarStore((UBYTE *)a,(WORD)(sizeof(struct FuNcTiOn)),a->name,
2041  a->namesize) ) goto ErrToSto;
2042  w++; a++; j++;
2043  }
2044  }
2045  if ( VarStore((UBYTE *)0L,(WORD)0,(WORD)0,(WORD)0) ) goto ErrToSto; /* Flush buffer */
2046  TELLFILE(AR.StoreData.Handle,&(indexent->position));
2047  indexent->size = (WORD)DIFBASE(indexent->position,indexent->variables);
2048 /*
2049  The following code was added when it became apparent (30-jan-2007)
2050  that we need provisions for extra space without upsetting existing
2051  .sav files. Here we can put as much as we want.
2052  Look in GetTable on how to recover numdummies.
2053  Forgetting numdummies has been in there from the beginning.
2054 */
2055  if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&(e->numdummies)),(LONG)sizeof(WORD)) !=
2056  sizeof(WORD) ) {
2057  MesPrint("Error while writing storage file");
2058  goto ErrReturn;
2059  }
2060  if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&(e->numfactors)),(LONG)sizeof(WORD)) !=
2061  sizeof(WORD) ) {
2062  MesPrint("Error while writing storage file");
2063  goto ErrReturn;
2064  }
2065  if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&(e->vflags)),(LONG)sizeof(WORD)) !=
2066  sizeof(WORD) ) {
2067  MesPrint("Error while writing storage file");
2068  goto ErrReturn;
2069  }
2070  TELLFILE(AR.StoreData.Handle,&(indexent->position));
2071  if ( f->handle >= 0 ) {
2072  POSITION llength;
2073  llength = *length;
2074  SeekFile(f->handle,&(e->onfile),SEEK_SET);
2075  while ( ISPOSPOS(llength) ) {
2076  SETBASEPOSITION(scrpos,AO.wlen);
2077  if ( ISLESSPOS(llength,scrpos) ) size = BASEPOSITION(llength);
2078  else size = AO.wlen;
2079  if ( ReadFile(f->handle,AO.wpos,size) != size ) {
2080  MesPrint("Error while reading scratch file");
2081  goto ErrReturn;
2082  }
2083  if ( WriteFile(AR.StoreData.Handle,AO.wpos,size) != size ) {
2084  MesPrint("Error while writing storage file");
2085  goto ErrReturn;
2086  }
2087  ADDPOS(llength,-size);
2088  }
2089  }
2090  else {
2091  WORD *ppp;
2092  ppp = (WORD *)((UBYTE *)(f->PObuffer) + BASEPOSITION(e->onfile));
2093  if ( WriteFile(AR.StoreData.Handle,(UBYTE *)ppp,BASEPOSITION(*length)) !=
2094  BASEPOSITION(*length) ) {
2095  MesPrint("Error while writing storage file");
2096  goto ErrReturn;
2097  }
2098  }
2099  ADD2POS(*length,indexent->position);
2100  e->onfile = indexpos;
2101 /*
2102  AR.StoreData.Fill = SeekFile(AR.StoreData.Handle,&(AM.zeropos),SEEK_END);
2103 */
2104  AR.StoreData.Fill = *length;
2105  SeekFile(AR.StoreData.Handle,&(AR.StoreData.Fill),SEEK_SET);
2106  scrpos = AR.StoreData.Position;
2107  ADDPOS(scrpos,sizeof(POSITION));
2108  SeekFile(AR.StoreData.Handle,&scrpos,SEEK_SET);
2109  if ( WriteFile(AR.StoreData.Handle,((UBYTE *)&(AR.StoreData.Index.number))
2110  ,(LONG)(sizeof(POSITION))) != sizeof(POSITION) ) goto ErrInSto;
2111  SeekFile(AR.StoreData.Handle,&indexpos,SEEK_SET);
2112  if ( WriteFile(AR.StoreData.Handle,(UBYTE *)indexent,(LONG)(sizeof(INDEXENTRY))) !=
2113  sizeof(INDEXENTRY) ) goto ErrInSto;
2114  FlushFile(AR.StoreData.Handle);
2115  SeekFile(AR.StoreData.Handle,&(AC.StoreFileSize),SEEK_END);
2116  f = AR.infile; AR.infile = AR.outfile; AR.outfile = f;
2117  if ( AO.wpos ) M_free(AO.wpos,"AO.wpos buffer");
2118  AO.wpos = AO.wpoin = 0;
2119  return(0);
2120 ErrToSto:
2121  MesPrint("---Error while storing namelists");
2122  goto ErrReturn;
2123 ErrInSto:
2124  MesPrint("Error in storage");
2125 ErrReturn:
2126  if ( AO.wpos ) M_free(AO.wpos,"AO.wpos buffer");
2127  AO.wpos = AO.wpoin = 0;
2128  f = AR.infile; AR.infile = AR.outfile; AR.outfile = f;
2129  return(-1);
2130 }
2131 
2132 /*
2133  #] ToStorage :
2134  #[ NextFileIndex :
2135 */
2136 
2137 INDEXENTRY *NextFileIndex(POSITION *indexpos)
2138 {
2139  GETIDENTITY
2140  INDEXENTRY *ind;
2141  int i, j = sizeof(FILEINDEX)/(sizeof(LONG));
2142  LONG *lo;
2143  if ( AR.StoreData.Handle <= 0 ) {
2144  if ( SetFileIndex() ) {
2145  MesCall("NextFileIndex");
2146  return(0);
2147  }
2148  SETBASEPOSITION(AR.StoreData.Index.number,1);
2149 #ifdef SYSDEPENDENTSAVE
2150  SETBASEPOSITION(*indexpos,(2*sizeof(POSITION)));
2151 #else
2152  SETBASEPOSITION(*indexpos,(2*sizeof(POSITION)+sizeof(STOREHEADER)));
2153 #endif
2154  return(AR.StoreData.Index.expression);
2155  }
2156  while ( BASEPOSITION(AR.StoreData.Index.number) >= (LONG)(INFILEINDEX) ) {
2157  if ( ISNOTZEROPOS(AR.StoreData.Index.next) ) {
2158  SeekFile(AR.StoreData.Handle,&(AR.StoreData.Index.next),SEEK_SET);
2159  AR.StoreData.Position = AR.StoreData.Index.next;
2160  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)(&AR.StoreData.Index),(LONG)(sizeof(FILEINDEX))) !=
2161  (LONG)(sizeof(FILEINDEX)) ) goto ErrNextS;
2162  }
2163  else {
2164  PUTZERO(AR.StoreData.Index.number);
2165  SeekFile(AR.StoreData.Handle,&(AR.StoreData.Position),SEEK_SET);
2166  if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&(AR.StoreData.Fill)),(LONG)(sizeof(POSITION)))
2167  != (LONG)(sizeof(POSITION)) ) goto ErrNextS;
2168  PUTZERO(AR.StoreData.Index.next);
2169  SeekFile(AR.StoreData.Handle,&(AR.StoreData.Fill),SEEK_SET);
2170  AR.StoreData.Position = AR.StoreData.Fill;
2171  lo = (LONG *)(&AR.StoreData.Index);
2172  for ( i = 0; i < j; i++ ) *lo++ = 0;
2173  if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&AR.StoreData.Index),(LONG)(sizeof(FILEINDEX))) !=
2174  (LONG)(sizeof(FILEINDEX)) ) goto ErrNextS;
2175  ADDPOS(AR.StoreData.Fill,sizeof(FILEINDEX));
2176  }
2177  }
2178  *indexpos = AR.StoreData.Position;
2179  ADDPOS(*indexpos,(2*sizeof(POSITION)) +
2180  BASEPOSITION(AR.StoreData.Index.number) * sizeof(INDEXENTRY));
2181  ind = &AR.StoreData.Index.expression[BASEPOSITION(AR.StoreData.Index.number)];
2182  ADDPOS(AR.StoreData.Index.number,1);
2183  return(ind);
2184 ErrNextS:
2185  MesPrint("Error in storage file");
2186  return(0);
2187 }
2188 
2189 /*
2190  #] NextFileIndex :
2191  #[ SetFileIndex :
2192 */
2193 
2201 {
2202  GETIDENTITY
2203  int i, j = sizeof(FILEINDEX)/(sizeof(LONG));
2204  LONG *lo;
2205  if ( AR.StoreData.Handle < 0 ) {
2206  AR.StoreData.Handle = AC.StoreHandle;
2207  PUTZERO(AR.StoreData.Index.next);
2208  PUTZERO(AR.StoreData.Index.number);
2209 #ifdef SYSDEPENDENTSAVE
2210  SETBASEPOSITION(AR.StoreData.Fill,sizeof(FILEINDEX));
2211 #else
2212  if ( WriteStoreHeader(AR.StoreData.Handle) ) return(MesPrint("Error writing storage file header"));
2213  SETBASEPOSITION(AR.StoreData.Fill, (LONG)sizeof(FILEINDEX)+(LONG)sizeof(STOREHEADER));
2214 #endif
2215  lo = (LONG *)(&AR.StoreData.Index);
2216  for ( i = 0; i < j; i++ ) *lo++ = 0;
2217  if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&AR.StoreData.Index),(LONG)(sizeof(FILEINDEX))) !=
2218  (LONG)(sizeof(FILEINDEX)) ) return(MesPrint("Error writing storage file"));
2219  }
2220  else {
2221  POSITION scrpos;
2222 #ifdef SYSDEPENDENTSAVE
2223  PUTZERO(scrpos);
2224 #else
2225  SETBASEPOSITION(scrpos, (LONG)(sizeof(STOREHEADER)));
2226 #endif
2227  SeekFile(AR.StoreData.Handle,&scrpos,SEEK_SET);
2228  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)(&AR.StoreData.Index),(LONG)(sizeof(FILEINDEX))) !=
2229  (LONG)(sizeof(FILEINDEX)) ) return(MesPrint("Error reading storage file"));
2230  }
2231 #ifdef SYSDEPENDENTSAVE
2232  PUTZERO(AR.StoreData.Position);
2233 #else
2234  SETBASEPOSITION(AR.StoreData.Position, (LONG)(sizeof(STOREHEADER)));
2235 #endif
2236  return(0);
2237 }
2238 
2239 /*
2240  #] SetFileIndex :
2241  #[ VarStore :
2242 
2243  The n -= sizeof(WORD); makes that the real length comes in the
2244  padding space, provided there is padding space (it seems so).
2245  The reading of the information assumes this is the case and hence
2246  things work....
2247 */
2248 
2249 WORD VarStore(UBYTE *s, WORD n, WORD name, WORD namesize)
2250 {
2251  GETIDENTITY
2252  UBYTE *t, *u;
2253  if ( s ) {
2254  n -= sizeof(WORD);
2255  t = (UBYTE *)AO.wpoin;
2256 /*
2257  u = (UBYTE *)AT.WorkTop;
2258 */
2259  u = AO.wpos+AO.wlen;
2260  while ( n > 0 && t < u ) { *t++ = *s++; n--; }
2261  while ( t >= u ) {
2262  if ( WriteFile(AR.StoreData.Handle,AO.wpos,AO.wlen) != AO.wlen ) return(-1);
2263  t = AO.wpos;
2264  while ( n > 0 && t < u ) { *t++ = *s++; n--; }
2265  }
2266  s = AC.varnames->namebuffer + name;
2267  n = namesize;
2268  n += sizeof(void *)-1; n &= -(sizeof(void *));
2269  *((WORD *)t) = n;
2270  t += sizeof(WORD);
2271  while ( n > 0 && t < u ) {
2272  if ( namesize > 0 ) { *t++ = *s++; namesize--; }
2273  else { *t++ = 0; }
2274  n--;
2275  }
2276  while ( t >= u ) {
2277  if ( WriteFile(AR.StoreData.Handle,AO.wpos,AO.wlen) != AO.wlen ) return(-1);
2278  t = AO.wpos;
2279  while ( n > 0 && t < u ) {
2280  if ( namesize > 0 ) { *t++ = *s++; namesize--; }
2281  else { *t++ = 0; }
2282  n--;
2283  }
2284  }
2285  AO.wpoin = t;
2286  }
2287  else {
2288  LONG size;
2289  size = AO.wpoin - AO.wpos;
2290  if ( WriteFile(AR.StoreData.Handle,AO.wpos,size) != size ) return(-1);
2291  AO.wpoin = AO.wpos;
2292  }
2293  return(0);
2294 }
2295 
2296 /*
2297  #] VarStore :
2298  #[ TermRenumber :
2299 
2300  renumbers the variables inside term according to the information
2301  in struct renumber.
2302  The search is binary. This avoided having to read/write the
2303  expression twice when it was stored.
2304 
2305 */
2306 
2307 WORD TermRenumber(WORD *term, RENUMBER renumber, WORD nexpr)
2308 {
2309  WORD *stopper;
2314  WORD *t, *sarg, n;
2315  stopper = term + *term - 1;
2316  stopper = stopper - ABS(*stopper) + 1;
2317  term++;
2318  while ( term < stopper ) {
2322  if ( *term == SYMBOL ) {
2323  t = term + term[1];
2324  term += 2;
2325  do {
2326  if ( ( n = FindrNumber(*term,&(renumber->symb)) ) < 0 ) goto ErrR;
2327  *term = renumber->symnum[n];
2328  term += 2;
2329  } while ( term < t );
2330  }
2331  else if ( *term == DOTPRODUCT ) {
2332  t = term + term[1];
2333  term += 2;
2334  do {
2335  if ( ( n = FindrNumber(*term,&(renumber->vect)) )
2336  < 0 ) goto ErrR;
2337  *term++ = renumber->vecnum[n];
2338  if ( ( n = FindrNumber(*term,&(renumber->vect)) )
2339  < 0 ) goto ErrR;
2340  *term = renumber->vecnum[n];
2341  term += 2;
2342  } while ( term < t );
2343  }
2344  else if ( *term == VECTOR ) {
2345  t = term + term[1];
2346  term += 2;
2347  do {
2348  if ( ( n = FindrNumber(*term,&(renumber->vect)) )
2349  < 0 ) goto ErrR;
2350  *term++ = renumber->vecnum[n];
2351  if ( ( *term >= AM.OffsetIndex ) && ( *term < AM.IndDum ) ) {
2352  if ( ( n = FindrNumber(*term,&(renumber->indi)) )
2353  < 0 ) goto ErrR;
2354  *term++ = renumber->indnum[n];
2355  }
2356  else term++;
2357  } while ( term < t );
2358  }
2359  else if ( *term == INDEX || *term == LEVICIVITA || *term == GAMMA
2360  || *term == DELTA ) {
2361 Tensors:
2362  t = term + term[1];
2363  if ( *term == INDEX || * term == DELTA ) term += 2;
2364  else term += FUNHEAD;
2365 /*
2366  term += 2;
2367 */
2368  while ( term < t ) {
2369  if ( *term >= AM.OffsetIndex + WILDOFFSET ) {
2370 /*
2371  Still TOBEDONE
2372 */
2373  }
2374  else if ( ( *term >= AM.OffsetIndex ) && ( *term < AM.IndDum ) ) {
2375  if ( ( n = FindrNumber(*term,&(renumber->indi)) )
2376  < 0 ) goto ErrR;
2377  *term = renumber->indnum[n];
2378  }
2379  else if ( *term < (WILDOFFSET+AM.OffsetVector) ) {
2380  if ( ( n = FindrNumber(*term,&(renumber->vect)) )
2381  < 0 ) goto ErrR;
2382  *term = renumber->vecnum[n];
2383  }
2384  term++;
2385  }
2386  }
2387  else if ( *term == HAAKJE ) term += term[1];
2388  else {
2389  if ( *term > MAXBUILTINFUNCTION ) {
2390  if ( ( n = FindrNumber(*term,&(renumber->func)) )
2391  < 0 ) goto ErrR;
2392  *term = renumber->funnum[n];
2393  }
2394  if ( *term >= FUNCTION && functions[*term-FUNCTION].spec
2395  >= TENSORFUNCTION && term[1] > FUNHEAD ) goto Tensors;
2396  t = term + term[1]; /* General stopper */
2397  term += FUNHEAD; /* First argument */
2398  while ( term < t ) {
2399  sarg = term;
2400  NEXTARG(sarg)
2401  if ( *term > 0 ) {
2402 /*
2403  Problem here:
2404  Marking the argument as dirty attacks the heap
2405  very heavily and costs much computer time.
2406 */
2407  *++term = 1;
2408  term += ARGHEAD-1;
2409  while ( term < sarg ) {
2410  if ( TermRenumber(term,renumber,nexpr) ) goto ErrR;
2411  term += *term;
2412  }
2413  }
2414  else {
2415  if ( *term <= -MAXBUILTINFUNCTION ) {
2416  if ( ( n = FindrNumber(-*term,&(renumber->func)) )
2417  < 0 ) goto ErrR;
2418  *term = -renumber->funnum[n];
2419  }
2420  else if ( *term == -SYMBOL ) {
2421  term++;
2422  if ( ( n = FindrNumber(*term,
2423  &(renumber->symb)) ) < 0 ) goto ErrR;
2424  *term = renumber->symnum[n];
2425  }
2426  else if ( *term == -INDEX ) {
2427  term++;
2428  if ( *term >= AM.OffsetIndex + WILDOFFSET ) {
2429 /*
2430  Still TOBEDONE
2431 */
2432  }
2433  else if ( ( *term >= AM.OffsetIndex ) && ( *term < AM.IndDum ) ) {
2434  if ( ( n = FindrNumber(*term,&(renumber->indi)) )
2435  < 0 ) goto ErrR;
2436  *term = renumber->indnum[n];
2437  }
2438  else if ( *term < (WILDOFFSET+AM.OffsetVector) ) {
2439  if ( ( n = FindrNumber(*term,&(renumber->vect)) )
2440  < 0 ) goto ErrR;
2441  *term = renumber->vecnum[n];
2442  }
2443  }
2444  else if ( *term == -VECTOR || *term == -MINVECTOR ) {
2445  term++;
2446  if ( ( n = FindrNumber(*term,&(renumber->vect)) )
2447  < 0 ) goto ErrR;
2448  *term = renumber->vecnum[n];
2449  }
2450  }
2451  term = sarg; /* Next argument */
2452  }
2453  term = t;
2454  }
2455  }
2456  return(0);
2457 ErrR:
2458  MesCall("TermRenumber");
2459  SETERROR(-1)
2460 }
2461 
2462 /*
2463  #] TermRenumber :
2464  #[ FindrNumber :
2465 */
2466 
2467 WORD FindrNumber(WORD n, VARRENUM *v)
2468 {
2469  WORD *hi,*med,*lo;
2470  hi = v->hi;
2471  lo = v->lo;
2472  med = v->start;
2473  if ( *hi == 0 ) {
2474  if ( n != *hi ) {
2475  MesPrint("Serious problems coming up in FindrNumber");
2476  return(-1);
2477  }
2478  return(*hi);
2479  }
2480  while ( *med != n ) {
2481  if ( *med < n ) {
2482  if ( med == hi ) goto ErrFindr;
2483  lo = med;
2484  med = hi - ((WORDDIF(hi,med))/2);
2485  }
2486  else {
2487  if ( med == lo ) goto ErrFindr;
2488  hi = med;
2489  med = lo + ((WORDDIF(med,lo))/2);
2490  }
2491  }
2492  return(WORDDIF(med,v->lo));
2493 ErrFindr:
2494 /*
2495  Reconstruction:
2496 */
2497  {
2498  int i;
2499  i = WORDDIF(v->hi,v->lo);
2500  MesPrint("FindrNumber: n = %d, list has %d members",n,i);
2501  while ( i >= 0 ) {
2502  MesPrint("v->lo[%d] = %d",i,v->lo[i]); i--;
2503  }
2504  hi = v->hi;
2505  lo = v->lo;
2506  med = v->start;
2507  MesPrint("Start with %d,%d,%d",0,WORDDIF(med,v->lo),WORDDIF(hi,v->lo));
2508  while ( *med != n ) {
2509  if ( *med < n ) {
2510  if ( med == hi ) goto ErrFindr2;
2511  lo = med;
2512  med = hi - ((WORDDIF(hi,med))/2);
2513  }
2514  else {
2515  if ( med == lo ) goto ErrFindr2;
2516  hi = med;
2517  med = ((WORDDIF(med,lo))/2) + lo;
2518  }
2519  MesPrint("New: %d,%d,%d, *med = %d",WORDDIF(lo,v->lo),WORDDIF(med,v->lo),WORDDIF(hi,v->lo),*med);
2520  }
2521  }
2522  return(WORDDIF(med,v->lo));
2523 ErrFindr2:
2524  return(MesPrint("Renumbering problems"));
2525 }
2526 
2527 /*
2528  #] FindrNumber :
2529  #[ FindInIndex :
2530 
2531  Finds an expression in the storage index if it exists.
2532  If found it returns a pointer to the index entry, otherwise zero.
2533  par = 0 Search by address (--> f == &AR.StoreData, called by GetTable, CoSave )
2534  par = 1 Search by name (--> f == &AO.SaveData, called by CoLoad )
2535 
2536  When comparing parameter fields the parameters of the expression
2537  to be searched are in AT.TMaddr. This includes the primary expression
2538  and a possible FROMBRAC information. The FROMBRAC is always last.
2539 
2540  The parameter mode tells whether we should worry about arguments of
2541  a stored expression.
2542 */
2543 
2544 INDEXENTRY *FindInIndex(WORD expr, FILEDATA *f, WORD par, WORD mode)
2545 {
2546  GETIDENTITY
2547  INDEXENTRY *ind;
2548  WORD i, hand, *m;
2549  WORD *start, *stop, *stop2, *m2, nomatch = 0;
2550  POSITION stindex, indexpos, scrpos;
2551  LONG number, num;
2552  stindex = f->Position;
2553  m = AT.TMaddr;
2554  stop = m + m[1];
2555  m += SUBEXPSIZE;
2556  start = m;
2557  while ( m < stop ) {
2558  if ( *m == FROMBRAC || *m == WILDCARDS ) break;
2559  m += m[1];
2560  }
2561  stop = m;
2562  if ( !par ) hand = AR.StoreData.Handle;
2563  else hand = AO.SaveData.Handle;
2564  for(;;) {
2565  if ( ( i = (WORD)BASEPOSITION(f->Index.number) ) != 0 ) {
2566  indexpos = f->Position;
2567  ADDPOS(indexpos,(2*sizeof(POSITION)));
2568  ind = f->Index.expression;
2569  do {
2570  if ( ( !par && ISEQUALPOS(indexpos,Expressions[expr].onfile) )
2571  || ( par && !StrCmp(EXPRNAME(expr),(UBYTE *)(ind->name)) ) ) {
2572  nomatch = 1;
2573 /*
2574 MesPrint("index: position: %8p",&(ind->position));
2575 MesPrint("index: length: %8p",&(ind->length));
2576 MesPrint("index: variables: %8p",&(ind->variables));
2577 MesPrint("index: nsymbols: %d",ind->nsymbols);
2578 MesPrint("index: nindices: %d",ind->nindices);
2579 MesPrint("index: nvectors: %d",ind->nvectors);
2580 MesPrint("index: nfunctions: %d",ind->nfunctions);
2581 MesPrint("index: size: %d",ind->size);
2582 */
2583  if ( par ) return(ind);
2584  scrpos = ind->position;
2585  SeekFile(hand,&scrpos,SEEK_SET);
2586  if ( ISNOTEQUALPOS(scrpos,ind->position) ) goto ErrGt2;
2587  if ( ReadFile(hand,(UBYTE *)AT.WorkPointer,(LONG)sizeof(WORD)) !=
2588  sizeof(WORD) || !*AT.WorkPointer ) goto ErrGt2;
2589  num = *AT.WorkPointer - 1;
2590  num *= wsizeof(WORD);
2591  if ( *AT.WorkPointer < 0 ||
2592  ReadFile(hand,(UBYTE *)(AT.WorkPointer+1),num) != num ) goto ErrGt2;
2593  m = start; /* start of parameter field to be searched */
2594  m2 = AT.WorkPointer + 1;
2595  stop2 = m2 + m2[1];
2596  m2 += SUBEXPSIZE;
2597  while ( m < stop && m2 < stop2 ) {
2598  if ( *m == SYMBOL ) {
2599  if ( *m2 != SYMTOSYM ) break;
2600  m2[3] = m[2];
2601  }
2602  else if ( *m == INDEX ) {
2603  if ( m[2] >= 0 ) {
2604  if ( *m2 != INDTOIND ) break;
2605  }
2606  else {
2607  if ( *m2 != VECTOVEC ) break;
2608  }
2609  m2[3] = m[2];
2610  }
2611  else if ( *m >= FUNCTION ) {
2612  if ( *m2 != FUNTOFUN ) break;
2613  m2[3] = *m;
2614  }
2615  else {}
2616  m += m[1];
2617  m2 += m2[1];
2618  }
2619  if ( ( m >= stop && m2 >= stop2 ) || mode == 0 ) {
2620  AT.WorkPointer = stop2;
2621 
2622  return(ind);
2623  }
2624  }
2625  ind++;
2626  ADDPOS(indexpos,sizeof(INDEXENTRY));
2627  } while ( --i > 0 );
2628  }
2629  f->Position = f->Index.next;
2630 #ifndef SYSDEPENDENTSAVE
2631  if ( !ISNOTZEROPOS(f->Position) ) ADDPOS(f->Position,sizeof(STOREHEADER));
2632  number = sizeof(struct FiLeInDeX);
2633 #endif
2634  if ( ISEQUALPOS(f->Position,stindex) && !AO.bufferedInd ) goto ErrGetTab;
2635  if ( !par ) {
2636  SeekFile(AR.StoreData.Handle,&(f->Position),SEEK_SET);
2637  if ( ISNOTEQUALPOS(f->Position,AR.StoreData.Position) ) goto ErrGt2;
2638 #ifndef SYSDEPENDENTSAVE
2639  if ( ReadFile(f->Handle, (UBYTE *)(&(f->Index)), number) != number ) goto ErrGt2;
2640 #endif
2641  }
2642  else {
2643  SeekFile(AO.SaveData.Handle,&(f->Position),SEEK_SET);
2644  if ( ISNOTEQUALPOS(f->Position,AO.SaveData.Position) ) goto ErrGt2;
2645 #ifndef SYSDEPENDENTSAVE
2646  if ( ReadSaveIndex(&f->Index) ) goto ErrGt2;
2647 #endif
2648  }
2649 #ifdef SYSDEPENDENTSAVE
2650  number = sizeof(struct FiLeInDeX);
2651  if ( ReadFile(f->Handle,(UBYTE *)(&(f->Index)),number) !=
2652  number ) goto ErrGt2;
2653 #endif
2654  }
2655 ErrGetTab:
2656  if ( nomatch ) {
2657  MesPrint("Parameters of expression %s don't match."
2658  ,EXPRNAME(expr));
2659  }
2660  else {
2661  MesPrint("Cannot find expression %s",EXPRNAME(expr));
2662  }
2663  return(0);
2664 ErrGt2:
2665  MesPrint("Readerror in IndexSearch");
2666  return(0);
2667 }
2668 
2669 /*
2670  #] FindInIndex :
2671  #[ GetTable :
2672 
2673  Locates stored files and constructs the renumbering tables.
2674  They are allocated in the WorkSpace.
2675  First the expression data are located. The Index is treated
2676  as a circularly linked buffer which is paged forwardly.
2677  If the indexentry is located (in ind) the two renumber tables
2678  have to be constructed.
2679  Finally the prototype has to be put in the proper buffer, so
2680  that wildcards can be passed. There should be a test with
2681  an already existing prototype that is constructed by the
2682  pattern matcher. This has not been put in yet.
2683 
2684  There is a problem with the parallel processing.
2685  Feeding in the variables that were erased by a .store could in
2686  principle happen in different orders (ParFORM) or simultaneously
2687  (TFORM). The proper resolution is to have the compiler call GetTable
2688  when a stored expression is encountered.
2689 
2690  This has been mended in development of TFORM by reading the
2691  symbol tables during compilation. See the call to GetTable
2692  in the CodeGenerator.
2693 
2694  Next is the problem of FindInIndex which writes in AR.StoreData
2695  Copying this is expensive!
2696 
2697  This Doesn't work well for TFORM yet.!!!!!!!!
2698  e[x1,x2] versus e[x2,x1] messes up.
2699  For the rest is the reloading during execution not thread safe.
2700 
2701  The parameter mode tells whether we should worry about arguments
2702  of a stored expression.
2703 */
2704 
2705 RENUMBER GetTable(WORD expr, POSITION *position, WORD mode)
2706 {
2707  GETIDENTITY
2708  WORD i, j;
2709  WORD *w;
2710  RENUMBER r;
2711  LONG num, nsize, xx;
2712  WORD jsym, jind, jvec, jfun;
2713  WORD k, type, error = 0, *oldw, *neww, *oldwork = AT.WorkPointer;
2714  struct SyMbOl SyM;
2715  struct InDeX InD;
2716  struct VeCtOr VeC;
2717  struct FuNcTiOn FuN;
2718  INDEXENTRY *ind;
2719 /*
2720  Prepare for FindInIndex to put the prototype in the WorkSpace.
2721  oldw will point at the "wildcards"
2722 */
2723 /*
2724  Bug fix. Look also in Generator.
2725 #ifndef WITHPTHREADS
2726 
2727  if ( ( r = Expressions[expr].renum ) != 0 ) { }
2728  else {
2729  Expressions[expr].renum =
2730  r = (RENUMBER)Malloc1(sizeof(struct ReNuMbEr),"Renumber");
2731  }
2732 #else
2733  r = (RENUMBER)Malloc1(sizeof(struct ReNuMbEr),"Renumber");
2734 #endif
2735 */
2736  r = (RENUMBER)Malloc1(sizeof(struct ReNuMbEr),"Renumber");
2737 
2738  oldw = AT.WorkPointer + 1 + SUBEXPSIZE;
2739 /*
2740  The protoype is loaded in the WorkSpace by the Index routine.
2741  After all it has to find an occurrence with the proper arguments.
2742  This sets the WorkPointer. Hence be careful now.
2743 */
2744  LOCK(AM.storefilelock);
2745  if ( ( ind = FindInIndex(expr,&AR.StoreData,0,mode) ) == 0 ) {
2746  UNLOCK(AM.storefilelock);
2747  return(0);
2748  }
2749 
2750  xx = ind->nsymbols+ind->nindices+ind->nvectors+ind->nfunctions;
2751  if ( xx == 0 ) {
2752  Expressions[expr].renumlists =
2753  w = AN.dummyrenumlist;
2754  }
2755  else {
2756 /*
2757 #ifndef WITHPTHREADS
2758  Expressions[expr].renumlists =
2759 #endif
2760 */
2761  w = (WORD *)Malloc1(sizeof(WORD)*(xx*2),"VarSpace");
2762  }
2763  r->symb.lo = w;
2764  r->symb.start = w + ind->nsymbols/2;
2765  w += ind->nsymbols;
2766  r->symb.hi = w - 1;
2767  r->symnum = w;
2768  w += ind->nsymbols;
2769 
2770  r->indi.lo = w;
2771  r->indi.start = w + ind->nindices/2;
2772  w += ind->nindices;
2773  r->indi.hi = w - 1;
2774  r->indnum = w;
2775  w += ind->nindices;
2776 
2777  r->vect.lo = w;
2778  r->vect.start = w + ind->nvectors/2;
2779  w += ind->nvectors;
2780  r->vect.hi = w - 1;
2781  r->vecnum = w;
2782  w += ind->nvectors;
2783 
2784  r->func.lo = w;
2785  r->func.start = w + ind->nfunctions/2;
2786  w += ind->nfunctions;
2787  r->func.hi = w - 1;
2788  r->funnum = w;
2789 /* w += ind->nfunctions; */
2790 
2791  SeekFile(AR.StoreData.Handle,&(ind->variables),SEEK_SET);
2792  *position = ind->position;
2793  jsym = ind->nsymbols;
2794  jvec = ind->nvectors;
2795  jind = ind->nindices;
2796  jfun = ind->nfunctions;
2797 /*
2798  #[ Symbols :
2799 */
2800  {
2801  SYMBOLS s = &SyM;
2802  w = r->symb.lo; j = jsym;
2803  for ( i = 0; i < j; i++ ) {
2804  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)s,(LONG)(sizeof(struct SyMbOl)))
2805  != sizeof(struct SyMbOl) ) goto ErrGt2;
2806  nsize = s->namesize; nsize += sizeof(void *)-1;
2807  nsize &= -sizeof(void *);
2808  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)(AT.WorkPointer),nsize)
2809  != nsize ) goto ErrGt2;
2810  *w = s->number;
2811  if ( s->flags ) {
2812  /* Find the replacement. It must exist! */
2813  neww = oldw;
2814  while ( *neww != SYMTOSYM || neww[2] != *w ) neww += neww[1];
2815  k = neww[3];
2816  }
2817  else if ( GetVar((UBYTE *)AT.WorkPointer,&type,&k,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
2818  if ( type != CSYMBOL ) {
2819  MesPrint("Error: Conflicting types for %s",(AT.WorkPointer));
2820  error = -1;
2821  }
2822  else {
2823  if ( ( s->complex & (VARTYPEIMAGINARY|VARTYPECOMPLEX) ) !=
2824  ( symbols[k].complex & (VARTYPEIMAGINARY|VARTYPECOMPLEX) ) ) {
2825  MesPrint("Warning: Conflicting complexity for %s",AT.WorkPointer);
2826  error = -1;
2827  }
2828  if ( ( s->complex & (VARTYPEROOTOFUNITY) ) !=
2829  ( symbols[k].complex & (VARTYPEROOTOFUNITY) ) ) {
2830  MesPrint("Warning: Conflicting root of unity properties for %s",AT.WorkPointer);
2831  error = -1;
2832  }
2833  if ( ( s->complex & VARTYPEROOTOFUNITY ) == VARTYPEROOTOFUNITY ) {
2834  if ( s->maxpower != symbols[k].maxpower ) {
2835  MesPrint("Warning: Conflicting n in n-th root of unity properties for %s",AT.WorkPointer);
2836  error = -1;
2837  }
2838  }
2839  else if ( ( s->minpower !=
2840  symbols[k].minpower || s->maxpower !=
2841  symbols[k].maxpower ) && AC.WarnFlag ) {
2842  MesPrint("Warning: Conflicting power restrictions for %s",AT.WorkPointer);
2843  }
2844  }
2845  }
2846  else {
2847  if ( ( k = EntVar(CSYMBOL,(UBYTE *)(AT.WorkPointer),s->complex,s->minpower,
2848  s->maxpower,s->dimension) ) < 0 ) goto GetTcall;
2849  }
2850  *(w+j) = k;
2851  w++;
2852  }
2853  }
2854 /*
2855  #] Symbols :
2856  #[ Indices :
2857 */
2858  {
2859  INDICES s = &InD;
2860  w = r->indi.lo; j = jind;
2861  for ( i = 0; i < j; i++ ) {
2862  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)s,(LONG)(sizeof(struct InDeX)))
2863  != sizeof(struct InDeX) ) goto ErrGt2;
2864  nsize = s->namesize; nsize += sizeof(void *)-1;
2865  nsize &= -sizeof(void *);
2866  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)(AT.WorkPointer),nsize)
2867  != nsize ) goto ErrGt2;
2868  *w = s->number + AM.OffsetIndex;
2869  if ( s->dimension < 0 ) { /* Relabel the dimension */
2870  s->dimension = -r->symnum[FindrNumber(-s->dimension,&(r->symb))];
2871  if ( s->nmin4 < -NMIN4SHIFT ) { /* Relabel n-4 */
2872  s->nmin4 = -r->symnum[FindrNumber(-s->nmin4-NMIN4SHIFT
2873  ,&(r->symb))]-NMIN4SHIFT;
2874  }
2875  }
2876  if ( s->flags ) {
2877  /* Find the replacement. It must exist! */
2878  neww = oldw;
2879  while ( *neww != INDTOIND || neww[2] != *w ) neww += neww[1];
2880  k = neww[3] - AM.OffsetIndex;
2881  }
2882  else if ( s->type == DUMMY ) {
2883 /*
2884 --------> Here we may have to execute some renumbering
2885 */
2886  }
2887  else if ( GetVar((UBYTE *)(AT.WorkPointer),&type,&k,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
2888  if ( type != CINDEX ) {
2889  MesPrint("Error: Conflicting types for %s",(AT.WorkPointer));
2890  error = -1;
2891  }
2892  else {
2893  if ( s->type !=
2894  indices[k].type ) {
2895  MesPrint("Warning: %s is also a dummy index",(AT.WorkPointer));
2896  error = -1;
2897  goto GetTb3;
2898  }
2899  if ( s->dimension != indices[k].dimension ) {
2900  MesPrint("Warning: Conflicting dimensions for %s",(AT.WorkPointer));
2901  error = -1;
2902  }
2903  }
2904  }
2905  else {
2906 GetTb3:
2907  if ( ( k = EntVar(CINDEX,(UBYTE *)(AT.WorkPointer),
2908  s->dimension,0,s->nmin4,0) ) < 0 ) goto GetTcall;
2909 
2910  }
2911  *(w+j) = k + AM.OffsetIndex;
2912  w++;
2913  }
2914  }
2915 /*
2916  #] Indices :
2917  #[ Vectors :
2918 */
2919  {
2920  VECTORS s = &VeC;
2921  w = r->vect.lo; j = jvec;
2922  for ( i = 0; i < j; i++ ) {
2923  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)s,(LONG)(sizeof(struct VeCtOr)))
2924  != sizeof(struct VeCtOr) ) goto ErrGt2;
2925  nsize = s->namesize; nsize += sizeof(void *)-1;
2926  nsize &= -sizeof(void *);
2927  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)(AT.WorkPointer),nsize)
2928  != nsize ) goto ErrGt2;
2929  *w = s->number + AM.OffsetVector;
2930  if ( s->flags ) {
2931  /* Find the replacement. It must exist! */
2932  neww = oldw;
2933  while ( *neww != VECTOVEC || neww[2] != *w ) neww += neww[1];
2934  k = neww[3] - AM.OffsetVector;
2935  }
2936  else if ( GetVar((UBYTE *)(AT.WorkPointer),&type,&k,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
2937  if ( type != CVECTOR ) {
2938  MesPrint("Error: Conflicting types for %s",(AT.WorkPointer));
2939  error = -1;
2940  }
2941  else {
2942  if ( ( s->complex & (VARTYPEIMAGINARY|VARTYPECOMPLEX) ) !=
2943  ( vectors[k].complex & (VARTYPEIMAGINARY|VARTYPECOMPLEX) ) ) {
2944  MesPrint("Warning: Conflicting complexity for %s",(AT.WorkPointer));
2945  error = -1;
2946  }
2947  }
2948  }
2949  else {
2950  if ( ( k = EntVar(CVECTOR,(UBYTE *)(AT.WorkPointer),
2951  s->complex,0,0,s->dimension) ) < 0 ) goto GetTcall;
2952  }
2953  *(w+j) = k + AM.OffsetVector;
2954  w++;
2955  }
2956  }
2957 /*
2958  #] Vectors :
2959  #[ Functions :
2960 */
2961  {
2962  FUNCTIONS s = &FuN;
2963  w = r->func.lo; j = jfun;
2964  for ( i = 0; i < j; i++ ) {
2965  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)s,(LONG)(sizeof(struct FuNcTiOn)))
2966  != sizeof(struct FuNcTiOn) ) goto ErrGt2;
2967  nsize = s->namesize; nsize += sizeof(void *)-1;
2968  nsize &= -sizeof(void *);
2969  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)(AT.WorkPointer),nsize)
2970  != nsize ) goto ErrGt2;
2971  *w = s->number + FUNCTION;
2972  if ( s->flags ) {
2973  /* Find the replacement. It must exist! */
2974  neww = oldw;
2975  while ( *neww != FUNTOFUN || neww[2] != *w ) neww += neww[1];
2976  k = neww[3] - FUNCTION;
2977  }
2978  else if ( GetVar((UBYTE *)(AT.WorkPointer),&type,&k,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
2979  if ( type != CFUNCTION ) {
2980  MesPrint("Error: Conflicting types for %s",(AT.WorkPointer));
2981  error = -1;
2982  }
2983  else {
2984  if ( s->complex != functions[k].complex ) {
2985  MesPrint("Warning: Conflicting complexity for %s",(AT.WorkPointer));
2986  error = -1;
2987  }
2988  else if ( s->symmetric != functions[k].symmetric ) {
2989  MesPrint("Warning: Conflicting symmetry properties for %s",(AT.WorkPointer));
2990  error = -1;
2991  }
2992  else if ( ( s->maxnumargs != functions[k].maxnumargs )
2993  || ( s->minnumargs != functions[k].minnumargs ) ) {
2994  MesPrint("Warning: Conflicting argument restriction properties for %s",(AT.WorkPointer));
2995  error = -1;
2996  }
2997  }
2998  }
2999  else {
3000  if ( ( k = EntVar(CFUNCTION,(UBYTE *)(AT.WorkPointer),
3001  s->complex,s->commute,s->spec,s->dimension) ) < 0 ) goto GetTcall;
3002  functions[k].symmetric = s->symmetric;
3003  functions[k].maxnumargs = s->maxnumargs;
3004  functions[k].minnumargs = s->minnumargs;
3005  }
3006  *(w+j) = k + FUNCTION;
3007  w++;
3008  }
3009  }
3010 /*
3011  #] Functions :
3012 
3013  Now we skip the prototype. This sets the start position at the first term
3014 */
3015  if ( error ) {
3016  UNLOCK(AM.storefilelock);
3017  AT.WorkPointer = oldwork;
3018  return(0);
3019  }
3020 
3021  {
3022 /*
3023  For clarity we look where we are.
3024  We want to know: is this position already known?
3025  Could we have inserted extra information here?
3026 
3027  nummystery indicates extra words. We have currently in order
3028  (if they exist)
3029  numdummies
3030  numfactors
3031  vflags
3032 */
3033  POSITION pos;
3034  int nummystery;
3035  TELLFILE(AR.StoreData.Handle,&pos);
3036  nummystery = DIFBASE(ind->position,pos);
3037 /*
3038  MesPrint("--> We are at position %8p",&pos);
3039  MesPrint("--> The index says at %8p",&(ind->position));
3040  MesPrint("--> There are %d mystery bytes",nummystery);
3041 */
3042  if ( nummystery > 0 ) {
3043  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,(LONG)sizeof(WORD)) !=
3044  sizeof(WORD) ) {
3045  UNLOCK(AM.storefilelock);
3046  AT.WorkPointer = oldwork;
3047  return(0);
3048  }
3049  Expressions[expr].numdummies = *AT.WorkPointer;
3050 /*
3051  MesPrint("--> numdummies = %d",Expressions[expr].numdummies);
3052 */
3053  nummystery -= sizeof(WORD);
3054  }
3055  else {
3056  Expressions[expr].numdummies = 0;
3057  }
3058  if ( nummystery > 0 ) {
3059  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,(LONG)sizeof(WORD)) !=
3060  sizeof(WORD) ) {
3061  UNLOCK(AM.storefilelock);
3062  AT.WorkPointer = oldwork;
3063  return(0);
3064  }
3065  if ( ( AS.OldNumFactors == 0 ) || ( AS.NumOldNumFactors < NumExpressions ) ) {
3066  AS.NumOldNumFactors = 20;
3067  if ( AS.NumOldNumFactors < NumExpressions ) AS.NumOldNumFactors = NumExpressions*2;
3068  if ( AS.OldNumFactors ) M_free(AS.OldNumFactors,"numfactors pointers");
3069  AS.OldNumFactors = (WORD *)Malloc1(AS.NumOldNumFactors*sizeof(WORD),"numfactors pointers");
3070  if ( AS.Oldvflags ) M_free(AS.Oldvflags,"vflags pointers");
3071  AS.Oldvflags = (WORD *)Malloc1(AS.NumOldNumFactors*sizeof(WORD),"vflags pointers");
3072  }
3073 
3074  AS.OldNumFactors[expr] =
3075  Expressions[expr].numfactors = *AT.WorkPointer;
3076 /*
3077  MesPrint("--> numfactors = %d",Expressions[expr].numfactors);
3078 */
3079  nummystery -= sizeof(WORD);
3080  }
3081  else {
3082  Expressions[expr].numfactors = 0;
3083  }
3084  if ( nummystery > 0 ) {
3085  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,(LONG)sizeof(WORD)) !=
3086  sizeof(WORD) ) {
3087  UNLOCK(AM.storefilelock);
3088  AT.WorkPointer = oldwork;
3089  return(0);
3090  }
3091  AS.Oldvflags[expr] =
3092  Expressions[expr].vflags = *AT.WorkPointer;
3093 /*
3094  MesPrint("--> vflags = %d",Expressions[expr].vflags);
3095 */
3096  nummystery -= sizeof(WORD);
3097  }
3098  else {
3099  Expressions[expr].vflags = 0;
3100  }
3101  }
3102 
3103  SeekFile(AR.StoreData.Handle,&(ind->position),SEEK_SET);
3104  if ( ReadFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,(LONG)sizeof(WORD)) !=
3105  sizeof(WORD) || !*AT.WorkPointer ) {
3106  UNLOCK(AM.storefilelock);
3107  AT.WorkPointer = oldwork;
3108  return(0);
3109  }
3110  num = *AT.WorkPointer - 1;
3111  num *= sizeof(WORD);
3112  if ( *AT.WorkPointer < 0 ||
3113  ReadFile(AR.StoreData.Handle,(UBYTE *)(AT.WorkPointer+1),num) != num ) {
3114  MesPrint("@Error in stored expressions file at position %10p",*position);
3115  UNLOCK(AM.storefilelock);
3116  AT.WorkPointer = oldwork;
3117  return(0);
3118  }
3119  UNLOCK(AM.storefilelock);
3120  ADDPOS(*position,num+sizeof(WORD));
3121  r->startposition = *position;
3122  AT.WorkPointer = oldwork;
3123  return(r);
3124 GetTcall:
3125  UNLOCK(AM.storefilelock);
3126  AT.WorkPointer = oldwork;
3127  MesCall("GetTable");
3128  return(0);
3129 ErrGt2:
3130  UNLOCK(AM.storefilelock);
3131  AT.WorkPointer = oldwork;
3132  MesPrint("Readerror in GetTable");
3133  return(0);
3134 }
3135 
3136 /*
3137  #] GetTable :
3138  #[ CopyExpression :
3139 
3140  Copies from one scratch buffer to another.
3141  We assume here that the complete 'from' scratch buffer is taken.
3142  We also assume that the 'from' buffer is positioned at the end of
3143  the expression.
3144 
3145  The locks should be placed in the calling routine. We need basically
3146  AS.outputslock.
3147 */
3148 
3149 int CopyExpression(FILEHANDLE *from, FILEHANDLE *to)
3150 {
3151  POSITION posfrom, poscopy;
3152  LONG fullsize,i;
3153  WORD *t1, *t2;
3154  int RetCode;
3155  SeekScratch(from,&posfrom);
3156  if ( from->handle < 0 ) { /* input is in memory */
3157  fullsize = (BASEPOSITION(posfrom))/sizeof(WORD);
3158  if ( ( to->POstop - to->POfull ) >= fullsize ) {
3159 /*
3160  Fits inside the buffer of the output. This will be fast.
3161 */
3162  t1 = from->PObuffer;
3163  t2 = to->POfull;
3164  NCOPY(t2,t1,fullsize)
3165  to->POfull = to->POfill = t2;
3166  goto WriteTrailer;
3167  }
3168  if ( to->handle < 0 ) { /* First open the file */
3169  if ( ( RetCode = CreateFile(to->name) ) >= 0 ) {
3170  to->handle = (WORD)RetCode;
3171  PUTZERO(to->filesize);
3172  PUTZERO(to->POposition);
3173  }
3174  else {
3175  MLOCK(ErrorMessageLock);
3176  MesPrint("Cannot create scratch file %s",to->name);
3177  MUNLOCK(ErrorMessageLock);
3178  return(-1);
3179  }
3180  }
3181  t1 = from->PObuffer;
3182  while ( fullsize > 0 ) {
3183  i = to->POstop - to->POfull;
3184  if ( i > fullsize ) i = fullsize;
3185  fullsize -= i;
3186  t2 = to->POfull;
3187  NCOPY(t2,t1,i)
3188  if ( fullsize > 0 ) {
3189  SeekFile(to->handle,&(to->POposition),SEEK_SET);
3190  if ( WriteFile(to->handle,((UBYTE *)(to->PObuffer)),to->POsize) != to->POsize ) {
3191  MLOCK(ErrorMessageLock);
3192  MesPrint("Error while writing to disk. Disk full?");
3193  MUNLOCK(ErrorMessageLock);
3194  return(-1);
3195  }
3196  ADDPOS(to->POposition,to->POsize);
3197 /* SeekFile(to->handle,&(to->POposition),SEEK_CUR); */
3198  to->filesize = to->POposition;
3199  to->POfill = to->POfull = to->PObuffer;
3200  }
3201  else {
3202  to->POfill = to->POfull = t2;
3203  }
3204  }
3205  goto WriteTrailer;
3206  }
3207 /*
3208  Now the input involves a file. This needs the use of the PObuffer of from.
3209  First make sure the tail of the buffer has been written
3210 */
3211  if ( ((UBYTE *)(from->POfill)-(UBYTE *)(from->PObuffer)) > 0 ) {
3212  if ( WriteFile(from->handle,((UBYTE *)(from->PObuffer)),((UBYTE *)(from->POfill)-(UBYTE *)(from->PObuffer)))
3213  != ((UBYTE *)(from->POfill)-(UBYTE *)(from->PObuffer)) ) {
3214  MLOCK(ErrorMessageLock);
3215  MesPrint("Error while writing to disk. Disk full?");
3216  MUNLOCK(ErrorMessageLock);
3217  return(-1);
3218  }
3219  SeekFile(from->handle,&(from->POposition),SEEK_CUR);
3220  posfrom = from->filesize = from->POposition;
3221  from->POfill = from->POfull = from->PObuffer;
3222  }
3223 /*
3224  Now copy the complete contents
3225 */
3226  PUTZERO(poscopy);
3227  SeekFile(from->handle,&poscopy,SEEK_SET);
3228  while ( ISLESSPOS(poscopy,posfrom) ) {
3229  fullsize = ReadFile(from->handle,((UBYTE *)(from->PObuffer)),from->POsize);
3230  if ( fullsize < 0 || ( fullsize % sizeof(WORD) ) != 0 ) {
3231  MLOCK(ErrorMessageLock);
3232  MesPrint("Error while reading from disk while copying expression.");
3233  MUNLOCK(ErrorMessageLock);
3234  return(-1);
3235  }
3236  fullsize /= sizeof(WORD);
3237  from->POfull = from->PObuffer + fullsize;
3238  t1 = from->PObuffer;
3239 
3240  if ( ( to->POstop - to->POfull ) >= fullsize ) {
3241 /*
3242  Fits inside the buffer of the output. This will be fast.
3243 */
3244  t2 = to->POfull;
3245  NCOPY(t2,t1,fullsize)
3246  to->POfill = to->POfull = t2;
3247  }
3248  else {
3249  if ( to->handle < 0 ) { /* First open the file */
3250  if ( ( RetCode = CreateFile(to->name) ) >= 0 ) {
3251  to->handle = (WORD)RetCode;
3252  PUTZERO(to->POposition);
3253  PUTZERO(to->filesize);
3254  }
3255  else {
3256  MLOCK(ErrorMessageLock);
3257  MesPrint("Cannot create scratch file %s",to->name);
3258  MUNLOCK(ErrorMessageLock);
3259  return(-1);
3260  }
3261  }
3262  while ( fullsize > 0 ) {
3263  i = to->POstop - to->POfull;
3264  if ( i > fullsize ) i = fullsize;
3265  fullsize -= i;
3266  t2 = to->POfull;
3267  NCOPY(t2,t1,i)
3268  if ( fullsize > 0 ) {
3269  SeekFile(to->handle,&(to->POposition),SEEK_SET);
3270  if ( WriteFile(to->handle,((UBYTE *)(to->PObuffer)),to->POsize) != to->POsize ) {
3271  MLOCK(ErrorMessageLock);
3272  MesPrint("Error while writing to disk. Disk full?");
3273  MUNLOCK(ErrorMessageLock);
3274  return(-1);
3275  }
3276  ADDPOS(to->POposition,to->POsize);
3277 /* SeekFile(to->handle,&(to->POposition),SEEK_CUR); */
3278  to->filesize = to->POposition;
3279  to->POfill = to->POfull = to->PObuffer;
3280  }
3281  else {
3282  to->POfill = to->POfull = t2;
3283  }
3284  }
3285  }
3286  SeekFile(from->handle,&poscopy,SEEK_CUR);
3287  }
3288 WriteTrailer:
3289  if ( ( to->handle >= 0 ) && ( to->POfill > to->PObuffer ) ) {
3290  fullsize = (UBYTE *)(to->POfill) - (UBYTE *)(to->PObuffer);
3291 /*
3292  PUTZERO(to->POposition);
3293  SeekFile(to->handle,&(to->POposition),SEEK_END);
3294 */
3295  SeekFile(to->handle,&(to->filesize),SEEK_SET);
3296  if ( WriteFile(to->handle,((UBYTE *)(to->PObuffer)),fullsize) != fullsize ) {
3297  MLOCK(ErrorMessageLock);
3298  MesPrint("Error while writing to disk. Disk full?");
3299  MUNLOCK(ErrorMessageLock);
3300  return(-1);
3301  }
3302  ADDPOS(to->filesize,fullsize);
3303  to->POposition = to->filesize;
3304  to->POfill = to->POfull = to->PObuffer;
3305  }
3306 
3307  return(0);
3308 }
3309 
3310 /*
3311  #] CopyExpression :
3312  #[ ExprStatus :
3313 */
3314 
3315 #ifdef HIDEDEBUG
3316 
3317 static UBYTE *statusexpr[] = {
3318  (UBYTE *)"LOCALEXPRESSION"
3319  ,(UBYTE *)"SKIPLEXPRESSION"
3320  ,(UBYTE *)"DROPLEXPRESSION"
3321  ,(UBYTE *)"DROPPEDEXPRESSION"
3322  ,(UBYTE *)"GLOBALEXPRESSION"
3323  ,(UBYTE *)"SKIPGEXPRESSION"
3324  ,(UBYTE *)"DROPGEXPRESSION"
3325  ,(UBYTE *)"UNKNOWN"
3326  ,(UBYTE *)"STOREDEXPRESSION"
3327  ,(UBYTE *)"HIDDENLEXPRESSION"
3328  ,(UBYTE *)"HIDELEXPRESSION"
3329  ,(UBYTE *)"DROPHLEXPRESSION"
3330  ,(UBYTE *)"UNHIDELEXPRESSION"
3331  ,(UBYTE *)"HIDDENGEXPRESSION"
3332  ,(UBYTE *)"HIDEGEXPRESSION"
3333  ,(UBYTE *)"DROPHGEXPRESSION"
3334  ,(UBYTE *)"UNHIDEGEXPRESSION"
3335  ,(UBYTE *)"INTOHIDELEXPRESSION"
3336  ,(UBYTE *)"INTOHIDEGEXPRESSION"
3337 };
3338 
3339 void ExprStatus(EXPRESSIONS e)
3340 {
3341  MesPrint("Expression %s(%d) has status %s(%d,%d). Buffer: %d, Position: %15p",
3342  AC.exprnames->namebuffer+e->name,(WORD)(e-Expressions),
3343  statusexpr[e->status],e->status,e->hidelevel,
3344  e->whichbuffer,&(e->onfile));
3345 }
3346 
3347 #endif
3348 
3349 /*
3350  #] ExprStatus :
3351  #] StoreExpressions :
3352  #[ System Independent Saved Expressions :
3353 
3354  All functions concerned with the system independent reading of save-files
3355  are here. They are called by the functions CoLoad, PutInStore,
3356  SetFileIndex, FindInIndex. In case no translation (endianness flip,
3357  resizing of words, renumbering) has to be done, they just do simple file
3358  reading. The function SaveFileHeader() for writing a header with
3359  information about the system architecture, FORM version, etc. is also
3360  located here.
3361 
3362  #[ Flip :
3363 */
3364 
3365 #ifndef INT16
3366 #error "INT16 not defined!"
3367 #endif
3368 #ifndef INT32
3369 #error "INT32 not defined!"
3370 #endif
3371 
3381 static void FlipN(UBYTE *p, int length)
3382 {
3383  UBYTE *q, buf;
3384  q = p + length;
3385  do {
3386  --q;
3387  buf = *p; *p = *q; *q = buf;
3388  } while ( ++p != q );
3389 }
3390 
3400 static void Flip16(UBYTE *p)
3401 {
3402  INT16 in = *((INT16 *)p);
3403  INT16 out = (INT16)( (((in) >> 8) & 0x00FF) | (((in) << 8) & 0xFF00) );
3404  *((INT16 *)p) = out;
3405 }
3406 
3408 static void Flip32(UBYTE *p)
3409 {
3410  INT32 in = *((INT32 *)p);
3411  INT32 out =
3412  ( (((in) >> 24) & 0x000000FF) | (((in) >> 8) & 0x0000FF00) | \
3413  (((in) << 8) & 0x00FF0000) | (((in) << 24) & 0xFF000000) );
3414  *((INT32 *)p) = out;
3415 }
3416 
3418 #ifdef INT64
3419 static void Flip64(UBYTE *p)
3420 {
3421  INT64 in = *((INT64 *)p);
3422  INT64 out =
3423  ( (((in) >> 56) & (INT64)0x00000000000000FFLL) | (((in) >> 40) & (INT64)0x000000000000FF00LL) | \
3424  (((in) >> 24) & (INT64)0x0000000000FF0000LL) | (((in) >> 8) & (INT64)0x00000000FF000000LL) | \
3425  (((in) << 8) & (INT64)0x000000FF00000000LL) | (((in) << 24) & (INT64)0x0000FF0000000000LL) | \
3426  (((in) << 40) & (INT64)0x00FF000000000000LL) | (((in) << 56) & (INT64)0xFF00000000000000LL) );
3427  *((INT64 *)p) = out;
3428 }
3429 #else
3430 static void Flip64(UBYTE *p) { FlipN(p, 8); }
3431 #endif /* INT64 */
3432 
3434 static void Flip128(UBYTE *p) { FlipN(p, 16); }
3435 
3436 /*
3437  #] Flip :
3438  #[ Resize :
3439 */
3440 
3452 static void ResizeDataBE(UBYTE *src, int slen, UBYTE *dst, int dlen)
3453 {
3454  if ( slen > dlen ) {
3455  src += slen - dlen;
3456  while ( dlen-- ) { *dst++ = *src++; }
3457  }
3458  else {
3459  int i = dlen - slen;
3460  while ( i-- ) { *dst++ = 0; }
3461  while ( slen-- ) { *dst++ = *src++; }
3462  }
3463 }
3464 
3468 static void ResizeDataLE(UBYTE *src, int slen, UBYTE *dst, int dlen)
3469 {
3470  if ( slen > dlen ) {
3471  while ( dlen-- ) { *dst++ = *src++; }
3472  }
3473  else {
3474  int i = dlen - slen;
3475  while ( slen-- ) { *dst++ = *src++; }
3476  while ( i-- ) { *dst++ = 0; }
3477  }
3478 }
3479 
3492 static void Resize16t16(UBYTE *src, UBYTE *dst)
3493 {
3494  *((INT16 *)dst) = *((INT16 *)src);
3495 }
3496 
3498 static void Resize16t32(UBYTE *src, UBYTE *dst)
3499 {
3500  INT16 in = *((INT16 *)src);
3501  INT32 out = (INT32)in;
3502  *((INT32 *)dst) = out;
3503 }
3504 
3506 #ifdef INT64
3507 static void Resize16t64(UBYTE *src, UBYTE *dst)
3508 {
3509  INT16 in = *((INT16 *)src);
3510  INT64 out = (INT64)in;
3511  *((INT64 *)dst) = out;
3512 }
3513 #else
3514 static void Resize16t64(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 2, dst, 8); }
3515 #endif /* INT64 */
3516 
3518 static void Resize16t128(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 2, dst, 16); }
3519 
3521 static void Resize32t32(UBYTE *src, UBYTE *dst)
3522 {
3523  *((INT32 *)dst) = *((INT32 *)src);
3524 }
3525 
3527 #ifdef INT64
3528 static void Resize32t64(UBYTE *src, UBYTE *dst)
3529 {
3530  INT32 in = *((INT32 *)src);
3531  INT64 out = (INT64)in;
3532  *((INT64 *)dst) = out;
3533 }
3534 #else
3535 static void Resize32t64(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 4, dst, 8); }
3536 #endif /* INT64 */
3537 
3539 static void Resize32t128(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 4, dst, 16); }
3540 
3542 #ifdef INT64
3543 static void Resize64t64(UBYTE *src, UBYTE *dst)
3544 {
3545  *((INT64 *)dst) = *((INT64 *)src);
3546 }
3547 #else
3548 static void Resize64t64(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 8, dst, 8); }
3549 #endif /* INT64 */
3550 
3552 static void Resize64t128(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 8, dst, 16); }
3553 
3555 static void Resize128t128(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 16); }
3556 
3558 static void Resize32t16(UBYTE *src, UBYTE *dst)
3559 {
3560  INT32 in = *((INT32 *)src);
3561  INT16 out = (INT16)in;
3562  if ( in > (1<<15)-1 || in < -(1<<15)+1 ) AO.resizeFlag |= 1;
3563  *((INT16 *)dst) = out;
3564 }
3565 
3572 static void Resize32t16NC(UBYTE *src, UBYTE *dst)
3573 {
3574  INT32 in = *((INT32 *)src);
3575  INT16 out = (INT16)in;
3576  *((INT16 *)dst) = out;
3577 }
3578 
3579 #ifdef INT64
3580 
3581 static void Resize64t16(UBYTE *src, UBYTE *dst)
3582 {
3583  INT64 in = *((INT64 *)src);
3584  INT16 out = (INT16)in;
3585  if ( in > (1<<15)-1 || in < -(1<<15)+1 ) AO.resizeFlag |= 1;
3586  *((INT16 *)dst) = out;
3587 }
3589 static void Resize64t16NC(UBYTE *src, UBYTE *dst)
3590 {
3591  INT64 in = *((INT64 *)src);
3592  INT16 out = (INT16)in;
3593  *((INT16 *)dst) = out;
3594 }
3595 #else
3596 
3597 static void Resize64t16(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 8, dst, 2); }
3599 static void Resize64t16NC(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 8, dst, 2); }
3600 #endif /* INT64 */
3601 
3602 #ifdef INT64
3603 
3604 static void Resize64t32(UBYTE *src, UBYTE *dst)
3605 {
3606  INT64 in = *((INT64 *)src);
3607  INT32 out = (INT32)in;
3608  if ( in > ((INT64)1<<31)-1 || in < -((INT64)1<<31)+1 ) AO.resizeFlag |= 1;
3609  *((INT32 *)dst) = out;
3610 }
3612 static void Resize64t32NC(UBYTE *src, UBYTE *dst)
3613 {
3614  INT64 in = *((INT64 *)src);
3615  INT32 out = (INT32)in;
3616  *((INT32 *)dst) = out;
3617 }
3618 #else
3619 
3620 static void Resize64t32(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 8, dst, 4); }
3622 static void Resize64t32NC(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 8, dst, 4); }
3623 #endif /* INT64 */
3624 
3626 static void Resize128t16(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 2); }
3627 
3629 static void Resize128t16NC(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 2); }
3630 
3632 static void Resize128t32(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 4); }
3633 
3635 static void Resize128t32NC(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 4); }
3636 
3638 static void Resize128t64(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 8); }
3639 
3641 static void Resize128t64NC(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 8); }
3642 
3643 /*
3644  #] Resize :
3645  #[ CheckPower and RenumberVec :
3646 */
3647 
3654 static void CheckPower32(UBYTE *p)
3655 {
3656  if ( *((INT32 *)p) < -MAXPOWER ) {
3657  AO.powerFlag |= 0x01;
3658  *((INT32 *)p) = -MAXPOWER;
3659  }
3660  p += sizeof(INT32);
3661  if ( *((INT32 *)p) > MAXPOWER ) {
3662  AO.powerFlag |= 0x02;
3663  *((INT32 *)p) = MAXPOWER;
3664  }
3665 }
3666 
3674 static void RenumberVec32(UBYTE *p)
3675 {
3676 /* INT32 wildoffset = *((INT32 *)AO.SaveHeader.wildoffset); */
3677  void *dummy = (void *)AO.SaveHeader.wildoffset; /* to remove a warning about strict-aliasing rules in gcc */
3678  INT32 wildoffset = *(INT32 *)dummy;
3679  INT32 in = *((INT32 *)p);
3680  in = in + 2*wildoffset;
3681  in = in - 2*WILDOFFSET;
3682  *((INT32 *)p) = in;
3683 }
3684 
3685 /*
3686  #] CheckPower and RenumberVec :
3687  #[ ResizeCoeff :
3688 */
3689 
3703 static void ResizeCoeff32(UBYTE **bout, UBYTE *bend, UBYTE *top)
3704 {
3705  int i;
3706  INT32 sign;
3707  INT32 *in, *p;
3708  INT32 *out = (INT32 *)*bout;
3709  INT32 *end = (INT32 *)bend;
3710 
3711  if ( sizeof(WORD) == 2 ) {
3712  /* 4 -> 2 */
3713  INT32 len = (end - 1 - out) / 2;
3714  int zeros = 2;
3715  p = out + len - 1;
3716 
3717  if ( *p & 0xFFFF0000 ) --zeros;
3718  p += len;
3719  if ( *p & 0xFFFF0000 ) --zeros;
3720 
3721  in = end - 1;
3722  sign = ( *in-- > 0 ) ? 1 : -1;
3723  p = out + 4*len;
3724  if ( zeros == 2 ) p -= 2;
3725  out = p--;
3726 
3727  if ( zeros < 2 ) *p-- = *in >> 16;
3728  *p-- = *in-- & 0x0000FFFF;
3729  for ( i = 1; i < len; ++i ) {
3730  *p-- = *in >> 16;
3731  *p-- = *in-- & 0x0000FFFF;
3732  }
3733  if ( zeros < 2 ) *p-- = *in >> 16;
3734  *p-- = *in-- & 0x0000FFFF;
3735  for ( i = 1; i < len; ++i ) {
3736  *p-- = *in >> 16;
3737  *p-- = *in-- & 0x0000FFFF;
3738  }
3739 
3740  *out = (out - p) * sign;
3741  *bout = (UBYTE *)(out+1);
3742 
3743  }
3744  else {
3745  /* 2 -> 4 */
3746  INT32 len = (end - 1 - out) / 2;
3747  if ( len == 1 ) {
3748  *out = *(unsigned INT16 *)out;
3749  ++out;
3750  *out = *(unsigned INT16 *)out;
3751  ++out;
3752  ++out;
3753  }
3754  else {
3755  p = out;
3756  *out = *(unsigned INT16 *)out;
3757  in = out + 1;
3758  for ( i = 1; i < len; ++i ) {
3759  /* shift */
3760  *out = (unsigned INT32)(*(unsigned INT16 *)out)
3761  + ((unsigned INT32)(*(unsigned INT16 *)in) << 16);
3762  ++in;
3763  if ( ++i == len ) break;
3764  /* copy */
3765  ++out;
3766  *out = *(unsigned INT16 *)in;
3767  ++in;
3768  }
3769  ++out;
3770  *out = *(unsigned INT16 *)in;
3771  ++in;
3772  for ( i = 1; i < len; ++i ) {
3773  /* shift */
3774  *out = (unsigned INT32)(*(unsigned INT16 *)out)
3775  + ((unsigned INT32)(*(unsigned INT16 *)in) << 16);
3776  ++in;
3777  if ( ++i == len ) break;
3778  /* copy */
3779  ++out;
3780  *out = *(unsigned INT16 *)in;
3781  ++in;
3782  }
3783  ++out;
3784  if ( *in < 0 ) *out = -(out - p + 1);
3785  else *out = out - p + 1;
3786  ++out;
3787  }
3788 
3789  if ( out > (INT32 *)top ) {
3790  MesPrint("Error in resizing coefficient!");
3791  }
3792 
3793  *bout = (UBYTE *)out;
3794  }
3795 }
3796 
3797 /*
3798  #] ResizeCoeff :
3799  #[ WriteStoreHeader :
3800 */
3801 
3802 #define SAVEREVISION 0x02
3803 
3813 WORD WriteStoreHeader(WORD handle)
3814 {
3815  /* template of the STOREHEADER */
3816  static STOREHEADER sh = {
3817  { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, /* store header mark */
3818  0, 0, 0, 0, /* sizeof of WORD,LONG,POSITION,void* */
3819  { 0 }, /* endianness check number */
3820  0, 0, 0, 0, /* sizeof variable structs */
3821  { 0 }, /* maxpower */
3822  { 0 }, /* wildoffset */
3823  SAVEREVISION, /* revision */
3824  { 0 } }; /* reserved */
3825  int endian, i;
3826 
3827  /* if called for the first time ... */
3828  if ( sh.lenWORD == 0 ) {
3829  sh.lenWORD = sizeof(WORD);
3830  sh.lenLONG = sizeof(LONG);
3831  sh.lenPOS = sizeof(POSITION);
3832  sh.lenPOINTER = sizeof(void *);
3833 
3834  endian = 1;
3835  for ( i = 1; i < (int)sizeof(int); ++i ) {
3836  endian <<= 8;
3837  endian += i+1;
3838  }
3839  for ( i = 0; i < (int)sizeof(int); ++i ) sh.endianness[i] = ((char *)&endian)[i];
3840 
3841  sh.sSym = sizeof(struct SyMbOl);
3842  sh.sInd = sizeof(struct InDeX);
3843  sh.sVec = sizeof(struct VeCtOr);
3844  sh.sFun = sizeof(struct FuNcTiOn);
3845 
3846 /* *((WORD *)sh.maxpower) = MAXPOWER;
3847  *((WORD *)sh.wildoffset) = WILDOFFSET; */
3848  {
3849  WORD dumw[8];
3850  UBYTE *dummy;
3851  for ( i = 0; i < 8; i++ ) dumw[i] = 0;
3852  dummy = (UBYTE *)dumw;
3853  dumw[0] = (WORD)MAXPOWER;
3854  for ( i = 0; i < 16; i++ ) sh.maxpower[i] = dummy[i];
3855  dumw[0] = (WORD)WILDOFFSET;
3856  for ( i = 0; i < 16; i++ ) sh.wildoffset[i] = dummy[i];
3857  }
3858  }
3859 
3860  return ( WriteFile(handle,(UBYTE *)(&sh),(LONG)(sizeof(STOREHEADER)))
3861  != (LONG)(sizeof(STOREHEADER)) );
3862 }
3863 
3864 /*
3865  #] WriteStoreHeader :
3866  #[ CompactifySizeof :
3867 */
3868 
3876 static unsigned int CompactifySizeof(unsigned int size)
3877 {
3878  switch ( size ) {
3879  case 2: return 0;
3880  case 4: return 1;
3881  case 8: return 2;
3882  case 16: return 3;
3883  default: MesPrint("Error compactifying size.");
3884  return 3;
3885  }
3886 }
3887 
3888 /*
3889  #] CompactifySizeof :
3890  #[ ReadSaveHeader :
3891 */
3892 
3907 {
3908  /* Read-only tables of function pointers for conversions. */
3909  static VOID (*flipJumpTable[4])(UBYTE *) =
3910  { Flip16, Flip32, Flip64, Flip128 };
3911  static VOID (*resizeJumpTable[4][4])(UBYTE *, UBYTE *) = /* "own x saved"-sizes */
3912  { { Resize16t16, Resize32t16, Resize64t16, Resize128t16 },
3913  { Resize16t32, Resize32t32, Resize64t32, Resize128t32 },
3914  { Resize16t64, Resize32t64, Resize64t64, Resize128t64 },
3915  { Resize16t128, Resize32t128, Resize64t128, Resize128t128 } };
3916  static VOID (*resizeNCJumpTable[4][4])(UBYTE *, UBYTE *) = /* "own x saved"-sizes */
3917  { { Resize16t16, Resize32t16NC, Resize64t16NC, Resize128t16NC },
3918  { Resize16t32, Resize32t32, Resize64t32NC, Resize128t32NC },
3919  { Resize16t64, Resize32t64, Resize64t64, Resize128t64NC },
3920  { Resize16t128, Resize32t128, Resize64t128, Resize128t128 } };
3921 
3922  int endian, i;
3923  WORD idxW = CompactifySizeof(sizeof(WORD));
3924  WORD idxL = CompactifySizeof(sizeof(LONG));
3925  WORD idxP = CompactifySizeof(sizeof(POSITION));
3926  WORD idxVP = CompactifySizeof(sizeof(void *));
3927 
3928  AO.transFlag = 0;
3929  AO.powerFlag = 0;
3930  AO.resizeFlag = 0;
3931  AO.bufferedInd = 0;
3932 
3933  if ( ReadFile(AO.SaveData.Handle,(UBYTE *)(&AO.SaveHeader),
3934  (LONG)sizeof(STOREHEADER)) != (LONG)sizeof(STOREHEADER) )
3935  return(MesPrint("Error reading save file header"));
3936 
3937  /* check whether save-file has no header. if yes then it is an old version
3938  of FORM -> go back to position 0 in file which then contains the first
3939  index and skip the rest. */
3940  for ( i = 0; i < 8; ++i ) {
3941  if ( AO.SaveHeader.headermark[i] != 0xFF ) {
3942  POSITION p;
3943  PUTZERO(p);
3944  SeekFile(AO.SaveData.Handle, &p, SEEK_SET);
3945  return ( 0 );
3946  }
3947  }
3948 
3949  if ( AO.SaveHeader.revision != SAVEREVISION ) {
3950  return(MesPrint("Save file header from an old version. Cannot read this file."));
3951  }
3952 
3953  endian = 1;
3954  for ( i = 1; i < (int)sizeof(int); ++i ) {
3955  endian <<= 8;
3956  endian += i+1;
3957  }
3958  if ( ((char *)&endian)[0] < ((char *)&endian)[1] ) {
3959  /* this machine is big-endian */
3960  AO.ResizeData = ResizeDataBE;
3961  }
3962  else {
3963  /* this machine is little-endian */
3964  AO.ResizeData = ResizeDataLE;
3965  }
3966 
3967  /* set AO.transFlag if ANY conversion has to be done later */
3968  if ( AO.SaveHeader.endianness[0] > AO.SaveHeader.endianness[1] ) {
3969  AO.transFlag = ( ((char *)&endian)[0] < ((char *)&endian)[1] );
3970  }
3971  else {
3972  AO.transFlag = ( ((char *)&endian)[0] > ((char *)&endian)[1] );
3973  }
3974  if ( (WORD)AO.SaveHeader.lenWORD != sizeof(WORD) ) AO.transFlag |= 0x02;
3975  if ( (WORD)AO.SaveHeader.lenLONG != sizeof(LONG) ) AO.transFlag |= 0x04;
3976  if ( (WORD)AO.SaveHeader.lenPOS != sizeof(POSITION) ) AO.transFlag |= 0x08;
3977  if ( (WORD)AO.SaveHeader.lenPOINTER != sizeof(void *) ) AO.transFlag |= 0x10;
3978 
3979  AO.FlipWORD = flipJumpTable[idxW];
3980  AO.FlipLONG = flipJumpTable[idxL];
3981  AO.FlipPOS = flipJumpTable[idxP];
3982  AO.FlipPOINTER = flipJumpTable[idxVP];
3983 
3984  /* Works only for machines where WORD is not greater than 32bit ! */
3985  AO.CheckPower = CheckPower32;
3986  AO.RenumberVec = RenumberVec32;
3987 
3988  AO.ResizeWORD = resizeJumpTable[idxW][CompactifySizeof(AO.SaveHeader.lenWORD)];
3989  AO.ResizeNCWORD = resizeNCJumpTable[idxW][CompactifySizeof(AO.SaveHeader.lenWORD)];
3990  AO.ResizeLONG = resizeJumpTable[idxL][CompactifySizeof(AO.SaveHeader.lenLONG)];
3991  AO.ResizePOS = resizeJumpTable[idxP][CompactifySizeof(AO.SaveHeader.lenPOS)];
3992  AO.ResizePOINTER = resizeJumpTable[idxVP][CompactifySizeof(AO.SaveHeader.lenPOINTER)];
3993 
3994  {
3995  WORD dumw[8];
3996  UBYTE *dummy;
3997  for ( i = 0; i < 8; i++ ) dumw[i] = 0;
3998  dummy = (UBYTE *)dumw;
3999  for ( i = 0; i < 16; i++ ) dummy[i] = AO.SaveHeader.maxpower[i];
4000  AO.mpower = dumw[0];
4001  }
4002 
4003  return ( 0 );
4004 }
4005 
4006 /*
4007  #] ReadSaveHeader :
4008  #[ ReadSaveIndex :
4009 */
4010 
4024 WORD ReadSaveIndex(FILEINDEX *fileind)
4025 {
4026  /* do we need some translation for the FILEINDEX? */
4027  if ( AO.transFlag ) {
4028  /* if a translated FILEINDEX can hold less entries than the original
4029  FILEINDEX, then we need to buffer the extra entires in this static
4030  variable (can happen going from 32bit to 64bit */
4031  static FILEINDEX sbuffer;
4032 
4033  FILEINDEX buffer;
4034  UBYTE *p, *q;
4035  int i;
4036 
4037  /* shortcuts */
4038  int lenW = AO.SaveHeader.lenWORD;
4039  int lenL = AO.SaveHeader.lenLONG;
4040  int lenP = AO.SaveHeader.lenPOS;
4041 
4042  /* if we have a buffered FILEINDEX then just return it */
4043  if ( AO.bufferedInd ) {
4044  *fileind = sbuffer;
4045  AO.bufferedInd = 0;
4046  return ( 0 );
4047  }
4048 
4049  if ( ReadFile(AO.SaveData.Handle, (UBYTE *)fileind, sizeof(FILEINDEX))
4050  != sizeof(FILEINDEX) ) {
4051  return ( MesPrint("Error(1) reading stored expression.") );
4052  }
4053 
4054  /* do we need to flip the endianness? */
4055  if ( AO.transFlag & 1 ) {
4056  LONG number;
4057  /* padding bytes */
4058  int padp = lenL - ((lenW*5+(MAXENAME + 1)) & (lenL-1));
4059  p = (UBYTE *)fileind;
4060  AO.FlipPOS(p); p += lenP; /* next */
4061  AO.FlipPOS(p); /* number */
4062  AO.ResizePOS(p, (UBYTE *)&number);
4063  p += lenP;
4064  for ( i = 0; i < number; ++i ) {
4065  AO.FlipPOS(p); p += lenP; /* position */
4066  AO.FlipPOS(p); p += lenP; /* length */
4067  AO.FlipPOS(p); p += lenP; /* variables */
4068  AO.FlipLONG(p); p += lenL; /* CompressSize */
4069  AO.FlipWORD(p); p += lenW; /* nsymbols */
4070  AO.FlipWORD(p); p += lenW; /* nindices */
4071  AO.FlipWORD(p); p += lenW; /* nvectors */
4072  AO.FlipWORD(p); p += lenW; /* nfunctions */
4073  AO.FlipWORD(p); p += lenW; /* size */
4074  p += padp;
4075  }
4076  }
4077 
4078  /* do we need to resize data? */
4079  if ( AO.transFlag > 1 ) {
4080  LONG number, maxnumber;
4081  int n;
4082  /* padding bytes */
4083  int padp = lenL - ((lenW*5+(MAXENAME + 1)) & (lenL-1));
4084  int padq = sizeof(LONG) - ((sizeof(WORD)*5+(MAXENAME + 1)) & (sizeof(LONG)-1));
4085 
4086  p = (UBYTE *)fileind; q = (UBYTE *)&buffer;
4087  AO.ResizePOS(p, q); /* next */
4088  p += lenP; q += sizeof(POSITION);
4089  AO.ResizePOS(p, q); /* number */
4090  p += lenP;
4091  number = BASEPOSITION(*((POSITION *)q));
4092  /* if FILEINDEX in file contains more entries than the FILEINDEX in
4093  memory can contain, then adjust the numbers and prepare for
4094  buffering */
4095  if ( number > (LONG)INFILEINDEX ) {
4096  AO.bufferedInd = number-INFILEINDEX;
4097  if ( AO.bufferedInd > (WORD)INFILEINDEX ) {
4098  /* can happen when reading 32bit and writing >=128bit.
4099  Fix: more than one static buffer for FILEINDEX */
4100  return ( MesPrint("Too many index entries.") );
4101  }
4102  maxnumber = INFILEINDEX;
4103  SETBASEPOSITION(*((POSITION *)q),INFILEINDEX);
4104  }
4105  else {
4106  maxnumber = number;
4107  }
4108  q += sizeof(POSITION);
4109  /* read all INDEXENTRY that fit into the output buffer */
4110  for ( i = 0; i < maxnumber; ++i ) {
4111  AO.ResizePOS(p, q); /* position */
4112  p += lenP; q += sizeof(POSITION);
4113  AO.ResizePOS(p, q); /* length */
4114  p += lenP; q += sizeof(POSITION);
4115  AO.ResizePOS(p, q); /* variables */
4116  p += lenP; q += sizeof(POSITION);
4117  AO.ResizeLONG(p, q); /* CompressSize */
4118  p += lenL; q += sizeof(LONG);
4119  AO.ResizeWORD(p, q); /* nsymbols */
4120  p += lenW; q += sizeof(WORD);
4121  AO.ResizeWORD(p, q); /* nindices */
4122  p += lenW; q += sizeof(WORD);
4123  AO.ResizeWORD(p, q); /* nvectors */
4124  p += lenW; q += sizeof(WORD);
4125  AO.ResizeWORD(p, q); /* nfunctions */
4126  p += lenW; q += sizeof(WORD);
4127  AO.ResizeWORD(p, q); /* size (unchanged!) */
4128  p += lenW; q += sizeof(WORD);
4129  n = MAXENAME + 1;
4130  NCOPYB(q, p, n)
4131  p += padp;
4132  q += padq;
4133  }
4134  /* read all the remaining INDEXENTRY and put them into the static buffer */
4135  if ( AO.bufferedInd ) {
4136  sbuffer.next = buffer.next;
4137  SETBASEPOSITION(sbuffer.number,AO.bufferedInd);
4138  q = (UBYTE *)&sbuffer + sizeof(POSITION) + sizeof(LONG);
4139  for ( i = maxnumber; i < number; ++i ) {
4140  AO.ResizePOS(p, q); /* position */
4141  p += lenP; q += sizeof(POSITION);
4142  AO.ResizePOS(p, q); /* length */
4143  p += lenP; q += sizeof(POSITION);
4144  AO.ResizePOS(p, q); /* variables */
4145  p += lenP; q += sizeof(POSITION);
4146  AO.ResizeLONG(p, q); /* CompressSize */
4147  p += lenL; q += sizeof(LONG);
4148  AO.ResizeWORD(p, q); /* nsymbols */
4149  p += lenW; q += sizeof(WORD);
4150  AO.ResizeWORD(p, q); /* nindices */
4151  p += lenW; q += sizeof(WORD);
4152  AO.ResizeWORD(p, q); /* nvectors */
4153  p += lenW; q += sizeof(WORD);
4154  AO.ResizeWORD(p, q); /* nfunctions */
4155  p += lenW; q += sizeof(WORD);
4156  AO.ResizeWORD(p, q); /* size (unchanged!) */
4157  p += lenW; q += sizeof(WORD);
4158  n = MAXENAME + 1;
4159  NCOPYB(q, p, n)
4160  p += padp;
4161  q += padq;
4162  }
4163  }
4164  /* copy to output */
4165  p = (UBYTE *)fileind; q = (UBYTE *)&buffer; n = sizeof(FILEINDEX);
4166  NCOPYB(p, q, n)
4167  }
4168  return ( 0 );
4169  } else {
4170  return ( ReadFile(AO.SaveData.Handle, (UBYTE *)fileind, sizeof(FILEINDEX))
4171  != sizeof(FILEINDEX) );
4172  }
4173 }
4174 
4175 /*
4176  #] ReadSaveIndex :
4177  #[ ReadSaveVariables :
4178 */
4179 
4210 WORD ReadSaveVariables(UBYTE *buffer, UBYTE *top, LONG *size, LONG *outsize,\
4211  INDEXENTRY *ind, LONG *stage)
4212 {
4213  /* do we need some translation for the variables? */
4214  if ( AO.transFlag ) {
4215  /* counters for the number of already read symbols, indices, ... that
4216  need to remain valid between different calls to ReadSaveVariables().
4217  are initialized if stage == -1 */
4218  static WORD numReadSym;
4219  static WORD numReadInd;
4220  static WORD numReadVec;
4221  static WORD numReadFun;
4222 
4223  POSITION pos;
4224  UBYTE *in, *out, *pp = 0, *end, *outbuf;
4225  LONG numread;
4226  WORD namelen, realnamelen;
4227  /* shortcuts */
4228  WORD lenW = AO.SaveHeader.lenWORD;
4229  WORD lenL = AO.SaveHeader.lenLONG;
4230  WORD lenP = AO.SaveHeader.lenPOINTER;
4231  WORD flip = AO.transFlag & 1;
4232 
4233  /* remember file position in case we have to rewind */
4234  TELLFILE(AO.SaveData.Handle,&pos);
4235 
4236  /* decide on the position of the in and out buffers.
4237  if the input is "bigger" than the output, we resize in-place, i.e.
4238  we immediately overwrite the source data by the translated data. in
4239  and out buffers start at the same place.
4240  if not, we read from the end of the given buffer and write at the
4241  beginning. */
4242  if ( (lenW > (WORD)sizeof(WORD))
4243  || ( (lenW == (WORD)sizeof(WORD))
4244  && ( (lenL > (WORD)sizeof(LONG))
4245  || ( (lenL == (WORD)sizeof(LONG)) && lenP > (WORD)sizeof(void *))
4246  )
4247  ) ) {
4248  in = out = buffer;
4249  end = buffer + *size;
4250  }
4251  else {
4252  /* data will grow roughly by sizeof(WORD)/lenW. the exact value is
4253  not important. if reading and writing areas start to overlap, the
4254  reading will already be near the end of the data and overwriting
4255  doesn't matter. */
4256  LONG newsize = (top - buffer) / (1 + sizeof(WORD)/lenW);
4257  end = top;
4258  out = buffer;
4259  in = end - newsize;
4260  if ( *size > newsize ) *size = newsize;
4261  }
4262 
4263  if ( ( numread = ReadFile(AO.SaveData.Handle, in, *size) ) != *size ) {
4264  return ( MesPrint("Error(2) reading stored expression.") );
4265  }
4266 
4267  *size = 0;
4268  *outsize = 0;
4269 
4270  /* first time in ReadSaveVariables(). initialize counters. */
4271  if ( *stage == -1 ) {
4272  numReadSym = 0;
4273  numReadInd = 0;
4274  numReadVec = 0;
4275  numReadFun = 0;
4276  ++*stage;
4277  }
4278 
4279  while ( in < end ) {
4280  /* Symbols */
4281  if ( *stage == 0 ) {
4282  if ( ind->nsymbols <= numReadSym ) {
4283  ++*stage;
4284  continue;
4285  }
4286  if ( end - in < AO.SaveHeader.sSym ) {
4287  goto RSVEnd;
4288  }
4289  if ( flip ) {
4290  pp = in;
4291  AO.FlipLONG(pp); pp += lenL;
4292  while ( pp < in + AO.SaveHeader.sSym ) {
4293  AO.FlipWORD(pp); pp += lenW;
4294  }
4295  }
4296  pp = in + AO.SaveHeader.sSym;
4297  AO.ResizeLONG(in, out); in += lenL; out += sizeof(LONG); /* name */
4298  AO.CheckPower(in);
4299  AO.ResizeWORD(in, out); in += lenW;
4300  if ( *((WORD *)out) == -AO.mpower ) *((WORD *)out) = -MAXPOWER;
4301  out += sizeof(WORD); /* minpower */
4302  AO.ResizeWORD(in, out); in += lenW;
4303  if ( *((WORD *)out) == AO.mpower ) *((WORD *)out) = MAXPOWER;
4304  out += sizeof(WORD); /* maxpower */
4305  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* complex */
4306  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* number */
4307  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* flags */
4308  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* node */
4309  AO.ResizeWORD(in, out); in += lenW; /* namesize */
4310  realnamelen = *((WORD *)out);
4311  realnamelen += sizeof(void *)-1; realnamelen &= -(sizeof(void *));
4312  out += sizeof(WORD);
4313  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* dimension */
4314  while ( in < pp ) {
4315  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD);
4316  }
4317  namelen = *((WORD *)out-1); /* cares for padding "bug" */
4318  if ( end - in < namelen ) {
4319  goto RSVEnd;
4320  }
4321  *((WORD *)out-1) = realnamelen;
4322  *size += AO.SaveHeader.sSym + namelen;
4323  *outsize += sizeof(struct SyMbOl) + realnamelen;
4324  if ( realnamelen > namelen ) {
4325  int j = namelen;
4326  NCOPYB(out, in, j);
4327  out += realnamelen - namelen;
4328  }
4329  else {
4330  int j = realnamelen;
4331  NCOPYB(out, in, j);
4332  in += namelen - realnamelen;
4333  }
4334  ++numReadSym;
4335  continue;
4336  }
4337  /* Indices */
4338  if ( *stage == 1 ) {
4339  if ( ind->nindices <= numReadInd ) {
4340  ++*stage;
4341  continue;
4342  }
4343  if ( end - in < AO.SaveHeader.sInd ) {
4344  goto RSVEnd;
4345  }
4346  if ( flip ) {
4347  pp = in;
4348  AO.FlipLONG(pp); pp += lenL;
4349  while ( pp < in + AO.SaveHeader.sInd ) {
4350  AO.FlipWORD(pp); pp += lenW;
4351  }
4352  }
4353  pp = in + AO.SaveHeader.sInd;
4354  AO.ResizeLONG(in, out); in += lenL; out += sizeof(LONG); /* name */
4355  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* type */
4356  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* dimension */
4357  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* number */
4358  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* flags */
4359  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* nmin4 */
4360  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* node */
4361  AO.ResizeWORD(in, out); in += lenW; /* namesize */
4362  realnamelen = *((WORD *)out);
4363  realnamelen += sizeof(void *)-1; realnamelen &= -(sizeof(void *));
4364  out += sizeof(WORD);
4365  while ( in < pp ) {
4366  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD);
4367  }
4368  namelen = *((WORD *)out-1); /* cares for padding "bug" */
4369  if ( end - in < namelen ) {
4370  goto RSVEnd;
4371  }
4372  *((WORD *)out-1) = realnamelen;
4373  *size += AO.SaveHeader.sInd + namelen;
4374  *outsize += sizeof(struct InDeX) + realnamelen;
4375  if ( realnamelen > namelen ) {
4376  int j = namelen;
4377  NCOPYB(out, in, j);
4378  out += realnamelen - namelen;
4379  }
4380  else {
4381  int j = realnamelen;
4382  NCOPYB(out, in, j);
4383  in += namelen - realnamelen;
4384  }
4385  ++numReadInd;
4386  continue;
4387  }
4388  /* Vectors */
4389  if ( *stage == 2 ) {
4390  if ( ind->nvectors <= numReadVec ) {
4391  ++*stage;
4392  continue;
4393  }
4394  if ( end - in < AO.SaveHeader.sVec ) {
4395  goto RSVEnd;
4396  }
4397  if ( flip ) {
4398  pp = in;
4399  AO.FlipLONG(pp); pp += lenL;
4400  while ( pp < in + AO.SaveHeader.sVec ) {
4401  AO.FlipWORD(pp); pp += lenW;
4402  }
4403  }
4404  pp = in + AO.SaveHeader.sVec;
4405  AO.ResizeLONG(in, out); in += lenL; out += sizeof(LONG); /* name */
4406  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* complex */
4407  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* number */
4408  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* flags */
4409  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* node */
4410  AO.ResizeWORD(in, out); in += lenW; /* namesize */
4411  realnamelen = *((WORD *)out);
4412  realnamelen += sizeof(void *)-1; realnamelen &= -(sizeof(void *));
4413  out += sizeof(WORD);
4414  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* dimension */
4415  while ( in < pp ) {
4416  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD);
4417  }
4418  namelen = *((WORD *)out-1); /* cares for padding "bug" */
4419  if ( end - in < namelen ) {
4420  goto RSVEnd;
4421  }
4422  *((WORD *)out-1) = realnamelen;
4423  *size += AO.SaveHeader.sVec + namelen;
4424  *outsize += sizeof(struct VeCtOr) + realnamelen;
4425  if ( realnamelen > namelen ) {
4426  int j = namelen;
4427  NCOPYB(out, in, j)
4428  out += realnamelen - namelen;
4429  }
4430  else {
4431  int j = realnamelen;
4432  NCOPYB(out, in, j)
4433  in += namelen - realnamelen;
4434  }
4435  ++numReadVec;
4436  continue;
4437  }
4438  /* Functions */
4439  if ( *stage == 3 ) {
4440  if ( ind->nfunctions <= numReadFun ) {
4441  ++*stage;
4442  continue;
4443  }
4444  if ( end - in < AO.SaveHeader.sFun ) {
4445  goto RSVEnd;
4446  }
4447  if ( flip ) {
4448  pp = in;
4449  AO.FlipPOINTER(pp); pp += lenP;
4450  AO.FlipLONG(pp); pp += lenL;
4451  AO.FlipLONG(pp); pp += lenL;
4452  while ( pp < in + AO.SaveHeader.sFun ) {
4453  AO.FlipWORD(pp); pp += lenW;
4454  }
4455  }
4456  pp = in + AO.SaveHeader.sFun;
4457  outbuf = out;
4458  AO.ResizePOINTER(in, out); in += lenP; out += sizeof(void *); /* tabl */
4459  AO.ResizeLONG(in, out); in += lenL; out += sizeof(LONG); /* symminfo */
4460  AO.ResizeLONG(in, out); in += lenL; out += sizeof(LONG); /* name */
4461  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* commute */
4462  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* complex */
4463  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* number */
4464  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* flags */
4465  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* spec */
4466  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* symmetric */
4467  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* numargs */
4468  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* node */
4469  AO.ResizeWORD(in, out); in += lenW; /* namesize */
4470  realnamelen = *((WORD *)out);
4471  realnamelen += sizeof(void *)-1; realnamelen &= -(sizeof(void *));
4472  out += sizeof(WORD);
4473  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* dimension */
4474  while ( in < pp ) {
4475  AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD);
4476  }
4477  namelen = *((WORD *)out-1); /* cares for padding "bug" */
4478  if ( end - in < namelen ) {
4479  goto RSVEnd;
4480  }
4481  *((WORD *)out-1) = realnamelen;
4482  *size += AO.SaveHeader.sFun + namelen;
4483  *outsize += sizeof(struct FuNcTiOn) + realnamelen;
4484  if ( realnamelen > namelen ) {
4485  int j = namelen;
4486  NCOPYB(out, in, j);
4487  out += realnamelen - namelen;
4488  }
4489  else {
4490  int j = realnamelen;
4491  NCOPYB(out, in, j);
4492  in += namelen - realnamelen;
4493  }
4494  ++numReadFun;
4495  /* we use the information whether a function is tensorial later in ReadSaveTerm */
4496  AO.tensorList[((FUNCTIONS)outbuf)->number+FUNCTION] =
4497  (UBYTE)(((FUNCTIONS)outbuf)->spec == TENSORFUNCTION);
4498  continue;
4499  }
4500  /* handle numdummies */
4501  if ( end - in >= lenW ) {
4502  if ( flip ) AO.FlipWORD(in);
4503  AO.ResizeWORD(in, out);
4504  *size += lenW;
4505  *outsize += sizeof(WORD);
4506  }
4507  /* handle numfactors */
4508  if ( end - in >= lenW ) {
4509  if ( flip ) AO.FlipWORD(in);
4510  AO.ResizeWORD(in, out);
4511  *size += lenW;
4512  *outsize += sizeof(WORD);
4513  }
4514  /* handle vflags */
4515  if ( end - in >= lenW ) {
4516  if ( flip ) AO.FlipWORD(in);
4517  AO.ResizeWORD(in, out);
4518  *size += lenW;
4519  *outsize += sizeof(WORD);
4520  }
4521  return ( 0 );
4522  }
4523 
4524 RSVEnd:
4525  /* we are here because the remaining buffer cannot hold the next
4526  struct. we position the file behind the last sucessfully translated
4527  struct and return. */
4528  ADDPOS(pos, *size);
4529  SeekFile(AO.SaveData.Handle, &pos, SEEK_SET);
4530  return ( 0 );
4531  } else {
4532  return ( ReadFile(AO.SaveData.Handle, buffer, *size) != *size );
4533  }
4534 }
4535 
4536 /*
4537  #] ReadSaveVariables :
4538  #[ ReadSaveTerm :
4539 */
4540 
4569 UBYTE *
4570 ReadSaveTerm32(UBYTE *bin, UBYTE *binend, UBYTE **bout, UBYTE *boutend, UBYTE *top, int terminbuf)
4571 {
4572  GETIDENTITY
4573 
4574  UBYTE *boutbuf;
4575  INT32 len, j, id;
4576  INT32 *r, *t, *coeff, *end, *newtermsize, *rend;
4577  INT32 *newsubtermp;
4578  INT32 *in = (INT32 *)bin;
4579  INT32 *out = (INT32 *)*bout;
4580 
4581  /* if called recursively the term is already decompressed in buffer.
4582  is this the case? */
4583  if ( terminbuf ) {
4584  /* don't do any decompression, just adjust the pointers */
4585  len = *out;
4586  end = out + len;
4587  r = in + 1;
4588  rend = (INT32 *)boutend;
4589  coeff = end - ABS(*(end-1));
4590  newtermsize = (INT32 *)*bout;
4591  out = newtermsize + 1;
4592  }
4593  else {
4594  /* do deprompression of necessary. always return if the space in the
4595  buffer is not sufficient */
4596  INT32 rbuf;
4597  r = (INT32 *)AR.CompressBuffer;
4598  rbuf = *r;
4599  len = j = *in;
4600  /* first copy from AR.CompressBuffer if necessary */
4601  if ( j < 0 ) {
4602  ++in;
4603  if ( (UBYTE *)in >= binend ) {
4604  return ( bin );
4605  }
4606  *out = len = -j + 1 + *in;
4607  end = out + *out;
4608  if ( (UBYTE *)end >= top ) {
4609  return ( bin );
4610  }
4611  ++out;
4612  *r++ = len;
4613  while ( ++j <= 0 ) {
4614  INT32 bb = *r++;
4615  *out++ = bb;
4616  }
4617  j = *in++;
4618  }
4619  else if ( j == 0 ) {
4620  /* care for padding words */
4621  while ( (UBYTE *)in < binend ) {
4622  *out++ = 0;
4623  if ( (UBYTE *)out > top ) {
4624  return ( (UBYTE *)bin );
4625  }
4626 
4627  *r++ = 0;
4628  ++in;
4629  }
4630  *bout = (UBYTE *)out;
4631  return ( (UBYTE *)in );
4632  }
4633  else {
4634  end = out + len;
4635  if ( (UBYTE *)end >= top ) {
4636  return ( bin );
4637  }
4638  }
4639  if ( (UBYTE *)(in + j) >= binend ) {
4640  *(AR.CompressBuffer) = rbuf;
4641  return ( bin );
4642  }
4643  if ( (UBYTE *)out + j >= top ) {
4644  return ( bin );
4645  }
4646  /* second copy from input buffer */
4647  while ( --j >= 0 ) {
4648  INT32 bb = *in++;
4649  *r++ = *out++ = bb;
4650  }
4651 
4652  rend = r;
4653  r = (INT32 *)AR.CompressBuffer + 1;
4654  coeff = end - ABS(*(end-1));
4655  newtermsize = (INT32 *)*bout;
4656  out = newtermsize + 1;
4657  }
4658 
4659  /* iterate over subterms */
4660  while ( out < coeff ) {
4661 
4662  id = *out++;
4663  ++r;
4664  t = out + *out - 1;
4665  newsubtermp = out;
4666  ++out; ++r;
4667 
4668  if ( id == SYMBOL ) {
4669  while ( out < t ) {
4670  ++out; ++r; /* symbol number */
4671  /* if exponent is too big, rewrite as exponent function */
4672  if ( ABS(*out) >= MAXPOWER ) {
4673  INT32 *a, *b;
4674  INT32 n;
4675  INT32 num = *(out-1);
4676  INT32 exp = *out;
4677  coeff += 9;
4678  end += 9;
4679  t += 9;
4680  if ( (UBYTE *)end > top ) return ( bin );
4681  out -= 3;
4682  *out++ = EXPONENT; /* id */
4683  *out++ = 13; /* size */
4684  *out++ = 1; /* dirtyflag */
4685  *out++ = -SYMBOL; /* first short arg */
4686  *out++ = num;
4687  *out++ = 8; /* second arg, size */
4688  *out++ = 0; /* dirtyflag */
4689  *out++ = 6; /* term size */
4690  *out++ = ABS(exp) & 0x0000FFFF;
4691  *out++ = ABS(exp) >> 16;
4692  *out++ = 1;
4693  *out++ = 0;
4694  *out++ = ( exp < 0 ) ? -5 : 5;
4695  a = ++r;
4696  b = out;
4697  n = rend - r;
4698  NCOPYI32(b, a, n)
4699  }
4700  else {
4701  ++out; ++r;
4702  }
4703  }
4704  }
4705  else if ( id == DOTPRODUCT ) {
4706  while ( out < t ) {
4707  AO.RenumberVec((UBYTE *)out); /* vector 1 */
4708  ++out; ++r;
4709  AO.RenumberVec((UBYTE *)out); /* vector 2 */
4710  ++out; ++r;
4711  /* if exponent is too big, rewrite as exponent function */
4712  if ( ABS(*out) >= MAXPOWER ) {
4713  INT32 *a, *b;
4714  INT32 n;
4715  INT32 num1 = *(out-2);
4716  INT32 num2 = *(out-1);
4717  INT32 exp = *out;
4718  coeff += 17;
4719  end += 17;
4720  t += 17;
4721  if ( (UBYTE *)end > top ) return ( bin );
4722  out -= 4;
4723  *out++ = EXPONENT; /* id */
4724  *out++ = 22; /* size */
4725  *out++ = 1; /* dirtyflag */
4726  *out++ = 11; /* first arg, size */
4727  *out++ = 0; /* dirtyflag */
4728  *out++ = 9; /* term size */
4729  *out++ = DOTPRODUCT; /* p1.p2 */
4730  *out++ = 5; /* subterm size */
4731  *out++ = num1; /* p1 */
4732  *out++ = num2; /* p2 */
4733  *out++ = 1; /* exponent */
4734  *out++ = 1; /* coeff */
4735  *out++ = 1;
4736  *out++ = 3;
4737  *out++ = 8; /* second arg, size */
4738  *out++ = 0; /* dirtyflag */
4739  *out++ = 6; /* term size */
4740  *out++ = ABS(exp) & 0x0000FFFF;
4741  *out++ = ABS(exp) >> 16;
4742  *out++ = 1;
4743  *out++ = 0;
4744  *out++ = ( exp < 0 ) ? -5 : 5;
4745  a = ++r;
4746  b = out;
4747  n = rend - r;
4748  NCOPYI32(b, a, n)
4749  }
4750  else {
4751  ++out; ++r;
4752  }
4753  }
4754  }
4755  else if ( id == VECTOR ) {
4756  while ( out < t ) {
4757  AO.RenumberVec((UBYTE *)out); /* vector number */
4758  ++out; ++r;
4759  ++out; ++r; /* index, do nothing */
4760  }
4761  }
4762  else if ( id == INDEX ) {
4763 /* INT32 vectoroffset = -2 * *((INT32 *)AO.SaveHeader.wildoffset); */
4764  void *dummy = (void *)AO.SaveHeader.wildoffset; /* to remove a warning about strict-aliasing rules in gcc */
4765  INT32 vectoroffset = -2 * *((INT32 *)dummy);
4766  while ( out < t ) {
4767  /* if there is a vector, renumber it */
4768  if ( *out < vectoroffset ) {
4769  AO.RenumberVec((UBYTE *)out);
4770  }
4771  ++out; ++r;
4772  }
4773  }
4774  else if ( id == SUBEXPRESSION ) {
4775  /* nothing to translate */
4776  while ( out < t ) {
4777  ++out; ++r;
4778  }
4779  }
4780  else if ( id == DELTA ) {
4781  /* nothing to translate */
4782  r += t - out;
4783  out = t;
4784  }
4785  else if ( id == HAAKJE ) {
4786  /* nothing to translate */
4787  r += t - out;
4788  out = t;
4789  }
4790  else if ( id == GAMMA || id == LEVICIVITA || (id >= FUNCTION && AO.tensorList[id]) ) {
4791 /* INT32 vectoroffset = -2 * *((INT32 *)AO.SaveHeader.wildoffset); */
4792  void *dummy = (void *)AO.SaveHeader.wildoffset; /* to remove a warning about strict-aliasing rules in gcc */
4793  INT32 vectoroffset = -2 * *((INT32 *)dummy);
4794  while ( out < t ) {
4795  /* if there is a vector as an argument, renumber it */
4796  if ( *out < vectoroffset ) {
4797  AO.RenumberVec((UBYTE *)out);
4798  }
4799  ++out; ++r;
4800  }
4801  }
4802  else if ( id >= FUNCTION ) {
4803  INT32 *argEnd;
4804  UBYTE *newbin;
4805 
4806  ++out; ++r; /* dirty flags */
4807 
4808  /* loop over arguments */
4809  while ( out < t ) {
4810  if ( *out < 0 ) {
4811  /* short notation arguments */
4812  switch ( -*out ) {
4813  case SYMBOL:
4814  ++out; ++r;
4815  ++out; ++r;
4816  break;
4817  case SNUMBER:
4818  ++out; ++r;
4819  if ( sizeof(WORD) == 2 ) {
4820  /* resize if needed */
4821  if ( *out > (1<<15)-1 || *out < -(1<<15)+1 ) {
4822  INT32 *a, *b;
4823  INT32 n;
4824  INT32 num = *out;
4825  coeff += 6;
4826  end += 6;
4827  argEnd += 6;
4828  t += 6;
4829  if ( (UBYTE *)end > top ) return ( bin );
4830  --out;
4831  *out++ = 8; /* argument size */
4832  *out++ = 0; /* dirtyflag */
4833  *out++ = 6; /* term size */
4834  *out++ = ABS(num) & 0x0000FFFF;
4835  *out++ = ABS(num) >> 16;
4836  *out++ = 1;
4837  *out++ = 0;
4838  *out++ = ( num < 0 ) ? -5 : 5;
4839  a = ++r;
4840  b = out;
4841  n = rend - r;
4842  NCOPYI32(b, a, n)
4843  }
4844  else {
4845  ++out; ++r;
4846  }
4847  }
4848  else {
4849  ++out; ++r;
4850  }
4851  break;
4852  case VECTOR:
4853  ++out; ++r;
4854  AO.RenumberVec((UBYTE *)out);
4855  ++out; ++r;
4856  break;
4857  case INDEX:
4858  ++out; ++r;
4859  ++out; ++r;
4860  break;
4861  case MINVECTOR:
4862  ++out; ++r;
4863  AO.RenumberVec((UBYTE *)out);
4864  ++out; ++r;
4865  break;
4866  default:
4867  if ( -*out >= FUNCTION ) {
4868  ++out; ++r;
4869  break;
4870  } else {
4871  MesPrint("short function code %d not implemented.", *out);
4872  return ( (UBYTE *)in );
4873  }
4874  }
4875  }
4876  else {
4877  /* long arguments */
4878  INT32 *newargsize = out;
4879  argEnd = out + *out;
4880  ++out; ++r;
4881  ++out; ++r; /* dirty flags */
4882  while ( out < argEnd ) {
4883  INT32 *keepsizep = out + *out;
4884  INT32 lenbuf = *out;
4885  INT32 **ppp = &out; /* to avoid a compiler warning */
4886  /* recursion */
4887  newbin = ReadSaveTerm32((UBYTE *)r, binend, (UBYTE **)ppp, (UBYTE *)rend, top, 1);
4888  r += lenbuf;
4889  if ( newbin == (UBYTE *)r ) {
4890  return ( (UBYTE *)in );
4891  }
4892  /* if the term done by recursion has changed in size,
4893  we need to move the rest of the data accordingly */
4894  if ( out > keepsizep ) {
4895  INT32 *a, *b;
4896  INT32 n;
4897  INT32 extention = out - keepsizep;
4898  a = r;
4899  b = out;
4900  n = rend - r;
4901  NCOPYI32(b, a, n)
4902  coeff += extention;
4903  end += extention;
4904  argEnd += extention;
4905  t += extention;
4906  }
4907  else if ( out < keepsizep ) {
4908  INT32 *a, *b;
4909  INT32 n;
4910  INT32 extention = keepsizep - out;
4911  a = keepsizep;
4912  b = out;
4913  n = rend - r;
4914  NCOPYI32(b, a, n)
4915  coeff -= extention;
4916  end -= extention;
4917  argEnd -= extention;
4918  t -= extention;
4919  }
4920  }
4921  *newargsize = out - newargsize;
4922  }
4923  }
4924  }
4925  else {
4926  MesPrint("ID %d not recognized.", id);
4927  return ( (UBYTE *)in );
4928  }
4929 
4930  *newsubtermp = out - newsubtermp + 1;
4931  }
4932 
4933  if ( (UBYTE *)end >= top ) {
4934  return ( bin );
4935  }
4936 
4937  /* do coefficient and adjust term size */
4938  boutbuf = *bout;
4939  *bout = (UBYTE *)out;
4940 
4941  ResizeCoeff32(bout, (UBYTE *)end, top);
4942 
4943  if ( *bout >= top ) {
4944  *bout = boutbuf;
4945  return ( bin );
4946  }
4947 
4948  *newtermsize = (INT32 *)*bout - newtermsize;
4949 
4950  return ( (UBYTE *)in );
4951 }
4952 
4953 /*
4954  #] ReadSaveTerm :
4955  #[ ReadSaveExpression :
4956 */
4957 
4979 WORD ReadSaveExpression(UBYTE *buffer, UBYTE *top, LONG *size, LONG *outsize)
4980 {
4981  if ( AO.transFlag ) {
4982  UBYTE *in, *end, *out, *outend, *p;
4983  POSITION pos;
4984  LONG half;
4985  WORD lenW = AO.SaveHeader.lenWORD;
4986 
4987  /* remember the last file position in case an expression cannot be
4988  fully processed */
4989  TELLFILE(AO.SaveData.Handle,&pos);
4990 
4991  /* adjust 'size' depending on whether the translated data is bigger or
4992  smaller */
4993  half = (top-buffer)/2;
4994  if ( *size > half ) *size = half;
4995  if ( lenW < (WORD)sizeof(WORD) ) {
4996  if ( *size * (LONG)sizeof(WORD)/lenW > half ) *size = half*lenW/(LONG)sizeof(WORD);
4997  }
4998  else {
4999  if ( *size > half ) *size = half;
5000  }
5001 
5002  /* depending on the necessary resizing we position the input pointer
5003  either at the start of the buffer or in the middle. if the data will
5004  roughly remain the same size, we need only one processing step, so
5005  we put the 'in' at the middle and 'out' and the beginning. in the
5006  other cases we need two processing steps, so first we put 'in' at
5007  the beginning and write at the middle. the second step can then read
5008  from the middle and put its results at the beginning. */
5009  in = out = buffer;
5010  if ( lenW == sizeof(WORD) ) in += half;
5011  else out += half;
5012  end = in + *size;
5013  outend = out + *size;
5014 
5015  if ( ReadFile(AO.SaveData.Handle, in, *size) != *size ) {
5016  return ( MesPrint("Error(3) reading stored expression.") );
5017  }
5018 
5019  if ( AO.transFlag & 1 ) {
5020  p = in;
5021  end -= lenW;
5022  while ( p <= end ) {
5023  AO.FlipWORD(p); p += lenW;
5024  }
5025  end += lenW;
5026  }
5027 
5028  if ( lenW > (WORD)sizeof(WORD) ) {
5029  /* renumber first */
5030  do {
5031  outend = out+*size;
5032  if ( outend > top ) outend = top;
5033  p = ReadSaveTerm32(in, end, &out, outend, top, 0);
5034  if ( p == in ) break;
5035  in = p;
5036  } while ( in <= end - lenW );
5037  /* then resize */
5038  *size = in - buffer;
5039  in = buffer + half;
5040  end = out;
5041  out = buffer;
5042 
5043  while ( in < end ) {
5044  /* resize without checking */
5045  AO.ResizeNCWORD(in, out);
5046  in += lenW; out += sizeof(WORD);
5047  }
5048  }
5049  else {
5050  if ( lenW < (WORD)sizeof(WORD) ) {
5051  /* resize first */
5052  while ( in < end ) {
5053  AO.ResizeWORD(in, out);
5054  in += lenW; out += sizeof(WORD);
5055  }
5056  in = buffer + half;
5057  end = out;
5058  out = buffer;
5059  }
5060  /* then renumber */
5061  do {
5062  p = ReadSaveTerm32(in, end, &out, buffer+half, buffer+half, 0);
5063  if ( p == in ) break;
5064  in = p;
5065  } while ( in <= end - sizeof(WORD) );
5066  *size = (in - buffer - half) * lenW / (ULONG)sizeof(WORD);
5067  }
5068  *outsize = out - buffer;
5069  ADDPOS(pos, *size);
5070  SeekFile(AO.SaveData.Handle, &pos, SEEK_SET);
5071 
5072  return ( 0 );
5073  }
5074  else {
5075  return ( ReadFile(AO.SaveData.Handle, buffer, *size) != *size );
5076  }
5077 }
5078 
5079 /*
5080  #] ReadSaveExpression :
5081  #] System Independent Saved Expressions :
5082 */
WORD number
Definition: structs.h:467
UBYTE wildoffset[16]
Definition: structs.h:87
UBYTE sFun
Definition: structs.h:85
UBYTE * ReadSaveTerm32(UBYTE *bin, UBYTE *binend, UBYTE **bout, UBYTE *boutend, UBYTE *top, int terminbuf)
Definition: store.c:4570
#define INFILEINDEX
Definition: structs.h:118
Definition: structs.h:429
WORD flags
Definition: structs.h:468
WORD type
Definition: structs.h:240
WORD nsymbols
Definition: structs.h:104
Definition: structs.h:618
WORD nvectors
Definition: structs.h:106
POSITION position
Definition: structs.h:100
#define PHEAD
Definition: ftypes.h:56
VARRENUM indi
Definition: structs.h:181
LONG CompressSize
Definition: structs.h:103
VARRENUM vect
Definition: structs.h:182
POSITION next
Definition: structs.h:138
WORD number
Definition: structs.h:241
WORD node
Definition: structs.h:471
WORD ReadSaveIndex(FILEINDEX *fileind)
Definition: store.c:4024
UBYTE lenPOINTER
Definition: structs.h:80
UBYTE sVec
Definition: structs.h:84
UBYTE sInd
Definition: structs.h:83
POSITION variables
Definition: structs.h:102
UBYTE lenPOS
Definition: structs.h:79
struct ReNuMbEr * RENUMBER
SBYTE name[MAXENAME+1]
Definition: structs.h:109
WORD * vecnum
Definition: structs.h:187
INDEXENTRY expression[INFILEINDEX]
Definition: structs.h:140
WORD symmetric
Definition: structs.h:470
WORD * symnum
Definition: structs.h:185
UBYTE sSym
Definition: structs.h:82
UBYTE lenWORD
Definition: structs.h:77
WORD SetFileIndex()
Definition: store.c:2200
UBYTE lenLONG
Definition: structs.h:78
POSITION length
Definition: structs.h:101
WORD * hi
Definition: structs.h:168
POSITION number
Definition: structs.h:139
WORD ReadSaveExpression(UBYTE *buffer, UBYTE *top, LONG *size, LONG *outsize)
Definition: store.c:4979
WORD nindices
Definition: structs.h:105
WORD complex
Definition: structs.h:466
struct StOrEcAcHe * STORECACHE
WORD size
Definition: structs.h:108
LONG name
Definition: structs.h:464
WORD ReadSaveVariables(UBYTE *buffer, UBYTE *top, LONG *size, LONG *outsize, INDEXENTRY *ind, LONG *stage)
Definition: store.c:4210
WORD spec
Definition: structs.h:469
WORD * start
Definition: structs.h:166
WORD WriteStoreHeader(WORD handle)
Definition: store.c:3813
UBYTE endianness[16]
Definition: structs.h:81
WORD * indnum
Definition: structs.h:186
UBYTE maxpower[16]
Definition: structs.h:86
WORD namesize
Definition: structs.h:472
VARRENUM func
Definition: structs.h:183
struct FuNcTiOn * FUNCTIONS
WORD TermRenumber(WORD *term, RENUMBER renumber, WORD nexpr)
Definition: store.c:2307
struct FiLeInDeX FILEINDEX
WORD nfunctions
Definition: structs.h:107
int handle
Definition: structs.h:646
WORD ReadSaveHeader()
Definition: store.c:3906
VARRENUM symb
Definition: structs.h:180
WORD commute
Definition: structs.h:465
WORD * funnum
Definition: structs.h:188
WORD * lo
Definition: structs.h:167