• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vermaseren / form / 9364948935

04 Jun 2024 09:49AM UTC coverage: 49.979% (-0.02%) from 49.999%
9364948935

Pull #526

github

web-flow
Merge 7062bd769 into 83e3d4185
Pull Request #526: RFC: better debugging

52 of 415 new or added lines in 46 files covered. (12.53%)

32 existing lines in 2 files now uncovered.

41391 of 82816 relevant lines covered (49.98%)

878690.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

25.3
/sources/store.c
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-2023 J.A.M. Vermaseren
9
 *   When using this file you are requested to refer to the publication
10
 *   J.A.M.Vermaseren "New features of FORM" math-ph/0010025
11
 *   This is considered a matter of courtesy as the development was paid
12
 *   for by FOM the Dutch physics granting agency and we would like to
13
 *   be able to track its scientific use to convince FOM of its value
14
 *   for the community.
15
 *
16
 *   This file is part of FORM.
17
 *
18
 *   FORM is free software: you can redistribute it and/or modify it under the
19
 *   terms of the GNU General Public License as published by the Free Software
20
 *   Foundation, either version 3 of the License, or (at your option) any later
21
 *   version.
22
 *
23
 *   FORM is distributed in the hope that it will be useful, but WITHOUT ANY
24
 *   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
25
 *   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
26
 *   details.
27
 *
28
 *   You should have received a copy of the GNU General Public License along
29
 *   with FORM.  If not, see <http://www.gnu.org/licenses/>.
30
 */
31
/* #] License : */ 
32
/*
33
#define HIDEDEBUG
34
          #[ Includes : store.c
35
*/
36

37
#include "form3.h"
38

39
/*
40
          #] Includes : 
41
        #[ StoreExpressions :
42
                 #[ OpenTemp :
43

44
                Opens the scratch files for the input -> output operations.
45

46
*/
47

48
WORD OpenTemp(VOID)
3,499✔
49
{
50
        GETIDENTITY
1,030✔
51
        if ( AR.outfile->handle >= 0 ) {
3,499✔
52
                SeekFile(AR.outfile->handle,&(AR.outfile->filesize),SEEK_SET);
6✔
53
                AR.outfile->POposition = AR.outfile->filesize;
6✔
54
                AR.outfile->POfill = AR.outfile->PObuffer;
6✔
55
        }
56
        return(0);
3,499✔
57
}
58

59
/*
60
                 #] OpenTemp : 
61
                 #[ SeekScratch :
62
*/
63

64
VOID SeekScratch(FILEHANDLE *fi, POSITION *pos)
151,264✔
65
{
66
        *pos = fi->POposition;
151,264✔
67
        ADDPOS(*pos,(TOLONG(fi->POfill)-TOLONG(fi->PObuffer)));
151,264✔
68
}
151,264✔
69

70
/*
71
                 #] SeekScratch : 
72
                 #[ SetEndScratch :
73
*/
74

75
VOID SetEndScratch(FILEHANDLE *f, POSITION *position)
793✔
76
{
77
        if ( f->handle < 0 ) {
793✔
78
                SETBASEPOSITION(*position,(f->POfull-f->PObuffer)*sizeof(WORD));
793✔
79
        }
80
        else *position = f->filesize;
×
81
        SetScratch(f,position);
793✔
82
}
793✔
83

84
/*
85
                 #] SetEndScratch : 
86
                 #[ SetEndHScratch :
87
*/
88

89
VOID SetEndHScratch(FILEHANDLE *f, POSITION *position)
981✔
90
{
91
        if ( f->handle < 0 ) {
981✔
92
                SETBASEPOSITION(*position,(f->POfull-f->PObuffer)*sizeof(WORD));
981✔
93
                f->POfill = f->POfull;
981✔
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
}
981✔
109

110
/*
111
                 #] SetEndHScratch : 
112
                 #[ SetScratch :
113
*/
114

115
VOID SetScratch(FILEHANDLE *f, POSITION *position)
115,236✔
116
{
117
        GETIDENTITY
25,688✔
118
        POSITION possize;
115,236✔
119
        LONG size, *whichInInBuf;
115,236✔
120
        if ( f == AR.hidefile ) whichInInBuf = &(AR.InHiBuf);
115,236✔
121
        else                    whichInInBuf = &(AR.InInBuf);
115,207✔
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) ||
115,236✔
131
        ISGEPOSINC(*position,f->POposition,(f->POfull-f->PObuffer)*sizeof(WORD)) ) {
106,880✔
132
                if ( f->handle < 0 ) {
18,239✔
133
                        if ( ISEQUALPOSINC(*position,f->POposition,
2,822✔
134
                                (f->POfull-f->PObuffer)*sizeof(WORD)) ) goto endpos;
2,822✔
135
                        MesPrint("Illegal position in SetScratch");
×
NEW
136
                        TERMINATE(-1);
×
137
                }
138
                possize = *position;
15,417✔
139
                LOCK(AS.inputslock);
15,417✔
140
                SeekFile(f->handle,&possize,SEEK_SET);
15,417✔
141
                if ( ISNOTEQUALPOS(possize,*position) ) {
15,417✔
142
                        UNLOCK(AS.inputslock);
×
143
                        MesPrint("Cannot position file in SetScratch");
×
NEW
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
15,417✔
150
                || ( size & 1 ) != 0 ) {
15,417✔
151
                        UNLOCK(AS.inputslock);
×
152
                        MesPrint("Read error in SetScratch");
×
NEW
153
                        TERMINATE(-1);
×
154
                }
155
                UNLOCK(AS.inputslock);
15,417✔
156
                if ( size == 0 ) {
15,417✔
157
                        f->PObuffer[0] = 0;
6✔
158
                }
159
                f->POfill = f->PObuffer;
15,417✔
160
                f->POposition = *position;
15,417✔
161
#ifdef WORD2
162
                *whichInInBuf = size >> 1;
163
#else
164
                *whichInInBuf = size / TABLESIZE(WORD,UBYTE);
15,417✔
165
#endif
166
                f->POfull = f->PObuffer + *whichInInBuf;
15,417✔
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:
96,997✔
175
                DIFPOS(possize,*position,f->POposition);
99,819✔
176
                f->POfill = (WORD *)(BASEPOSITION(possize)+(UBYTE *)(f->PObuffer));
99,819✔
177
                *whichInInBuf = f->POfull-f->POfill;
99,819✔
178
        }
179
}
115,236✔
180

181
/*
182
                 #] SetScratch : 
183
                 #[ RevertScratch :
184

185
                Reverts the input/output directions. This way input comes
186
                always from AR.infile
187

188
*/
189

190
WORD RevertScratch(VOID)
3,453✔
191
{
192
        GETIDENTITY
1,020✔
193
        FILEHANDLE *f;
3,453✔
194
        if ( AR.infile->handle >= 0 && AR.infile->handle != AR.outfile->handle ) {
3,453✔
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;
3,453✔
200
        AR.infile->POfull = AR.infile->POfill;
3,453✔
201
        AR.infile->POfill = AR.infile->PObuffer;
3,453✔
202
        if ( AR.infile->handle >= 0 ) {
3,453✔
203
                POSITION scrpos;
6✔
204
                PUTZERO(scrpos);
6✔
205
                SeekFile(AR.infile->handle,&scrpos,SEEK_SET);
6✔
206
                if ( ISNOTZEROPOS(scrpos) ) {
6✔
207
                        return(MesPrint("Error with scratch output."));
×
208
                }
209
                if ( ( AR.InInBuf = ReadFile(AR.infile->handle,(UBYTE *)(AR.infile->PObuffer)
6✔
210
                        ,AR.infile->POsize) ) < 0 || AR.InInBuf & 1 ) {
12✔
211
                        return(MesPrint("Error while reading from scratch file"));
×
212
                }
213
                else {
214
                        AR.InInBuf /= TABLESIZE(WORD,UBYTE);
6✔
215
                }
216
                AR.infile->POfull = AR.infile->PObuffer + AR.InInBuf;
6✔
217
        }
218
        PUTZERO(AR.infile->POposition);
3,453✔
219
        AR.outfile->POfill = AR.outfile->POfull = AR.outfile->PObuffer;
3,453✔
220
        PUTZERO(AR.outfile->POposition);
3,453✔
221
        PUTZERO(AR.outfile->filesize);
3,453✔
222
        return(0);
3,453✔
223
}
224

225
/*
226
                 #] RevertScratch : 
227
                 #[ ResetScratch :
228

229
                Resets the output scratch file to its beginning in such a way
230
                that the write routines can read it. The output buffers are
231
                left untouched as they may still be needed for extra declarations.
232

233
*/
234

235
WORD ResetScratch(VOID)
1,966✔
236
{
237
        GETIDENTITY
990✔
238
        FILEHANDLE *f;
1,966✔
239
        if ( AR.infile->handle >= 0 ) {
1,966✔
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 ) {
1,966✔
246
                POSITION scrpos;
6✔
247
                PUTZERO(scrpos);
6✔
248
                SeekFile(AR.outfile->handle,&scrpos,SEEK_SET);
6✔
249
                if ( ISNOTZEROPOS(scrpos) ) {
6✔
250
                        return(MesPrint("Error with scratch output."));
×
251
                }
252
                if ( ( AR.InInBuf = ReadFile(AR.outfile->handle,(UBYTE *)(AR.outfile->PObuffer)
6✔
253
                ,AR.outfile->POsize) ) < 0 || AR.InInBuf & 1 ) {
12✔
254
                        return(MesPrint("Error while reading from scratch file"));
×
255
                }
256
                else AR.InInBuf /= TABLESIZE(WORD,UBYTE);
6✔
257
                AR.outfile->POfull = AR.outfile->PObuffer + AR.InInBuf;
6✔
258
        }
259
        else AR.outfile->POfull = AR.outfile->POfill;
1,960✔
260
        AR.outfile->POfill = AR.outfile->PObuffer;
1,966✔
261
        PUTZERO(AR.outfile->POposition);
1,966✔
262
        f = AR.outfile; AR.outfile = AR.infile; AR.infile = f;
1,966✔
263
        return(0);
1,966✔
264
}
265

266
/*
267
                 #] ResetScratch : 
268
                 #[ ReadFromScratch :
269

270
        Routine is used to copy files from scratch to hide.
271
*/
272

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

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

363
int CoSave(UBYTE *inp)
21✔
364
{
365
        GETIDENTITY
6✔
366
        UBYTE *p, c;
21✔
367
        WORD n = 0, i;
21✔
368
        WORD error = 0, type, number;
21✔
369
        WORD exprInStorageFlag = 0;
21✔
370
        LONG RetCode = 0, wSize;
21✔
371
        EXPRESSIONS e;
21✔
372
        INDEXENTRY *ind;
21✔
373
        INDEXENTRY *indold;
21✔
374
        WORD TMproto[SUBEXPSIZE];
21✔
375
        POSITION scrpos, scrpos1, filesize;
21✔
376
        int ii, j = sizeof(FILEINDEX)/(sizeof(LONG));
21✔
377
        LONG *lo;
21✔
378
        while ( *inp == ',' ) inp++;
21✔
379
        p = inp;
21✔
380

381
#ifdef WITHMPI
382
        if(        PF.me != MASTER) return(0);
12✔
383
#endif
384

385
        if ( !*p ) return(MesPrint("No filename in save statement"));
12✔
386
        if ( FG.cTable[*p] > 1 && ( *p != '.' ) && ( *p != SEPARATOR ) && ( *p != ALTSEPARATOR ) )
12✔
387
                                return(MesPrint("Illegal filename"));
×
388
        while ( *++p && *p != ',' ) {}
96✔
389
        c = *p;
12✔
390
        *p = 0;
12✔
391
        if ( !AP.preError ) {
12✔
392
                if ( ( RetCode = CreateFile((char *)inp) ) < 0 ) {
12✔
393
                        return(MesPrint("Cannot open file %s",inp));
×
394
                }
395
        }
396
        AO.SaveData.Handle = (WORD)RetCode;
12✔
397
        PUTZERO(filesize);
12✔
398

399
        e = Expressions;
12✔
400
        n = NumExpressions;
12✔
401
        if ( c ) {                        /* There follows a list of expressions */
12✔
402
                *p++ = c;
8✔
403
                inp = p;
8✔
404
                i = (WORD)(INFILEINDEX);
8✔
405
                if ( WriteStoreHeader(AO.SaveData.Handle) ) return(MesPrint("Error writing storage file header"));
8✔
406
/*                PUTZERO(AO.SaveData.Index.number); */
407
/*                PUTZERO(AO.SaveData.Index.next); */
408
                lo = (LONG *)(&AO.SaveData.Index);
409
                for ( ii = 0; ii < j; ii++ ) *lo++ = 0;
520✔
410
                SETBASEPOSITION(AO.SaveData.Position,(LONG)sizeof(STOREHEADER));
8✔
411
                ind = AO.SaveData.Index.expression;
8✔
412
                if ( !AP.preError && WriteFile(AO.SaveData.Handle,(UBYTE *)(&(AO.SaveData.Index))
8✔
413
                ,(LONG)sizeof(struct FiLeInDeX))!= (LONG)sizeof(struct FiLeInDeX) ) goto SavWrt;
×
414
                SeekFile(AO.SaveData.Handle,&(filesize),SEEK_END);
8✔
415
/*                ADDPOS(filesize,sizeof(struct FiLeInDeX)); */
416

417
                do {                        /* Scan the list */
8✔
418
                        if ( !FG.cTable[*p] || *p == '[' ) {
8✔
419
                                p = SkipAName(p);
8✔
420
                                if ( p == 0 ) return(-1);
8✔
421
                        }
422
                        c = *p; *p = 0;
8✔
423
                        if ( GetVar(inp,&type,&number,CEXPRESSION,NOAUTO) != NAMENOTFOUND ) {
8✔
424
                                if ( e[number].status == STOREDEXPRESSION ) {
8✔
425
                                        if ( StrLen(AC.exprnames->namebuffer+e[number].name) > MAXENAME ) {
8✔
426
                                                MesPrint("&Warning: saved expr name over %d char: %s", MAXENAME, AC.exprnames->namebuffer+e[number].name);
4✔
427
                                        }
428
/*
429
                Here we have to locate the stored expression, copy its index entry
430
                possibly after making a new fileindex and then copy the whole
431
                expression.
432
*/
433
                                        if ( AP.preError ) goto NextExpr;
8✔
434
                                        TMproto[0] = EXPRESSION;
8✔
435
                                        TMproto[1] = SUBEXPSIZE;
8✔
436
                                        TMproto[2] = number;
8✔
437
                                        TMproto[3] = 1;
8✔
438
                                        { int ie; for ( ie = 4; ie < SUBEXPSIZE; ie++ ) TMproto[ie] = 0; }
16✔
439
                                        AT.TMaddr = TMproto;
8✔
440
                                        if ( ( indold = FindInIndex(number,&AR.StoreData,0,0) ) != 0 ) {
8✔
441
                                                if ( i <= 0 ) {
8✔
442
/*
443
                                                        AO.SaveData.Index.next = filesize;
444
*/
445
                                                        SeekFile(AO.SaveData.Handle,&(AO.SaveData.Index.next),SEEK_END);
×
446
                                                        scrpos = AO.SaveData.Position;
×
447
                                                        SeekFile(AO.SaveData.Handle,&scrpos,SEEK_SET);
×
448
                                                        if ( ISNOTEQUALPOS(scrpos,AO.SaveData.Position) ) goto SavWrt;
×
449
                                                        if ( WriteFile(AO.SaveData.Handle,(UBYTE *)(&(AO.SaveData.Index))
×
450
                                                                        ,(LONG)sizeof(struct FiLeInDeX)) != (LONG)sizeof(struct FiLeInDeX) )
451
                                                                goto SavWrt;
×
452
                                                        i = (WORD)(INFILEINDEX);
×
453
                                                        AO.SaveData.Position = AO.SaveData.Index.next;
×
454
                                                        lo = (LONG *)(&AO.SaveData.Index);
×
455
                                                        for ( ii = 0; ii < j; ii++ ) *lo++ = 0;
×
456
                                                        ind = AO.SaveData.Index.expression;
×
457
                                                        scrpos = AO.SaveData.Position;
×
458
                                                        SeekFile(AO.SaveData.Handle,&scrpos,SEEK_SET);
×
459
                                                        if ( ISNOTEQUALPOS(scrpos,AO.SaveData.Position) ) goto SavWrt;
×
460
                                                        if ( WriteFile(AO.SaveData.Handle,(UBYTE *)(&(AO.SaveData.Index))
×
461
                                                        ,(LONG)sizeof(struct FiLeInDeX)) != (LONG)sizeof(struct FiLeInDeX) )
462
                                                                goto SavWrt;
×
463
                                                        ADDPOS(filesize,sizeof(struct FiLeInDeX));
×
464
                                                }
465
                                                *ind = *indold;
8✔
466
/*
467
                                                ind->variables = SeekFile(AO.SaveData.Handle,&(AM.zeropos),SEEK_END);
468
*/
469
                                                ind->variables = filesize;
8✔
470
                                                ind->position = ind->variables;
8✔
471
                                                ADDPOS(ind->position,DIFBASE(indold->position,indold->variables));
8✔
472
                                                SeekFile(AR.StoreData.Handle,&(indold->variables),SEEK_SET);
8✔
473
                                                wSize = TOLONG(AT.WorkTop) - TOLONG(AT.WorkPointer);
8✔
474
                                                scrpos = ind->length;
8✔
475
                                                ADDPOS(scrpos,DIFBASE(ind->position,ind->variables));
8✔
476
                                                ADD2POS(filesize,scrpos);
8✔
477
                                                SETBASEPOSITION(scrpos1,wSize);
8✔
478
                                                do {
8✔
479
                                                        if ( ISLESSPOS(scrpos,scrpos1) ) wSize = BASEPOSITION(scrpos);
8✔
480
                                                        if ( ReadFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,wSize)
8✔
481
                                                        != wSize ) {
482
                                                                MesPrint("ReadError");
×
483
                                                                error = -1;
×
484
                                                                goto EndSave;
×
485
                                                        }
486
                                                        if ( WriteFile(AO.SaveData.Handle,(UBYTE *)AT.WorkPointer,wSize)
8✔
487
                                                        != wSize ) goto SavWrt;
×
488
                                                        ADDPOS(scrpos,-wSize);
8✔
489
                                                } while ( ISPOSPOS(scrpos) );
8✔
490
                                                ADDPOS(AO.SaveData.Index.number,1);
8✔
491
                                                ind++;
8✔
492
                                        }
493
                                        else error = -1;
494
                                        i--;
8✔
495
                                }
496
                                else {
497
                                        MesPrint("%s is not a stored expression",inp);
×
498
                                        error = -1;
×
499
                                }
500
NextExpr:;
8✔
501
                        }
502
                        else {
503
                                MesPrint("%s is not an expression",inp);
×
504
                                error = -1;
×
505
                        }
506
                        *p = c;
8✔
507
                        if ( c != ',' && c ) {
8✔
508
                                MesComp("Illegal character",inp,p);
×
509
                                error = -1;
×
510
                                goto EndSave;
×
511
                        }
512
                        if ( c ) c = *++p;
8✔
513
                        inp = p;
8✔
514
                } while ( c );
8✔
515
                if ( !AP.preError ) {
8✔
516
                        scrpos = AO.SaveData.Position;
8✔
517
                        SeekFile(AO.SaveData.Handle,&scrpos,SEEK_SET);
8✔
518
                        if ( ISNOTEQUALPOS(scrpos,AO.SaveData.Position) ) goto SavWrt;
8✔
519
                }
520
                if ( !AP.preError &&
16✔
521
                WriteFile(AO.SaveData.Handle,(UBYTE *)(&(AO.SaveData.Index))
8✔
522
                        ,(LONG)sizeof(struct FiLeInDeX)) != (LONG)sizeof(struct FiLeInDeX) ) goto SavWrt;
×
523
        }
524
        else if ( !AP.preError ) {                                /* All stored expressions should be saved. Easy */
4✔
525
                /* Make sure there is at least one stored expression: */
526
                if ( n > 0 ) { do {
4✔
527
                        if ( StrLen(AC.exprnames->namebuffer+e->name) > MAXENAME ) {
8✔
528
                                MesPrint("&Warning: saved expr name over %d char: %s", MAXENAME, AC.exprnames->namebuffer+e->name);
4✔
529
                        }
530
                        if ( e->status == STOREDEXPRESSION ) exprInStorageFlag = 1;
8✔
531
                        e++;
8✔
532
                } while ( --n > 0 ); }
8✔
533
                if ( exprInStorageFlag ) {
4✔
534
                        wSize = TOLONG(AT.WorkTop) - TOLONG(AT.WorkPointer);
4✔
535
                        PUTZERO(scrpos);
4✔
536
                        SeekFile(AR.StoreData.Handle,&scrpos,SEEK_SET);                /* Start at the beginning */
4✔
537
                        scrpos = AR.StoreData.Fill;                        /* Number of bytes to be copied */
4✔
538
                        SETBASEPOSITION(scrpos1,wSize);
4✔
539
                        do {
4✔
540
                                if ( ISLESSPOS(scrpos,scrpos1) ) wSize = BASEPOSITION(scrpos);
4✔
541
                                if ( ReadFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,wSize) != wSize ) {
4✔
542
                                        MesPrint("ReadError");
×
543
                                        error = -1;
×
544
                                        goto EndSave;
×
545
                                }
546
                                if ( WriteFile(AO.SaveData.Handle,(UBYTE *)AT.WorkPointer,wSize) != wSize )
4✔
547
                                        goto SavWrt;
×
548
                                ADDPOS(scrpos,-wSize);
4✔
549
                        } while ( ISPOSPOS(scrpos) );
4✔
550
                }
551
        }
552
EndSave:
4✔
553
        if ( !AP.preError ) {
12✔
554
                CloseFile(AO.SaveData.Handle);
12✔
555
                AO.SaveData.Handle = -1;
12✔
556
        }
557
        return(error);
558
SavWrt:
×
559
        MesPrint("WriteError");
×
560
        error = -1;
×
561
        goto EndSave;
×
562
}
563

564
/*
565
                 #] CoSave : 
566
                 #[ CoLoad :
567
*/
568

569
int CoLoad(UBYTE *inp)
×
570
{
571
        GETIDENTITY
572
        INDEXENTRY *ind;
×
573
        LONG RetCode;
×
574
        UBYTE *p, c;
×
575
        WORD num, i, error = 0;
×
576
        WORD type, number, silentload = 0;
×
577
        WORD TMproto[SUBEXPSIZE];
×
578
        POSITION scrpos,firstposition;
×
579
        while ( *inp == ',' ) inp++;
×
580
        p = inp;
×
581
        if ( ( *p == ',' && p[1] == '-' ) || *p == '-' ) {
×
582
                if ( *p == ',' ) p++;
×
583
                p++;
×
584
                if ( *p == 's' || *p == 'S' ) {
×
585
                        silentload = 1;
×
586
                        while ( *p && ( *p != ',' && *p != '-' && *p != '+'
×
587
                        && *p != SEPARATOR && *p != ALTSEPARATOR && *p != '.' ) ) p++;
×
588
                }
589
                else if ( *p != ',' ) {
×
590
                        return(MesPrint("Illegal option in Load statement"));
×
591
                }
592
                while ( *p == ',' ) p++;
×
593
        }
594
        inp = p;
×
595
        if ( !*p ) return(MesPrint("No filename in load statement"));
×
596
        if ( FG.cTable[*p] > 1 && ( *p != '.' ) && ( *p != SEPARATOR ) && ( *p != ALTSEPARATOR ) )
×
597
                                return(MesPrint("Illegal filename"));
×
598
        while ( *++p && *p != ',' ) {}
×
599
        c = *p;
×
600
        *p = 0;
×
601
        if ( ( RetCode = OpenFile((char *)inp) ) < 0 ) {
×
602
                return(MesPrint("Cannot open file %s",inp));
×
603
        }
604
 
605
        if ( SetFileIndex() ) {
×
606
                MesCall("CoLoad");
×
607
                SETERROR(-1)
×
608
        }
609

610
        AO.SaveData.Handle = (WORD)(RetCode);
×
611

612
#ifdef SYSDEPENDENTSAVE
613
        if ( ReadFile(AO.SaveData.Handle,(UBYTE *)(&(AO.SaveData.Index)),
614
                (LONG)sizeof(struct FiLeInDeX)) != (LONG)sizeof(struct FiLeInDeX) ) goto LoadRead;
615
#else
616
        if ( ReadSaveHeader() ) goto LoadRead;
×
617
        TELLFILE(AO.SaveData.Handle,&firstposition);
×
618
        if ( ReadSaveIndex(&AO.SaveData.Index) ) goto LoadRead;
×
619
#endif
620
        if ( c ) {                        /* There follows a list of expressions */
×
621
                *p++ = c;
×
622
                inp = p;
×
623

624
                do {                        /* Scan the list */
×
625
                        if ( !FG.cTable[*p] || *p == '[' ) {
×
626
                                p = SkipAName(p);
×
627
                                if ( p == 0 ) return(-1);
×
628
                        }
629
                        c = *p; *p = 0;
×
630
                        if ( GetVar(inp,&type,&number,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
×
631
                                MesPrint("Conflicting name: %s",inp);
×
632
                                error = -1;
×
633
                        }
634
                        else {
635
                                if ( ( num = EntVar(CEXPRESSION,inp,STOREDEXPRESSION,0,0,0) ) >= 0 ) {
×
636
                                        TMproto[0] = EXPRESSION;
×
637
                                        TMproto[1] = SUBEXPSIZE;
×
638
                                        TMproto[2] = num;
×
639
                                        TMproto[3] = 1;
×
640
                                        { int ie; for ( ie = 4; ie < SUBEXPSIZE; ie++ ) TMproto[ie] = 0; }
×
641
                                        AT.TMaddr = TMproto;
×
642
                                        SeekFile(AO.SaveData.Handle,&firstposition,SEEK_SET);
×
643
                                        AO.SaveData.Position = firstposition;
×
644
                                        if ( ReadSaveIndex(&AO.SaveData.Index) ) goto LoadRead;
×
645
                                        if ( ( ind = FindInIndex(num,&AO.SaveData,1,0) ) != 0 ) {
×
646
                                                if ( !error ) {
×
647
                                                        if ( PutInStore(ind,num) ) error = -1;
×
648
                                                        else if ( !AM.silent && silentload == 0 )
×
649
                                                                MesPrint(" %s loaded",ind->name);
×
650
                                                }
651
/*
652
!!!        Added 1-feb-1998
653
*/
654
                                                Expressions[num].counter = -1;
×
655
                                        }
656
                                        else {
657
                                                MesPrint(" %s not found",inp);
×
658
                                                error = -1;
×
659
                                        }
660
                                }
661
                                else error = -1;
662
                        }
663
                        *p = c;
×
664
                        if ( c != ',' && c ) {
×
665
                                MesComp("Illegal character",inp,p);
×
666
                                error = -1;
×
667
                                goto EndLoad;
×
668
                        }
669
                        if ( c ) c = *++p;
×
670
                        inp = p;
×
671
                } while ( c );
×
672
                scrpos = AR.StoreData.Position;
×
673
                SeekFile(AR.StoreData.Handle,&scrpos,SEEK_SET);
×
674
                if ( ISNOTEQUALPOS(scrpos,AR.StoreData.Position) ) goto LoadWrt;
×
675
                if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&(AR.StoreData.Index))
×
676
                        ,(LONG)sizeof(struct FiLeInDeX)) != (LONG)sizeof(struct FiLeInDeX) ) goto LoadWrt;
×
677
        }
678
        else {                                /* All saved expressions should be stored. Easy */
679
                i = (WORD)BASEPOSITION(AO.SaveData.Index.number);
×
680
                ind = AO.SaveData.Index.expression;
×
681
#ifdef SYSDEPENDENTSAVE
682
                if ( i > 0 ) { do {
683
                        if ( GetVar((UBYTE *)(ind->name),&type,&number,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
684
                                MesPrint("Conflicting name: %s",ind->name);
685
                                error = -1;
686
                        }
687
                        else {
688
                                if ( ( num = EntVar(CEXPRESSION,(UBYTE *)(ind->name),STOREDEXPRESSION,0,0,0) ) >= 0 ) {
689
                                        if ( !error ) {
690
                                                if ( PutInStore(ind,num) ) error = -1;
691
                                                else if ( !AM.silent && silentload == 0 )
692
                                                        MesPrint(" %s loaded",ind->name);
693
                                        }
694
                                }
695
                                else error = -1;
696
                        }
697
                        i--;
698
                        if ( i == 0 && ISNOTZEROPOS(AO.SaveData.Index.next) ) {
699
                                SeekFile(AO.SaveData.Handle,&(AO.SaveData.Index.next),SEEK_SET);
700
                                if ( ReadFile(AO.SaveData.Handle,(UBYTE *)(&(AO.SaveData.Index)),
701
                                        (LONG)sizeof(struct FiLeInDeX)) != (LONG)sizeof(struct FiLeInDeX) ) goto LoadRead;
702
                                i = (WORD)BASEPOSITION(AO.SaveData.Index.number);
703
                                ind = AO.SaveData.Index.expression;
704
                        }
705
                        else ind++;
706
                } while ( i > 0 ); }
707
#else
708
                if ( i > 0 ) { 
×
709
                        do {
×
710
                                if ( GetVar((UBYTE *)(ind->name),&type,&number,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
×
711
                                        MesPrint("Conflicting name: %s",ind->name);
×
712
                                        error = -1;
×
713
                                }
714
                                else {
715
                                        if ( ( num = EntVar(CEXPRESSION,(UBYTE *)(ind->name),STOREDEXPRESSION,0,0,0) ) >= 0 ) {
×
716
                                                if ( !error ) {
×
717
                                                        if ( PutInStore(ind,num) ) error = -1;
×
718
                                                        else if ( !AM.silent && silentload == 0 )
×
719
                                                                MesPrint(" %s loaded",ind->name);
×
720
                                                }
721
                                        }
722
                                        else error = -1;
723
                                }
724
                                i--;
×
725
                                if ( i == 0 && (ISNOTZEROPOS(AO.SaveData.Index.next) || AO.bufferedInd) ) {
×
726
                                        SeekFile(AO.SaveData.Handle,&(AO.SaveData.Index.next),SEEK_SET);
×
727
                                        if ( ReadSaveIndex(&AO.SaveData.Index) ) goto LoadRead;
×
728
                                        i = (WORD)BASEPOSITION(AO.SaveData.Index.number);
×
729
                                        ind = AO.SaveData.Index.expression;
×
730
                                }
731
                                else ind++;
×
732
                        } while ( i > 0 );
×
733
                }
734
#endif
735
        }
736
EndLoad:
×
737
#ifndef SYSDEPENDENTSAVE
738
        if ( AO.powerFlag ) {
×
739
                MesPrint("WARNING: min-/maxpower had to be adjusted!");
×
740
        }
741
        if ( AO.resizeFlag ) {
×
742
                MesPrint("ERROR: could not downsize data!");
×
743
                return ( -2 );
×
744
        }
745
#endif
746
        CloseFile(AO.SaveData.Handle);
×
747
        AO.SaveData.Handle = -1;
×
748
        SeekFile(AR.StoreData.Handle,&(AC.StoreFileSize),SEEK_END);
×
749
        return(error);
×
750
LoadWrt:
×
751
        MesPrint("WriteError");
×
752
        error = -1;
×
753
        goto EndLoad;
×
754
LoadRead:
×
755
        MesPrint("ReadError");
×
756
        error = -1;
×
757
        goto EndLoad;
×
758
}
759

760
/*
761
                 #] CoLoad : 
762
                 #[ DeleteStore :
763

764
                Routine deletes the contents of the entire storage file.
765
                We close the file and recreate it.
766
                If par > 0 we have to remove the expressions from the namelists.
767
*/
768

769
WORD DeleteStore(WORD par)
×
770
{
771
        GETIDENTITY
772
        char *s;
×
773
        WORD j, n = 0;
×
774
        EXPRESSIONS e_in, e_out;
×
775
        WORD DidClean = 0;
×
776
        if ( AR.StoreData.Handle >= 0 ) {
×
777
                if ( par > 0 ) {
×
778
                        n = NumExpressions;
×
779
                        j = 0;
×
780
                        e_in = e_out = Expressions;
×
781
                        if ( n > 0 ) { do {
×
782
                                if ( e_in->status == STOREDEXPRESSION ) {
×
783
                                        NAMENODE *node = GetNode(AC.exprnames,
×
784
                                                        AC.exprnames->namebuffer+e_in->name);
×
785
                                        node->type = CDELETE;
×
786
                                        DidClean = 1;
×
787
                                }
788
                                else {
789
                                        if ( e_out != e_in ) {
×
790
                                                NAMENODE *node;
×
791
                                                node = GetNode(AC.exprnames,
×
792
                                                        AC.exprnames->namebuffer+e_in->name);
×
793
                                                node->number = (WORD)(e_out - Expressions);
×
794
                                                e_out->onfile = e_in->onfile;
×
795
                                                e_out->prototype = e_in->prototype;
×
796
                                                e_out->printflag = 0;
×
797
                                                e_out->status = e_in->status;
×
798
                                                e_out->name = e_in->name;
×
799
                                                e_out->inmem = e_in->inmem;
×
800
                                                e_out->counter = e_in->counter;
×
801
                                                e_out->numfactors = e_in->numfactors;
×
802
                                                e_out->numdummies = e_in->numdummies;
×
803
                                                e_out->compression = e_in->compression;
×
804
                                                e_out->namesize = e_in->namesize;
×
805
                                                e_out->whichbuffer = e_in->whichbuffer;
×
806
                                                e_out->hidelevel = e_in->hidelevel;
×
807
                                                e_out->node = e_in->node;
×
808
                                                e_out->replace = e_in->replace;
×
809
                                                e_out->vflags = e_in->vflags;
×
810
                                                e_out->uflags = e_in->uflags;
×
811
#ifdef PARALLELCODE
812
                                                e_out->partodo = e_in->partodo;
813
#endif
814
                                        }
815
                                        e_out++;
×
816
                                        j++;
×
817
                                }
818
                                e_in++;
×
819
                        } while ( --n > 0 ); }
×
820
                        NumExpressions = j;
×
821
                        if ( DidClean ) CompactifyTree(AC.exprnames,EXPRNAMES);
×
822
                }
823
                AR.StoreData.Handle = -1;
×
824
                CloseFile(AC.StoreHandle);
×
825
                AC.StoreHandle = -1;
×
826
                {
827
/*
828
                        Knock out the storage caches (25-apr-1990!)
829
*/
830
                        STORECACHE st;
×
831
                        st = (STORECACHE)(AT.StoreCache);
×
832
                        while ( st ) {
×
833
                                SETBASEPOSITION(st->position,-1);
×
834
                                SETBASEPOSITION(st->toppos,-1);
×
835
                                st = st->next;
×
836
                        }
837
#ifdef WITHPTHREADS
838
                        for ( j = 1; j < AM.totalnumberofthreads; j++ ) {
839
                                st = (STORECACHE)(AB[j]->T.StoreCache);
840
                                while ( st ) {
841
                                        SETBASEPOSITION(st->position,-1);
842
                                        SETBASEPOSITION(st->toppos,-1);
843
                                        st = st->next;
844
                                }
845
                        }
846
#endif
847
                }
848
                PUTZERO(AC.StoreFileSize);
×
849
                s = FG.fname; while ( *s ) s++;
×
850
#ifdef VMS
851
                *s = ';'; s[1] = '*'; s[2] = 0;
852
                remove(FG.fname);
853
                *s = 0;
854
#endif
855
                return(AC.StoreHandle = CreateFile(FG.fname));
×
856
        }
857
        else return(0);
858
}
859

860
/*
861
                 #] DeleteStore : 
862
                 #[ PutInStore :
863

864
                Copies the expression indicated by ind from a load file to the
865
                internal storage file. A return value of zero indicates that
866
                everything is OK.
867

868
*/
869

870
WORD PutInStore(INDEXENTRY *ind, WORD num)
×
871
{
872
        GETIDENTITY
873
        INDEXENTRY *newind;
×
874
        LONG wSize;
×
875
#ifndef SYSDEPENDENTSAVE
876
        LONG wSizeOut;
×
877
        LONG stage;
×
878
#endif
879
        POSITION scrpos,scrpos1;
×
880
        newind = NextFileIndex(&(Expressions[num].onfile));
×
881
        *newind = *ind;
×
882
#ifndef SYSDEPENDENTSAVE
883
        SETBASEPOSITION(newind->length, 0);
×
884
#endif
885
        newind->variables = AR.StoreData.Fill;
×
886
        SeekFile(AR.StoreData.Handle,&(newind->variables),SEEK_SET);
×
887
        if ( ISNOTEQUALPOS(newind->variables,AR.StoreData.Fill) ) goto PutErrS;
×
888
        newind->position = newind->variables;
×
889
#ifdef SYSDEPENDENTSAVE
890
        ADDPOS(newind->position,DIFBASE(ind->position,ind->variables));
891
#endif
892
        /* set read position to ind->variables */
893
        scrpos = ind->variables;
×
894
        SeekFile(AO.SaveData.Handle,&scrpos,SEEK_SET);
×
895
        if ( ISNOTEQUALPOS(scrpos,ind->variables) ) goto PutErrS;
×
896
        /* set max size for read-in */
897
        wSize = TOLONG(AT.WorkTop) - TOLONG(AT.WorkPointer);
×
898
#ifdef SYSDEPENDENTSAVE
899
        scrpos = ind->length;
900
        ADDPOS(scrpos,DIFBASE(ind->position,ind->variables));
901
        ADD2POS(AR.StoreData.Fill,scrpos);
902
#endif
903
        SETBASEPOSITION(scrpos1,wSize);
×
904
#ifndef SYSDEPENDENTSAVE
905
        /* prepare look-up table for tensor functions */
906
        if ( ind->nfunctions ) {
×
907
                AO.tensorList = (UBYTE *)Malloc1(MAXSAVEFUNCTION,"PutInStore");
×
908
        }
909
        SETBASEPOSITION(scrpos, DIFBASE(ind->position,ind->variables));
×
910
        /* copy variables first */
911
        stage = -1;
×
912
        do {
×
913
                wSize = TOLONG(AT.WorkTop) - TOLONG(AT.WorkPointer);
×
914
                if ( ISLESSPOS(scrpos,scrpos1) ) wSize = BASEPOSITION(scrpos);
×
915
                wSizeOut = wSize;
×
916
                if ( ReadSaveVariables(
×
917
                        (UBYTE *)AT.WorkPointer, (UBYTE *)AT.WorkTop, &wSize, &wSizeOut, ind, &stage) ) {
918
                        goto PutErrS;
×
919
                }
920
                if ( WriteFile(AR.StoreData.Handle, (UBYTE *)AT.WorkPointer, wSizeOut)
×
921
                != wSizeOut ) goto PutErrS;
×
922
                ADDPOS(scrpos,-wSize);
×
923
                ADDPOS(newind->position, wSizeOut);
×
924
                ADDPOS(AR.StoreData.Fill, wSizeOut);
×
925
        } while ( ISPOSPOS(scrpos) );
×
926
        /* then copy the expression itself */
927
        wSize = TOLONG(AT.WorkTop) - TOLONG(AT.WorkPointer);
×
928
        scrpos = ind->length;
×
929
#endif
930
        do {
×
931
                wSize = TOLONG(AT.WorkTop) - TOLONG(AT.WorkPointer);
×
932
                if ( ISLESSPOS(scrpos,scrpos1) ) wSize = BASEPOSITION(scrpos);
×
933
#ifdef SYSDEPENDENTSAVE
934
                if ( ReadFile(AO.SaveData.Handle,(UBYTE *)AT.WorkPointer,wSize)
935
                != wSize ) goto PutErrS;
936
                if ( WriteFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,wSize)
937
                != wSize ) goto PutErrS;
938
                ADDPOS(scrpos,-wSize);
939
#else
940
                wSizeOut = wSize;
×
941

942
                if ( ReadSaveExpression((UBYTE *)AT.WorkPointer, (UBYTE *)AT.WorkTop, &wSize, &wSizeOut) ) {
×
943
                        goto PutErrS;
×
944
                }
945

946
                if ( WriteFile(AR.StoreData.Handle, (UBYTE *)AT.WorkPointer, wSizeOut)
×
947
                != wSizeOut ) goto PutErrS;
×
948
                ADDPOS(scrpos,-wSize);
×
949
                ADDPOS(AR.StoreData.Fill, wSizeOut);
×
950
                ADDPOS(newind->length, wSizeOut);
×
951
#endif
952
        } while ( ISPOSPOS(scrpos) );
×
953
        /* free look-up table for tensor functions */
954
        if ( ind->nfunctions ) {
×
955
                M_free(AO.tensorList,"PutInStore");
×
956
        }
957
        scrpos = AR.StoreData.Position;
×
958
        SeekFile(AR.StoreData.Handle,&scrpos,SEEK_SET);
×
959
        if ( ISNOTEQUALPOS(scrpos,AR.StoreData.Position) ) goto PutErrS;
×
960
        if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&AR.StoreData.Index),(LONG)sizeof(FILEINDEX))
×
961
        == (LONG)sizeof(FILEINDEX) ) return(0);
962
PutErrS:
×
963
        return(MesPrint("File error"));
×
964
}
965

966
/*
967
                 #] PutInStore : 
968
                 #[ GetTerm :
969

970
                Gets one term from input scratch stream.
971
                Puts it in 'term'.
972
                Returns the length of the term.
973

974
                Used by Processor        (proces.c)
975
                        WriteAll         (sch.c)
976
                        WriteOne         (sch.c)
977
                        GetMoreTerms     (store.c)
978
                        ToStorage        (store.c)
979
                        CoFillExpression (comexpr.c)
980
                                FactorInExpr     (factor.c)
981
                        LoadOpti         (optim.c)
982
                                PF_Processor     (parallel.c)
983
                                ThreadsProcessor (threads.c)
984
                In multi thread/processor mode all calls are done by the master.
985
                Note however that other routines, used by the threads, can use
986
                the same file. Hence we need to be careful about SeekFile and locks.
987
*/
988
 
989
WORD GetTerm(PHEAD WORD *term)
305,791✔
990
{
991
        GETBIDENTITY
992
        WORD *inp, i, j = 0, len;
305,791✔
993
        LONG InIn, *whichInInBuf;
305,791✔
994
        WORD *r, *m, *mstop = 0, minsiz = 0, *bra = 0, *from;
305,791✔
995
        WORD first, *start = 0, testing = 0;
305,791✔
996
        FILEHANDLE *fi;
305,791✔
997
        AN.deferskipped = 0;
305,791✔
998
        if ( AR.GetFile == 2 ) {
305,791✔
999
                fi = AR.hidefile;
12✔
1000
                whichInInBuf = &(AR.InHiBuf);
12✔
1001
        }
1002
        else {
1003
                fi = AR.infile;
305,779✔
1004
                whichInInBuf = &(AR.InInBuf);
305,779✔
1005
        }
1006
        InIn = *whichInInBuf;
305,791✔
1007
        from = term;
305,791✔
1008
        if ( AR.KeptInHold ) {
305,791✔
1009
                r = AR.CompressBuffer;
335✔
1010
                i = *r;
335✔
1011
                AR.KeptInHold = 0;
335✔
1012
                if ( i <= 0 ) { *term = 0; goto RegRet; }
335✔
1013
                m = term;
1014
                NCOPY(m,r,i);
374✔
1015
                goto RegRet;
15✔
1016
        }
1017
        if ( AR.DeferFlag ) {
305,456✔
1018
                m = AR.CompressBuffer;
56✔
1019
                if ( *m > 0 ) {
56✔
1020
                        mstop = m + *m;
56✔
1021
                        mstop -= ABS(mstop[-1]);
56✔
1022
                        m++;
56✔
1023
                        while ( m < mstop ) {
152✔
1024
                                if ( *m == HAAKJE ) {
142✔
1025
                                        testing = 1;
46✔
1026
                                        mstop = m + m[1];
46✔
1027
                                    bra = (WORD *)(((UBYTE *)(term)) + 2*AM.MaxTer);
46✔
1028
                                        m = AR.CompressBuffer+1;
46✔
1029
                                        r = bra;
46✔
1030
                                        while ( m < mstop ) *r++ = *m++;
505✔
1031
                                        mstop = r;
46✔
1032
                                        minsiz = WORDDIF(mstop,bra);
46✔
1033
                                        goto ReStart;
46✔
1034
/*
1035
                                        We have the bracket to be tested in bra till mstop
1036
*/
1037
                                }
1038
                                m += m[1];
96✔
1039
                        }
1040
                }
1041
            bra = (WORD *)(((UBYTE *)(term)) + 2*AM.MaxTer);
10✔
1042
                mstop = bra+1;
10✔
1043
                *bra = 0;
10✔
1044
                minsiz = 1;
10✔
1045
                testing = 1;
10✔
1046
        }
1047
ReStart:
305,456✔
1048
        first = 0;
305,559✔
1049
        r = AR.CompressBuffer;
305,559✔
1050
        if ( fi->handle >= 0 ) {
305,559✔
1051
                if ( InIn <= 0 ) {
60,012✔
1052
                        ADDPOS(fi->POposition,(fi->POfull-fi->PObuffer)*sizeof(WORD));
2✔
1053
                        LOCK(AS.inputslock);
2✔
1054
                        SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
2✔
1055
                        InIn = ReadFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize);
2✔
1056
                        UNLOCK(AS.inputslock);
2✔
1057
                        if ( ( InIn < 0 ) || ( InIn & 1 ) ) {
2✔
1058
                                goto GTerr;
×
1059
                        }
1060
#ifdef WORD2
1061
                        InIn >>= 1;
1062
#else
1063
                        InIn /= TABLESIZE(WORD,UBYTE);
2✔
1064
#endif
1065
                        *whichInInBuf = InIn;
2✔
1066
                        if ( !InIn ) { *r = 0; *from = 0; goto RegRet; }
2✔
1067
                        fi->POfill = fi->PObuffer;
2✔
1068
                        fi->POfull = fi->PObuffer + InIn;
2✔
1069
                }
1070
                inp = fi->POfill;
60,012✔
1071
                if ( ( len = i = *inp ) == 0 ) {
60,012✔
1072
                        (*whichInInBuf)--;
4✔
1073
                        (fi->POfill)++;
4✔
1074
                        *r = 0;
4✔
1075
                        *from = 0;
4✔
1076
                        goto RegRet;
4✔
1077
                }
1078
                if ( i < 0 ) {
60,008✔
1079
                        InIn--;
59,994✔
1080
                        inp++;
59,994✔
1081
                        r++;
59,994✔
1082
                        start = term;
59,994✔
1083
                        *term++ = -i + 1;
59,994✔
1084
                        while ( ++i <= 0 ) *term++ = *r++;
686,070✔
1085
                        if ( InIn > 0 ) {
59,994✔
1086
                                i = *inp++;
59,989✔
1087
                                InIn--;
59,989✔
1088
                                *start += i;
59,989✔
1089
                                *(AR.CompressBuffer) = len = *start;
59,989✔
1090
                        }
1091
                        else {
1092
                                first = 1;
5✔
1093
                                goto NewIn;
5✔
1094
                        }
1095
                }
1096
                InIn -= i;
60,003✔
1097
                if ( InIn < 0 ) {
60,003✔
1098
                        j = (WORD)(- InIn);
77✔
1099
                        i -= j;
77✔
1100
                }
1101
                else j = 0;
60,003✔
1102
                while ( --i >= 0 ) {
303,710✔
1103
                                *r++ = *term++ = *inp++;
243,707✔
1104
                }
1105
                if ( j ) {
60,003✔
1106
NewIn:
77✔
1107
                        ADDPOS(fi->POposition,(fi->POfull-fi->PObuffer)*sizeof(WORD));
82✔
1108
                        LOCK(AS.inputslock);
82✔
1109
                        SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
82✔
1110
                        InIn = ReadFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize);
82✔
1111
                        UNLOCK(AS.inputslock);
82✔
1112
                        if ( ( InIn <= 0 ) || ( InIn & 1 ) ) {
82✔
1113
                                goto GTerr;
×
1114
                        }
1115
#ifdef WORD2
1116
                        InIn >>= 1;
1117
#else
1118
                        InIn /= TABLESIZE(WORD,UBYTE);
82✔
1119
#endif
1120
                        inp = fi->PObuffer;
82✔
1121
                        fi->POfull = inp + InIn;
82✔
1122

1123
                        if ( first ) {
82✔
1124
                                j = *inp++;
5✔
1125
                                InIn--;
5✔
1126
                                *start += j;
5✔
1127
                                *(AR.CompressBuffer) = len = *start;
5✔
1128
                        }
1129
                        InIn -= j;
82✔
1130
                        while ( --j >= 0 ) { *r++ = *term++ = *inp++; }
377✔
1131
                }
1132
                fi->POfill = inp;
60,008✔
1133
                *whichInInBuf = InIn;
60,008✔
1134
                AR.DefPosition = fi->POposition;
60,008✔
1135
                ADDPOS(AR.DefPosition,((UBYTE *)(fi->POfill)-(UBYTE *)(fi->PObuffer)));
60,008✔
1136
        }
1137
        else {
1138
                inp = fi->POfill;
245,547✔
1139
                if ( inp >= fi->POfull ) { *from = 0; goto RegRet; }
245,547✔
1140
                len = j = *inp;
244,542✔
1141
                if ( j < 0 ) {
244,542✔
1142
                        inp++;
192,419✔
1143
                        *term++ = *r++ = len = - j + 1 + *inp;
192,419✔
1144
                        while ( ++j <= 0 ) *term++ = *r++;
1,604,025✔
1145
                        j = *inp++;
192,419✔
1146
                }
1147
                else if ( !j ) j = 1;
52,123✔
1148
                while ( --j >= 0 ) { *r++ = *term++ = *inp++; }
22,067,530✔
1149
                fi->POfill = inp;
244,542✔
1150
/*%%%%%ADDED 7-apr-2006 for Keep Brackets in bucket */
1151
                SETBASEPOSITION(AR.DefPosition,((UBYTE *)(fi->POfill)-(UBYTE *)(fi->PObuffer)));
244,542✔
1152
                if ( inp > fi->POfull ) {
244,542✔
1153
                        goto GTerr;
×
1154
                }
1155
        }
1156
        if ( r >= AR.ComprTop ) {
304,550✔
1157
                MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
×
NEW
1158
                TERMINATE(-1);
×
1159
        }
1160
        AR.CompressPointer = r; *r = 0;
304,550✔
1161
/*
1162
                The next *from is a bug fix that made the program read in forbidden
1163
                territory.
1164
*/
1165
        if ( testing && *from != 0 ) {
304,550✔
1166
                WORD jj;
149✔
1167
                r = from;
149✔
1168
                jj = *r - 1 - ABS(*(r+*r-1));
149✔
1169
                if ( jj < minsiz ) goto strip;
149✔
1170
                r++;
149✔
1171
                m = bra;
149✔
1172
                while ( m < mstop ) {
875✔
1173
                        if ( *m != *r ) {
772✔
1174
strip:                        r = from;
46✔
1175
                                m = r + *r;
46✔
1176
                                mstop = m - ABS(m[-1]);
46✔
1177
                                r++;
46✔
1178
                                while ( r < mstop ) {
132✔
1179
                                        if ( *r == HAAKJE ) {
132✔
1180
                                                *r++ = 1;
46✔
1181
                                                *r++ = 1;
46✔
1182
                                                *r++ = 3;
46✔
1183
                                                len = WORDDIF(r,from);
46✔
1184
                                                *from = len;
46✔
1185
                                                goto RegRet;
46✔
1186
                                        }
1187
                                        r += r[1];
86✔
1188
                                }
1189
                                goto RegRet;
×
1190
                        }
1191
                        m++;
726✔
1192
                        r++;
726✔
1193
                }
1194
                term = from;
103✔
1195
                AN.deferskipped++;
103✔
1196
                goto ReStart;
103✔
1197
        }
1198
RegRet:;
304,401✔
1199
/*
1200
                        #[ debug :
1201
*/
1202
        {
1203
                UBYTE OutBuf[140];
305,791✔
1204
/*                if ( AP.DebugFlag ) { */
1205
                if ( ( AP.PreDebug & DUMPINTERMS ) == DUMPINTERMS ) {
305,791✔
1206
                        MLOCK(ErrorMessageLock);
×
1207
                        AO.OutFill = AO.OutputLine = OutBuf;
×
1208
                        AO.OutSkip = 3;
×
1209
                        FiniLine();
×
1210
                        r = from;
×
1211
                        i = *r;
×
1212
                        TokenToLine((UBYTE *)("Input: "));
×
1213
                        if ( i == 0 ) {
×
1214
                                TokenToLine((UBYTE *)"zero");
×
1215
                        }
1216
                        else if ( i < 0 ) {
×
1217
                                TokenToLine((UBYTE *)"negative!!");
×
1218
                        }
1219
                        else {
1220
                                while ( --i >= 0 ) {
×
1221
                                        TalToLine((UWORD)(*r++)); TokenToLine((UBYTE *)"  ");
×
1222
                                }
1223
                        }
1224
                        FiniLine();
×
1225
                        MUNLOCK(ErrorMessageLock);
91,849✔
1226
                }
1227
        }
1228
/*
1229
                        #] debug : 
1230
*/
1231
        return(*from);
305,791✔
1232
GTerr:
×
1233
        MesPrint("Error while reading scratch file in GetTerm");
×
NEW
1234
        TERMINATE(-1);
×
1235
        return(-1);
×
1236
}
1237

1238
/*
1239
                 #] GetTerm : 
1240
                 #[ GetOneTerm :
1241

1242
                Gets one term from stream AR.infile->handle.
1243
                Puts it in 'term'.
1244
                Returns the length of the term.
1245
                Input is unbuffered.
1246
                Compression via AR.CompressPointer
1247
                par is actually in all calls a file handle
1248

1249
                Routine is called from
1250
                        DoOnePow           Get one power of an expression
1251
                        Deferred           Get the contents of a bracket
1252
                        GetFirstBracket
1253
                        FindBracket
1254
                We should do something about the lack of buffering.
1255
                Maybe a buffer of a few times AM.MaxTer (MaxTermSize*sizeof(WORD)).
1256
                Each thread will need its own buffer!
1257

1258
                If par == 0 we use ReadPosFile which can fill the whole buffer.
1259
                If par == 1 we use ReadFile and do actual read operations.
1260

1261
                Note: we cannot use ReadPosFile when running in the master thread.
1262
*/
1263

1264
WORD GetOneTerm(PHEAD WORD *term, FILEHANDLE *fi, POSITION *pos, int par)
9,215,277✔
1265
{
1266
        GETBIDENTITY
1267
        WORD i, *p;
9,215,277✔
1268
        LONG j, siz;
9,215,277✔
1269
        WORD *r, *rr = AR.CompressPointer;
9,215,277✔
1270
        int error = 0;
9,215,277✔
1271
        r = rr;
9,215,277✔
1272
        if ( fi->handle >= 0 ) {
9,215,277✔
1273
#ifdef READONEBYONE
1274
#ifdef WITHPTHREADS
1275
/*
1276
                This code needs some investigation.
1277
                It may be that we should do this always.
1278
                It may be that even for workers it is no good.
1279
                We may have to make a variable like AM.ReadDirect with
1280
                if ( AM.ReadDirect ) par = 1;
1281
                and a user command like
1282
                On ReadDirect;
1283
*/
1284
                if ( AT.identity > 0 ) par = 1;
1285
#endif
1286
#endif
1287
/*
1288
                To be changed:
1289
                1: check first whether the term lies completely inside the buffer
1290
                2: if not a: use old strategy for AT.identity == 0 (master)
1291
                          b: for workers, position file and read buffer
1292
*/
1293
                if ( par == 0 ) {
3,030,000✔
1294
                        siz = ReadPosFile(BHEAD fi,(UBYTE *)term,1L,pos);
3,030,000✔
1295
                }
1296
                else {
1297
                        LOCK(AS.inputslock);
×
1298
                        SeekFile(fi->handle,pos,SEEK_SET);
×
1299
                        siz = ReadFile(fi->handle,(UBYTE *)term,sizeof(WORD));
×
1300
                        UNLOCK(AS.inputslock);
×
1301
                        ADDPOS(*pos,siz);
×
1302
                }
1303
                if ( siz == sizeof(WORD) ) {
3,030,000✔
1304
                        p = term;
3,030,000✔
1305
                        j = i = *term++;
3,030,000✔
1306
                        if ( ( i > AM.MaxTer/((WORD)sizeof(WORD)) ) || ( -i >= AM.MaxTer/((WORD)sizeof(WORD)) ) )
3,030,000✔
1307
                        {
1308
                                error = 1;
×
1309
                                goto ErrGet;
×
1310
                        }
1311
                        r++;
3,030,000✔
1312
                        if ( i < 0 ) {
3,030,000✔
1313
                                *p = -i + 1;
3,029,400✔
1314
                                while ( ++i <= 0 ) *term++ = *r++;
38,907,000✔
1315
                                if ( par == 0 ) {
3,029,400✔
1316
                                        siz = ReadPosFile(BHEAD fi,(UBYTE *)term,1L,pos);
3,029,400✔
1317
                                }
1318
                                else {
1319
                                        LOCK(AS.inputslock);
×
1320
                                        SeekFile(fi->handle,pos,SEEK_SET);
×
1321
                                        siz = ReadFile(fi->handle,(UBYTE *)term,sizeof(WORD));
×
1322
                                        UNLOCK(AS.inputslock);
×
1323
                                        ADDPOS(*pos,sizeof(WORD));
×
1324
                                }
1325
                                if ( siz != sizeof(WORD) ) {
3,029,400✔
1326
                                        error = 2;
×
1327
                                        goto ErrGet;
×
1328
                                }
1329
                                *p += *term;
3,029,400✔
1330
                                j = *term;
3,029,400✔
1331
                                if ( ( j > AM.MaxTer/((WORD)sizeof(WORD)) ) || ( j <= 0 ) )
3,029,400✔
1332
                                {
1333
                                        error = 3;
×
1334
                                        goto ErrGet;
×
1335
                                }
1336
                                *rr = *p;
3,029,400✔
1337
                        }
1338
                        else {
1339
                                if ( !j ) return(0);
600✔
1340
                                j--;
300✔
1341
                        }
1342
                        i = (WORD)j;
3,029,700✔
1343
                        if ( par == 0 ) {
3,029,700✔
1344
                                siz = ReadPosFile(BHEAD fi,(UBYTE *)term,j,pos);
3,029,700✔
1345
                                j *= TABLESIZE(WORD,UBYTE);
3,029,700✔
1346
                        }
1347
                        else {
1348
                                j *= TABLESIZE(WORD,UBYTE);
×
1349
                                LOCK(AS.inputslock);
×
1350
                                SeekFile(fi->handle,pos,SEEK_SET);
×
1351
                                siz = ReadFile(fi->handle,(UBYTE *)term,j);
×
1352
                                UNLOCK(AS.inputslock);
×
1353
                                ADDPOS(*pos,j);
×
1354
                        }
1355
                        if ( siz != j ) {
3,029,700✔
1356
                                error = 4;
×
1357
                                goto ErrGet;
×
1358
                        }
1359
                        while ( --i >= 0 ) *r++ = *term++;
15,627,300✔
1360
                        if ( r >= AR.ComprTop ) {
3,029,700✔
1361
                                MLOCK(ErrorMessageLock);
×
1362
                                MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
×
1363
                                MUNLOCK(ErrorMessageLock);
×
NEW
1364
                                TERMINATE(-1);
×
1365
                        }
1366
                        AR.CompressPointer = r; *r = 0;
3,029,700✔
1367
                        return(*p);
3,029,700✔
1368
                }
1369
                error = 5;
1370
        }
1371
        else {
1372
/*
1373
                Here the whole expression is in the buffer.
1374
*/
1375
                fi->POfill = (WORD *)((UBYTE *)(fi->PObuffer) + BASEPOSITION(*pos));
6,185,277✔
1376
                p = fi->POfill;
6,185,277✔
1377
                if ( p >= fi->POfull ) { *term = 0; return(0); }
6,185,277✔
1378
                j = i = *p;
6,185,277✔
1379
                if ( i < 0 ) {
6,185,277✔
1380
                        p++;
78,263✔
1381
                        j = *r++ = *term++ = -i + 1 + *p;
78,263✔
1382
                        while ( ++i <= 0 ) *term++ = *r++;
695,764✔
1383
                        i = *p++;
78,263✔
1384
                }
1385
                if ( i == 0 ) { i = 1; *r++ = 0; *term++ = 0; }
6,185,277✔
1386
                else { while ( --i >= 0 ) { *r++ = *term++ = *p++; } }
1,248,229✔
1387
                fi->POfill = p;
6,185,277✔
1388
                SETBASEPOSITION(*pos,(UBYTE *)(fi->POfill)-(UBYTE *)(fi->PObuffer));
6,185,277✔
1389
                if ( p <= fi->POfull ) {
6,185,277✔
1390
                        if ( r >= AR.ComprTop ) {
6,185,277✔
1391
                                MLOCK(ErrorMessageLock);
×
1392
                                MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
×
1393
                                MUNLOCK(ErrorMessageLock);
×
NEW
1394
                                TERMINATE(-1);
×
1395
                        }
1396
                        AR.CompressPointer = r; *r = 0;
6,185,277✔
1397
                        return((WORD)j);
6,185,277✔
1398
                }
1399
                error = 6;
1400
        }
1401
ErrGet:
×
1402
        MLOCK(ErrorMessageLock);
×
1403
        MesPrint("Error while reading scratch file in GetOneTerm (%d)",error);
×
1404
        MUNLOCK(ErrorMessageLock);
×
NEW
1405
        TERMINATE(-1);
×
1406
        return(-1);
×
1407
}
1408

1409
/*
1410
                 #] GetOneTerm : 
1411
                 #[ GetMoreTerms :
1412
        Routine collects more contents of brackets inside a function,
1413
        indicated by the number in AC.CollectFun.
1414
        The first term is in term already.
1415
        We can keep calling GetTerm either till a bracket is finished 
1416
        or till it would make the term too long (> AM.MaxTer/2)
1417
        In all cases this function makes that the routine GetTerm
1418
        has a term in 'hold', so the AR.KeptInHold flag must be turned on.
1419
*/
1420

1421
WORD GetMoreTerms(WORD *term)
332✔
1422
{
1423
        GETIDENTITY
166✔
1424
        WORD *t, *r, *m, *h, *tstop, i, inc, same;
332✔
1425
        WORD extra;
332✔
1426
        WORD retval = 0;
332✔
1427
/*
1428
        We use 23% as a quasi-random default value.
1429
*/
1430
        extra = ((AM.MaxTer/sizeof(WORD))*((LONG)100-AC.CollectPercentage))/100;
332✔
1431
        if ( extra < 23 ) extra = 23;
332✔
1432
/*
1433
        First find the bracket pointer
1434
*/
1435
        t = term + *term;
332✔
1436
        tstop = t - ABS(t[-1]);
332✔
1437
        h = term+1;
332✔
1438
        while ( *h != HAAKJE && h < tstop ) h += h[1];
344✔
1439
        if ( h >= tstop ) return(retval);
332✔
1440
        inc = FUNHEAD+ARGHEAD+1-h[1];
332✔
1441
        same = WORDDIF(h,term) + h[1] - 1;
332✔
1442
        r = m = t + inc;
332✔
1443
        tstop = h + h[1];
332✔
1444
        while ( t > tstop ) *--r = *--t;
11,532✔
1445
        r--;
332✔
1446
        *r = WORDDIF(m,r);
332✔
1447
        while ( GetTerm(BHEAD m) > 0 ) {
2,936✔
1448
                r = m + 1;
2,616✔
1449
                t = m + *m - 1;
2,616✔
1450
                if ( same > ( i = ( *m - ABS(*t) -1 ) ) ) { /* Must fail */
2,616✔
1451
                        if ( AC.AltCollectFun && AS.CollectOverFlag == 2 ) AS.CollectOverFlag = 3;
4✔
1452
                        break;
1453
                }
1454
                t = term+1;
1455
                i = same;
1456
                while ( --i >= 0 ) {
14,868✔
1457
                        if ( *r != *t ) {
12,264✔
1458
                                if ( AC.AltCollectFun && AS.CollectOverFlag == 2 ) AS.CollectOverFlag = 3;
8✔
1459
                                goto FullTerm;
8✔
1460
                        }
1461
                        r++; t++;
12,256✔
1462
                }
1463
                if ( ( WORDDIF(m,term) + i + extra ) > (WORD)(AM.MaxTer/sizeof(WORD)) ) {
2,604✔
1464
/* 23 = 3 +20. The 20 is to have some extra for substitutions or whatever */
1465
                        if ( AS.CollectOverFlag == 0 && AC.AltCollectFun == 0 ) {
×
1466
                                Warning("Bracket contents too long in Collect statement");
×
1467
                                Warning("Contents spread over more than one term");
×
1468
                                Warning("If possible: increase MaxTermSize in setfile");
×
1469
                                AS.CollectOverFlag = 1;
×
1470
                        }
1471
                        else if ( AC.AltCollectFun ) {
×
1472
                                AS.CollectOverFlag = 2;
×
1473
                        }
1474
                        break;
1475
                }
1476
                tstop = m + *m;
2,604✔
1477
                *m -= same;
2,604✔
1478
                m++;
2,604✔
1479
                while ( r < tstop ) *m++ = *r++;
138,072✔
1480
                retval++;
2,604✔
1481
                if ( extra == 23 ) extra = ((AM.MaxTer/sizeof(WORD))/6);
2,604✔
1482
        }
1483
FullTerm:
320✔
1484
        h[1] = WORDDIF(m,h);
332✔
1485
        if ( AS.CollectOverFlag > 1 ) {
332✔
1486
                *h = AC.AltCollectFun;
×
1487
                if ( AS.CollectOverFlag == 3 ) AS.CollectOverFlag = 1;
×
1488
        }
1489
        else *h = AC.CollectFun;
332✔
1490
        h[2] |= DIRTYFLAG;
332✔
1491
        h[FUNHEAD] = h[1] - FUNHEAD;
332✔
1492
        h[FUNHEAD+1] = 0;
332✔
1493
        if ( ToFast(h+FUNHEAD,h+FUNHEAD) ) {
332✔
1494
                if ( h[FUNHEAD] <= -FUNCTION ) {
×
1495
                        h[1] = FUNHEAD+1;
×
1496
                        m = h + FUNHEAD+1;
×
1497
                }
1498
                else {
1499
                        h[1] = FUNHEAD+2;
×
1500
                        m = h + FUNHEAD+2;
×
1501
                }
1502
        }
1503
        *m++ = 1;
332✔
1504
        *m++ = 1;
332✔
1505
        *m++ = 3;
332✔
1506
        *term = WORDDIF(m,term);
332✔
1507
        AR.KeptInHold = 1;
332✔
1508
        return(retval);
332✔
1509
}
1510

1511
/*
1512
                 #] GetMoreTerms : 
1513
                 #[ GetMoreFromMem :
1514

1515
*/
1516

1517
WORD GetMoreFromMem(WORD *term, WORD **tpoin)
×
1518
{
1519
        GETIDENTITY
1520
        WORD *t, *r, *m, *h, *tstop, i, j, inc, same;
×
1521
        LONG extra = 23;
×
1522
/*
1523
        First find the bracket pointer
1524
*/
1525
        t = term + *term;
×
1526
        tstop = t - ABS(t[-1]);
×
1527
        h = term+1;
×
1528
        while ( *h != HAAKJE && h < tstop ) h += h[1];
×
1529
        if ( h >= tstop ) return(0);
×
1530
        inc = FUNHEAD+ARGHEAD+1-h[1];
×
1531
        same = WORDDIF(h,term) + h[1] - 1;
×
1532
        r = m = t + inc;
×
1533
        tstop = h + h[1];
×
1534
        while ( t > tstop ) *--r = *--t;
×
1535
        r--;
×
1536
        *r = WORDDIF(m,r);
×
1537
        while ( **tpoin ) {
×
1538
                r = *tpoin; j = *r;
×
1539
                for ( i = 0; i < j; i++ ) m[i] = *r++;
×
1540
                *tpoin = r;                
×
1541
                r = m + 1;
×
1542
                t = m + *m - 1;
×
1543
                if ( same > ( i = ( *m - ABS(*t) -1 ) ) ) { /* Must fail */
×
1544
                        if ( AC.AltCollectFun && AS.CollectOverFlag == 2 ) AS.CollectOverFlag = 3;
×
1545
                        break;
1546
                }
1547
                t = term+1;
1548
                i = same;
1549
                while ( --i >= 0 ) {
×
1550
                        if ( *r != *t ) {
×
1551
                                if ( AC.AltCollectFun && AS.CollectOverFlag == 2 ) AS.CollectOverFlag = 3;
×
1552
                                goto FullTerm;
×
1553
                        }
1554
                        r++; t++;
×
1555
                }
1556
                if ( ( WORDDIF(m,term) + i + extra ) > (LONG)(AM.MaxTer/(2*sizeof(WORD))) ) {
×
1557
/* 23 = 3 +20. The 20 is to have some extra for substitutions or whatever */
1558
                        if ( AS.CollectOverFlag == 0 && AC.AltCollectFun == 0 ) {
×
1559
                                Warning("Bracket contents too long in Collect statement");
×
1560
                                Warning("Contents spread over more than one term");
×
1561
                                Warning("If possible: increase MaxTermSize in setfile");
×
1562
                                AS.CollectOverFlag = 1;
×
1563
                        }
1564
                        else if ( AC.AltCollectFun ) {
×
1565
                                AS.CollectOverFlag = 2;
×
1566
                        }
1567
                        break;
1568
                }
1569
                tstop = m + *m;
×
1570
                *m -= same;
×
1571
                m++;
×
1572
                while ( r < tstop ) *m++ = *r++;
×
1573
                if ( extra == 23 ) extra = ((AM.MaxTer/sizeof(WORD))/6);
×
1574
        }
1575
FullTerm:
×
1576
        h[1] = WORDDIF(m,h);
×
1577
        if ( AS.CollectOverFlag > 1 ) {
×
1578
                *h = AC.AltCollectFun;
×
1579
                if ( AS.CollectOverFlag == 3 ) AS.CollectOverFlag = 1;
×
1580
        }
1581
        else *h = AC.CollectFun;
×
1582
        h[2] |= DIRTYFLAG;
×
1583
        h[FUNHEAD] = h[1] - FUNHEAD;
×
1584
        h[FUNHEAD+1] = 0;
×
1585
        if ( ToFast(h+FUNHEAD,h+FUNHEAD) ) {
×
1586
                if ( h[FUNHEAD] <= -FUNCTION ) {
×
1587
                        h[1] = FUNHEAD+1;
×
1588
                        m = h + FUNHEAD+1;
×
1589
                }
1590
                else {
1591
                        h[1] = FUNHEAD+2;
×
1592
                        m = h + FUNHEAD+2;
×
1593
                }
1594
        }
1595
        *m++ = 1;
×
1596
        *m++ = 1;
×
1597
        *m++ = 3;
×
1598
        *term = WORDDIF(m,term);
×
1599
        AR.KeptInHold = 1;
×
1600
        return(0);
×
1601
}
1602

1603
/*
1604
                 #] GetMoreFromMem : 
1605
                 #[ GetFromStore :
1606

1607
                Gets a single term from the storage file at position and puts
1608
                it at 'to'.
1609
                The value to be returned is the number of words read.
1610
                Renumbering is done also.
1611
                This is controlled by the renumber table, given in 'renumber'
1612

1613
                This routine should work with a number of cache buffers. The
1614
                exact number should be definable in form.set.
1615
                The parameters are:
1616
                AM.SizeStoreCache        (4096)
1617
                The numbers are the proposed default values.
1618

1619
                The cache is a pure read cache.
1620
*/
1621

1622
static int gfs = 0;
1623

1624
WORD GetFromStore(WORD *to, POSITION *position, RENUMBER renumber, WORD *InCompState, WORD nexpr)
×
1625
{
1626
        GETIDENTITY
1627
        LONG RetCode, num, first = 0;
×
1628
        WORD *from, *m;
×
1629
        struct StOrEcAcHe sc;
×
1630
        STORECACHE s;
×
1631
        STORECACHE snext, sold;
×
1632
        WORD *r, *rr = AR.CompressPointer;
×
1633
        r = rr;
×
1634
        gfs++;
×
1635
        sc.next = AT.StoreCache;
×
1636
        sold = s = &sc;
×
1637
        snext = s->next;
×
1638
        while ( snext ) {
×
1639
                sold = s;
×
1640
                s = snext;
×
1641
                snext = s->next;
×
1642
                if ( BASEPOSITION(s->position) == -1 ) break;
×
1643
                if ( ISLESSPOS(*position,s->toppos) &&
×
1644
                ISGEPOS(*position,s->position) ) {        /* Hit */
1645
                        if ( AT.StoreCache != s ) {
×
1646
                                sold->next = s->next;
×
1647
                                s->next = AT.StoreCache->next;
×
1648
                                AT.StoreCache = s;
×
1649
                        }
1650
                        from = (WORD *)(((UBYTE *)(s->buffer)) + DIFBASE(*position,s->position));
×
1651
                        num = *from;
×
1652
                        if ( !num ) { return(*to = 0); }
×
1653
                        *InCompState = (WORD)num;
×
1654
                        m = to;
×
1655
                        if ( num < 0 ) {
×
1656
                                from++;
×
1657
                                ADDPOS(*position,sizeof(WORD));
×
1658
                                *m++ = (WORD)(-num+1);
×
1659
                                r++;
×
1660
                                while ( ++num <= 0 ) *m++ = *r++;
×
1661
                                if ( ISLESSPOS(*position,s->toppos) ) {
×
1662
                                        num = *from++;
×
1663
                                        *to += (WORD)num;
×
1664
                                        ADDPOS(*position,sizeof(WORD));
×
1665
                                        *InCompState = (WORD)(num + 2);
×
1666
                                }
1667
                                else {
1668
                                        first = 1;
×
1669
                                        goto InNew;
×
1670
                                }
1671
                        }
1672
PastCon:;
×
1673
                        while ( num > 0 && ISLESSPOS(*position,s->toppos) ) {
×
1674
                                *r++ = *m++ = *from++; ADDPOS(*position,sizeof(WORD)); num--;
×
1675
                        }
1676
                        if ( num > 0 ) {
×
1677
InNew:
×
1678
                                SETBASEPOSITION(s->position,-1);
×
1679
                                SETBASEPOSITION(s->toppos,-1);
×
1680
                                LOCK(AM.storefilelock);
×
1681
                                SeekFile(AR.StoreData.Handle,position,SEEK_SET);
×
1682
                                RetCode = ReadFile(AR.StoreData.Handle,(UBYTE *)(s->buffer),AM.SizeStoreCache);
×
1683
                                UNLOCK(AM.storefilelock);
×
1684
                                if ( RetCode < 0 ) goto PastErr;
×
1685
                                if ( !RetCode ) return( *to = 0 );
×
1686
                                s->position = *position;
×
1687
                                s->toppos = *position;
×
1688
                                ADDPOS(s->toppos,RetCode);
×
1689
                                from = s->buffer;
×
1690
                                if ( first ) {
×
1691
                                        num = *from++;
×
1692
                                        ADDPOS(*position,sizeof(WORD));
×
1693
                                        *to += (WORD)num;
×
1694
/*                                        first = 0; */
1695
                                        *InCompState = (WORD)(num + 2);
×
1696
                                }
1697
                                goto PastCon;
×
1698
                        }
1699
                        goto PastEnd;
×
1700
                }
1701
        }
1702
        if ( AT.StoreCache ) {                /* Fill the last buffer */
×
1703
                s->position = *position;
×
1704
                LOCK(AM.storefilelock);
×
1705
                SeekFile(AR.StoreData.Handle,position,SEEK_SET);
×
1706
                RetCode = ReadFile(AR.StoreData.Handle,(UBYTE *)(s->buffer),AM.SizeStoreCache);
×
1707
                UNLOCK(AM.storefilelock);
×
1708
                if ( RetCode < 0 ) goto PastErr;
×
1709
                if ( !RetCode ) return( *to = 0 );
×
1710
                s->toppos = *position;
×
1711
                ADDPOS(s->toppos,RetCode);
×
1712
                if ( AT.StoreCache != s ) {
×
1713
                        sold->next = s->next;
×
1714
                        s->next = AT.StoreCache->next;
×
1715
                        AT.StoreCache = s;
×
1716
                }
1717
                m = to;
×
1718
                from = s->buffer;
×
1719
                num = *from;
×
1720
                if ( !num ) { return( *to = 0 ); }
×
1721
                *InCompState = (WORD)num;
×
1722
                if ( num < 0 ) {
×
1723
                        *m++ = (WORD)(-num+1);
×
1724
                        r++;
×
1725
                        from++;
×
1726
                        ADDPOS(*position,sizeof(WORD));
×
1727
                        while ( ++num <= 0 ) *m++ = *r++;
×
1728
                        num = *from++;
×
1729
                        *to += (WORD)num;
×
1730
                        ADDPOS(*position,sizeof(WORD));
×
1731
                        *InCompState = (WORD)(num+2);
×
1732
                }
1733
                goto PastCon;
×
1734
        }
1735
/*                No caching available */
1736
        LOCK(AM.storefilelock);
×
1737
        SeekFile(AR.StoreData.Handle,position,SEEK_SET);
×
1738
        RetCode = ReadFile(AR.StoreData.Handle,(UBYTE *)to,(LONG)sizeof(WORD));
×
1739
        SeekFile(AR.StoreData.Handle,position,SEEK_CUR);
×
1740
        UNLOCK(AM.storefilelock);
×
1741
        if ( RetCode != sizeof(WORD) ) {
×
1742
                *to = 0;
×
1743
                return((WORD)RetCode);
×
1744
        }
1745
        if ( !*to ) return(0);
×
1746
        m = to;
×
1747
        if ( *to < 0 ) {
×
1748
                num = *m++;
×
1749
                *to = *r++ = (WORD)(-num + 1);
×
1750
                while ( ++num <= 0 ) *m++ = *r++;
×
1751
                LOCK(AM.storefilelock);
×
1752
                SeekFile(AR.StoreData.Handle,position,SEEK_SET);
×
1753
                RetCode = ReadFile(AR.StoreData.Handle,(UBYTE *)m,(LONG)sizeof(WORD));
×
1754
                SeekFile(AR.StoreData.Handle,position,SEEK_CUR);
×
1755
                UNLOCK(AM.storefilelock);
×
1756
                if ( RetCode != sizeof(WORD) ) {
×
1757
                        MLOCK(ErrorMessageLock);
×
1758
                        MesPrint("@Error in compression of store file");
×
1759
                        MUNLOCK(ErrorMessageLock);
×
1760
                        return(-1);
×
1761
                }
1762
                num = *m;
×
1763
                *to += (WORD)num;
×
1764
                *InCompState = (WORD)(num + 2);
×
1765
        }
1766
        else {
1767
                *InCompState = *to;
×
1768
                num = *to - 1; m = to + 1; r = rr + 1;
×
1769
        }
1770
        first = num;
×
1771
        num *= wsizeof(WORD);
×
1772
        if ( num < 0 ) {
×
1773
                MLOCK(ErrorMessageLock);
×
1774
                MesPrint("@Error in stored expressions file at position %9p",position);
×
1775
                MUNLOCK(ErrorMessageLock);
×
1776
                return(-1);
×
1777
        }
1778
        LOCK(AM.storefilelock);
×
1779
        SeekFile(AR.StoreData.Handle,position,SEEK_SET);
×
1780
        RetCode = ReadFile(AR.StoreData.Handle,(UBYTE *)m,num);
×
1781
        SeekFile(AR.StoreData.Handle,position,SEEK_CUR);
×
1782
        UNLOCK(AM.storefilelock);
×
1783
        if ( RetCode != num ) {
×
1784
                MLOCK(ErrorMessageLock);
×
1785
                MesPrint("@Error in stored expressions file at position %9p",position);
×
1786
                MUNLOCK(ErrorMessageLock);
×
1787
                return(-1);
×
1788
        }
1789
        NCOPY(r,m,first);
×
1790
PastEnd:
×
1791
        *rr = *to;
×
1792
        if ( r >= AR.ComprTop ) {
×
1793
                MLOCK(ErrorMessageLock);
×
1794
                MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
×
1795
                MUNLOCK(ErrorMessageLock);
×
NEW
1796
                TERMINATE(-1);
×
1797
        }
1798
        AR.CompressPointer = r; *r = 0;
×
1799
        if ( !TermRenumber(to,renumber,nexpr) ) {
×
1800
                MarkDirty(to,DIRTYSYMFLAG);
×
1801
                if ( AR.CurDum > AM.IndDum && Expressions[nexpr].numdummies > 0 )
×
1802
                        MoveDummies(BHEAD to,AR.CurDum - AM.IndDum);
×
1803
                return((WORD)*to);
×
1804
        }
1805
PastErr:
×
1806
        MLOCK(ErrorMessageLock);
×
1807
        MesCall("GetFromStore");
×
1808
        MUNLOCK(ErrorMessageLock);
×
1809
        SETERROR(-1)
×
1810
}
1811

1812
/*
1813
                 #] GetFromStore : 
1814
                 #[ DetVars :                        VOID DetVars(term)
1815

1816
        Determines which variables are used in term.
1817

1818
        When par = 1 we are scanning a prototype expression which involves
1819
        completely different rules.
1820

1821
*/
1822

1823
VOID DetVars(WORD *term, WORD par)
98✔
1824
{
1825
        GETIDENTITY
28✔
1826
        WORD *stopper;
98✔
1827
        WORD *t, sym;
98✔
1828
        WORD *sarg;
98✔
1829
        stopper = term + *term - 1;
98✔
1830
        stopper = stopper - ABS(*stopper) + 1;
98✔
1831
        term++;
98✔
1832
        if ( par ) {                /* Prototype expression */
98✔
1833
                WORD n;
49✔
1834
                if ( ( n = NumSymbols ) > 0 ) {
49✔
1835
                        SYMBOLS tt;
49✔
1836
                        tt = symbols;
49✔
1837
                        do {
987✔
1838
                                (tt++)->flags &= ~INUSE;
987✔
1839
                        } while ( --n > 0 );
987✔
1840
                }
1841
                if ( ( n = NumIndices ) > 0 ) {
49✔
1842
                        INDICES tt;
49✔
1843
                        tt = indices;
49✔
1844
                        do {
49✔
1845
                                (tt++)->flags &= ~INUSE;
49✔
1846
                        } while ( --n > 0 );
49✔
1847
                }
1848
                if ( ( n = NumVectors ) > 0 ) {
49✔
1849
                        VECTORS tt;
49✔
1850
                        tt = vectors;
49✔
1851
                        do {
49✔
1852
                                (tt++)->flags &= ~INUSE;
49✔
1853
                        } while ( --n > 0 );
49✔
1854
                }
1855
                if ( ( n = NumFunctions ) > 0 ) {
49✔
1856
                        FUNCTIONS tt;
49✔
1857
                        tt = functions;
49✔
1858
                        do {
6,370✔
1859
                                (tt++)->flags &= ~INUSE;
6,370✔
1860
                        } while ( --n > 0 );
6,370✔
1861
                }
1862
                term += SUBEXPSIZE;
49✔
1863
                while ( term < stopper ) {
49✔
1864
                        if ( *term == SYMTOSYM || *term == SYMTONUM ) {
×
1865
                                term += 2;
×
1866
                                AN.UsedSymbol[*term] = 1;
×
1867
                                symbols[*term].flags |= INUSE;
×
1868
                        }
1869
                        else if ( *term == VECTOVEC ) {
×
1870
                                term += 2;
×
1871
                                AN.UsedVector[*term-AM.OffsetVector] = 1;
×
1872
                                vectors[*term-AM.OffsetVector].flags |= INUSE;
×
1873
                        }
1874
                        else if ( *term == INDTOIND ) {
×
1875
                                term += 2;
×
1876
                                sym = indices[*term - AM.OffsetIndex].dimension;
×
1877
                                if ( sym < 0 ) AN.UsedSymbol[-sym] = 1;
×
1878
                                AN.UsedIndex[(*term) - AM.OffsetIndex] = 1;
×
1879
                                sym = indices[*term-AM.OffsetIndex].nmin4;
×
1880
                                if ( sym < -NMIN4SHIFT ) AN.UsedSymbol[-sym-NMIN4SHIFT] = 1;
×
1881
                                indices[*term-AM.OffsetIndex].flags |= INUSE;
×
1882
                        }
1883
                        else if ( *term == FUNTOFUN ) {
×
1884
                                term += 2;
×
1885
                                AN.UsedFunction[*term-FUNCTION] = 1;
×
1886
                                functions[*term-FUNCTION].flags |= INUSE;
×
1887
                        }
1888
                        term += 2;
×
1889
                }
1890
        }
1891
        else {
1892
                while ( term < stopper ) {
56✔
1893
                        t = term + term[1];
7✔
1894
                        if ( *term == SYMBOL ) {
7✔
1895
                                term += 2;
7✔
1896
                                do {
7✔
1897
                                        AN.UsedSymbol[*term] = 1;
7✔
1898
                                        term += 2;
7✔
1899
                                } while ( term < t );
7✔
1900
                        }
1901
                        else if ( *term == DOTPRODUCT ) {
×
1902
                                term += 2;
×
1903
                                do {
×
1904
                                        AN.UsedVector[(*term++) - AM.OffsetVector] = 1;
×
1905
                                        AN.UsedVector[(*term) - AM.OffsetVector] = 1;
×
1906
                                        term += 2;
×
1907
                                } while ( term < t );
×
1908
                        }
1909
                        else if ( *term == VECTOR ) {
×
1910
                                term += 2;
×
1911
                                do {
×
1912
                                        AN.UsedVector[(*term++) - AM.OffsetVector] = 1;
×
1913
                                        if ( *term >= AM.OffsetIndex && *term < AM.DumInd ) {
×
1914
                                                sym = indices[*term - AM.OffsetIndex].dimension;
×
1915
                                                if ( sym < 0 ) AN.UsedSymbol[-sym] = 1;
×
1916
                                                AN.UsedIndex[*term - AM.OffsetIndex] = 1;
×
1917
                                                sym = indices[(*term++)-AM.OffsetIndex].nmin4;
×
1918
                                                if ( sym < -NMIN4SHIFT ) AN.UsedSymbol[-sym-NMIN4SHIFT] = 1;
×
1919
                                        }
1920
                                        else term++;
×
1921
                                } while ( term < t );
×
1922
                        }
1923
                        else if ( *term == INDEX || *term == LEVICIVITA || *term == GAMMA
×
1924
                        || *term == DELTA ) {
×
1925
/*
1926
Tensors:
1927
                                term += 2;
1928
*/
1929
                                if ( *term == INDEX || *term == DELTA ) term += 2;
×
1930
                                else {
1931
Tensors:
×
1932
                                        term += FUNHEAD;
×
1933
                                }
1934
                                while ( term < t ) {
×
1935
                                        if ( *term  >= AM.OffsetIndex && *term < AM.DumInd ) {
×
1936
                                                sym = indices[*term - AM.OffsetIndex].dimension;
×
1937
                                                if ( sym < 0 ) AN.UsedSymbol[-sym] = 1;
×
1938
                                                AN.UsedIndex[(*term) - AM.OffsetIndex] = 1;
×
1939
                                                sym = indices[*term-AM.OffsetIndex].nmin4;
×
1940
                                                if ( sym < -NMIN4SHIFT ) AN.UsedSymbol[-sym-NMIN4SHIFT] = 1;
×
1941
                                        }
1942
                                        else if ( *term < (WILDOFFSET+AM.OffsetVector) )
×
1943
                                                AN.UsedVector[(*term) - AM.OffsetVector] = 1;
×
1944
                                        term++;
×
1945
                                }
1946
                        }
1947
                        else if ( *term == HAAKJE ) term = t;
×
1948
                        else {
1949
                                if ( *term > MAXBUILTINFUNCTION )
×
1950
                                        AN.UsedFunction[(*term)-FUNCTION] = 1;
×
1951
                                if ( *term >= FUNCTION && functions[*term-FUNCTION].spec
×
1952
                                >= TENSORFUNCTION && term[1] > FUNHEAD ) goto Tensors;
×
1953
                                term += FUNHEAD;                        /* First argument */
×
1954
                                while ( term < t ) {
×
1955
                                        sarg = term;
×
1956
                                        NEXTARG(sarg)
×
1957
                                        if ( *term > 0 ) {
×
1958
                                                sarg = term + *term;        /* End of argument */
×
1959
                                                term += ARGHEAD;                /* First term in argument */
×
1960
                                                if ( term < sarg ) { do {
×
1961
                                                        DetVars(term,par);
×
1962
                                                        term += *term;
×
1963
                                                } while ( term < sarg ); }
×
1964
                                        }
1965
                                        else {
1966
                                                if ( *term < -MAXBUILTINFUNCTION ) {
×
1967
                                                        AN.UsedFunction[-*term-FUNCTION] = 1;
×
1968
                                                }
1969
                                                else if ( *term == -SYMBOL ) {
×
1970
                                                        AN.UsedSymbol[term[1]] = 1;
×
1971
                                                }
1972
                                                else if ( *term == -INDEX ) {
×
1973
                                                        if ( term[1] < (WILDOFFSET+AM.OffsetVector) ) {
×
1974
                                                                AN.UsedVector[term[1]-AM.OffsetVector] = 1;
×
1975
                                                        }
1976
                                                        else if ( term[1] >= AM.OffsetIndex && term[1] < AM.DumInd ) {
×
1977
                                                                sym = indices[term[1] - AM.OffsetIndex].dimension;
×
1978
                                                                if ( sym < 0 ) AN.UsedSymbol[-sym] = 1;
×
1979
                                                                AN.UsedIndex[term[1] - AM.OffsetIndex] = 1;
×
1980
                                                                sym = indices[term[1]-AM.OffsetIndex].nmin4;
×
1981
                                                                if ( sym < -NMIN4SHIFT ) AN.UsedSymbol[-sym-NMIN4SHIFT] = 1;
×
1982
                                                        }
1983
                                                }
1984
                                                else if ( *term == -VECTOR || *term == -MINVECTOR ) {
×
1985
                                                        AN.UsedVector[term[1]-AM.OffsetVector] = 1;
×
1986
                                                }
1987
                                        }
1988
                                        term = sarg;                        /* Next argument */
1989
                                }
1990
                                term = t;
1991
                        }
1992
                }
1993
        }
1994
}
98✔
1995

1996
/*
1997
                 #] DetVars : 
1998
                 #[ ToStorage :
1999

2000
        This routine takes an expression in the scratch buffer (indicated by e)
2001
        and puts it in the storage file. The necessary actions are:
2002

2003
        1:        determine the list of the used variables.
2004
        2:        make an index entry.
2005
        3:        write the namelists.
2006
        4:        copy the 'length' bytes of the expression.
2007

2008
*/
2009

2010
WORD ToStorage(EXPRESSIONS e, POSITION *length)
49✔
2011
{
2012
        GETIDENTITY
14✔
2013
        WORD *w, i, j;
49✔
2014
        WORD *term;
49✔
2015
        INDEXENTRY *indexent;
49✔
2016
        LONG size;
49✔
2017
        POSITION indexpos, scrpos;
49✔
2018
        FILEHANDLE *f;
49✔
2019
        if ( ( indexent = NextFileIndex(&indexpos) ) == 0 ) {
49✔
2020
                MesCall("ToStorage");
×
2021
                SETERROR(-1)
×
2022
        }
2023
        indexent->CompressSize = 0;                /* thus far no compression */
49✔
2024
        f = AR.infile; AR.infile = AR.outfile; AR.outfile = f;
49✔
2025
        if ( e->status == HIDDENGEXPRESSION ) {
49✔
2026
                AR.InHiBuf = 0; f = AR.hidefile; AR.GetFile = 2;
×
2027
        }
2028
        else {
2029
                AR.InInBuf = 0; f = AR.infile;   AR.GetFile = 0;
49✔
2030
        }
2031
        if ( f->handle >= 0 ) {
49✔
2032
                scrpos = e->onfile;
×
2033
                SeekFile(f->handle,&scrpos,SEEK_SET);
×
2034
                if ( ISNOTEQUALPOS(scrpos,e->onfile) ) {
×
2035
                        MesPrint(":::Error in Scratch file");
×
2036
                        goto ErrReturn;
×
2037
                }
2038
                f->POposition = e->onfile;
×
2039
                f->POfull = f->PObuffer;
×
2040
                if ( e->status == HIDDENGEXPRESSION ) AR.InHiBuf = 0;
×
2041
                else                                  AR.InInBuf = 0;
×
2042
        }
2043
        else {
2044
                f->POfill = (WORD *)((UBYTE *)(f->PObuffer)+BASEPOSITION(e->onfile));
49✔
2045
        }
2046
        w = AT.WorkPointer;
49✔
2047
        AN.UsedSymbol   = w;        w += NumSymbols;
49✔
2048
        AN.UsedVector   = w;        w += NumVectors;
49✔
2049
        AN.UsedIndex    = w;        w += NumIndices;
49✔
2050
        AN.UsedFunction = w;        w += NumFunctions;
49✔
2051
        term = w;
49✔
2052
    w = (WORD *)(((UBYTE *)(w)) + AM.MaxTer);
49✔
2053
        if ( w > AT.WorkTop ) {
49✔
2054
                MesWork();
×
2055
                goto ErrReturn;
×
2056
        }
2057
        w = AN.UsedSymbol;
49✔
2058
        i = NumSymbols + NumVectors + NumIndices + NumFunctions;
49✔
2059
        do { *w++ = 0; } while ( --i > 0 );
7,455✔
2060
        if ( GetTerm(BHEAD term) > 0 ) {
49✔
2061
                DetVars(term,1);
49✔
2062
                if ( GetTerm(BHEAD term) ) {
49✔
2063
                        do { DetVars(term,0); } while ( GetTerm(BHEAD term) > 0 );
49✔
2064
                }
2065
        }
2066
        j = 0;
49✔
2067
        w = AN.UsedSymbol;
49✔
2068
        i = NumSymbols;
49✔
2069
        while ( --i >= 0 ) { if ( *w++ ) j++; }
1,036✔
2070
        indexent->nsymbols = j;
49✔
2071
/*        size = j * sizeof(struct SyMbOl);  */
2072
        j = 0;
49✔
2073
        w = AN.UsedIndex;
49✔
2074
        i = NumIndices;
49✔
2075
        while ( --i >= 0 ) { if ( *w++ ) j++; }
98✔
2076
        indexent->nindices = j;
49✔
2077
/*        size += j * sizeof(struct InDeX);  */
2078
        j = 0;
49✔
2079
        w = AN.UsedVector;
49✔
2080
        i = NumVectors;
49✔
2081
        while ( --i >= 0 ) { if ( *w++ ) j++; }
98✔
2082
        indexent->nvectors = j;
49✔
2083
/*        size += j * sizeof(struct VeCtOr);  */
2084
        j = 0;
49✔
2085
        w = AN.UsedFunction;
49✔
2086
        i = NumFunctions;
49✔
2087
        while ( --i >= 0 ) { if ( *w++ ) j++; }
6,419✔
2088
        indexent->nfunctions = j;
49✔
2089
/*        size += j * sizeof(struct FuNcTiOn); */
2090
        indexent->length = *length;
49✔
2091
        indexent->variables = AR.StoreData.Fill;
49✔
2092
/*        indexent->position = AR.StoreData.Fill + size; */
2093
        StrCopy(AC.exprnames->namebuffer+e->name,(UBYTE *)(indexent->name));
49✔
2094
        SeekFile(AR.StoreData.Handle,&(AR.StoreData.Fill),SEEK_SET);
49✔
2095
        AO.wlen = 100000;
49✔
2096
        AO.wpos = (UBYTE *)Malloc1(AO.wlen,"AO.wpos buffer");
49✔
2097
        AO.wpoin = AO.wpos;
49✔
2098
        {
2099
                 SYMBOLS a;
49✔
2100
                w = AN.UsedSymbol;
49✔
2101
                a = symbols;
49✔
2102
                j = 0;
49✔
2103
                i = indexent->nsymbols;
49✔
2104
                while ( --i >= 0 ) {
56✔
2105
                        while ( !*w ) { w++; a++; j++; }
147✔
2106
                        a->number = j;
7✔
2107
                        if ( VarStore((UBYTE *)a,(WORD)(sizeof(struct SyMbOl)),a->name,
7✔
2108
                                a->namesize) ) goto ErrToSto;
×
2109
                        w++; j++; a++;
7✔
2110
                }
2111
        }
2112
        {
2113
                 INDICES a;
49✔
2114
                w = AN.UsedIndex;
49✔
2115
                a = indices;
49✔
2116
                j = 0;
49✔
2117
                i = indexent->nindices;
49✔
2118
                while ( --i >= 0 ) {
49✔
2119
                        while ( !*w ) { w++; a++; j++; }
×
2120
                        a->number = j;
×
2121
                        if ( VarStore((UBYTE *)a,(WORD)(sizeof(struct InDeX)),a->name,
×
2122
                                a->namesize) ) goto ErrToSto;
×
2123
                        w++; j++; a++;
×
2124
                }
2125
        }
2126
        {
2127
                 VECTORS a;
49✔
2128
                w = AN.UsedVector;
49✔
2129
                a = vectors;
49✔
2130
                j = 0;
49✔
2131
                i = indexent->nvectors;
49✔
2132
                while ( --i >= 0 ) {
49✔
2133
                        while ( !*w ) { w++; a++; j++; }
×
2134
                        a->number = j;
×
2135
                        if ( VarStore((UBYTE *)a,(WORD)(sizeof(struct VeCtOr)),a->name,
×
2136
                                a->namesize) ) goto ErrToSto;
×
2137
                        w++; j++; a++;
×
2138
                }
2139
        }
2140
        {
2141
                 FUNCTIONS a;
49✔
2142
                w = AN.UsedFunction;
49✔
2143
                a = functions;
49✔
2144
                j = 0;
49✔
2145
                i = indexent->nfunctions;
49✔
2146
                while ( --i >= 0 ) {
49✔
2147
                        while ( !*w ) { w++; a++; j++; }
×
2148
                        a->number = j;
×
2149
                        if ( VarStore((UBYTE *)a,(WORD)(sizeof(struct FuNcTiOn)),a->name,
×
2150
                                a->namesize) ) goto ErrToSto;
×
2151
                        w++; a++; j++;
×
2152
                }
2153
        }
2154
        if ( VarStore((UBYTE *)0L,(WORD)0,(WORD)0,(WORD)0) ) goto ErrToSto;        /* Flush buffer */
49✔
2155
        TELLFILE(AR.StoreData.Handle,&(indexent->position));
49✔
2156
        indexent->size = (WORD)DIFBASE(indexent->position,indexent->variables);
49✔
2157
/*
2158
                The following code was added when it became apparent (30-jan-2007)
2159
                that we need provisions for extra space without upsetting existing
2160
                .sav files. Here we can put as much as we want.
2161
                Look in GetTable on how to recover numdummies.
2162
                Forgetting numdummies has been in there from the beginning.
2163
*/
2164
        if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&(e->numdummies)),(LONG)sizeof(WORD)) != 
49✔
2165
                sizeof(WORD) ) {
2166
                        MesPrint("Error while writing storage file");
×
2167
                        goto ErrReturn;
×
2168
        }
2169
        if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&(e->numfactors)),(LONG)sizeof(WORD)) != 
49✔
2170
                sizeof(WORD) ) {
2171
                        MesPrint("Error while writing storage file");
×
2172
                        goto ErrReturn;
×
2173
        }
2174
        if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&(e->vflags)),(LONG)sizeof(WORD)) != 
49✔
2175
                sizeof(WORD) ) {
2176
                        MesPrint("Error while writing storage file");
×
2177
                        goto ErrReturn;
×
2178
        }
2179
        if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&(e->uflags)),(LONG)sizeof(WORD)) != 
49✔
2180
                sizeof(WORD) ) {
2181
                        MesPrint("Error while writing storage file");
×
2182
                        goto ErrReturn;
×
2183
        }
2184
        TELLFILE(AR.StoreData.Handle,&(indexent->position));
49✔
2185
        if ( f->handle >= 0 ) {
49✔
2186
                POSITION llength;
×
2187
                llength = *length;
×
2188
                SeekFile(f->handle,&(e->onfile),SEEK_SET);
×
2189
                while ( ISPOSPOS(llength) ) {
×
2190
                        SETBASEPOSITION(scrpos,AO.wlen);
×
2191
                        if ( ISLESSPOS(llength,scrpos) ) size = BASEPOSITION(llength);
×
2192
                        else                                             size = AO.wlen;
×
2193
                        if ( ReadFile(f->handle,AO.wpos,size) != size ) {
×
2194
                                MesPrint("Error while reading scratch file");
×
2195
                                goto ErrReturn;
×
2196
                        }
2197
                        if ( WriteFile(AR.StoreData.Handle,AO.wpos,size) != size ) {
×
2198
                                MesPrint("Error while writing storage file");
×
2199
                                goto ErrReturn;
×
2200
                        }
2201
                        ADDPOS(llength,-size);
×
2202
                }
2203
        }
2204
        else {
2205
                WORD *ppp;
49✔
2206
                ppp = (WORD *)((UBYTE *)(f->PObuffer) + BASEPOSITION(e->onfile));
49✔
2207
                if ( WriteFile(AR.StoreData.Handle,(UBYTE *)ppp,BASEPOSITION(*length)) != 
49✔
2208
                BASEPOSITION(*length) ) {
49✔
2209
                        MesPrint("Error while writing storage file");
×
2210
                        goto ErrReturn;
×
2211
                }
2212
        }
2213
        ADD2POS(*length,indexent->position);
49✔
2214
        e->onfile = indexpos;
49✔
2215
/*
2216
        AR.StoreData.Fill = SeekFile(AR.StoreData.Handle,&(AM.zeropos),SEEK_END);
2217
*/
2218
        AR.StoreData.Fill = *length;
49✔
2219
        SeekFile(AR.StoreData.Handle,&(AR.StoreData.Fill),SEEK_SET);
49✔
2220
        scrpos = AR.StoreData.Position;
49✔
2221
        ADDPOS(scrpos,sizeof(POSITION));
49✔
2222
        SeekFile(AR.StoreData.Handle,&scrpos,SEEK_SET);
49✔
2223
        if ( WriteFile(AR.StoreData.Handle,((UBYTE *)&(AR.StoreData.Index.number))
49✔
2224
                ,(LONG)(sizeof(POSITION))) != sizeof(POSITION) ) goto ErrInSto;
×
2225
        SeekFile(AR.StoreData.Handle,&indexpos,SEEK_SET);
49✔
2226
        if ( WriteFile(AR.StoreData.Handle,(UBYTE *)indexent,(LONG)(sizeof(INDEXENTRY))) !=
49✔
2227
                sizeof(INDEXENTRY) ) goto ErrInSto;
×
2228
        FlushFile(AR.StoreData.Handle);
49✔
2229
        SeekFile(AR.StoreData.Handle,&(AC.StoreFileSize),SEEK_END);
49✔
2230
        f = AR.infile; AR.infile = AR.outfile; AR.outfile = f;
49✔
2231
        if ( AO.wpos ) M_free(AO.wpos,"AO.wpos buffer");
49✔
2232
        AO.wpos = AO.wpoin = 0;
49✔
2233
        return(0);
49✔
2234
ErrToSto:
×
2235
        MesPrint("---Error while storing namelists");
×
2236
        goto ErrReturn;
×
2237
ErrInSto:
×
2238
        MesPrint("Error in storage");
×
2239
ErrReturn:
×
2240
        if ( AO.wpos ) M_free(AO.wpos,"AO.wpos buffer");
×
2241
        AO.wpos = AO.wpoin = 0;
×
2242
        f = AR.infile; AR.infile = AR.outfile; AR.outfile = f;
×
2243
        return(-1);
×
2244
}
2245

2246
/*
2247
                 #] ToStorage : 
2248
                 #[ NextFileIndex :
2249
*/
2250

2251
INDEXENTRY *NextFileIndex(POSITION *indexpos)
49✔
2252
{
2253
        GETIDENTITY
14✔
2254
        INDEXENTRY *ind;
49✔
2255
        int i, j = sizeof(FILEINDEX)/(sizeof(LONG));
49✔
2256
        LONG *lo;
49✔
2257
        if ( AR.StoreData.Handle <= 0 ) {
49✔
2258
                if ( SetFileIndex() ) {
28✔
2259
                        MesCall("NextFileIndex");
×
2260
                        return(0);
×
2261
                }
2262
                SETBASEPOSITION(AR.StoreData.Index.number,1);
28✔
2263
#ifdef SYSDEPENDENTSAVE
2264
                SETBASEPOSITION(*indexpos,(2*sizeof(POSITION)));
2265
#else
2266
                SETBASEPOSITION(*indexpos,(2*sizeof(POSITION)+sizeof(STOREHEADER)));
28✔
2267
#endif
2268
                return(AR.StoreData.Index.expression);
28✔
2269
        }
2270
        while ( BASEPOSITION(AR.StoreData.Index.number) >= (LONG)(INFILEINDEX) ) {
21✔
2271
                if ( ISNOTZEROPOS(AR.StoreData.Index.next) ) {
×
2272
                        SeekFile(AR.StoreData.Handle,&(AR.StoreData.Index.next),SEEK_SET);
×
2273
                        AR.StoreData.Position = AR.StoreData.Index.next;
×
2274
                        if ( ReadFile(AR.StoreData.Handle,(UBYTE *)(&AR.StoreData.Index),(LONG)(sizeof(FILEINDEX))) !=
×
2275
                        (LONG)(sizeof(FILEINDEX)) ) goto ErrNextS;
×
2276
                }
2277
                else {
2278
                        PUTZERO(AR.StoreData.Index.number);
×
2279
                        SeekFile(AR.StoreData.Handle,&(AR.StoreData.Position),SEEK_SET);
×
2280
                        if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&(AR.StoreData.Fill)),(LONG)(sizeof(POSITION)))
×
2281
                        != (LONG)(sizeof(POSITION)) ) goto ErrNextS;
×
2282
                        PUTZERO(AR.StoreData.Index.next);
×
2283
                        SeekFile(AR.StoreData.Handle,&(AR.StoreData.Fill),SEEK_SET);
×
2284
                        AR.StoreData.Position = AR.StoreData.Fill;
×
2285
                        lo = (LONG *)(&AR.StoreData.Index);
×
2286
                        for ( i = 0; i < j; i++ ) *lo++ = 0;
×
2287
                        if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&AR.StoreData.Index),(LONG)(sizeof(FILEINDEX))) !=
×
2288
                        (LONG)(sizeof(FILEINDEX)) ) goto ErrNextS;
×
2289
                        ADDPOS(AR.StoreData.Fill,sizeof(FILEINDEX));
×
2290
                }
2291
        }
2292
        *indexpos = AR.StoreData.Position;
21✔
2293
        ADDPOS(*indexpos,(2*sizeof(POSITION)) +
21✔
2294
                BASEPOSITION(AR.StoreData.Index.number) * sizeof(INDEXENTRY));
2295
        ind = &AR.StoreData.Index.expression[BASEPOSITION(AR.StoreData.Index.number)];
21✔
2296
        ADDPOS(AR.StoreData.Index.number,1);
21✔
2297
        return(ind);
21✔
2298
ErrNextS:
×
2299
        MesPrint("Error in storage file");
×
2300
        return(0);
×
2301
}
2302

2303
/*
2304
                 #] NextFileIndex : 
2305
                 #[ SetFileIndex :
2306
*/
2307

2308
/**
2309
 *  Reads the next file index and puts it into AR.StoreData.Index. TODO
2310
 *
2311
 *  @return  = 0 everything okay, != 0 an error occurred
2312
 */
2313

2314
WORD SetFileIndex(VOID)
28✔
2315
{
2316
        GETIDENTITY
8✔
2317
        int i, j = sizeof(FILEINDEX)/(sizeof(LONG));
28✔
2318
        LONG *lo;
28✔
2319
        if ( AR.StoreData.Handle < 0 ) {
28✔
2320
                AR.StoreData.Handle = AC.StoreHandle;
28✔
2321
                PUTZERO(AR.StoreData.Index.next);
28✔
2322
                PUTZERO(AR.StoreData.Index.number);
28✔
2323
#ifdef SYSDEPENDENTSAVE
2324
                SETBASEPOSITION(AR.StoreData.Fill,sizeof(FILEINDEX));
2325
#else
2326
                if ( WriteStoreHeader(AR.StoreData.Handle) ) return(MesPrint("Error writing storage file header"));
28✔
2327
                SETBASEPOSITION(AR.StoreData.Fill, (LONG)sizeof(FILEINDEX)+(LONG)sizeof(STOREHEADER));
28✔
2328
#endif
2329
                lo = (LONG *)(&AR.StoreData.Index);
28✔
2330
                for ( i = 0; i < j; i++ ) *lo++ = 0;
1,820✔
2331
                if ( WriteFile(AR.StoreData.Handle,(UBYTE *)(&AR.StoreData.Index),(LONG)(sizeof(FILEINDEX))) !=
28✔
2332
                (LONG)(sizeof(FILEINDEX)) ) return(MesPrint("Error writing storage file"));
×
2333
        }
2334
        else {
2335
                POSITION scrpos;
×
2336
#ifdef SYSDEPENDENTSAVE
2337
                PUTZERO(scrpos);
2338
#else
2339
                SETBASEPOSITION(scrpos, (LONG)(sizeof(STOREHEADER)));
×
2340
#endif
2341
                SeekFile(AR.StoreData.Handle,&scrpos,SEEK_SET);
×
2342
                if ( ReadFile(AR.StoreData.Handle,(UBYTE *)(&AR.StoreData.Index),(LONG)(sizeof(FILEINDEX))) !=
×
2343
                (LONG)(sizeof(FILEINDEX)) ) return(MesPrint("Error reading storage file"));
×
2344
        }
2345
#ifdef SYSDEPENDENTSAVE
2346
        PUTZERO(AR.StoreData.Position);
2347
#else
2348
        SETBASEPOSITION(AR.StoreData.Position, (LONG)(sizeof(STOREHEADER)));
28✔
2349
#endif
2350
        return(0);
28✔
2351
}
2352

2353
/*
2354
                 #] SetFileIndex : 
2355
                 #[ VarStore :
2356

2357
                The n -= sizeof(WORD); makes that the real length comes in the
2358
                padding space, provided there is padding space (it seems so).
2359
                The reading of the information assumes this is the case and hence
2360
                things work....
2361
*/
2362

2363
WORD VarStore(UBYTE *s, WORD n, WORD name, WORD namesize)
56✔
2364
{
2365
        GETIDENTITY
16✔
2366
        UBYTE *t, *u;
56✔
2367
        if ( s ) {
56✔
2368
                n -= sizeof(WORD);
7✔
2369
                t = (UBYTE *)AO.wpoin;
7✔
2370
/*
2371
                u = (UBYTE *)AT.WorkTop;
2372
*/
2373
                u = AO.wpos+AO.wlen;
7✔
2374
                while ( n > 0 && t < u ) { *t++ = *s++; n--; }
315✔
2375
                while ( t >= u ) {
7✔
2376
                        if ( WriteFile(AR.StoreData.Handle,AO.wpos,AO.wlen) != AO.wlen ) return(-1);
×
2377
                        t = AO.wpos;
×
2378
                        while ( n > 0 && t < u ) { *t++ = *s++; n--; }
×
2379
                }
2380
                s = AC.varnames->namebuffer + name;
7✔
2381
                n = namesize;
7✔
2382
                n += sizeof(void *)-1; n &= -(sizeof(void *));
7✔
2383
                *((WORD *)t) = n;
7✔
2384
                t += sizeof(WORD);
7✔
2385
                while ( n > 0 && t < u ) {
63✔
2386
                        if ( namesize > 0 ) { *t++ = *s++; namesize--; }
56✔
2387
                        else { *t++ = 0; }
42✔
2388
                        n--;
56✔
2389
                }
2390
                while ( t >= u ) {
7✔
2391
                        if ( WriteFile(AR.StoreData.Handle,AO.wpos,AO.wlen) != AO.wlen ) return(-1);
×
2392
                        t = AO.wpos;
×
2393
                        while ( n > 0 && t < u ) {
×
2394
                                if ( namesize > 0 ) { *t++ = *s++; namesize--; }
×
2395
                                else { *t++ = 0; }
×
2396
                                n--;
×
2397
                        }
2398
                }
2399
                AO.wpoin = t;
7✔
2400
        }
2401
        else {
2402
                LONG size;
49✔
2403
                size = AO.wpoin - AO.wpos;
49✔
2404
                if ( WriteFile(AR.StoreData.Handle,AO.wpos,size) != size ) return(-1);
49✔
2405
                AO.wpoin = AO.wpos;
49✔
2406
        }
2407
        return(0);
2408
}
2409

2410
/*
2411
                 #] VarStore : 
2412
                 #[ TermRenumber :
2413

2414
                renumbers the variables inside term according to the information
2415
                in struct renumber.
2416
                The search is binary. This avoided having to read/write the
2417
                expression twice when it was stored.
2418

2419
*/
2420

2421
WORD TermRenumber(WORD *term, RENUMBER renumber, WORD nexpr)
×
2422
{
2423
        WORD *stopper;
×
2424
/*!!!
2425
WORD *memterm=term;
2426
static LONG ctrap=0;
2427
  !!!*/
2428
        WORD *t, *sarg, n;
×
2429
        stopper = term + *term - 1;
×
2430
        stopper = stopper - ABS(*stopper) + 1;
×
2431
        term++;
×
2432
        while ( term < stopper ) {
×
2433
/*!!!
2434
ctrap++;
2435
  !!!*/
2436
                if ( *term == SYMBOL ) {
×
2437
                        t = term + term[1];
×
2438
                        term += 2;
×
2439
                        do {
×
2440
                                if ( ( n = FindrNumber(*term,&(renumber->symb)) ) < 0 ) goto ErrR;
×
2441
                                *term = renumber->symnum[n];
×
2442
                                term += 2;
×
2443
                        } while ( term < t );
×
2444
                }
2445
                else if ( *term == DOTPRODUCT ) {
×
2446
                        t = term + term[1];
×
2447
                        term += 2;
×
2448
                        do {
×
2449
                                if ( ( n = FindrNumber(*term,&(renumber->vect)) )
×
2450
                                         < 0 ) goto ErrR;
×
2451
                                *term++ = renumber->vecnum[n];
×
2452
                                if ( ( n = FindrNumber(*term,&(renumber->vect)) )
×
2453
                                         < 0 ) goto ErrR;
×
2454
                                *term = renumber->vecnum[n];
×
2455
                                term += 2;
×
2456
                        } while ( term < t );
×
2457
                }
2458
                else if ( *term == VECTOR ) {
×
2459
                        t = term + term[1];
×
2460
                        term += 2;
×
2461
                        do {
×
2462
                                if ( ( n = FindrNumber(*term,&(renumber->vect)) )
×
2463
                                         < 0 ) goto ErrR;
×
2464
                                *term++ = renumber->vecnum[n];
×
2465
                                if ( ( *term >= AM.OffsetIndex ) && ( *term < AM.IndDum ) ) {
×
2466
                                        if ( ( n = FindrNumber(*term,&(renumber->indi)) )
×
2467
                                                 < 0 ) goto ErrR;
×
2468
                                        *term++ = renumber->indnum[n];
×
2469
                                }
2470
                                else term++;
×
2471
                        } while ( term < t );
×
2472
                }
2473
                else if ( *term == INDEX || *term == LEVICIVITA || *term == GAMMA
×
2474
                || *term == DELTA ) {
×
2475
Tensors:
×
2476
                        t = term + term[1];
×
2477
                        if ( *term == INDEX || * term == DELTA ) term += 2;
×
2478
                        else term += FUNHEAD;
×
2479
/*
2480
                        term += 2;
2481
*/
2482
                        while ( term < t ) {
×
2483
                                if ( *term >= AM.OffsetIndex + WILDOFFSET ) {
×
2484
/*
2485
                Still TOBEDONE
2486
*/
2487
                                }
2488
                                else if ( ( *term  >= AM.OffsetIndex ) && ( *term < AM.IndDum ) ) {
×
2489
                                        if ( ( n = FindrNumber(*term,&(renumber->indi)) )
×
2490
                                                 < 0 ) goto ErrR;
×
2491
                                        *term = renumber->indnum[n];
×
2492
                                }
2493
                                else if ( *term < (WILDOFFSET+AM.OffsetVector) ) {
×
2494
                                        if ( ( n = FindrNumber(*term,&(renumber->vect)) )
×
2495
                                                 < 0 ) goto ErrR;
×
2496
                                        *term = renumber->vecnum[n];
×
2497
                                }
2498
                                term++;
×
2499
                        }
2500
                }
2501
                else if ( *term == HAAKJE ) term += term[1];
×
2502
                else {
2503
                        if ( *term > MAXBUILTINFUNCTION ) {
×
2504
                                if ( ( n = FindrNumber(*term,&(renumber->func)) )
×
2505
                                         < 0 ) goto ErrR;
×
2506
                                *term = renumber->funnum[n];
×
2507
                        }
2508
                        if ( *term >= FUNCTION && functions[*term-FUNCTION].spec
×
2509
                                        >= TENSORFUNCTION && term[1] > FUNHEAD ) goto Tensors;
×
2510
                        t = term + term[1];                        /* General stopper */
×
2511
                        term += FUNHEAD;                        /* First argument */
×
2512
                        while ( term < t ) {
×
2513
                                sarg = term;
×
2514
                                NEXTARG(sarg)
×
2515
                                if ( *term > 0 ) {
×
2516
/*
2517
                                        Problem here:
2518
                                        Marking the argument as dirty attacks the heap
2519
                                        very heavily and costs much computer time.
2520
*/
2521
                                        *++term = 1;
×
2522
                                        term += ARGHEAD-1;
×
2523
                                        while ( term < sarg ) {
×
2524
                                                if ( TermRenumber(term,renumber,nexpr) ) goto ErrR;
×
2525
                                                term += *term;
×
2526
                                        }
2527
                                }
2528
                                else {
2529
                                        if ( *term <= -MAXBUILTINFUNCTION ) {
×
2530
                                                if ( ( n = FindrNumber(-*term,&(renumber->func)) )
×
2531
                                                 < 0 ) goto ErrR;
×
2532
                                                *term = -renumber->funnum[n];
×
2533
                                        }
2534
                                        else if ( *term == -SYMBOL ) {
×
2535
                                                term++;
×
2536
                                                if ( ( n = FindrNumber(*term,
×
2537
                                                        &(renumber->symb)) ) < 0 ) goto ErrR;
×
2538
                                                *term = renumber->symnum[n];
×
2539
                                        }
2540
                                        else if ( *term == -INDEX ) {
×
2541
                                                term++;
×
2542
                                                if ( *term >= AM.OffsetIndex + WILDOFFSET ) {
×
2543
/*
2544
                        Still TOBEDONE
2545
*/
2546
                                                }
2547
                                                else if ( ( *term  >= AM.OffsetIndex ) && ( *term < AM.IndDum ) ) {
×
2548
                                                        if ( ( n = FindrNumber(*term,&(renumber->indi)) )
×
2549
                                                                 < 0 ) goto ErrR;
×
2550
                                                        *term = renumber->indnum[n];
×
2551
                                                }
2552
                                                else if ( *term < (WILDOFFSET+AM.OffsetVector) ) {
×
2553
                                                        if ( ( n = FindrNumber(*term,&(renumber->vect)) )
×
2554
                                                                 < 0 ) goto ErrR;
×
2555
                                                        *term = renumber->vecnum[n];
×
2556
                                                }
2557
                                        }
2558
                                        else if ( *term == -VECTOR || *term == -MINVECTOR ) {
×
2559
                                                term++;
×
2560
                                                if ( ( n = FindrNumber(*term,&(renumber->vect)) )
×
2561
                                                 < 0 ) goto ErrR;
×
2562
                                                *term = renumber->vecnum[n];
×
2563
                                        }
2564
                                }
2565
                                term = sarg;                        /* Next argument */
2566
                        }
2567
                        term = t;
2568
                }
2569
        }
2570
        return(0);
2571
ErrR:
×
2572
        MesCall("TermRenumber");
×
2573
        SETERROR(-1)
×
2574
}
2575

2576
/*
2577
                 #] TermRenumber : 
2578
                 #[ FindrNumber :
2579
*/
2580

2581
WORD FindrNumber(WORD n, VARRENUM *v)
×
2582
{
2583
        WORD *hi,*med,*lo;
×
2584
        hi = v->hi;
×
2585
        lo = v->lo;
×
2586
        med = v->start;
×
2587
        if ( *hi == 0 ) {
×
2588
                if ( n != *hi ) {
×
2589
                        MesPrint("Serious problems coming up in FindrNumber");
×
2590
                        return(-1);
×
2591
                }
2592
                return(*hi);
2593
        }
2594
        while ( *med != n ) {
×
2595
                if ( *med < n ) {
×
2596
                        if ( med == hi ) goto ErrFindr;
×
2597
                        lo = med;
×
2598
                        med = hi - ((WORDDIF(hi,med))/2);
×
2599
                }
2600
                else {
2601
                        if ( med == lo ) goto ErrFindr;
×
2602
                        hi = med;
×
2603
                        med = lo + ((WORDDIF(med,lo))/2);
×
2604
                }
2605
        }
2606
        return(WORDDIF(med,v->lo));
×
2607
ErrFindr:
×
2608
/*
2609
        Reconstruction:
2610
*/
2611
        {
2612
                int i;
×
2613
                i = WORDDIF(v->hi,v->lo);
×
2614
                MesPrint("FindrNumber: n = %d, list has %d members",n,i);
×
2615
                while ( i >= 0 ) {
×
2616
                        MesPrint("v->lo[%d] = %d",i,v->lo[i]); i--;
×
2617
                }
2618
                hi = v->hi;
×
2619
                lo = v->lo;
×
2620
                med = v->start;
×
2621
                MesPrint("Start with %d,%d,%d",0,WORDDIF(med,v->lo),WORDDIF(hi,v->lo));
×
2622
                while ( *med != n ) {
×
2623
                        if ( *med < n ) {
×
2624
                                if ( med == hi ) goto ErrFindr2;
×
2625
                                lo = med;
×
2626
                                med = hi - ((WORDDIF(hi,med))/2);
×
2627
                        }
2628
                        else {
2629
                                if ( med == lo ) goto ErrFindr2;
×
2630
                                hi = med;
×
2631
                                med = ((WORDDIF(med,lo))/2) + lo;
×
2632
                        }
2633
                        MesPrint("New: %d,%d,%d, *med = %d",WORDDIF(lo,v->lo),WORDDIF(med,v->lo),WORDDIF(hi,v->lo),*med);
×
2634
                }
2635
        }
2636
        return(WORDDIF(med,v->lo));
×
2637
ErrFindr2:
×
2638
        return(MesPrint("Renumbering problems"));
×
2639
}
2640

2641
/*
2642
                 #] FindrNumber : 
2643
                 #[ FindInIndex :
2644

2645
                Finds an expression in the storage index if it exists.
2646
                If found it returns a pointer to the index entry, otherwise zero.
2647
                par = 0                Search by address (--> f == &AR.StoreData, called by GetTable, CoSave )
2648
                par = 1                Search by name    (--> f == &AO.SaveData,  called by CoLoad )
2649

2650
                When comparing parameter fields the parameters of the expression
2651
                to be searched are in AT.TMaddr. This includes the primary expression
2652
                and a possible FROMBRAC information. The FROMBRAC is always last.
2653

2654
                The parameter mode tells whether we should worry about arguments of
2655
                a stored expression.
2656
*/
2657

2658
INDEXENTRY *FindInIndex(WORD expr, FILEDATA *f, WORD par, WORD mode)
8✔
2659
{
2660
        GETIDENTITY
4✔
2661
        INDEXENTRY *ind;
8✔
2662
        WORD i, hand, *m;
8✔
2663
        WORD *start, *stop, *stop2, *m2, nomatch = 0;
8✔
2664
        POSITION stindex, indexpos, scrpos;
8✔
2665
        LONG number, num;
8✔
2666
        stindex = f->Position;
8✔
2667
        m = AT.TMaddr;
8✔
2668
        stop = m + m[1];
8✔
2669
        m += SUBEXPSIZE;
8✔
2670
        start = m;
8✔
2671
        while ( m < stop ) {
8✔
2672
                if ( *m == FROMBRAC || *m == WILDCARDS ) break;
×
2673
                m += m[1];
×
2674
        }
2675
        stop = m;
8✔
2676
        if ( !par ) hand = AR.StoreData.Handle;
8✔
2677
        else        hand = AO.SaveData.Handle;
×
2678
        for(;;) {
8✔
2679
                if ( ( i = (WORD)BASEPOSITION(f->Index.number) ) != 0 ) {
8✔
2680
                        indexpos = f->Position;
8✔
2681
                        ADDPOS(indexpos,(2*sizeof(POSITION)));
8✔
2682
                        ind = f->Index.expression;
8✔
2683
                        do {
12✔
2684
                                if ( ( !par && ISEQUALPOS(indexpos,Expressions[expr].onfile) )
12✔
2685
                                || ( par && !StrCmp(EXPRNAME(expr),(UBYTE *)(ind->name)) ) ) {
4✔
2686
                                        nomatch = 1;
8✔
2687
/*
2688
MesPrint("index: position: %8p",&(ind->position));
2689
MesPrint("index: length: %8p",&(ind->length));
2690
MesPrint("index: variables: %8p",&(ind->variables));
2691
MesPrint("index: nsymbols: %d",ind->nsymbols);
2692
MesPrint("index: nindices: %d",ind->nindices);
2693
MesPrint("index: nvectors: %d",ind->nvectors);
2694
MesPrint("index: nfunctions: %d",ind->nfunctions);
2695
MesPrint("index: size: %d",ind->size);
2696
*/
2697
                                        if ( par ) return(ind);
8✔
2698
                                        scrpos = ind->position;
8✔
2699
                                        SeekFile(hand,&scrpos,SEEK_SET);
8✔
2700
                                        if ( ISNOTEQUALPOS(scrpos,ind->position) ) goto ErrGt2;
8✔
2701
                                        if ( ReadFile(hand,(UBYTE *)AT.WorkPointer,(LONG)sizeof(WORD)) != 
8✔
2702
                                        sizeof(WORD) || !*AT.WorkPointer ) goto ErrGt2;
8✔
2703
                                        num = *AT.WorkPointer - 1;
8✔
2704
                                        num *= wsizeof(WORD);
8✔
2705
                                        if ( *AT.WorkPointer < 0 ||
16✔
2706
                                        ReadFile(hand,(UBYTE *)(AT.WorkPointer+1),num) != num ) goto ErrGt2;
8✔
2707
                                        m = start;        /* start of parameter field to be searched */
8✔
2708
                                        m2 = AT.WorkPointer + 1;
8✔
2709
                                        stop2 = m2 + m2[1];
8✔
2710
                                        m2 += SUBEXPSIZE;
8✔
2711
                                        while ( m < stop && m2 < stop2 ) {
8✔
2712
                                                if ( *m == SYMBOL ) {
×
2713
                                                        if ( *m2 != SYMTOSYM ) break;
×
2714
                                                        m2[3] = m[2];
×
2715
                                                }
2716
                                                else if ( *m == INDEX ) {
×
2717
                                                        if ( m[2] >= 0 ) {
×
2718
                                                                if ( *m2 != INDTOIND ) break;
×
2719
                                                        }
2720
                                                        else {
2721
                                                                if ( *m2 != VECTOVEC ) break;
×
2722
                                                        }
2723
                                                        m2[3] = m[2];
×
2724
                                                }
2725
                                                else if ( *m >= FUNCTION ) {
×
2726
                                                        if ( *m2 != FUNTOFUN ) break;
×
2727
                                                        m2[3] = *m;
×
2728
                                                }
2729
                                                else {}
×
2730
                                                m += m[1];
×
2731
                                                m2 += m2[1];
×
2732
                                        }
2733
                                        if ( ( m >= stop && m2 >= stop2 ) || mode == 0 ) {
8✔
2734
                                                AT.WorkPointer = stop2;
8✔
2735

2736
                                                return(ind);
8✔
2737
                                        }
2738
                                }
2739
                                ind++;
4✔
2740
                                ADDPOS(indexpos,sizeof(INDEXENTRY));
4✔
2741
                        } while ( --i > 0 );
4✔
2742
                }
2743
                f->Position = f->Index.next;
×
2744
#ifndef SYSDEPENDENTSAVE
2745
                if ( !ISNOTZEROPOS(f->Position) ) ADDPOS(f->Position,sizeof(STOREHEADER));
×
2746
                number = sizeof(struct FiLeInDeX);
×
2747
#endif
2748
                if ( ISEQUALPOS(f->Position,stindex) && !AO.bufferedInd ) goto ErrGetTab;
×
2749
                if ( !par ) {
×
2750
                        SeekFile(AR.StoreData.Handle,&(f->Position),SEEK_SET);
×
2751
                        if ( ISNOTEQUALPOS(f->Position,AR.StoreData.Position) ) goto ErrGt2;
×
2752
#ifndef SYSDEPENDENTSAVE
2753
                        if ( ReadFile(f->Handle, (UBYTE *)(&(f->Index)), number) != number ) goto ErrGt2;
×
2754
#endif
2755
                }
2756
                else {
2757
                        SeekFile(AO.SaveData.Handle,&(f->Position),SEEK_SET);
×
2758
                        if ( ISNOTEQUALPOS(f->Position,AO.SaveData.Position) ) goto ErrGt2;
×
2759
#ifndef SYSDEPENDENTSAVE
2760
                        if ( ReadSaveIndex(&f->Index) ) goto ErrGt2;
×
2761
#endif
2762
                }
2763
#ifdef SYSDEPENDENTSAVE
2764
                number = sizeof(struct FiLeInDeX);
2765
                if ( ReadFile(f->Handle,(UBYTE *)(&(f->Index)),number) !=
2766
                number ) goto ErrGt2;
2767
#endif
2768
        }
2769
ErrGetTab:
×
2770
        if ( nomatch ) {
×
2771
                MesPrint("Parameters of expression %s don't match."
×
2772
                ,EXPRNAME(expr));
×
2773
        }
2774
        else {
2775
                MesPrint("Cannot find expression %s",EXPRNAME(expr));
×
2776
        }
2777
        return(0);
2778
ErrGt2:
×
2779
        MesPrint("Readerror in IndexSearch");
×
2780
        return(0);
×
2781
}
2782

2783
/*
2784
                 #] FindInIndex : 
2785
                 #[ GetTable :
2786

2787
                Locates stored files and constructs the renumbering tables.
2788
                They are allocated in the WorkSpace.
2789
                First the expression data are located. The Index is treated
2790
                as a circularly linked buffer which is paged forwardly.
2791
                If the indexentry is located (in ind) the two renumber tables
2792
                have to be constructed.
2793
                Finally the prototype has to be put in the proper buffer, so
2794
                that wildcards can be passed. There should be a test with
2795
                an already existing prototype that is constructed by the
2796
                pattern matcher. This has not been put in yet.
2797

2798
                There is a problem with the parallel processing.
2799
                Feeding in the variables that were erased by a .store could in
2800
                principle happen in different orders (ParFORM) or simultaneously
2801
                (TFORM). The proper resolution is to have the compiler call GetTable
2802
                when a stored expression is encountered.
2803

2804
                This has been mended in development of TFORM by reading the
2805
                symbol tables during compilation. See the call to GetTable
2806
                in the CodeGenerator.
2807

2808
                Next is the problem of FindInIndex which writes in AR.StoreData
2809
                Copying this is expensive!
2810

2811
                This Doesn't work well for TFORM yet.!!!!!!!!
2812
                e[x1,x2] versus e[x2,x1] messes up.
2813
                For the rest is the reloading during execution not thread safe.
2814

2815
                The parameter mode tells whether we should worry about arguments
2816
                of a stored expression.
2817
*/
2818

2819
RENUMBER GetTable(WORD expr, POSITION *position, WORD mode)
×
2820
{
2821
        GETIDENTITY
2822
        WORD i, j;
×
2823
        WORD *w;
×
2824
        RENUMBER r;
×
2825
        LONG num, nsize, xx;
×
2826
        WORD jsym, jind, jvec, jfun;
×
2827
        WORD k, type, error = 0, *oldw, *neww, *oldwork = AT.WorkPointer;
×
2828
        struct SyMbOl SyM;
×
2829
        struct InDeX InD;
×
2830
        struct VeCtOr VeC;
×
2831
        struct FuNcTiOn FuN;
×
2832
        INDEXENTRY *ind;
×
2833
/*
2834
        Prepare for FindInIndex to put the prototype in the WorkSpace.
2835
        oldw will point at the "wildcards"
2836
*/
2837
/*
2838
                Bug fix. Look also in Generator.
2839
#ifndef WITHPTHREADS
2840

2841
        if ( ( r = Expressions[expr].renum ) != 0 ) { }
2842
        else {
2843
                Expressions[expr].renum = 
2844
                r = (RENUMBER)Malloc1(sizeof(struct ReNuMbEr),"Renumber");
2845
        }
2846
#else
2847
                r = (RENUMBER)Malloc1(sizeof(struct ReNuMbEr),"Renumber");
2848
#endif
2849
*/
2850
                r = (RENUMBER)Malloc1(sizeof(struct ReNuMbEr),"Renumber");
×
2851

2852
        oldw = AT.WorkPointer + 1 + SUBEXPSIZE;
×
2853
/*
2854
        The prototype is loaded in the WorkSpace by the Index routine.
2855
        After all it has to find an occurrence with the proper arguments.
2856
        This sets the WorkPointer. Hence be careful now.
2857
*/
2858
        LOCK(AM.storefilelock);
×
2859
        if ( ( ind = FindInIndex(expr,&AR.StoreData,0,mode) ) == 0 ) {
×
2860
                UNLOCK(AM.storefilelock);
2861
                return(0);
2862
        }
2863

2864
        xx = ind->nsymbols+ind->nindices+ind->nvectors+ind->nfunctions;
×
2865
        if ( xx == 0 ) {
×
2866
                Expressions[expr].renumlists = 
×
2867
                w = AN.dummyrenumlist;
×
2868
        }
2869
        else {
2870
/*
2871
#ifndef WITHPTHREADS
2872
                Expressions[expr].renumlists = 
2873
#endif
2874
*/
2875
                w = (WORD *)Malloc1(sizeof(WORD)*(xx*2),"VarSpace");
×
2876
        }
2877
        r->symb.lo = w;
×
2878
        r->symb.start = w + ind->nsymbols/2;
×
2879
        w += ind->nsymbols;
×
2880
        r->symb.hi = w - 1;
×
2881
        r->symnum = w;
×
2882
        w += ind->nsymbols;
×
2883

2884
        r->indi.lo = w;
×
2885
        r->indi.start = w + ind->nindices/2;
×
2886
        w += ind->nindices;
×
2887
        r->indi.hi = w - 1;
×
2888
        r->indnum = w;
×
2889
        w += ind->nindices;
×
2890

2891
        r->vect.lo = w;
×
2892
        r->vect.start = w + ind->nvectors/2;
×
2893
        w += ind->nvectors;
×
2894
        r->vect.hi = w - 1;
×
2895
        r->vecnum = w;
×
2896
        w += ind->nvectors;
×
2897

2898
        r->func.lo = w;
×
2899
        r->func.start = w + ind->nfunctions/2;
×
2900
        w += ind->nfunctions;
×
2901
        r->func.hi = w - 1;
×
2902
        r->funnum = w;
×
2903
/*        w += ind->nfunctions; */
2904

2905
        SeekFile(AR.StoreData.Handle,&(ind->variables),SEEK_SET);
×
2906
        *position = ind->position;
×
2907
        jsym = ind->nsymbols;
×
2908
        jvec = ind->nvectors;
×
2909
        jind = ind->nindices;
×
2910
        jfun = ind->nfunctions;
×
2911
/*
2912
                        #[ Symbols :
2913
*/
2914
        {
2915
        SYMBOLS s = &SyM;
×
2916
        w = r->symb.lo; j = jsym;
×
2917
        for ( i = 0; i < j; i++ ) {
×
2918
                if ( ReadFile(AR.StoreData.Handle,(UBYTE *)s,(LONG)(sizeof(struct SyMbOl)))
×
2919
                != sizeof(struct SyMbOl) ) goto ErrGt2;
×
2920
                nsize = s->namesize; nsize += sizeof(void *)-1;
×
2921
                nsize &= -sizeof(void *);
×
2922
                if ( ReadFile(AR.StoreData.Handle,(UBYTE *)(AT.WorkPointer),nsize)
×
2923
                != nsize ) goto ErrGt2;
×
2924
                *w = s->number;
×
2925
                if ( ( s->flags & INUSE ) != 0 ) {
×
2926
                        /* Find the replacement. It must exist! */
2927
                        neww = oldw;
2928
                        while ( *neww != SYMTOSYM || neww[2] != *w ) neww += neww[1];
×
2929
                        k = neww[3];
×
2930
                }
2931
                else if ( GetVar((UBYTE *)AT.WorkPointer,&type,&k,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
×
2932
                        if ( type != CSYMBOL ) {
×
2933
                                MesPrint("Error: Conflicting types for %s",(AT.WorkPointer));
×
2934
                                error = -1;
×
2935
                        }
2936
                        else {
2937
                                if ( ( s->complex & (VARTYPEIMAGINARY|VARTYPECOMPLEX) ) !=
×
2938
                                ( symbols[k].complex & (VARTYPEIMAGINARY|VARTYPECOMPLEX) ) ) {
×
2939
                                        MesPrint("Warning: Conflicting complexity for %s",AT.WorkPointer);
×
2940
                                        error = -1;
×
2941
                                }
2942
                                if ( ( s->complex & (VARTYPEROOTOFUNITY) ) !=
×
2943
                                ( symbols[k].complex & (VARTYPEROOTOFUNITY) ) ) {
×
2944
                                        MesPrint("Warning: Conflicting root of unity properties for %s",AT.WorkPointer);
×
2945
                                        error = -1;
×
2946
                                }
2947
                                if ( ( s->complex & VARTYPEROOTOFUNITY ) == VARTYPEROOTOFUNITY ) {
×
2948
                                        if ( s->maxpower != symbols[k].maxpower ) {
×
2949
                                                MesPrint("Warning: Conflicting n in n-th root of unity properties for %s",AT.WorkPointer);
×
2950
                                                error = -1;
×
2951
                                        }
2952
                                }
2953
                                else if ( ( s->minpower !=
×
2954
                                symbols[k].minpower || s->maxpower !=
×
2955
                                symbols[k].maxpower ) && AC.WarnFlag ) {
×
2956
                                        MesPrint("Warning: Conflicting power restrictions for %s",AT.WorkPointer);
×
2957
                                }
2958
                        }
2959
                }
2960
                else {
2961
                        if ( ( k = EntVar(CSYMBOL,(UBYTE *)(AT.WorkPointer),s->complex,s->minpower,
×
2962
                        s->maxpower,s->dimension) ) < 0 ) goto GetTcall;
×
2963
                }
2964
                *(w+j) = k;
×
2965
                w++;
×
2966
        }
2967
        }
2968
/*
2969
                        #] Symbols : 
2970
                        #[ Indices :
2971
*/
2972
        {
2973
        INDICES s = &InD;
×
2974
        w = r->indi.lo; j = jind;
×
2975
        for ( i = 0; i < j; i++ ) {
×
2976
                if ( ReadFile(AR.StoreData.Handle,(UBYTE *)s,(LONG)(sizeof(struct InDeX)))
×
2977
                != sizeof(struct InDeX) ) goto ErrGt2;
×
2978
                nsize = s->namesize; nsize += sizeof(void *)-1;
×
2979
                nsize &= -sizeof(void *);
×
2980
                if ( ReadFile(AR.StoreData.Handle,(UBYTE *)(AT.WorkPointer),nsize)
×
2981
                != nsize ) goto ErrGt2;
×
2982
                *w = s->number + AM.OffsetIndex;
×
2983
                if ( s->dimension < 0 ) {        /* Relabel the dimension */
×
2984
                        s->dimension = -r->symnum[FindrNumber(-s->dimension,&(r->symb))];
×
2985
                        if ( s->nmin4 < -NMIN4SHIFT ) {        /* Relabel n-4 */
×
2986
                                s->nmin4 = -r->symnum[FindrNumber(-s->nmin4-NMIN4SHIFT
×
2987
                                ,&(r->symb))]-NMIN4SHIFT;
×
2988
                        }
2989
                }
2990
                if ( ( s->flags & INUSE ) != 0 ) {
×
2991
                        /* Find the replacement. It must exist! */
2992
                        neww = oldw;
2993
                        while ( *neww != INDTOIND || neww[2] != *w ) neww += neww[1];
×
2994
                        k = neww[3] - AM.OffsetIndex;
×
2995
                }
2996
                else if ( s->type == DUMMY ) {
×
2997
/*
2998
-------->                        Here we may have to execute some renumbering
2999
*/
3000
                }
3001
                else if ( GetVar((UBYTE *)(AT.WorkPointer),&type,&k,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
×
3002
                        if ( type != CINDEX ) {
×
3003
                                MesPrint("Error: Conflicting types for %s",(AT.WorkPointer));
×
3004
                                error = -1;
×
3005
                        }
3006
                        else {
3007
                                if ( s->type !=
×
3008
                                indices[k].type ) {
×
3009
                                        MesPrint("Warning: %s is also a dummy index",(AT.WorkPointer));
×
3010
                                        error = -1;
×
3011
                                        goto GetTb3;
×
3012
                                }
3013
                                if ( s->dimension != indices[k].dimension ) {
×
3014
                                        MesPrint("Warning: Conflicting dimensions for %s",(AT.WorkPointer));
×
3015
                                        error = -1;
×
3016
                                }
3017
                        }
3018
                }
3019
                else {
3020
GetTb3:
×
3021
                        if ( ( k = EntVar(CINDEX,(UBYTE *)(AT.WorkPointer),
×
3022
                        s->dimension,0,s->nmin4,0) ) < 0 ) goto GetTcall;
×
3023

3024
                }
3025
                *(w+j) = k + AM.OffsetIndex;
×
3026
                w++;
×
3027
        }
3028
        }
3029
/*
3030
                        #] Indices : 
3031
                        #[ Vectors :
3032
*/
3033
        {
3034
        VECTORS s = &VeC;
×
3035
        w = r->vect.lo; j = jvec;
×
3036
        for ( i = 0; i < j; i++ ) {
×
3037
                if ( ReadFile(AR.StoreData.Handle,(UBYTE *)s,(LONG)(sizeof(struct VeCtOr)))
×
3038
                != sizeof(struct VeCtOr) ) goto ErrGt2;
×
3039
                nsize = s->namesize; nsize += sizeof(void *)-1;
×
3040
                nsize &= -sizeof(void *);
×
3041
                if ( ReadFile(AR.StoreData.Handle,(UBYTE *)(AT.WorkPointer),nsize)
×
3042
                != nsize ) goto ErrGt2;
×
3043
                *w = s->number + AM.OffsetVector;
×
3044
                if ( ( s->flags & INUSE ) != 0 ) {
×
3045
                        /* Find the replacement. It must exist! */
3046
                        neww = oldw;
3047
                        while ( *neww != VECTOVEC || neww[2] != *w ) neww += neww[1];
×
3048
                        k = neww[3] - AM.OffsetVector;
×
3049
                }
3050
                else if ( GetVar((UBYTE *)(AT.WorkPointer),&type,&k,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
×
3051
                        if ( type != CVECTOR ) {
×
3052
                                MesPrint("Error: Conflicting types for %s",(AT.WorkPointer));
×
3053
                                error = -1;
×
3054
                        }
3055
                        else {
3056
                                if ( ( s->complex & (VARTYPEIMAGINARY|VARTYPECOMPLEX) ) !=
×
3057
                                ( vectors[k].complex & (VARTYPEIMAGINARY|VARTYPECOMPLEX) ) ) {
×
3058
                                        MesPrint("Warning: Conflicting complexity for %s",(AT.WorkPointer));
×
3059
                                        error = -1;
×
3060
                                }
3061
                        }
3062
                }
3063
                else {
3064
                        if ( ( k = EntVar(CVECTOR,(UBYTE *)(AT.WorkPointer),
×
3065
                        s->complex,0,0,s->dimension) ) < 0 ) goto GetTcall;
×
3066
                }
3067
                *(w+j) = k + AM.OffsetVector;
×
3068
                w++;
×
3069
        }
3070
        }
3071
/*
3072
                        #] Vectors : 
3073
                        #[ Functions :
3074
*/
3075
        {
3076
        FUNCTIONS s = &FuN;
×
3077
        w = r->func.lo; j = jfun;
×
3078
        for ( i = 0; i < j; i++ ) {
×
3079
                if ( ReadFile(AR.StoreData.Handle,(UBYTE *)s,(LONG)(sizeof(struct FuNcTiOn)))
×
3080
                != sizeof(struct FuNcTiOn) ) goto ErrGt2;
×
3081
                nsize = s->namesize; nsize += sizeof(void *)-1;
×
3082
                nsize &= -sizeof(void *);
×
3083
                if ( ReadFile(AR.StoreData.Handle,(UBYTE *)(AT.WorkPointer),nsize)
×
3084
                != nsize ) goto ErrGt2;
×
3085
                *w = s->number + FUNCTION;
×
3086
                if ( ( s->flags & INUSE ) != 0 ) {
×
3087
                        /* Find the replacement. It must exist! */
3088
                        neww = oldw;
3089
                        while ( *neww != FUNTOFUN || neww[2] != *w ) neww += neww[1];
×
3090
                        k = neww[3] - FUNCTION;
×
3091
                }
3092
                else if ( GetVar((UBYTE *)(AT.WorkPointer),&type,&k,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
×
3093
                        if ( type != CFUNCTION ) {
×
3094
                                MesPrint("Error: Conflicting types for %s",(AT.WorkPointer));
×
3095
                                error = -1;
×
3096
                        }
3097
                        else {
3098
                                if ( s->complex != functions[k].complex ) {
×
3099
                                        MesPrint("Warning: Conflicting complexity for %s",(AT.WorkPointer));
×
3100
                                        error = -1;
×
3101
                                }
3102
                                else if ( s->symmetric != functions[k].symmetric ) {
×
3103
                                        MesPrint("Warning: Conflicting symmetry properties for %s",(AT.WorkPointer));
×
3104
                                        error = -1;
×
3105
                                }
3106
                                else if ( ( s->maxnumargs != functions[k].maxnumargs )
×
3107
                                || ( s->minnumargs != functions[k].minnumargs ) ) {
×
3108
                                        MesPrint("Warning: Conflicting argument restriction properties for %s",(AT.WorkPointer));
×
3109
                                        error = -1;
×
3110
                                }
3111
                        }
3112
                }
3113
                else {
3114
                        if ( ( k = EntVar(CFUNCTION,(UBYTE *)(AT.WorkPointer),
×
3115
                        s->complex,s->commute,s->spec,s->dimension) ) < 0 ) goto GetTcall;
×
3116
                        functions[k].symmetric = s->symmetric;
×
3117
                        functions[k].maxnumargs = s->maxnumargs;
×
3118
                        functions[k].minnumargs = s->minnumargs;
×
3119
                }
3120
                *(w+j) = k + FUNCTION;
×
3121
                w++;
×
3122
        }
3123
        }
3124
/*
3125
                        #] Functions : 
3126

3127
        Now we skip the prototype. This sets the start position at the first term
3128
*/
3129
        if ( error ) {
×
3130
                UNLOCK(AM.storefilelock);
×
3131
                AT.WorkPointer = oldwork;
×
3132
                return(0);
×
3133
        }
3134

3135
        {
3136
/*
3137
                For clarity we look where we are.
3138
                We want to know: is this position already known?
3139
                Could we have inserted extra information here?
3140

3141
                nummystery indicates extra words. We have currently in order
3142
                (if they exist)
3143
                        numdummies
3144
                        numfactors
3145
                        vflags
3146
                        uflags
3147
*/
3148
                POSITION pos;
×
3149
                int nummystery;
×
3150
                TELLFILE(AR.StoreData.Handle,&pos);
×
3151
                nummystery = DIFBASE(ind->position,pos);
×
3152
/*
3153
                MesPrint("--> We are at position       %8p",&pos);
3154
                MesPrint("--> The index says        at %8p",&(ind->position));
3155
                MesPrint("--> There are %d mystery bytes",nummystery);
3156
*/
3157
                if ( nummystery > 0 ) {
×
3158
                        if ( ReadFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,(LONG)sizeof(WORD)) != 
×
3159
                        sizeof(WORD) ) {
3160
                                UNLOCK(AM.storefilelock);
×
3161
                                AT.WorkPointer = oldwork;
×
3162
                                return(0);
×
3163
                        }
3164
                        Expressions[expr].numdummies = *AT.WorkPointer;
×
3165
/*
3166
                        MesPrint("--> numdummies = %d",Expressions[expr].numdummies);
3167
*/
3168
                        nummystery -= sizeof(WORD);
×
3169
                }
3170
                else {
3171
                        Expressions[expr].numdummies = 0;
×
3172
                }
3173
                if ( nummystery > 0 ) {
×
3174
                        if ( ReadFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,(LONG)sizeof(WORD)) != 
×
3175
                        sizeof(WORD) ) {
3176
                                UNLOCK(AM.storefilelock);
×
3177
                                AT.WorkPointer = oldwork;
×
3178
                                return(0);
×
3179
                        }
3180
                        if ( ( AS.OldNumFactors == 0 ) || ( AS.NumOldNumFactors < NumExpressions ) ) {
×
3181
                                WORD *buffer;
×
3182
                                int capacity = 20;
×
3183
                                if (capacity < NumExpressions) capacity = NumExpressions * 2;
×
3184

3185
                                buffer = (WORD *)Malloc1(capacity * sizeof(WORD), "numfactors pointers");
×
3186
                                if (AS.OldNumFactors) {
×
3187
                                        WCOPY(buffer, AS.OldNumFactors, AS.NumOldNumFactors);
×
3188
                                        M_free(AS.OldNumFactors, "numfactors pointers");
×
3189
                                }
3190
                                AS.OldNumFactors = buffer;
×
3191

3192
                                buffer = (WORD *)Malloc1(capacity * sizeof(WORD), "vflags pointers");
×
3193
                                if (AS.Oldvflags) {
×
3194
                                        WCOPY(buffer, AS.Oldvflags, AS.NumOldNumFactors);
×
3195
                                        M_free(AS.Oldvflags, "vflags pointers");
×
3196
                                }
3197
                                AS.Oldvflags = buffer;
×
3198

3199
                                buffer = (WORD *)Malloc1(capacity * sizeof(WORD), "uflags pointers");
×
3200
                                if (AS.Olduflags) {
×
3201
                                        WCOPY(buffer, AS.Olduflags, AS.NumOldNumFactors);
×
3202
                                        M_free(AS.Olduflags, "uflags pointers");
×
3203
                                }
3204
                                AS.Oldvflags = buffer;
×
3205

3206
                                AS.NumOldNumFactors = capacity;
×
3207
                        }
3208

3209
                        AS.OldNumFactors[expr] =
×
3210
                        Expressions[expr].numfactors = *AT.WorkPointer;
×
3211
/*
3212
                        MesPrint("--> numfactors = %d",Expressions[expr].numfactors);
3213
*/
3214
                        nummystery -= sizeof(WORD);
×
3215
                }
3216
                else {
3217
                        Expressions[expr].numfactors = 0;
×
3218
                }
3219
                if ( nummystery > 0 ) {
×
3220
                        if ( ReadFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,(LONG)sizeof(WORD)) != 
×
3221
                        sizeof(WORD) ) {
3222
                                UNLOCK(AM.storefilelock);
×
3223
                                AT.WorkPointer = oldwork;
×
3224
                                return(0);
×
3225
                        }
3226
                        AS.Oldvflags[expr] =
×
3227
                        Expressions[expr].vflags = *AT.WorkPointer;
×
3228
/*
3229
                        MesPrint("--> vflags = %d",Expressions[expr].vflags);
3230
*/
3231
                        nummystery -= sizeof(WORD);
×
3232
                }
3233
                else {
3234
                        Expressions[expr].vflags = 0;
×
3235
                }
3236
                if ( nummystery > 0 ) {
×
3237
                        if ( ReadFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,(LONG)sizeof(WORD)) != 
×
3238
                        sizeof(WORD) ) {
3239
                                UNLOCK(AM.storefilelock);
×
3240
                                AT.WorkPointer = oldwork;
×
3241
                                return(0);
×
3242
                        }
3243
                        AS.Olduflags[expr] =
×
3244
                        Expressions[expr].uflags = *AT.WorkPointer;
×
3245
/*
3246
                        MesPrint("--> uflags = %d",Expressions[expr].uflags);
3247
*/
3248
                        nummystery -= sizeof(WORD);
×
3249
                }
3250
                else {
3251
                        Expressions[expr].uflags = 0;
×
3252
                }
3253
        }
3254

3255
        SeekFile(AR.StoreData.Handle,&(ind->position),SEEK_SET);
×
3256
        if ( ReadFile(AR.StoreData.Handle,(UBYTE *)AT.WorkPointer,(LONG)sizeof(WORD)) != 
×
3257
        sizeof(WORD) || !*AT.WorkPointer ) {
×
3258
                UNLOCK(AM.storefilelock);
×
3259
                AT.WorkPointer = oldwork;
×
3260
                return(0);
×
3261
        }
3262
        num = *AT.WorkPointer - 1;
×
3263
        num *= sizeof(WORD);
×
3264
        if ( *AT.WorkPointer < 0 ||
×
3265
        ReadFile(AR.StoreData.Handle,(UBYTE *)(AT.WorkPointer+1),num) != num ) {
×
3266
                MesPrint("@Error in stored expressions file at position %10p",*position);
×
3267
                UNLOCK(AM.storefilelock);
×
3268
                AT.WorkPointer = oldwork;
×
3269
                return(0);
×
3270
        }
3271
        UNLOCK(AM.storefilelock);
×
3272
        ADDPOS(*position,num+sizeof(WORD));
×
3273
        r->startposition = *position;
×
3274
        AT.WorkPointer = oldwork;
×
3275
        return(r);
×
3276
GetTcall:
×
3277
        UNLOCK(AM.storefilelock);
×
3278
        AT.WorkPointer = oldwork;
×
3279
        MesCall("GetTable");
×
3280
        return(0);
×
3281
ErrGt2:
×
3282
        UNLOCK(AM.storefilelock);
×
3283
        AT.WorkPointer = oldwork;
×
3284
        MesPrint("Readerror in GetTable");
×
3285
        return(0);
×
3286
}
3287

3288
/*
3289
                 #] GetTable : 
3290
                 #[ CopyExpression :
3291

3292
                Copies from one scratch buffer to another.
3293
                We assume here that the complete 'from' scratch buffer is taken.
3294
                We also assume that the 'from' buffer is positioned at the end of
3295
                the expression.
3296

3297
                The locks should be placed in the calling routine. We need basically
3298
                AS.outputslock.
3299
*/
3300

3301
int CopyExpression(FILEHANDLE *from, FILEHANDLE *to)
2✔
3302
{
3303
        POSITION posfrom, poscopy;
2✔
3304
        LONG fullsize,i;
2✔
3305
        WORD *t1, *t2;
2✔
3306
        int RetCode;
2✔
3307
        SeekScratch(from,&posfrom);
2✔
3308
        if ( from->handle < 0 ) {        /* input is in memory */
2✔
3309
                fullsize = (BASEPOSITION(posfrom))/sizeof(WORD);
2✔
3310
                if ( ( to->POstop - to->POfull ) >= fullsize ) {
2✔
3311
/*
3312
                        Fits inside the buffer of the output. This will be fast.
3313
*/
3314
                        t1 = from->PObuffer;
2✔
3315
                        t2 = to->POfull;
2✔
3316
                        NCOPY(t2,t1,fullsize)
30✔
3317
                        to->POfull = to->POfill = t2;
2✔
3318
                        goto WriteTrailer;
2✔
3319
                }
3320
                if ( to->handle < 0 ) {                /* First open the file */
×
3321
                        if ( ( RetCode = CreateFile(to->name) ) >= 0 ) {
×
3322
                                to->handle = (WORD)RetCode;
×
3323
                                PUTZERO(to->filesize);
×
3324
                                PUTZERO(to->POposition);
×
3325
                        }
3326
                        else {
3327
                                MLOCK(ErrorMessageLock);
×
3328
                                MesPrint("Cannot create scratch file %s",to->name);
×
3329
                                MUNLOCK(ErrorMessageLock);
×
3330
                                return(-1);
×
3331
                        }
3332
                }
3333
                t1 = from->PObuffer;
×
3334
                while ( fullsize > 0 ) {
×
3335
                        i = to->POstop - to->POfull;
×
3336
                        if ( i > fullsize ) i = fullsize;
×
3337
                        fullsize -= i;
×
3338
                        t2 = to->POfull;
×
3339
                        NCOPY(t2,t1,i)
×
3340
                        if ( fullsize > 0 ) {
×
3341
                                SeekFile(to->handle,&(to->POposition),SEEK_SET);
×
3342
                                if ( WriteFile(to->handle,((UBYTE *)(to->PObuffer)),to->POsize) != to->POsize ) {
×
3343
                                        MLOCK(ErrorMessageLock);
×
3344
                                        MesPrint("Error while writing to disk. Disk full?");
×
3345
                                        MUNLOCK(ErrorMessageLock);
×
3346
                                        return(-1);
×
3347
                                }
3348
                                ADDPOS(to->POposition,to->POsize);
×
3349
/*                                SeekFile(to->handle,&(to->POposition),SEEK_CUR); */
3350
                                to->filesize = to->POposition;
×
3351
                                to->POfill = to->POfull = to->PObuffer;
×
3352
                        }
3353
                        else {
3354
                                to->POfill = to->POfull = t2;
×
3355
                        }
3356
                }
3357
                goto WriteTrailer;
×
3358
        }
3359
/*
3360
        Now the input involves a file. This needs the use of the PObuffer of from.
3361
        First make sure the tail of the buffer has been written
3362
*/
3363
        if ( ((UBYTE *)(from->POfill)-(UBYTE *)(from->PObuffer)) > 0 ) {
×
3364
                if ( WriteFile(from->handle,((UBYTE *)(from->PObuffer)),((UBYTE *)(from->POfill)-(UBYTE *)(from->PObuffer)))
×
3365
                != ((UBYTE *)(from->POfill)-(UBYTE *)(from->PObuffer)) ) {
×
3366
                        MLOCK(ErrorMessageLock);
×
3367
                        MesPrint("Error while writing to disk. Disk full?");
×
3368
                        MUNLOCK(ErrorMessageLock);
×
3369
                        return(-1);
×
3370
                }
3371
                SeekFile(from->handle,&(from->POposition),SEEK_CUR);
×
3372
                posfrom = from->filesize = from->POposition;
×
3373
                from->POfill = from->POfull = from->PObuffer;
×
3374
        }
3375
/*
3376
        Now copy the complete contents
3377
*/
3378
        PUTZERO(poscopy);
×
3379
        SeekFile(from->handle,&poscopy,SEEK_SET);
×
3380
        while ( ISLESSPOS(poscopy,posfrom) ) {
×
3381
                fullsize = ReadFile(from->handle,((UBYTE *)(from->PObuffer)),from->POsize);
×
3382
                if ( fullsize < 0 || ( fullsize % sizeof(WORD) ) != 0 ) {
×
3383
                        MLOCK(ErrorMessageLock);
×
3384
                        MesPrint("Error while reading from disk while copying expression.");
×
3385
                        MUNLOCK(ErrorMessageLock);
×
3386
                        return(-1);
×
3387
                }
3388
                fullsize /= sizeof(WORD);
×
3389
                from->POfull = from->PObuffer + fullsize;
×
3390
                t1 = from->PObuffer;
×
3391

3392
                if ( ( to->POstop - to->POfull ) >= fullsize ) {
×
3393
/*
3394
                        Fits inside the buffer of the output. This will be fast.
3395
*/
3396
                        t2 = to->POfull;
3397
                        NCOPY(t2,t1,fullsize)
×
3398
                        to->POfill = to->POfull = t2;
×
3399
                }
3400
                else {
3401
                  if ( to->handle < 0 ) {                /* First open the file */
×
3402
                        if ( ( RetCode = CreateFile(to->name) ) >= 0 ) {
×
3403
                                to->handle = (WORD)RetCode;
×
3404
                                PUTZERO(to->POposition);
×
3405
                                PUTZERO(to->filesize);
×
3406
                        }
3407
                        else {
3408
                                MLOCK(ErrorMessageLock);
×
3409
                                MesPrint("Cannot create scratch file %s",to->name);
×
3410
                                MUNLOCK(ErrorMessageLock);
×
3411
                                return(-1);
×
3412
                        }
3413
                  }
3414
                  while ( fullsize > 0 ) {
×
3415
                        i = to->POstop - to->POfull;
×
3416
                        if ( i > fullsize ) i = fullsize;
×
3417
                        fullsize -= i;
×
3418
                        t2 = to->POfull;
×
3419
                        NCOPY(t2,t1,i)
×
3420
                        if ( fullsize > 0 ) {
×
3421
                                SeekFile(to->handle,&(to->POposition),SEEK_SET);
×
3422
                                if ( WriteFile(to->handle,((UBYTE *)(to->PObuffer)),to->POsize) != to->POsize ) {
×
3423
                                        MLOCK(ErrorMessageLock);
×
3424
                                        MesPrint("Error while writing to disk. Disk full?");
×
3425
                                        MUNLOCK(ErrorMessageLock);
×
3426
                                        return(-1);
×
3427
                                }
3428
                                ADDPOS(to->POposition,to->POsize);
×
3429
/*                                SeekFile(to->handle,&(to->POposition),SEEK_CUR); */
3430
                                to->filesize = to->POposition;
×
3431
                                to->POfill = to->POfull = to->PObuffer;
×
3432
                        }
3433
                        else {
3434
                                to->POfill = to->POfull = t2;
×
3435
                        }
3436
                  }
3437
                }
3438
                SeekFile(from->handle,&poscopy,SEEK_CUR);
×
3439
        }
3440
WriteTrailer:
×
3441
        if ( ( to->handle >= 0 ) && ( to->POfill > to->PObuffer ) ) {
2✔
3442
                fullsize = (UBYTE *)(to->POfill) - (UBYTE *)(to->PObuffer);
×
3443
/*
3444
                PUTZERO(to->POposition);
3445
                SeekFile(to->handle,&(to->POposition),SEEK_END);
3446
*/
3447
                SeekFile(to->handle,&(to->filesize),SEEK_SET);
×
3448
                if ( WriteFile(to->handle,((UBYTE *)(to->PObuffer)),fullsize) != fullsize ) {
×
3449
                        MLOCK(ErrorMessageLock);
×
3450
                        MesPrint("Error while writing to disk. Disk full?");
×
3451
                        MUNLOCK(ErrorMessageLock);
×
3452
                        return(-1);
×
3453
                }
3454
                ADDPOS(to->filesize,fullsize);
×
3455
                to->POposition = to->filesize;
×
3456
                to->POfill = to->POfull = to->PObuffer;
×
3457
        }
3458

3459
        return(0);
3460
}
3461

3462
/*
3463
                 #] CopyExpression : 
3464
                 #[ ExprStatus :
3465
*/
3466

3467
#ifdef HIDEDEBUG
3468

3469
static UBYTE *statusexpr[] = {
3470
         (UBYTE *)"LOCALEXPRESSION"
3471
        ,(UBYTE *)"SKIPLEXPRESSION"
3472
        ,(UBYTE *)"DROPLEXPRESSION"
3473
        ,(UBYTE *)"DROPPEDEXPRESSION"
3474
        ,(UBYTE *)"GLOBALEXPRESSION"
3475
        ,(UBYTE *)"SKIPGEXPRESSION"
3476
        ,(UBYTE *)"DROPGEXPRESSION"
3477
        ,(UBYTE *)"UNKNOWN"
3478
        ,(UBYTE *)"STOREDEXPRESSION"
3479
        ,(UBYTE *)"HIDDENLEXPRESSION"
3480
        ,(UBYTE *)"HIDELEXPRESSION"
3481
        ,(UBYTE *)"DROPHLEXPRESSION"
3482
        ,(UBYTE *)"UNHIDELEXPRESSION"
3483
        ,(UBYTE *)"HIDDENGEXPRESSION"
3484
        ,(UBYTE *)"HIDEGEXPRESSION"
3485
        ,(UBYTE *)"DROPHGEXPRESSION"
3486
        ,(UBYTE *)"UNHIDEGEXPRESSION"
3487
        ,(UBYTE *)"INTOHIDELEXPRESSION"
3488
        ,(UBYTE *)"INTOHIDEGEXPRESSION"
3489
};
3490

3491
void ExprStatus(EXPRESSIONS e)
3492
{
3493
        MesPrint("Expression %s(%d) has status %s(%d,%d). Buffer: %d, Position: %15p",
3494
                AC.exprnames->namebuffer+e->name,(WORD)(e-Expressions),
3495
                statusexpr[e->status],e->status,e->hidelevel,
3496
                e->whichbuffer,&(e->onfile));
3497
}
3498

3499
#endif
3500

3501
/*
3502
                 #] ExprStatus : 
3503
        #] StoreExpressions :
3504
        #[ System Independent Saved Expressions :
3505

3506
        All functions concerned with the system independent reading of save-files
3507
        are here. They are called by the functions CoLoad, PutInStore,
3508
        SetFileIndex, FindInIndex. In case no translation (endianness flip,
3509
        resizing of words, renumbering) has to be done, they just do simple file
3510
        reading. The function SaveFileHeader() for writing a header with
3511
        information about the system architecture, FORM version, etc. is also
3512
        located here.
3513

3514
                 #[ Flip :
3515
*/
3516

3517
#ifndef INT16
3518
#error "INT16 not defined!"
3519
#endif
3520
#ifndef INT32
3521
#error "INT32 not defined!"
3522
#endif
3523

3524
/**
3525
 *  Flips the endianness. This function will be called via function pointers.
3526
 *  See struct O_const and ReadSaveHeader().
3527
 *
3528
 *  It is a general version for arbitrary word sizes.
3529
 *  
3530
 *  @param  p       pointer to data
3531
 *  @param  length  length of data in bytes
3532
 */
3533
static void FlipN(UBYTE *p, int length)
×
3534
{
3535
        UBYTE *q, buf;
×
3536
        q = p + length;
×
3537
        do {
×
3538
                --q;
×
3539
                buf = *p; *p = *q; *q = buf;
×
3540
        } while ( ++p != q );
×
3541
}
×
3542

3543
/**
3544
 *  Flips the endianness. This function will be called via function pointers.
3545
 *  See struct O_const and ReadSaveHeader().
3546
 *
3547
 *  It is an optimized version for 16 bit (other versions for 32bit and 64bit
3548
 *  do exist).
3549
 *  
3550
 *  @param  p  pointer to data
3551
 */
3552
static void Flip16(UBYTE *p)
×
3553
{
3554
        INT16 in = *((INT16 *)p);
×
3555
        INT16 out = (INT16)( (((in) >> 8) & 0x00FF) | (((in) << 8) & 0xFF00) );
×
3556
        *((INT16 *)p) = out;
×
3557
}
×
3558

3559
/** @see Flip16() */
3560
static void Flip32(UBYTE *p)
×
3561
{
3562
        INT32 in = *((INT32 *)p);
×
3563
        INT32 out =
×
3564
                ( (((in) >> 24) & 0x000000FF) | (((in) >>  8) & 0x0000FF00) | \
×
3565
                  (((in) <<  8) & 0x00FF0000) | (((in) << 24) & 0xFF000000) );
×
3566
        *((INT32 *)p) = out;
×
3567
}
×
3568

3569
/** @see Flip16() */
3570
#ifdef INT64
3571
static void Flip64(UBYTE *p)
×
3572
{
3573
        INT64 in = *((INT64 *)p);
×
3574
        INT64 out =
×
3575
                ( (((in) >> 56) & (INT64)0x00000000000000FFLL) | (((in) >> 40) & (INT64)0x000000000000FF00LL) | \
×
3576
                  (((in) >> 24) & (INT64)0x0000000000FF0000LL) | (((in) >>  8) & (INT64)0x00000000FF000000LL) | \
×
3577
                  (((in) <<  8) & (INT64)0x000000FF00000000LL) | (((in) << 24) & (INT64)0x0000FF0000000000LL) | \
×
3578
                  (((in) << 40) & (INT64)0x00FF000000000000LL) | (((in) << 56) & (INT64)0xFF00000000000000LL) );
×
3579
        *((INT64 *)p) = out;
×
3580
}
×
3581
#else
3582
static void Flip64(UBYTE *p) { FlipN(p, 8); }
3583
#endif /* INT64 */
3584

3585
/** @see Flip16() */
3586
static void Flip128(UBYTE *p) { FlipN(p, 16); }
×
3587

3588
/*
3589
                 #] Flip : 
3590
                 #[ Resize :
3591
*/
3592

3593
/**
3594
 *  Resizes words. This function will be called via function pointers. See
3595
 *  struct O_const and ReadSaveHeader().
3596
 *
3597
 *  General version for arbitrary word sizes and big-endian machines.
3598
 *
3599
 *  @param  src  pointer to input data
3600
 *  @param  dst  pointer to output data
3601
 *  @param  slen number of bytes of input
3602
 *  @param  dlen number of bytes of output
3603
 */
3604
static void ResizeDataBE(UBYTE *src, int slen, UBYTE *dst, int dlen)
×
3605
{
3606
        if ( slen > dlen ) {
×
3607
                src += slen - dlen;
×
3608
                while ( dlen-- ) { *dst++ = *src++; }
×
3609
        }
3610
        else {
3611
                int i = dlen - slen;
×
3612
                while ( i-- ) { *dst++ = 0; }
×
3613
                while ( slen-- ) { *dst++ = *src++; }
×
3614
        }
3615
}
×
3616

3617
/**
3618
 *  The same as ResizeDataBE() but for little-endian machines.
3619
 */
3620
static void ResizeDataLE(UBYTE *src, int slen, UBYTE *dst, int dlen)
×
3621
{
3622
        if ( slen > dlen ) {
×
3623
                while ( dlen-- ) { *dst++ = *src++; }
×
3624
        }
3625
        else {
3626
                int i = dlen - slen;
×
3627
                while ( slen-- ) { *dst++ = *src++; }
×
3628
                while ( i-- ) { *dst++ = 0; }
×
3629
        }
3630
}
×
3631

3632
/**
3633
 *  Resizes words. This function will be called via function pointers. See
3634
 *  struct O_const and ReadSaveHeader().
3635
 *
3636
 *  Specialized version for the specific combination of reading 16bit and
3637
 *  writing 16bit (more versions for other bit-combinations do exist).
3638
 *  
3639
 *  No checking for too big numbers is done.
3640
 *
3641
 *  @param  src  pointer to input data
3642
 *  @param  dst  pointer to output data
3643
 */
3644
static void Resize16t16(UBYTE *src, UBYTE *dst)
×
3645
{
3646
        *((INT16 *)dst) = *((INT16 *)src);
×
3647
}
×
3648

3649
/** @see Resize16t16() */
3650
static void Resize16t32(UBYTE *src, UBYTE *dst)
×
3651
{
3652
        INT16 in = *((INT16 *)src);
×
3653
        INT32 out = (INT32)in;
×
3654
        *((INT32 *)dst) = out;
×
3655
}
×
3656

3657
/** @see Resize16t16() */
3658
#ifdef INT64
3659
static void Resize16t64(UBYTE *src, UBYTE *dst)
×
3660
{
3661
        INT16 in = *((INT16 *)src);
×
3662
        INT64 out = (INT64)in;
×
3663
        *((INT64 *)dst) = out;
×
3664
}
×
3665
#else
3666
static void Resize16t64(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 2, dst, 8); }
3667
#endif /* INT64 */
3668

3669
/** @see Resize16t16() */
3670
static void Resize16t128(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 2, dst, 16); }
×
3671

3672
/** @see Resize16t16() */
3673
static void Resize32t32(UBYTE *src, UBYTE *dst)
×
3674
{
3675
        *((INT32 *)dst) = *((INT32 *)src);
×
3676
}
×
3677

3678
/** @see Resize16t16() */
3679
#ifdef INT64
3680
static void Resize32t64(UBYTE *src, UBYTE *dst)
×
3681
{
3682
        INT32 in = *((INT32 *)src);
×
3683
        INT64 out = (INT64)in;
×
3684
        *((INT64 *)dst) = out;
×
3685
}
×
3686
#else
3687
static void Resize32t64(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 4, dst, 8); }
3688
#endif /* INT64 */
3689

3690
/** @see Resize16t16() */
3691
static void Resize32t128(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 4, dst, 16); }
×
3692

3693
/** @see Resize16t16() */
3694
#ifdef INT64
3695
static void Resize64t64(UBYTE *src, UBYTE *dst)
×
3696
{
3697
        *((INT64 *)dst) = *((INT64 *)src);
×
3698
}
×
3699
#else
3700
static void Resize64t64(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 8, dst, 8); }
3701
#endif /* INT64 */
3702

3703
/** @see Resize16t16() */
3704
static void Resize64t128(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 8, dst, 16); }
×
3705

3706
/** @see Resize16t16() */
3707
static void Resize128t128(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 16); }
×
3708

3709
/** @see Resize16t16() */
3710
static void Resize32t16(UBYTE *src, UBYTE *dst)
×
3711
{
3712
        INT32 in = *((INT32 *)src);
×
3713
        INT16 out = (INT16)in;
×
3714
        if ( in > (1<<15)-1 || in < -(1<<15)+1 ) AO.resizeFlag |= 1;
×
3715
        *((INT16 *)dst) = out;
×
3716
}
×
3717

3718
/**
3719
 *  The same as Resize32t16() but with checking for too big numbers.
3720
 *
3721
 *  The resizeFlag in struct O_const will be used to signal the result of the
3722
 *  checking. This flag is used by CoLoad().
3723
 */
3724
static void Resize32t16NC(UBYTE *src, UBYTE *dst)
×
3725
{
3726
        INT32 in = *((INT32 *)src);
×
3727
        INT16 out = (INT16)in;
×
3728
        *((INT16 *)dst) = out;
×
3729
}
×
3730

3731
#ifdef INT64
3732
/** @see Resize16t16() */
3733
static void Resize64t16(UBYTE *src, UBYTE *dst)
×
3734
{
3735
        INT64 in = *((INT64 *)src);
×
3736
        INT16 out = (INT16)in;
×
3737
        if ( in > (1<<15)-1 || in < -(1<<15)+1 ) AO.resizeFlag |= 1;
×
3738
        *((INT16 *)dst) = out;
×
3739
}
×
3740
/** @see Resize32t16NC() */
3741
static void Resize64t16NC(UBYTE *src, UBYTE *dst)
×
3742
{
3743
        INT64 in = *((INT64 *)src);
×
3744
        INT16 out = (INT16)in;
×
3745
        *((INT16 *)dst) = out;
×
3746
}
×
3747
#else
3748
/** @see Resize16t16() */
3749
static void Resize64t16(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 8, dst, 2); }
3750
/** @see Resize32t16NC() */
3751
static void Resize64t16NC(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 8, dst, 2); }
3752
#endif /* INT64 */
3753

3754
#ifdef INT64
3755
/** @see Resize16t16() */
3756
static void Resize64t32(UBYTE *src, UBYTE *dst)
×
3757
{
3758
        INT64 in = *((INT64 *)src);
×
3759
        INT32 out = (INT32)in;
×
3760
        if ( in > ((INT64)1<<31)-1 || in < -((INT64)1<<31)+1 ) AO.resizeFlag |= 1;
×
3761
        *((INT32 *)dst) = out;
×
3762
}
×
3763
/** @see Resize32t16NC() */
3764
static void Resize64t32NC(UBYTE *src, UBYTE *dst)
×
3765
{
3766
        INT64 in = *((INT64 *)src);
×
3767
        INT32 out = (INT32)in;
×
3768
        *((INT32 *)dst) = out;
×
3769
}
×
3770
#else
3771
/** @see Resize16t16() */
3772
static void Resize64t32(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 8, dst, 4); }
3773
/** @see Resize32t16NC() */
3774
static void Resize64t32NC(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 8, dst, 4); }
3775
#endif /* INT64 */
3776

3777
/** @see Resize16t16() */
3778
static void Resize128t16(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 2); }
×
3779

3780
/** @see Resize32t16NC() */
3781
static void Resize128t16NC(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 2); }
×
3782

3783
/** @see Resize16t16() */
3784
static void Resize128t32(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 4); }
×
3785

3786
/** @see Resize32t16NC() */
3787
static void Resize128t32NC(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 4); }
×
3788

3789
/** @see Resize16t16() */
3790
static void Resize128t64(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 8); }
×
3791

3792
/** @see Resize32t16NC() */
3793
static void Resize128t64NC(UBYTE *src, UBYTE *dst) { AO.ResizeData(src, 16, dst, 8); }
×
3794

3795
/*
3796
                 #] Resize : 
3797
                 #[ CheckPower and RenumberVec :
3798
*/
3799

3800
/**
3801
 *  Checks the size of exponents. If a checking fails, the powerFlag in struct
3802
 *  O_const will be set. This flag is used by CoLoad().
3803
 *
3804
 *  @param  p  pointer to WORD containing exponent
3805
 */
3806
static void CheckPower32(UBYTE *p)
×
3807
{
3808
        if ( *((INT32 *)p) < -MAXPOWER ) {
×
3809
                AO.powerFlag |= 0x01;
×
3810
                *((INT32 *)p) = -MAXPOWER;
×
3811
        }
3812
        p += sizeof(INT32);
×
3813
        if ( *((INT32 *)p) > MAXPOWER ) {
×
3814
                AO.powerFlag |= 0x02;
×
3815
                *((INT32 *)p) = MAXPOWER;
×
3816
        }
3817
}
×
3818

3819
/**
3820
 *  Renumbers vectors by compensating for the different WILDOFFSET on the
3821
 *  involved machines and FORM versions. The WILDOFFSET from the writing
3822
 *  machine is coded in the header of the save-file.
3823
 *
3824
 *  @param  p  pointer to WORD containing vector code
3825
 */
3826
static void RenumberVec32(UBYTE *p)
×
3827
{
3828
/*        INT32 wildoffset = *((INT32 *)AO.SaveHeader.wildoffset); */
3829
        void *dummy = (void *)AO.SaveHeader.wildoffset;  /* to remove a warning about strict-aliasing rules in gcc */
×
3830
        INT32 wildoffset = *(INT32 *)dummy;
×
3831
        INT32 in = *((INT32 *)p);
×
3832
        in = in + 2*wildoffset;
×
3833
        in = in - 2*WILDOFFSET;
×
3834
        *((INT32 *)p) = in;
×
3835
}
×
3836

3837
/*
3838
                 #] CheckPower and RenumberVec : 
3839
                 #[ ResizeCoeff :
3840
*/
3841

3842
/**
3843
 *  Resizes the coefficients of expressions and terms. The function only
3844
 *  work on uniform data with a word size of 32bit (ReadSaveExpression()
3845
 *  provides for that). The resizing then actually means whether zeros can be
3846
 *  removed when going from 64bit to 32bit, or whether the coefficient size has
3847
 *  to be doubled effectively when going from 32bit to 64bit. Both cases
3848
 *  involve copying of words and a shrinking or growing of the memory used in
3849
 *  @e *bout.
3850
 *
3851
 *  @param  bout  input and output buffer for coefficient
3852
 *  @param  bend  end of input
3853
 *  @param  top   end of buffer
3854
 */
3855
static void ResizeCoeff32(UBYTE **bout, UBYTE *bend, UBYTE *top)
×
3856
{
3857
        int i;
×
3858
        INT32 sign;
×
3859
        INT32 *in, *p;
×
3860
        INT32 *out = (INT32 *)*bout;
×
3861
        INT32 *end = (INT32 *)bend;
×
3862

3863
        if ( sizeof(WORD) == 2 ) {
×
3864
                /* 4 -> 2 */
3865
                INT32 len = (end - 1 - out) / 2;
3866
                int zeros = 2;
3867
                p = out + len - 1;
3868

3869
                if ( *p & 0xFFFF0000 ) --zeros;
3870
                p += len;
3871
                if ( *p & 0xFFFF0000 ) --zeros;
3872

3873
                in = end - 1;
3874
                sign = ( *in-- > 0 ) ? 1 : -1;
3875
                p = out + 4*len;
3876
                if ( zeros == 2 ) p -= 2;
3877
                out = p--;
3878

3879
                if ( zeros < 2 ) *p-- = *in >> 16;
3880
                *p-- = *in-- & 0x0000FFFF;
3881
                for ( i = 1; i < len; ++i ) {
3882
                        *p-- = *in >> 16;
3883
                        *p-- = *in-- & 0x0000FFFF;
3884
                }
3885
                if ( zeros < 2 ) *p-- = *in >> 16;
3886
                *p-- = *in-- & 0x0000FFFF;
3887
                for ( i = 1; i < len; ++i ) {
3888
                        *p-- = *in >> 16;
3889
                        *p-- = *in-- & 0x0000FFFF;
3890
                }
3891

3892
                *out = (out - p) * sign;
3893
                *bout = (UBYTE *)(out+1);
3894

3895
        }
3896
        else {
3897
                /* 2 -> 4 */
3898
                INT32 len = (end - 1 - out) / 2;
×
3899
                if ( len == 1 ) {
×
3900
                        *out = *(unsigned INT16 *)out;
×
3901
                        ++out;
×
3902
                        *out = *(unsigned INT16 *)out;
×
3903
                        ++out;
×
3904
                        ++out;
×
3905
                }
3906
                else {
3907
                        p = out;
×
3908
                        *out = *(unsigned INT16 *)out;
×
3909
                        in = out + 1;
×
3910
                        for ( i = 1; i < len; ++i ) {
×
3911
                                /* shift */
3912
                                *out = (unsigned INT32)(*(unsigned INT16 *)out)
×
3913
                                        + ((unsigned INT32)(*(unsigned INT16 *)in) << 16);
×
3914
                                ++in;
×
3915
                                if ( ++i == len ) break;
×
3916
                                /* copy */
3917
                                ++out;
×
3918
                                *out = *(unsigned INT16 *)in;
×
3919
                                ++in;
×
3920
                        }
3921
                        ++out;
×
3922
                        *out = *(unsigned INT16 *)in;
×
3923
                        ++in;
×
3924
                        for ( i = 1; i < len; ++i ) {
×
3925
                                /* shift */
3926
                                *out = (unsigned INT32)(*(unsigned INT16 *)out)
×
3927
                                        + ((unsigned INT32)(*(unsigned INT16 *)in) << 16);
×
3928
                                ++in;
×
3929
                                if ( ++i == len ) break;
×
3930
                                /* copy */
3931
                                ++out;
×
3932
                                *out = *(unsigned INT16 *)in;
×
3933
                                ++in;
×
3934
                        }
3935
                        ++out;
×
3936
                        if ( *in < 0 ) *out = -(out - p + 1);
×
3937
                        else *out = out - p + 1;
×
3938
                        ++out;
×
3939
                }
3940

3941
                if ( out > (INT32 *)top ) {
×
3942
                        MesPrint("Error in resizing coefficient!");
×
3943
                }
3944

3945
                *bout = (UBYTE *)out;
×
3946
        }
3947
}
×
3948

3949
/*
3950
                 #] ResizeCoeff : 
3951
                 #[ WriteStoreHeader :
3952
*/
3953

3954
#define SAVEREVISION 0x02
3955

3956
/**
3957
 *  Writes header with information about system architecture and FORM revision
3958
 *  to an open store file.
3959
 *
3960
 *  Called by SetFileIndex().
3961
 *
3962
 *  @param  handle  specifies open file to which header will be written
3963
 *  @return         = 0 everything okay, != 0 an error occurred
3964
 */
3965
WORD WriteStoreHeader(WORD handle)
36✔
3966
{
3967
        /* template of the STOREHEADER */
3968
        static STOREHEADER sh = {
36✔
3969
                { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },        /* store header mark */
3970
                0, 0, 0, 0,                                                                                        /* sizeof of WORD,LONG,POSITION,void* */
3971
                { 0 },                                                                                                /* endianness check number */
3972
                0, 0, 0, 0,                                                                                        /* sizeof variable structs */
3973
                { 0 },                                                                                                /* maxpower */
3974
                { 0 },                                                                                                /* wildoffset */
3975
                SAVEREVISION,                                                                                /* revision */
3976
                { 0 } };                                                                                        /* reserved */
3977
        int endian, i;
36✔
3978

3979
        /* if called for the first time ... */
3980
        if ( sh.lenWORD == 0 ) {
36✔
3981
                sh.lenWORD = sizeof(WORD);
28✔
3982
                sh.lenLONG = sizeof(LONG);
28✔
3983
                sh.lenPOS = sizeof(POSITION);
28✔
3984
                sh.lenPOINTER = sizeof(void *);
28✔
3985

3986
                endian = 1;
28✔
3987
                for ( i = 1; i < (int)sizeof(int); ++i ) {
112✔
3988
                        endian <<= 8;
84✔
3989
                        endian += i+1;
84✔
3990
                }
3991
                for ( i = 0; i < (int)sizeof(int); ++i ) sh.endianness[i] = ((char *)&endian)[i];
140✔
3992

3993
                sh.sSym = sizeof(struct SyMbOl);
28✔
3994
                sh.sInd = sizeof(struct InDeX);
28✔
3995
                sh.sVec = sizeof(struct VeCtOr);
28✔
3996
                sh.sFun = sizeof(struct FuNcTiOn);
28✔
3997

3998
/*                *((WORD *)sh.maxpower) = MAXPOWER;
3999
                *((WORD *)sh.wildoffset) = WILDOFFSET; */
4000
        {
4001
            WORD dumw[8];
28✔
4002
            UBYTE *dummy;
28✔
4003
            for ( i = 0; i < 8; i++ ) dumw[i] = 0;
252✔
4004
            dummy = (UBYTE *)dumw;
28✔
4005
            dumw[0] = (WORD)MAXPOWER;
28✔
4006
            for ( i = 0; i < 16; i++ ) sh.maxpower[i] = dummy[i];
476✔
4007
            dumw[0] = (WORD)WILDOFFSET;
28✔
4008
            for ( i = 0; i < 16; i++ ) sh.wildoffset[i] = dummy[i];
476✔
4009
        }
4010
        }
4011

4012
        return ( WriteFile(handle,(UBYTE *)(&sh),(LONG)(sizeof(STOREHEADER)))
36✔
4013
                 != (LONG)(sizeof(STOREHEADER)) );
36✔
4014
}
4015

4016
/*
4017
                 #] WriteStoreHeader : 
4018
                 #[ CompactifySizeof :
4019
*/
4020

4021
/**
4022
 *  Utility function used by ReadSaveHeader() to convert a sizeof into a
4023
 *  convenient array index.
4024
 *
4025
 *  @param  size  size in bytes
4026
 *  @return       log_2(size) - 1
4027
 */
4028
static unsigned int CompactifySizeof(unsigned int size)
×
4029
{
4030
        switch ( size ) {
×
4031
                case  2: return 0;
4032
                case  4: return 1;
×
4033
                case  8: return 2;
×
4034
                case 16: return 3;
×
4035
                default: MesPrint("Error compactifying size.");
×
4036
                         return 3;
×
4037
        }
4038
}
4039

4040
/*
4041
                 #] CompactifySizeof : 
4042
                 #[ ReadSaveHeader :
4043
*/
4044

4045
/**
4046
 *  Reads the header in the save file and sets function pointers and flags
4047
 *  according to the information found there. Must be called before any other
4048
 *  ReadSave... function.
4049
 *
4050
 *  Currently works only for the exchange between 32bit and 64bit machines
4051
 *  (WORD size must be 2 or 4 bytes)!
4052
 *
4053
 *  It is called by CoLoad().
4054
 *
4055
 *  @return   = 0 everything okay, != 0 an error occurred
4056
 */
4057

4058
WORD ReadSaveHeader(VOID)
×
4059
{
4060
        /* Read-only tables of function pointers for conversions. */
4061
        static VOID (*flipJumpTable[4])(UBYTE *) =
×
4062
                { Flip16, Flip32, Flip64, Flip128 };
4063
        static VOID (*resizeJumpTable[4][4])(UBYTE *, UBYTE *) = /* "own x saved"-sizes  */
×
4064
                { { Resize16t16,  Resize32t16,  Resize64t16,  Resize128t16  },
4065
                  { Resize16t32,  Resize32t32,  Resize64t32,  Resize128t32  },
4066
                  { Resize16t64,  Resize32t64,  Resize64t64,  Resize128t64  },
4067
                  { Resize16t128, Resize32t128, Resize64t128, Resize128t128 } };
4068
        static VOID (*resizeNCJumpTable[4][4])(UBYTE *, UBYTE *) = /* "own x saved"-sizes  */
×
4069
                { { Resize16t16,  Resize32t16NC,  Resize64t16NC,  Resize128t16NC  },
4070
                  { Resize16t32,  Resize32t32,  Resize64t32NC,  Resize128t32NC  },
4071
                  { Resize16t64,  Resize32t64,  Resize64t64,  Resize128t64NC  },
4072
                  { Resize16t128, Resize32t128, Resize64t128, Resize128t128 } };
4073

4074
        int endian, i;
×
4075
        WORD idxW = CompactifySizeof(sizeof(WORD));
×
4076
        WORD idxL = CompactifySizeof(sizeof(LONG));
×
4077
        WORD idxP = CompactifySizeof(sizeof(POSITION));
×
4078
        WORD idxVP = CompactifySizeof(sizeof(void *));
×
4079

4080
        AO.transFlag = 0;
×
4081
        AO.powerFlag = 0;
×
4082
        AO.resizeFlag = 0;
×
4083
        AO.bufferedInd = 0;
×
4084

4085
        if ( ReadFile(AO.SaveData.Handle,(UBYTE *)(&AO.SaveHeader),
×
4086
                (LONG)sizeof(STOREHEADER)) != (LONG)sizeof(STOREHEADER) )
4087
                return(MesPrint("Error reading save file header"));
×
4088

4089
        /* check whether save-file has no header. if yes then it is an old version
4090
           of FORM -> go back to position 0 in file which then contains the first
4091
           index and skip the rest. */
4092
        for ( i = 0; i < 8; ++i ) {
×
4093
                if ( AO.SaveHeader.headermark[i] != 0xFF ) {
×
4094
                        POSITION p;
×
4095
                        PUTZERO(p);
×
4096
                        SeekFile(AO.SaveData.Handle, &p, SEEK_SET);
×
4097
                        return ( 0 );
×
4098
                }
4099
        }
4100

4101
        if ( AO.SaveHeader.revision != SAVEREVISION ) {
×
4102
                return(MesPrint("Save file header from an old version. Cannot read this file."));
×
4103
        }
4104

4105
        endian = 1;
4106
        for ( i = 1; i < (int)sizeof(int); ++i ) {
×
4107
                endian <<= 8;
×
4108
                endian += i+1;
×
4109
        }
4110
        if ( ((char *)&endian)[0] < ((char *)&endian)[1] ) {
×
4111
                /* this machine is big-endian */
4112
                AO.ResizeData = ResizeDataBE;
×
4113
        }
4114
        else {
4115
                /* this machine is little-endian */
4116
                AO.ResizeData = ResizeDataLE;
×
4117
        }
4118

4119
        /* set AO.transFlag if ANY conversion has to be done later */
4120
        if ( AO.SaveHeader.endianness[0] > AO.SaveHeader.endianness[1] ) {
×
4121
                AO.transFlag = ( ((char *)&endian)[0] < ((char *)&endian)[1] );
×
4122
        }
4123
        else {
4124
                AO.transFlag = ( ((char *)&endian)[0] > ((char *)&endian)[1] );
×
4125
        }
4126
        if ( (WORD)AO.SaveHeader.lenWORD != sizeof(WORD) ) AO.transFlag |= 0x02;
×
4127
        if ( (WORD)AO.SaveHeader.lenLONG != sizeof(LONG) ) AO.transFlag |= 0x04;
×
4128
        if ( (WORD)AO.SaveHeader.lenPOS != sizeof(POSITION) ) AO.transFlag |= 0x08;
×
4129
        if ( (WORD)AO.SaveHeader.lenPOINTER != sizeof(void *) ) AO.transFlag |= 0x10;
×
4130

4131
        AO.FlipWORD = flipJumpTable[idxW];
×
4132
        AO.FlipLONG = flipJumpTable[idxL];
×
4133
        AO.FlipPOS = flipJumpTable[idxP];
×
4134
        AO.FlipPOINTER = flipJumpTable[idxVP];
×
4135

4136
        /* Works only for machines where WORD is not greater than 32bit ! */
4137
        AO.CheckPower = CheckPower32;
×
4138
        AO.RenumberVec = RenumberVec32;
×
4139

4140
        AO.ResizeWORD = resizeJumpTable[idxW][CompactifySizeof(AO.SaveHeader.lenWORD)];
×
4141
        AO.ResizeNCWORD = resizeNCJumpTable[idxW][CompactifySizeof(AO.SaveHeader.lenWORD)];
×
4142
        AO.ResizeLONG = resizeJumpTable[idxL][CompactifySizeof(AO.SaveHeader.lenLONG)];
×
4143
        AO.ResizePOS = resizeJumpTable[idxP][CompactifySizeof(AO.SaveHeader.lenPOS)];
×
4144
        AO.ResizePOINTER = resizeJumpTable[idxVP][CompactifySizeof(AO.SaveHeader.lenPOINTER)];
×
4145

4146
        {
4147
                WORD dumw[8];
×
4148
                UBYTE *dummy;
×
4149
                for ( i = 0; i < 8; i++ ) dumw[i] = 0;
×
4150
                dummy = (UBYTE *)dumw;
×
4151
                for ( i = 0; i < 16; i++ ) dummy[i] = AO.SaveHeader.maxpower[i];
×
4152
                AO.mpower = dumw[0];
×
4153
    }
4154

4155
        return ( 0 );
×
4156
}
4157

4158
/*
4159
                 #] ReadSaveHeader : 
4160
                 #[ ReadSaveIndex :
4161
*/
4162

4163
/**
4164
 *  Reads a FILEINDEX from the open save file specified by AO.SaveData.Handle.
4165
 *  Translations for adjusting endianness and data sizes are done if necessary.
4166
 *
4167
 *  Depends on the assumption that sizeof(FILEINDEX) is the same everywhere.
4168
 *  If FILEINDEX or INDEXENTRY change, then this functions has to be adjusted.
4169
 *
4170
 *  Called by CoLoad() and FindInIndex().
4171
 *
4172
 *  @param  fileind  contains the read FILEINDEX after successful return. must
4173
 *                   point to allocated, big enough memory.
4174
 *  @return          = 0 everything okay, != 0 an error occurred
4175
 */
4176
WORD ReadSaveIndex(FILEINDEX *fileind)
×
4177
{
4178
        /* do we need some translation for the FILEINDEX? */
4179
        if ( AO.transFlag ) {
×
4180
                /* if a translated FILEINDEX can hold less entries than the original
4181
                   FILEINDEX, then we need to buffer the extra entries in this static
4182
                   variable (can happen going from 32bit to 64bit */
4183
                static FILEINDEX sbuffer;
×
4184

4185
                FILEINDEX buffer;
×
4186
                UBYTE *p, *q;
×
4187
                int i;
×
4188

4189
                /* shortcuts */
4190
                int lenW = AO.SaveHeader.lenWORD;
×
4191
                int lenL = AO.SaveHeader.lenLONG;
×
4192
                int lenP = AO.SaveHeader.lenPOS;
×
4193

4194
                /* if we have a buffered FILEINDEX then just return it */
4195
                if ( AO.bufferedInd ) {
×
4196
                        *fileind = sbuffer;
×
4197
                        AO.bufferedInd = 0;
×
4198
                        return ( 0 );
×
4199
                }
4200

4201
                if ( ReadFile(AO.SaveData.Handle, (UBYTE *)fileind, sizeof(FILEINDEX))
×
4202
                                != sizeof(FILEINDEX) ) {
4203
                        return ( MesPrint("Error(1) reading stored expression.") );
×
4204
                }
4205

4206
                /* do we need to flip the endianness? */
4207
                if ( AO.transFlag & 1 ) {
×
4208
                        LONG number;
×
4209
                        /* padding bytes */
4210
                        int padp = lenL - ((lenW*5+(MAXENAME + 1)) & (lenL-1));
×
4211
                        p = (UBYTE *)fileind;
×
4212
                        AO.FlipPOS(p); p += lenP;                        /* next */
×
4213
                        AO.FlipPOS(p);                                                /* number */
×
4214
                        AO.ResizePOS(p, (UBYTE *)&number);
×
4215
                        p += lenP;
×
4216
                        for ( i = 0; i < number; ++i ) {
×
4217
                                AO.FlipPOS(p); p += lenP;                /* position */
×
4218
                                AO.FlipPOS(p); p += lenP;                /* length */
×
4219
                                AO.FlipPOS(p); p += lenP;                /* variables */
×
4220
                                AO.FlipLONG(p); p += lenL;                /* CompressSize */
×
4221
                                AO.FlipWORD(p); p += lenW;                /* nsymbols */
×
4222
                                AO.FlipWORD(p); p += lenW;                /* nindices */
×
4223
                                AO.FlipWORD(p); p += lenW;                /* nvectors */
×
4224
                                AO.FlipWORD(p); p += lenW;                /* nfunctions */
×
4225
                                AO.FlipWORD(p); p += lenW;                /* size */
×
4226
                                p += padp;
×
4227
                        }
4228
                }
4229

4230
                /* do we need to resize data? */
4231
                if ( AO.transFlag > 1 ) {
×
4232
                        LONG number, maxnumber;
×
4233
                        int n;
×
4234
                        /* padding bytes */
4235
                        int padp = lenL - ((lenW*5+(MAXENAME + 1)) & (lenL-1));
×
4236
                        int padq = sizeof(LONG) - ((sizeof(WORD)*5+(MAXENAME + 1)) & (sizeof(LONG)-1));
×
4237

4238
                        p = (UBYTE *)fileind; q = (UBYTE *)&buffer;
×
4239
                        AO.ResizePOS(p, q);                                                /* next */
×
4240
                        p += lenP; q += sizeof(POSITION);
×
4241
                        AO.ResizePOS(p, q);                                        /* number */
×
4242
                        p += lenP;
×
4243
                        number = BASEPOSITION(*((POSITION *)q));
×
4244
                        /* if FILEINDEX in file contains more entries than the FILEINDEX in
4245
                           memory can contain, then adjust the numbers and prepare for
4246
                           buffering */
4247
                        if ( number > (LONG)INFILEINDEX ) {
×
4248
                                AO.bufferedInd = number-INFILEINDEX;
×
4249
                                if ( AO.bufferedInd > (WORD)INFILEINDEX ) {
×
4250
                                        /* can happen when reading 32bit and writing >=128bit.
4251
                                           Fix: more than one static buffer for FILEINDEX */
4252
                                        return ( MesPrint("Too many index entries.") );
×
4253
                                }
4254
                                maxnumber = INFILEINDEX;
×
4255
                                SETBASEPOSITION(*((POSITION *)q),INFILEINDEX);
×
4256
                        }
4257
                        else {
4258
                                maxnumber = number;
4259
                        }
4260
                        q += sizeof(POSITION);
×
4261
                        /* read all INDEXENTRY that fit into the output buffer */
4262
                        for ( i = 0; i < maxnumber; ++i ) {
×
4263
                                AO.ResizePOS(p, q);                                        /* position */
×
4264
                                p += lenP; q += sizeof(POSITION);
×
4265
                                AO.ResizePOS(p, q);                                        /* length */
×
4266
                                p += lenP; q += sizeof(POSITION);
×
4267
                                AO.ResizePOS(p, q);                                        /* variables */
×
4268
                                p += lenP; q += sizeof(POSITION);
×
4269
                                AO.ResizeLONG(p, q);                                /* CompressSize */
×
4270
                                p += lenL; q += sizeof(LONG);
×
4271
                                AO.ResizeWORD(p, q);                                /* nsymbols */
×
4272
                                p += lenW; q += sizeof(WORD);
×
4273
                                AO.ResizeWORD(p, q);                                /* nindices */
×
4274
                                p += lenW; q += sizeof(WORD);
×
4275
                                AO.ResizeWORD(p, q);                                /* nvectors */
×
4276
                                p += lenW; q += sizeof(WORD);
×
4277
                                AO.ResizeWORD(p, q);                                /* nfunctions */
×
4278
                                p += lenW; q += sizeof(WORD);
×
4279
                                AO.ResizeWORD(p, q);                                /* size (unchanged!) */
×
4280
                                p += lenW; q += sizeof(WORD);
×
4281
                                n = MAXENAME + 1;
×
4282
                                NCOPYB(q, p, n)
×
4283
                                p += padp;
×
4284
                                q += padq;
×
4285
                        }
4286
                        /* read all the remaining INDEXENTRY and put them into the static buffer */
4287
                        if ( AO.bufferedInd ) {
×
4288
                                sbuffer.next = buffer.next;
×
4289
                                SETBASEPOSITION(sbuffer.number,AO.bufferedInd);
×
4290
                                q = (UBYTE *)&sbuffer + sizeof(POSITION) + sizeof(LONG);
×
4291
                                for ( i = maxnumber; i < number; ++i ) {
×
4292
                                        AO.ResizePOS(p, q);                                /* position */
×
4293
                                        p += lenP; q += sizeof(POSITION);
×
4294
                                        AO.ResizePOS(p, q);                                /* length */
×
4295
                                        p += lenP; q += sizeof(POSITION);
×
4296
                                        AO.ResizePOS(p, q);                                /* variables */
×
4297
                                        p += lenP; q += sizeof(POSITION);
×
4298
                                        AO.ResizeLONG(p, q);                        /* CompressSize */
×
4299
                                        p += lenL; q += sizeof(LONG);
×
4300
                                        AO.ResizeWORD(p, q);                        /* nsymbols */
×
4301
                                        p += lenW; q += sizeof(WORD);
×
4302
                                        AO.ResizeWORD(p, q);                        /* nindices */
×
4303
                                        p += lenW; q += sizeof(WORD);
×
4304
                                        AO.ResizeWORD(p, q);                        /* nvectors */
×
4305
                                        p += lenW; q += sizeof(WORD);
×
4306
                                        AO.ResizeWORD(p, q);                        /* nfunctions */
×
4307
                                        p += lenW; q += sizeof(WORD);
×
4308
                                        AO.ResizeWORD(p, q);                        /* size (unchanged!) */
×
4309
                                        p += lenW; q += sizeof(WORD);
×
4310
                                        n = MAXENAME + 1;
×
4311
                                        NCOPYB(q, p, n)
×
4312
                                        p += padp;
×
4313
                                        q += padq;
×
4314
                                }
4315
                        }
4316
                        /* copy to output */
4317
                        p = (UBYTE *)fileind; q = (UBYTE *)&buffer; n = sizeof(FILEINDEX);
4318
                        NCOPYB(p, q, n)
×
4319
                }
4320
                return ( 0 );
×
4321
        } else {
4322
                return ( ReadFile(AO.SaveData.Handle, (UBYTE *)fileind, sizeof(FILEINDEX))
×
4323
                         != sizeof(FILEINDEX) );
×
4324
        }
4325
}
4326

4327
/*
4328
                 #] ReadSaveIndex : 
4329
                 #[ ReadSaveVariables :
4330
*/
4331

4332
/**
4333
 *  Reads the variables from the open file specified by AO.SaveData.Handle. It
4334
 *  reads the *size bytes and writes them to the *buffer. It is called by
4335
 *  PutInStore().
4336
 *
4337
 *  If translation is necessary, the data might shrink or grow in size, then
4338
 *  @e *size is adjusted so that the reading and writing fits into the memory
4339
 *  from the buffer to the top. The actual number of read bytes is returned in
4340
 *  @e *size, the number of written bytes is returned in @e *outsize.
4341
 *
4342
 *  If the *size is smaller than the actual size of the variables, this function
4343
 *  will be called several times and needs to remember the current position in
4344
 *  the variable structure. The parameter @e stage does this job. When
4345
 *  ReadSaveVariables() is called for the first time, this parameter should
4346
 *  have the value -1.
4347
 *
4348
 *  The parameter @e ind is used to get the number of variables.
4349
 *
4350
 *  @param  buffer   read variables are written into this allocated memory
4351
 *  @param  top      upper end of allocated memory
4352
 *  @param  size     number of bytes to read. might return a smaller number
4353
 *                   of read bytes if translation was necessary
4354
 *  @param  outsize  if translation has be done, outsize contains the number
4355
 *                   of written bytes
4356
 *  @param  ind      pointer of INDEXENTRY for the current expression. read-only
4357
 *  @param  stage    should be -1 for the first call, will be increased by
4358
 *                   ReadSaveVariables to memorize the position in the
4359
 *                   variable structure
4360
 *  @return          = 0 everything okay, != 0 an error occurred
4361
 */
4362
WORD ReadSaveVariables(UBYTE *buffer, UBYTE *top, LONG *size, LONG *outsize,\
×
4363
                       INDEXENTRY *ind, LONG *stage)
4364
{
4365
        /* do we need some translation for the variables? */
4366
        if ( AO.transFlag ) {
×
4367
                /* counters for the number of already read symbols, indices, ... that
4368
                   need to remain valid between different calls to ReadSaveVariables().
4369
                   are initialized if stage == -1 */
4370
                static WORD numReadSym;
×
4371
                static WORD numReadInd;
×
4372
                static WORD numReadVec;
×
4373
                static WORD numReadFun;
×
4374

4375
                POSITION pos;
×
4376
                UBYTE *in, *out, *pp = 0, *end, *outbuf;
×
4377
                LONG numread;
×
4378
                WORD namelen, realnamelen;
×
4379
                /* shortcuts */
4380
                WORD lenW = AO.SaveHeader.lenWORD;
×
4381
                WORD lenL = AO.SaveHeader.lenLONG;
×
4382
                WORD lenP = AO.SaveHeader.lenPOINTER;
×
4383
                WORD flip = AO.transFlag & 1;
×
4384

4385
                /* remember file position in case we have to rewind */
4386
                TELLFILE(AO.SaveData.Handle,&pos);
×
4387

4388
                /* decide on the position of the in and out buffers.
4389
                   if the input is "bigger" than the output, we resize in-place, i.e.
4390
                   we immediately overwrite the source data by the translated data. in
4391
                   and out buffers start at the same place.
4392
                   if not, we read from the end of the given buffer and write at the
4393
                   beginning. */
4394
                if ( (lenW > (WORD)sizeof(WORD))
×
4395
                || ( (lenW == (WORD)sizeof(WORD))
×
4396
                     && ( (lenL > (WORD)sizeof(LONG))
×
4397
                          || ( (lenL == (WORD)sizeof(LONG)) && lenP > (WORD)sizeof(void *))
×
4398
                        )
4399
                   ) ) {
4400
                        in = out = buffer;
×
4401
                        end = buffer + *size;
×
4402
                }
4403
                else {
4404
                        /* data will grow roughly by sizeof(WORD)/lenW. the exact value is
4405
                           not important. if reading and writing areas start to overlap, the
4406
                           reading will already be near the end of the data and overwriting
4407
                           doesn't matter. */
4408
                        LONG newsize = (top - buffer) / (1 + sizeof(WORD)/lenW);
×
4409
                        end = top;
×
4410
                        out = buffer;
×
4411
                        in = end - newsize;
×
4412
                        if ( *size > newsize ) *size = newsize;
×
4413
                }
4414

4415
                if ( ( numread = ReadFile(AO.SaveData.Handle, in, *size) ) != *size ) {
×
4416
                        return ( MesPrint("Error(2) reading stored expression.") );
×
4417
                }
4418

4419
                *size = 0;
×
4420
                *outsize = 0;
×
4421

4422
                /* first time in ReadSaveVariables(). initialize counters. */
4423
                if ( *stage == -1 ) {
×
4424
                        numReadSym = 0;
×
4425
                        numReadInd = 0;
×
4426
                        numReadVec = 0;
×
4427
                        numReadFun = 0;
×
4428
                        ++*stage;
×
4429
                }
4430

4431
                while ( in < end ) {
×
4432
                        /* Symbols */
4433
                        if ( *stage == 0 ) {
×
4434
                                if ( ind->nsymbols <= numReadSym ) {
×
4435
                                        ++*stage;
×
4436
                                        continue;
×
4437
                                }
4438
                                if ( end - in < AO.SaveHeader.sSym ) {
×
4439
                                        goto RSVEnd;
×
4440
                                }
4441
                                if ( flip ) {
×
4442
                                        pp = in;
×
4443
                                        AO.FlipLONG(pp); pp += lenL;
×
4444
                                        while ( pp < in + AO.SaveHeader.sSym ) {
×
4445
                                                AO.FlipWORD(pp); pp += lenW;
×
4446
                                        }
4447
                                }
4448
                                pp = in + AO.SaveHeader.sSym;
×
4449
                                AO.ResizeLONG(in, out); in += lenL; out += sizeof(LONG); /* name     */
×
4450
                                AO.CheckPower(in);
×
4451
                                AO.ResizeWORD(in, out); in += lenW;
×
4452
                                if ( *((WORD *)out) == -AO.mpower ) *((WORD *)out) = -MAXPOWER;
×
4453
                                out += sizeof(WORD);                                                                         /* minpower */
×
4454
                                AO.ResizeWORD(in, out); in += lenW;
×
4455
                                if ( *((WORD *)out) == AO.mpower ) *((WORD *)out) = MAXPOWER;
×
4456
                                out += sizeof(WORD);                                                                         /* maxpower */
×
4457
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* complex  */
×
4458
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* number   */
×
4459
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* flags    */
×
4460
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* node     */
×
4461
                                AO.ResizeWORD(in, out); in += lenW;                      /* namesize */
×
4462
                                realnamelen = *((WORD *)out);
×
4463
                                realnamelen += sizeof(void *)-1; realnamelen &= -(sizeof(void *));
×
4464
                                out += sizeof(WORD);
×
4465
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* dimension */
×
4466
                                while ( in < pp ) {
×
4467
                                        AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD);
×
4468
                                }
4469
                                namelen = *((WORD *)out-1); /* cares for padding "bug" */
×
4470
                                if ( end - in < namelen ) {
×
4471
                                        goto RSVEnd;
×
4472
                                }
4473
                                *((WORD *)out-1) = realnamelen;
×
4474
                                *size += AO.SaveHeader.sSym + namelen;
×
4475
                                *outsize += sizeof(struct SyMbOl) + realnamelen;
×
4476
                                if ( realnamelen > namelen ) {
×
4477
                                        int j = namelen;
4478
                                        NCOPYB(out, in, j);
×
4479
                                        out += realnamelen - namelen;
×
4480
                                }
4481
                                else {
4482
                                        int j = realnamelen;
4483
                                        NCOPYB(out, in, j);
×
4484
                                        in += namelen - realnamelen;
×
4485
                                }
4486
                                ++numReadSym;
×
4487
                                continue;
×
4488
                        }
4489
                        /* Indices */
4490
                        if ( *stage == 1 ) {
×
4491
                                if ( ind->nindices <= numReadInd ) {
×
4492
                                        ++*stage;
×
4493
                                        continue;
×
4494
                                }
4495
                                if ( end - in < AO.SaveHeader.sInd ) {
×
4496
                                        goto RSVEnd;
×
4497
                                }
4498
                                if ( flip ) {
×
4499
                                        pp = in;
×
4500
                                        AO.FlipLONG(pp); pp += lenL;
×
4501
                                        while ( pp < in + AO.SaveHeader.sInd ) {
×
4502
                                                AO.FlipWORD(pp); pp += lenW;
×
4503
                                        }
4504
                                }
4505
                                pp = in + AO.SaveHeader.sInd;
×
4506
                                AO.ResizeLONG(in, out); in += lenL; out += sizeof(LONG); /* name      */
×
4507
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* type      */
×
4508
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* dimension */
×
4509
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* number    */
×
4510
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* flags     */
×
4511
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* nmin4     */
×
4512
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* node      */
×
4513
                                AO.ResizeWORD(in, out); in += lenW;                      /* namesize  */
×
4514
                                realnamelen = *((WORD *)out);
×
4515
                                realnamelen += sizeof(void *)-1; realnamelen &= -(sizeof(void *));
×
4516
                                out += sizeof(WORD);
×
4517
                                while ( in < pp ) {
×
4518
                                        AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD);
×
4519
                                }
4520
                                namelen = *((WORD *)out-1); /* cares for padding "bug" */
×
4521
                                if ( end - in < namelen ) {
×
4522
                                        goto RSVEnd;
×
4523
                                }
4524
                                *((WORD *)out-1) = realnamelen;
×
4525
                                *size += AO.SaveHeader.sInd + namelen;
×
4526
                                *outsize += sizeof(struct InDeX) + realnamelen;
×
4527
                                if ( realnamelen > namelen ) {
×
4528
                                        int j = namelen;
4529
                                        NCOPYB(out, in, j);
×
4530
                                        out += realnamelen - namelen;
×
4531
                                }
4532
                                else {
4533
                                        int j = realnamelen;
4534
                                        NCOPYB(out, in, j);
×
4535
                                        in += namelen - realnamelen;
×
4536
                                }
4537
                                ++numReadInd;
×
4538
                                continue;
×
4539
                        }
4540
                        /* Vectors */
4541
                        if ( *stage == 2 ) {
×
4542
                                if ( ind->nvectors <= numReadVec ) {
×
4543
                                        ++*stage;
×
4544
                                        continue;
×
4545
                                }
4546
                                if ( end - in < AO.SaveHeader.sVec ) {
×
4547
                                        goto RSVEnd;
×
4548
                                }
4549
                                if ( flip ) {
×
4550
                                        pp = in;
×
4551
                                        AO.FlipLONG(pp); pp += lenL;
×
4552
                                        while ( pp < in + AO.SaveHeader.sVec ) {
×
4553
                                                AO.FlipWORD(pp); pp += lenW;
×
4554
                                        }
4555
                                }
4556
                                pp = in + AO.SaveHeader.sVec;
×
4557
                                AO.ResizeLONG(in, out); in += lenL; out += sizeof(LONG); /* name     */
×
4558
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* complex  */
×
4559
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* number   */
×
4560
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* flags    */
×
4561
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* node     */
×
4562
                                AO.ResizeWORD(in, out); in += lenW;                      /* namesize */
×
4563
                                realnamelen = *((WORD *)out);
×
4564
                                realnamelen += sizeof(void *)-1; realnamelen &= -(sizeof(void *));
×
4565
                                out += sizeof(WORD);
×
4566
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* dimension */
×
4567
                                while ( in < pp ) {
×
4568
                                        AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD);
×
4569
                                }
4570
                                namelen = *((WORD *)out-1); /* cares for padding "bug" */
×
4571
                                if ( end - in < namelen ) {
×
4572
                                        goto RSVEnd;
×
4573
                                }
4574
                                *((WORD *)out-1) = realnamelen;
×
4575
                                *size += AO.SaveHeader.sVec + namelen;
×
4576
                                *outsize += sizeof(struct VeCtOr) + realnamelen;
×
4577
                                if ( realnamelen > namelen ) {
×
4578
                                        int j = namelen;
4579
                                        NCOPYB(out, in, j)
×
4580
                                        out += realnamelen - namelen;
×
4581
                                }
4582
                                else {
4583
                                        int j = realnamelen;
4584
                                        NCOPYB(out, in, j)
×
4585
                                        in += namelen - realnamelen;
×
4586
                                }
4587
                                ++numReadVec;
×
4588
                                continue;
×
4589
                        }
4590
                        /* Functions */
4591
                        if ( *stage == 3 ) {
×
4592
                                if ( ind->nfunctions <= numReadFun ) {
×
4593
                                        ++*stage;
×
4594
                                        continue;
×
4595
                                }
4596
                                if ( end - in < AO.SaveHeader.sFun ) {
×
4597
                                        goto RSVEnd;
×
4598
                                }
4599
                                if ( flip ) {
×
4600
                                        pp = in;
×
4601
                                        AO.FlipPOINTER(pp); pp += lenP;
×
4602
                                        AO.FlipLONG(pp); pp += lenL;
×
4603
                                        AO.FlipLONG(pp); pp += lenL;
×
4604
                                        while ( pp < in + AO.SaveHeader.sFun ) {
×
4605
                                                AO.FlipWORD(pp); pp += lenW;
×
4606
                                        }
4607
                                }
4608
                                pp = in + AO.SaveHeader.sFun;
×
4609
                                outbuf = out;
×
4610
                                AO.ResizePOINTER(in, out); in += lenP; out += sizeof(void *); /* tabl */
×
4611
                                AO.ResizeLONG(in, out); in += lenL; out += sizeof(LONG); /* symminfo  */
×
4612
                                AO.ResizeLONG(in, out); in += lenL; out += sizeof(LONG); /* name      */
×
4613
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* commute   */
×
4614
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* complex   */
×
4615
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* number    */
×
4616
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* flags     */
×
4617
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* spec      */
×
4618
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* symmetric */
×
4619
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* numargs */
×
4620
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* node      */
×
4621
                                AO.ResizeWORD(in, out); in += lenW;                      /* namesize  */
×
4622
                                realnamelen = *((WORD *)out);
×
4623
                                realnamelen += sizeof(void *)-1; realnamelen &= -(sizeof(void *));
×
4624
                                out += sizeof(WORD);
×
4625
                                AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD); /* dimension */
×
4626
                                while ( in < pp ) {
×
4627
                                        AO.ResizeWORD(in, out); in += lenW; out += sizeof(WORD);
×
4628
                                }
4629
                                namelen = *((WORD *)out-1); /* cares for padding "bug" */
×
4630
                                if ( end - in < namelen ) {
×
4631
                                        goto RSVEnd;
×
4632
                                }
4633
                                *((WORD *)out-1) = realnamelen;
×
4634
                                *size += AO.SaveHeader.sFun + namelen;
×
4635
                                *outsize += sizeof(struct FuNcTiOn) + realnamelen;
×
4636
                                if ( realnamelen > namelen ) {
×
4637
                                        int j = namelen;
4638
                                        NCOPYB(out, in, j);
×
4639
                                        out += realnamelen - namelen;
×
4640
                                }
4641
                                else {
4642
                                        int j = realnamelen;
4643
                                        NCOPYB(out, in, j);
×
4644
                                        in += namelen - realnamelen;
×
4645
                                }
4646
                                ++numReadFun;
×
4647
                                /* we use the information whether a function is tensorial later in ReadSaveTerm */
4648
                                AO.tensorList[((FUNCTIONS)outbuf)->number+FUNCTION] =
×
4649
                                        (UBYTE)(((FUNCTIONS)outbuf)->spec == TENSORFUNCTION);
×
4650
                                continue;
×
4651
                        }
4652
                        /* handle numdummies */
4653
                        if ( end - in >= lenW ) {
×
4654
                                if ( flip ) AO.FlipWORD(in);
×
4655
                                AO.ResizeWORD(in, out);
×
4656
                                *size += lenW;
×
4657
                                *outsize += sizeof(WORD);
×
4658
                        }
4659
                        /* handle numfactors */
4660
                        if ( end - in >= lenW ) {
×
4661
                                if ( flip ) AO.FlipWORD(in);
×
4662
                                AO.ResizeWORD(in, out);
×
4663
                                *size += lenW;
×
4664
                                *outsize += sizeof(WORD);
×
4665
                        }
4666
                        /* handle vflags */
4667
                        if ( end - in >= lenW ) {
×
4668
                                if ( flip ) AO.FlipWORD(in);
×
4669
                                AO.ResizeWORD(in, out);
×
4670
                                *size += lenW;
×
4671
                                *outsize += sizeof(WORD);
×
4672
                        }
4673
                        /* handle uflags */
4674
                        if ( end - in >= lenW ) {
×
4675
                                if ( flip ) AO.FlipWORD(in);
×
4676
                                AO.ResizeWORD(in, out);
×
4677
                                *size += lenW;
×
4678
                                *outsize += sizeof(WORD);
×
4679
                        }
4680
                        return ( 0 );
×
4681
                }
4682

4683
RSVEnd:
×
4684
                /* we are here because the remaining buffer cannot hold the next
4685
                   struct. we position the file behind the last successfully translated
4686
                   struct and return. */
4687
                ADDPOS(pos, *size);
×
4688
                SeekFile(AO.SaveData.Handle, &pos, SEEK_SET);
×
4689
                return ( 0 );
×
4690
        } else {
4691
                return ( ReadFile(AO.SaveData.Handle, buffer, *size) != *size );
×
4692
        }
4693
}
4694

4695
/*
4696
                 #] ReadSaveVariables : 
4697
                 #[ ReadSaveTerm :
4698
*/
4699

4700
/**
4701
 *  Reads a single term from the given buffer at @e bin and write the
4702
 *  translated term back to this buffer at @e bout.
4703
 *
4704
 *  ReadSaveTerm32() is currently the only instantiation of a
4705
 *  ReadSaveTerm-function. It only deals with data that already has the correct
4706
 *  endianness and that is resized to 32bit words but without being renumbered
4707
 *  or translated in any other way. It uses the compress buffer
4708
 *  AR.CompressBuffer.
4709
 *
4710
 *  The function is reentrant in order to cope with nested function arguments.
4711
 *  It is called by ReadSaveExpression() and itself.
4712
 *
4713
 *  The @e return @e value indicates the position in the input buffer up to
4714
 *  which the data has already been successfully processed. The parameter
4715
 *  @e bout returns the corresponding position in the output buffer.
4716
 *
4717
 *  @param  bin        start of the input buffer
4718
 *  @param  binend     end of the input buffer
4719
 *  @param  bout       as input points to the beginning of the output buffer,
4720
 *                     as output points behind the already translated data in
4721
 *                     the output buffer
4722
 *  @param  boutend    end of already decompressed data in output buffer
4723
 *  @param  top        end of output buffer
4724
 *  @param  terminbuf  flag whether decompressed data is already in the output
4725
 *                     buffer. used in recursive calls
4726
 *  @return            pointer to the next unprocessed data in the input buffer
4727
 */
4728
UBYTE *
4729
ReadSaveTerm32(UBYTE *bin, UBYTE *binend, UBYTE **bout, UBYTE *boutend, UBYTE *top, int terminbuf)
×
4730
{
4731
        GETIDENTITY
4732

4733
        UBYTE *boutbuf;
×
4734
        INT32 len, j, id;
×
4735
        INT32 *r, *t, *coeff, *end, *newtermsize, *rend;
×
4736
        INT32 *newsubtermp;
×
4737
        INT32 *in = (INT32 *)bin;
×
4738
        INT32 *out = (INT32 *)*bout;
×
4739

4740
        /* if called recursively the term is already decompressed in buffer.
4741
           is this the case? */
4742
        if ( terminbuf ) {
×
4743
                /* don't do any decompression, just adjust the pointers */
4744
                len = *out;
×
4745
                end = out + len;
×
4746
                r = in + 1;
×
4747
                rend = (INT32 *)boutend;
×
4748
                coeff = end - ABS(*(end-1));
×
4749
                newtermsize = (INT32 *)*bout;
×
4750
                out = newtermsize + 1;
×
4751
        }
4752
        else {
4753
                /* do decompression of necessary. always return if the space in the
4754
                   buffer is not sufficient */
4755
                INT32 rbuf;
×
4756
                r = (INT32 *)AR.CompressBuffer;
×
4757
                rbuf = *r;
×
4758
                len = j = *in;
×
4759
                /* first copy from AR.CompressBuffer if necessary */
4760
                if ( j < 0 ) {
×
4761
                        ++in;
×
4762
                        if ( (UBYTE *)in >= binend ) {
×
4763
                                return ( bin );
4764
                        }
4765
                        *out = len = -j + 1 + *in;
×
4766
                        end = out + *out;
×
4767
                        if ( (UBYTE *)end >= top ) {
×
4768
                                return ( bin );
4769
                        }
4770
                        ++out;
×
4771
                        *r++ = len;
×
4772
                        while ( ++j <= 0 ) {
×
4773
                                INT32 bb = *r++;
×
4774
                                *out++ = bb;
×
4775
                        }
4776
                        j = *in++;
×
4777
                }
4778
                else if ( j == 0 ) {
×
4779
                        /* care for padding words */
4780
                        while ( (UBYTE *)in < binend ) {
×
4781
                                *out++ = 0;
×
4782
                                if ( (UBYTE *)out > top ) {
×
4783
                                        return ( (UBYTE *)bin );
4784
                                }
4785

4786
                                *r++ = 0;
×
4787
                                ++in;
×
4788
                        }
4789
                        *bout = (UBYTE *)out;
×
4790
                        return ( (UBYTE *)in );
×
4791
                }
4792
                else {
4793
                        end = out + len;
×
4794
                        if ( (UBYTE *)end >= top ) {
×
4795
                                return ( bin );
4796
                        }
4797
                }
4798
                if ( (UBYTE *)(in + j) >= binend ) {
×
4799
                        *(AR.CompressBuffer) = rbuf;
×
4800
                        return ( bin );
×
4801
                }
4802
                if ( (UBYTE *)out + j >= top ) {
×
4803
                        return ( bin );
4804
                }
4805
                /* second copy from input buffer */
4806
                while ( --j >= 0 ) {
×
4807
                        INT32 bb = *in++;
×
4808
                        *r++ = *out++ = bb;
×
4809
                }
4810

4811
                rend = r;
×
4812
                r = (INT32 *)AR.CompressBuffer + 1;
×
4813
                coeff = end - ABS(*(end-1));
×
4814
                newtermsize = (INT32 *)*bout;
×
4815
                out = newtermsize + 1;
×
4816
        }
4817

4818
        /* iterate over subterms */
4819
        while ( out < coeff ) {
×
4820

4821
                id = *out++;
×
4822
                ++r;
×
4823
                t = out + *out - 1;
×
4824
                newsubtermp = out;
×
4825
                ++out; ++r;
×
4826

4827
                if ( id == SYMBOL ) {
×
4828
                        while ( out < t ) {
×
4829
                                ++out; ++r; /* symbol number */
×
4830
                                /* if exponent is too big, rewrite as exponent function */
4831
                                if ( ABS(*out) >= MAXPOWER ) { 
×
4832
                                        INT32 *a, *b;
×
4833
                                        INT32 n;
×
4834
                                        INT32 num = *(out-1);
×
4835
                                        INT32 exp = *out;
×
4836
                                        coeff += 9;
×
4837
                                        end += 9;
×
4838
                                        t += 9;
×
4839
                                        if ( (UBYTE *)end > top ) return ( bin );
×
4840
                                        out -= 3;
×
4841
                                        *out++ = EXPONENT;                /* id */
×
4842
                                        *out++ = 13;                        /* size */
×
4843
                                        *out++ = 1;                                /* dirtyflag */
×
4844
                                        *out++ = -SYMBOL;                /* first short arg */
×
4845
                                        *out++ = num;
×
4846
                                        *out++ = 8;                                /* second arg, size */
×
4847
                                        *out++ = 0;                                /* dirtyflag */
×
4848
                                        *out++ = 6;                                /* term size */
×
4849
                                        *out++ = ABS(exp) & 0x0000FFFF;
×
4850
                                        *out++ = ABS(exp) >> 16;
×
4851
                                        *out++ = 1;        
×
4852
                                        *out++ = 0;
×
4853
                                        *out++ = ( exp < 0 ) ? -5 : 5;
×
4854
                                        a = ++r;
×
4855
                                        b = out;
×
4856
                                        n = rend - r;
×
4857
                                        NCOPYI32(b, a, n)
×
4858
                                }
4859
                                else {
4860
                                        ++out; ++r;
×
4861
                                }
4862
                        }
4863
                }
4864
                else if ( id == DOTPRODUCT ) {
×
4865
                        while ( out < t ) {
×
4866
                                AO.RenumberVec((UBYTE *)out); /* vector 1 */
×
4867
                                ++out; ++r;
×
4868
                                AO.RenumberVec((UBYTE *)out); /* vector 2 */
×
4869
                                ++out; ++r;
×
4870
                                /* if exponent is too big, rewrite as exponent function */
4871
                                if ( ABS(*out) >= MAXPOWER ) { 
×
4872
                                        INT32 *a, *b;
×
4873
                                        INT32 n;
×
4874
                                        INT32 num1 = *(out-2);
×
4875
                                        INT32 num2 = *(out-1);
×
4876
                                        INT32 exp = *out;
×
4877
                                        coeff += 17;
×
4878
                                        end += 17;
×
4879
                                        t += 17;
×
4880
                                        if ( (UBYTE *)end > top ) return ( bin );
×
4881
                                        out -= 4;
×
4882
                                        *out++ = EXPONENT;                /* id */
×
4883
                                        *out++ = 22;                        /* size */
×
4884
                                        *out++ = 1;                                /* dirtyflag */
×
4885
                                        *out++ = 11;                        /* first arg, size */
×
4886
                                        *out++ = 0;                                /* dirtyflag */
×
4887
                                        *out++ = 9;                                /* term size */
×
4888
                                        *out++ = DOTPRODUCT;        /* p1.p2 */
×
4889
                                        *out++ = 5;                                /* subterm size */
×
4890
                                        *out++ = num1;                        /* p1 */
×
4891
                                        *out++ = num2;                        /* p2 */
×
4892
                                        *out++ = 1;                                /* exponent */
×
4893
                                        *out++ = 1;                                /* coeff */
×
4894
                                        *out++ = 1;
×
4895
                                        *out++ = 3;
×
4896
                                        *out++ = 8;                                /* second arg, size */
×
4897
                                        *out++ = 0;                                /* dirtyflag */
×
4898
                                        *out++ = 6;                                /* term size */
×
4899
                                        *out++ = ABS(exp) & 0x0000FFFF;
×
4900
                                        *out++ = ABS(exp) >> 16;
×
4901
                                        *out++ = 1;        
×
4902
                                        *out++ = 0;
×
4903
                                        *out++ = ( exp < 0 ) ? -5 : 5;
×
4904
                                        a = ++r;
×
4905
                                        b = out;
×
4906
                                        n = rend - r;
×
4907
                                        NCOPYI32(b, a, n)
×
4908
                                }
4909
                                else {
4910
                                        ++out; ++r;
×
4911
                                }
4912
                        }
4913
                }
4914
                else if ( id == VECTOR ) {
×
4915
                        while ( out < t ) {
×
4916
                                AO.RenumberVec((UBYTE *)out); /* vector number */
×
4917
                                ++out; ++r;
×
4918
                                ++out; ++r; /* index, do nothing */
×
4919
                        }
4920
                }
4921
                else if ( id == INDEX ) {
×
4922
/*                        INT32 vectoroffset = -2 * *((INT32 *)AO.SaveHeader.wildoffset); */
4923
                        void *dummy = (void *)AO.SaveHeader.wildoffset;  /* to remove a warning about strict-aliasing rules in gcc */
×
4924
                        INT32 vectoroffset = -2 * *((INT32 *)dummy);
×
4925
                        while ( out < t ) {
×
4926
                                /* if there is a vector, renumber it */
4927
                                if ( *out < vectoroffset ) {
×
4928
                                        AO.RenumberVec((UBYTE *)out);
×
4929
                                }
4930
                                ++out; ++r;
×
4931
                        }
4932
                }
4933
                else if ( id == SUBEXPRESSION ) {
×
4934
                        /* nothing to translate */
4935
                        while ( out < t ) {
×
4936
                                ++out; ++r;
×
4937
                        }
4938
                }
4939
                else if ( id == DELTA ) {
×
4940
                        /* nothing to translate */
4941
                        r += t - out;
×
4942
                        out = t;
×
4943
                }
4944
                else if ( id == HAAKJE ) {
×
4945
                        /* nothing to translate */
4946
                        r += t - out;
×
4947
                        out = t;
×
4948
                }
4949
                else if ( id == GAMMA || id == LEVICIVITA || (id >= FUNCTION && AO.tensorList[id]) ) {
×
4950
/*                        INT32 vectoroffset = -2 * *((INT32 *)AO.SaveHeader.wildoffset); */
4951
                        void *dummy = (void *)AO.SaveHeader.wildoffset;  /* to remove a warning about strict-aliasing rules in gcc */
×
4952
                        INT32 vectoroffset = -2 * *((INT32 *)dummy);
×
4953
                        while ( out < t ) {
×
4954
                                /* if there is a vector as an argument, renumber it */
4955
                                if ( *out < vectoroffset ) {
×
4956
                                        AO.RenumberVec((UBYTE *)out);
×
4957
                                }
4958
                                ++out; ++r;
×
4959
                        }
4960
                }
4961
                else if ( id >= FUNCTION ) {
×
4962
                        INT32 *argEnd;
×
4963
                        UBYTE *newbin;
×
4964

4965
                        ++out; ++r; /* dirty flags */
×
4966
                        
4967
                        /* loop over arguments */
4968
                        while ( out < t ) {
×
4969
                                if ( *out < 0 ) {
×
4970
                                        /* short notation arguments */
4971
                                        switch ( -*out ) {
×
4972
                                                case SYMBOL:
×
4973
                                                        ++out; ++r;
×
4974
                                                        ++out; ++r;
×
4975
                                                        break;
×
4976
                                                case SNUMBER:
×
4977
                                                        argEnd = out+2;
×
4978
                                                        ++out; ++r;
×
4979
                                                        if ( sizeof(WORD) == 2 ) {
×
4980
                                                                /* resize if needed */
4981
                                                                if ( *out > (1<<15)-1 || *out < -(1<<15)+1 ) {
4982
                                                                        INT32 *a, *b;
4983
                                                                        INT32 n;
4984
                                                                        INT32 num = *out;
4985
                                                                        coeff += 6;
4986
                                                                        end += 6;
4987
                                                                        argEnd += 6;
4988
                                                                        t += 6;
4989
                                                                        if ( (UBYTE *)end > top ) return ( bin );
4990
                                                                        --out;
4991
                                                                        *out++ = 8;                        /* argument size */
4992
                                                                        *out++ = 0;                        /* dirtyflag */
4993
                                                                        *out++ = 6;                        /* term size */
4994
                                                                        *out++ = ABS(num) & 0x0000FFFF;
4995
                                                                        *out++ = ABS(num) >> 16;
4996
                                                                        *out++ = 1;
4997
                                                                        *out++ = 0;
4998
                                                                        *out++ = ( num < 0 ) ? -5 : 5;
4999
                                                                        a = ++r;
5000
                                                                        b = out;
5001
                                                                        n = rend - r;
5002
                                                                        NCOPYI32(b, a, n)
5003
                                                                }
5004
                                                                else {
5005
                                                                        ++out; ++r;
5006
                                                                }
5007
                                                        }
5008
                                                        else {
5009
                                                                ++out; ++r;
×
5010
                                                        }
5011
                                                        break;
5012
                                                case VECTOR:
×
5013
                                                        ++out; ++r;
×
5014
                                                        AO.RenumberVec((UBYTE *)out);
×
5015
                                                        ++out; ++r;
×
5016
                                                        break;
×
5017
                                                case INDEX:
×
5018
                                                        ++out; ++r;
×
5019
                                                        ++out; ++r;
×
5020
                                                        break;
×
5021
                                                case MINVECTOR:
×
5022
                                                        ++out; ++r;
×
5023
                                                        AO.RenumberVec((UBYTE *)out);
×
5024
                                                        ++out; ++r;
×
5025
                                                        break;
×
5026
                                                default:
×
5027
                                                        if ( -*out >= FUNCTION ) {
×
5028
                                                                ++out; ++r;
×
5029
                                                                break;
×
5030
                                                        } else {
5031
                                                                MesPrint("short function code %d not implemented.", *out);
×
5032
                                                                return ( (UBYTE *)in );
×
5033
                                                        }
5034
                                        }
5035
                                }
5036
                                else {
5037
                                        /* long arguments */
5038
                                        INT32 *newargsize = out;
×
5039
                                        argEnd = out + *out;
×
5040
                                        ++out; ++r;
×
5041
                                        ++out; ++r; /* dirty flags */
×
5042
                                        while ( out < argEnd ) {
×
5043
                                                INT32 *keepsizep = out + *out;
×
5044
                                                INT32 lenbuf = *out;
×
5045
                                                INT32 **ppp = &out; /* to avoid a compiler warning */
×
5046
                                                /* recursion */
5047
                                                newbin = ReadSaveTerm32((UBYTE *)r, binend, (UBYTE **)ppp, (UBYTE *)rend, top, 1);
×
5048
                                                r += lenbuf;
×
5049
                                                if ( newbin == (UBYTE *)r ) {
×
5050
                                                        return ( (UBYTE *)in );
5051
                                                }
5052
                                                /* if the term done by recursion has changed in size,
5053
                                                   we need to move the rest of the data accordingly */
5054
                                                if ( out > keepsizep ) {
×
5055
                                                        INT32 *a, *b;
×
5056
                                                        INT32 n;
×
5057
                                                        INT32 extention = out - keepsizep;
×
5058
                                                        a = r;
×
5059
                                                        b = out;
×
5060
                                                        n = rend - r;
×
5061
                                                        NCOPYI32(b, a, n)
×
5062
                                                        coeff += extention;
×
5063
                                                        end += extention;
×
5064
                                                        argEnd += extention;
×
5065
                                                        t += extention;
×
5066
                                                }
5067
                                                else if ( out < keepsizep ) {
×
5068
                                                        INT32 *a, *b;
×
5069
                                                        INT32 n;
×
5070
                                                        INT32 extention = keepsizep - out;
×
5071
                                                        a = keepsizep;
×
5072
                                                        b = out;
×
5073
                                                        n = rend - r;
×
5074
                                                        NCOPYI32(b, a, n)
×
5075
                                                        coeff -= extention;
×
5076
                                                        end -= extention;
×
5077
                                                        argEnd -= extention;
×
5078
                                                        t -= extention;
×
5079
                                                }
5080
                                        }
5081
                                        *newargsize = out - newargsize;
×
5082
                                }
5083
                        }
5084
                }
5085
                else {
5086
                        MesPrint("ID %d not recognized.", id);
×
5087
                        return ( (UBYTE *)in );
×
5088
                }
5089

5090
                *newsubtermp = out - newsubtermp + 1;
×
5091
        }
5092

5093
        if ( (UBYTE *)end >= top ) {
×
5094
                return ( bin );
5095
        }
5096

5097
        /* do coefficient and adjust term size */
5098
        boutbuf = *bout;
×
5099
        *bout = (UBYTE *)out;
×
5100

5101
        ResizeCoeff32(bout, (UBYTE *)end, top);
×
5102

5103
        if ( *bout >= top ) {
×
5104
                *bout = boutbuf;
×
5105
                return ( bin );
×
5106
        }
5107

5108
        *newtermsize = (INT32 *)*bout - newtermsize;
×
5109

5110
        return ( (UBYTE *)in );
×
5111
}
5112

5113
/*
5114
                 #] ReadSaveTerm : 
5115
                 #[ ReadSaveExpression :
5116
*/
5117

5118
/**
5119
 *  Reads an expression from the open file specified by AO.SaveData.Handle.
5120
 *  The endianness flip and a resizing without renumbering is done in this
5121
 *  function. Thereafter the buffer consists of chunks with a uniform maximal
5122
 *  word size (32bit at the moment). The actual renumbering is then done by
5123
 *  calling the function ReadSaveTerm32(). The result is returned in @e buffer.
5124
 *
5125
 *  If the translation at some point doesn't fit into the buffer anymore, the
5126
 *  function returns and must be called again. In any case @e size returns the
5127
 *  number of successfully read bytes, @e outsize returns the number of
5128
 *  successfully written bytes, and the file will be positioned at the next
5129
 *  byte after the successfully read data.
5130
 *
5131
 *  It is called by PutInStore().
5132
 *
5133
 *  @param  buffer   output buffer, holds the (translated) expression
5134
 *  @param  top      end of buffer
5135
 *  @param  size     number of read bytes
5136
 *  @param  outsize  number of written bytes
5137
 *  @return          = 0 everything okay, != 0 an error occurred
5138
 */
5139
WORD ReadSaveExpression(UBYTE *buffer, UBYTE *top, LONG *size, LONG *outsize)
×
5140
{
5141
        if ( AO.transFlag ) {
×
5142
                UBYTE *in, *end, *out, *outend, *p;
×
5143
                POSITION pos;
×
5144
                LONG half;
×
5145
                WORD lenW = AO.SaveHeader.lenWORD;
×
5146

5147
                /* remember the last file position in case an expression cannot be
5148
                   fully processed */
5149
                TELLFILE(AO.SaveData.Handle,&pos);
×
5150

5151
                /* adjust 'size' depending on whether the translated data is bigger or
5152
                   smaller */ 
5153
                half = (top-buffer)/2;
×
5154
                if ( *size > half ) *size = half;
×
5155
                if ( lenW < (WORD)sizeof(WORD) ) {
×
5156
                        if ( *size * (LONG)sizeof(WORD)/lenW > half ) *size = half*lenW/(LONG)sizeof(WORD);
×
5157
                }
5158
                else {
5159
                        if ( *size > half ) *size = half;
×
5160
                }
5161

5162
                /* depending on the necessary resizing we position the input pointer
5163
                   either at the start of the buffer or in the middle. if the data will
5164
                   roughly remain the same size, we need only one processing step, so
5165
                   we put the 'in' at the middle and 'out' and the beginning. in the
5166
                   other cases we need two processing steps, so first we put 'in' at
5167
                   the beginning and write at the middle. the second step can then read
5168
                   from the middle and put its results at the beginning. */
5169
                in = out = buffer;
×
5170
                if ( lenW == sizeof(WORD) ) in += half;
×
5171
                else out += half;
×
5172
                end = in + *size;
×
5173
                outend = out + *size;
×
5174

5175
                if ( ReadFile(AO.SaveData.Handle, in, *size) != *size ) {
×
5176
                        return ( MesPrint("Error(3) reading stored expression.") );
×
5177
                }
5178

5179
                if ( AO.transFlag & 1 ) {
×
5180
                        p = in;
×
5181
                        end -= lenW;
×
5182
                        while ( p <= end ) {
×
5183
                                AO.FlipWORD(p); p += lenW;
×
5184
                        }
5185
                        end += lenW;
5186
                }
5187

5188
                if ( lenW > (WORD)sizeof(WORD) ) {
×
5189
                        /* renumber first */
5190
                        do {
×
5191
                                outend = out+*size;
×
5192
                                if ( outend > top ) outend = top;
×
5193
                                p = ReadSaveTerm32(in, end, &out, outend, top, 0);
×
5194
                                if ( p == in ) break;
×
5195
                                in = p;
×
5196
                        } while ( in <= end - lenW );
×
5197
                        /* then resize */
5198
                        *size = in - buffer;
×
5199
                        in = buffer + half;
×
5200
                        end = out;
×
5201
                        out = buffer;
×
5202

5203
                        while ( in < end ) {
×
5204
                                /* resize without checking */
5205
                                AO.ResizeNCWORD(in, out);
×
5206
                                in += lenW; out += sizeof(WORD);
×
5207
                        }
5208
                }
5209
                else {
5210
                        if ( lenW < (WORD)sizeof(WORD) ) {
×
5211
                                /* resize first */
5212
                                while ( in < end ) {
×
5213
                                        AO.ResizeWORD(in, out);
×
5214
                                        in += lenW; out += sizeof(WORD);
×
5215
                                }
5216
                                in = buffer + half;
×
5217
                                end = out;
×
5218
                                out = buffer;
×
5219
                        }
5220
                        /* then renumber */
5221
                        do {
×
5222
                                p = ReadSaveTerm32(in, end, &out,  buffer+half, buffer+half, 0);
×
5223
                                if ( p == in ) break;
×
5224
                                in = p;
×
5225
                        } while ( in <= end - sizeof(WORD) );
×
5226
                        *size = (in - buffer - half) * lenW / (ULONG)sizeof(WORD);
×
5227
                }
5228
                *outsize = out - buffer;
×
5229
                ADDPOS(pos, *size);
×
5230
                SeekFile(AO.SaveData.Handle, &pos, SEEK_SET);
×
5231

5232
                return ( 0 );
×
5233
        }
5234
        else {
5235
                return ( ReadFile(AO.SaveData.Handle, buffer, *size) != *size );
×
5236
        }
5237
}
5238

5239
/*
5240
                 #] ReadSaveExpression : 
5241
        #] System Independent Saved Expressions :
5242
*/
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc