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