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