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

form-dev / form / 15701338753

17 Jun 2025 07:49AM UTC coverage: 50.382% (-0.004%) from 50.386%
15701338753

Pull #662

github

web-flow
Merge f1f68c050 into 207386593
Pull Request #662: Cleanup: change VOID into void

178 of 245 new or added lines in 34 files covered. (72.65%)

2 existing lines in 1 file now uncovered.

41784 of 82935 relevant lines covered (50.38%)

2640008.85 hits per line

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

23.98
/sources/tables.c
1
/** @file tables.c
2
 * 
3
 *  Contains all functions that deal with the table bases on the 'FORM level'
4
 *  The low level database routines are in minos.c
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
          #[ Includes :
34

35
        File contains the routines for the tree structure of sparse tables
36
        We insert elements by
37
        InsTableTree(T,tp) with T the TABLES element and tp the pointer
38
                to the indices.
39
        We look for elements with
40
        FindTableTree(T,tp,inc) with T the TABLES element, tp the pointer to the
41
                indices or the function arguments and inc tells which of these options.
42
        The tree is cleared with ClearTableTree(T) and we rebuild the tree
43
        after a .store in which we lost a part of the table with
44
        RedoTableTree(T,newsize)
45

46
        In T->tablepointers we have the lists of indices for each element.
47
        Additionally for each element there is an extension. There are
48
        TABLEEXTENSION WORDs reserved for that. The old system had two words
49
        One for the element in the rhs of the compile buffer and one for
50
        an additional rhs in case the original would be overwritten by a new
51
        definition, but the old was fixed by .global and hence it should be possible
52
        to restore it.
53
        New use (new = 24-sep-2001)
54
                rhs1,numCompBuffer1,rhs2,numCompBuffer2,usage
55
        Hence TABLEEXTENSION will be 5. Note that for 64 bits the use of the
56
        compiler buffer is overdoing it a bit, but it would be too complicated
57
        to try to give it special code.
58
*/
59

60
#include "form3.h"
61
#include "minos.h"
62
#include "comtool.h"
63

64
/* static UBYTE *sparse = (UBYTE *)"sparse"; */
65
static UBYTE *tablebase = (UBYTE *)"tablebase";
66

67
/*
68
          #] Includes : 
69
          #[ ClearTableTree :
70
*/
71

72
void ClearTableTree(TABLES T)
30✔
73
{
74
        COMPTREE *root;
30✔
75
        if ( T->boomlijst == 0 ) {
30✔
76
                T->MaxTreeSize = 125;
30✔
77
                T->boomlijst = (COMPTREE *)Malloc1(T->MaxTreeSize*sizeof(COMPTREE),
30✔
78
                                "ClearTableTree");
79
        }
80
        root = T->boomlijst;
30✔
81
        T->numtree = 0;
30✔
82
        T->rootnum = 0;
30✔
83
        root->left = -1;                
30✔
84
        root->right = -1;
30✔
85
        root->parent = -1;
30✔
86
        root->blnce = 0;
30✔
87
        root->value = -1;
30✔
88
        root->usage = 0;
30✔
89
}
30✔
90

91
/*
92
          #] ClearTableTree : 
93
          #[ InsTableTree :
94

95
        int InsTableTree(TABLES T,WORD *,arglist)
96
                Searches for the element specified by the list of arguments.
97
                If found, it returns -(the offset in T->tablepointers)
98
                If not found, it will allocate a new element, balance the tree if
99
            necessary and return the number of the element in the boomlijst
100
                This number is always > 0, because we start from 1.
101
*/
102

103
int InsTableTree(TABLES T, WORD *tp)
96✔
104
{
105
        COMPTREE *boomlijst, *q, *p, *s;
96✔
106
        WORD *v1, *v2, *v3, xstop;
96✔
107
        int ip, iq, is;
96✔
108
        if ( T->numtree + 1 >= T->MaxTreeSize ) {
96✔
109
                if ( T->MaxTreeSize == 0 ) ClearTableTree(T);
×
110
                else {
111
                        is = T->MaxTreeSize * 2;
×
112
                        s  = (COMPTREE *)Malloc1(is*sizeof(COMPTREE),"InsTableTree");
×
113
                        for ( ip = 0; ip < T->MaxTreeSize; ip++ ) { s[ip] = T->boomlijst[ip]; }
×
114
                        if ( T->boomlijst ) M_free(T->boomlijst,"InsTableTree");
×
115
                        T->boomlijst = s;
×
116
                        T->MaxTreeSize = is;
×
117
                }
118
        }
119
        boomlijst = T->boomlijst;
96✔
120
        q = boomlijst + T->rootnum;
96✔
121
        if ( q->right == -1 ) { /* First element */
96✔
122
                T->numtree++;
18✔
123
                s = boomlijst+T->numtree;
18✔
124
                q->right = T->numtree;
18✔
125
                s->parent = T->rootnum;
18✔
126
                s->left = s->right = -1;
18✔
127
                s->blnce = 0;
18✔
128
                s->value = tp - T->tablepointers;
18✔
129
                s->usage = 0;
18✔
130
                return(T->numtree);
18✔
131
        }
132
        ip = q->right;
78✔
133
        if ( T->numind >= 0 ) xstop = T->numind;
78✔
134
        else xstop = *tp + 1;
×
135
        while ( ip >= 0 ) {
186✔
136
                p = boomlijst + ip;
186✔
137
                v1 = T->tablepointers + p->value;
186✔
138
                v2 = tp; v3 = tp + xstop;
186✔
139
                while ( *v1 == *v2 && v2 < v3 ) { v1++; v2++; }
186✔
140
                if ( v2 >= v3 ) return(-p->value);
186✔
141
                if ( *v1 > *v2 ) {
186✔
142
                        iq = p->right;
×
143
                        if ( iq >= 0 ) { ip = iq; }
×
144
                        else {
145
                                T->numtree++;
×
146
                                is = T->numtree; 
×
147
                                p->right = is;
×
148
                                s = boomlijst + is;
×
149
                                s->parent = ip; s->left = s->right = -1;
×
150
                                s->blnce = 0;   s->value = tp - T->tablepointers;
×
151
                                s->usage = 0;
×
152
                                p->blnce++;
×
153
                                if ( p->blnce == 0 ) return(T->numtree);
×
154
                                goto balance;
×
155
                        }
156
                }
157
                else if ( *v1 < *v2 ) {
186✔
158
                        iq = p->left;
186✔
159
                        if ( iq >= 0 ) { ip = iq; }
186✔
160
                        else {
161
                                T->numtree++;
78✔
162
                                is = T->numtree;
78✔
163
                                s = boomlijst+is;
78✔
164
                                p->left = is;
78✔
165
                                s->parent = ip; s->left = s->right = -1;
78✔
166
                                s->blnce = 0;   s->value = tp - T->tablepointers;
78✔
167
                                s->usage = 0;
78✔
168
                                p->blnce--;
78✔
169
                                if ( p->blnce == 0 ) return(T->numtree);
78✔
170
                                goto balance;
78✔
171
                        }
172
                }
173
        }
174
        MesPrint("Serious problems in InsTableTree!\n");
×
175
        Terminate(-1);
×
176
        return(0);
×
177
balance:;
108✔
178
        for (;;) {
108✔
179
                p = boomlijst + ip;
108✔
180
                iq = p->parent;
108✔
181
                if ( iq == T->rootnum ) break;
108✔
182
                q = boomlijst + iq;
78✔
183
                if ( ip == q->left ) q->blnce--;
78✔
184
                else                 q->blnce++;
×
185
                if ( q->blnce == 0 ) break;
78✔
186
                if ( q->blnce == -2 ) {
78✔
187
                        if ( p->blnce == -1 ) { /* single rotation */
48✔
188
                                q->left = p->right;
48✔
189
                                p->right = iq;
48✔
190
                                p->parent = q->parent;
48✔
191
                                q->parent = ip;
48✔
192
                                if ( boomlijst[p->parent].left == iq ) boomlijst[p->parent].left = ip;
48✔
193
                                else                                   boomlijst[p->parent].right = ip;
24✔
194
                                if ( q->left >= 0 ) boomlijst[q->left].parent = iq;
48✔
195
                                q->blnce = p->blnce = 0;
48✔
196
                        }
197
                        else {        /* double rotation */
198
                                s = boomlijst + is;
×
199
                                q->left = s->right;
×
200
                                p->right = s->left;
×
201
                                s->right = iq;
×
202
                                s->left = ip;
×
203
                                if ( p->right >= 0 ) boomlijst[p->right].parent = ip;
×
204
                                if ( q->left >= 0 ) boomlijst[q->left].parent = iq;
×
205
                                s->parent = q->parent;
×
206
                                q->parent = is;
×
207
                                p->parent = is;
×
208
                                if ( boomlijst[s->parent].left == iq )
×
209
                                           boomlijst[s->parent].left = is;
×
210
                                else   boomlijst[s->parent].right = is;
×
211
                                if ( s->blnce > 0 ) { q->blnce = s->blnce = 0; p->blnce = -1; }
×
212
                                else if ( s->blnce < 0 ) { p->blnce = s->blnce = 0; q->blnce = 1; }
×
213
                                else { p->blnce = s->blnce = q->blnce = 0; }
×
214
                        }
215
                        break;
216
                }
217
                else if ( q->blnce == 2 ) {
30✔
218
                        if ( p->blnce == 1 ) {        /* single rotation */
×
219
                                q->right = p->left;
×
220
                                p->left = iq;
×
221
                                p->parent = q->parent;
×
222
                                q->parent = ip;
×
223
                                if ( boomlijst[p->parent].left == iq ) boomlijst[p->parent].left = ip;
×
224
                                else                                   boomlijst[p->parent].right = ip;
×
225
                                if ( q->right >= 0 ) boomlijst[q->right].parent = iq;
×
226
                                q->blnce = p->blnce = 0;
×
227
                        }
228
                        else {        /* double rotation */
229
                                s = boomlijst + is;
×
230
                                q->right = s->left;
×
231
                                p->left = s->right;
×
232
                                s->left = iq;
×
233
                                s->right = ip;
×
234
                                if ( p->left >= 0 ) boomlijst[p->left].parent = ip;
×
235
                                if ( q->right >= 0 ) boomlijst[q->right].parent = iq;
×
236
                                s->parent = q->parent;
×
237
                                q->parent = is;
×
238
                                p->parent = is;
×
239
                                if ( boomlijst[s->parent].left == iq ) boomlijst[s->parent].left = is;
×
240
                                else                                   boomlijst[s->parent].right = is;
×
241
                                if ( s->blnce < 0 ) { q->blnce = s->blnce = 0; p->blnce = 1; }
×
242
                                else if ( s->blnce > 0 ) { p->blnce = s->blnce = 0; q->blnce = -1; }
×
243
                                else { p->blnce = s->blnce = q->blnce = 0; }
×
244
                        }
245
                        break;
246
                }
247
                is = ip; ip = iq;
248
        }
249
        return(T->numtree);
78✔
250
}
251

252
/*
253
          #] InsTableTree : 
254
          #[ RedoTableTree :
255

256
        To be used when a sparse table is trimmed due to a .store
257
        We rebuild the tree. In the future one could try to become faster
258
        at the cost of quite some complexity.
259
        We need to keep the first 'size' elements in the boomlijst.
260
        Kill all others and reconstruct the tree with the original ordering.
261
        This is very complicated! Because .store will either keep the whole
262
        table or remove the whole table we should not come here often.
263
        Hence we choose the slow solution for now.
264
*/
265

266
void RedoTableTree(TABLES T, int newsize)
×
267
{
268
        WORD *tp;
×
269
        int i;
×
270
        ClearTableTree(T);
×
271
        for ( i = 0, tp = T->tablepointers; i < newsize; i++ ) {
×
272
                InsTableTree(T,tp);
×
273
                tp += ABS(T->numind)+TABLEEXTENSION;
×
274
        }
275
}
×
276

277
/*
278
          #] RedoTableTree : 
279
          #[ FindTableTree :
280

281
        int FindTableTree(TABLES T,WORD *,arglist,int,inc)
282
                Searches for the element specified by the list of arguments.
283
                If found, it returns the offset in T->tablepointers
284
                If not found, it will return -1
285
                The list here is from the list of function arguments. Hence it
286
                has pairs of numbers -SNUMBER,index
287
                Actually inc says how many numbers there are and the above case is 
288
                for inc = 2. For inc = 1 we have just a list of indices.
289
*/
290

291
int FindTableTree(TABLES T, WORD *tp, int inc)
156✔
292
{
293
        COMPTREE *boomlijst = T->boomlijst, *q = boomlijst + T->rootnum, *p;
156✔
294
        WORD *v1, *v2, *v3, xstop;
156✔
295
        int ip, iq;
156✔
296
        if ( q->right == -1 ) return(-1);
156✔
297
        ip = q->right;
138✔
298
        if ( inc > 1 ) tp += inc-1;
138✔
299
        if ( T->numind >= 0 ) xstop = T->numind;
138✔
300
        else {        /* We have to read the number of arguments first */
301
                if ( *tp <= 0 ) return(-1); /* Cannot be! */
×
302
                xstop = *tp+1;
×
303
        }
304
        while ( ip >= 0 ) {
360✔
305
                p = boomlijst + ip;
360✔
306
                v1 = T->tablepointers + p->value;
360✔
307
                v2 = tp; v3 = v1 + xstop;
360✔
308
                while ( *v1 == *v2 && v1 < v3 ) { v1++; v2 += inc; }
420✔
309
                if ( v1 == v3 ) {
360✔
310
                        p->usage++;
60✔
311
                        return(p->value);
60✔
312
                }
313
                if ( *v1 > *v2 ) {
300✔
314
                        iq = p->right;
48✔
315
                        if ( iq >= 0 ) { ip = iq; }
48✔
316
                        else return(-1);
317
                }
318
                else if ( *v1 < *v2 ) {
252✔
319
                        iq = p->left;
252✔
320
                        if ( iq >= 0 ) { ip = iq; }
252✔
321
                        else return(-1);
322
                }
323
        }
324
        MesPrint("Serious problems in FindTableTree\n");
×
325
        Terminate(-1);
×
326
        return(-1);
×
327
}
328

329
/*
330
          #] FindTableTree : 
331
          #[ DoTableExpansion :
332
*/
333

334
WORD DoTableExpansion(WORD *term, WORD level)
6✔
335
{
336
        GETIDENTITY
4✔
337
        WORD *t, *tstop, *stopper, *termout, *m, *mm, *tp, *r, xx;
6✔
338
        WORD numsubexp, numbuf;
6✔
339
        TABLES T = 0;
6✔
340
        int i, j, num;
6✔
341
        AN.TeInFun = AR.TePos = 0;
6✔
342
        tstop = term + *term;
6✔
343
        stopper = tstop - ABS(tstop[-1]);
6✔
344
        t = term+1;
6✔
345
        while ( t < stopper ) {
6✔
346
                if ( *t != TABLEFUNCTION ) { t += t[1]; continue; }
6✔
347
                if ( t[FUNHEAD] > -FUNCTION ) { t += t[1]; continue; }
6✔
348
                T = functions[-t[FUNHEAD]-FUNCTION].tabl;
6✔
349
                if ( T == 0 ) { t += t[1]; continue; }
6✔
350
                if ( T->spare ) T = T->spare;
6✔
351
                if ( t[1] == FUNHEAD+2 && t[FUNHEAD+1] <= -FUNCTION ) break;
6✔
352
                if ( t[1] < FUNHEAD+1+2*ABS(T->numind) ) { t += t[1]; continue; }
6✔
353
                for ( i = 0; i < ABS(T->numind); i++ ) {
12✔
354
                        if ( t[FUNHEAD+1+2*i] != -SYMBOL ) break;
6✔
355
                }
356
                if ( i >= ABS(T->numind) ) break;
6✔
357
                t += t[1];
×
358
        }
359
        if ( t >= stopper ) {
6✔
360
                MesPrint("Internal error: Missing table_ function");
×
361
                Terminate(-1);
×
362
        }
363
/*
364
        Table in T. Now collect the numbers of the symbols;
365
*/
366
        termout = AT.WorkPointer;
6✔
367
        if ( T->sparse ) {
6✔
368
                for ( i = 0; i < T->totind; i++ ) {
×
369
/*
370
                        Loop over all table elements
371
*/
372
                        m = termout + 1; mm = term + 1;
×
373
                        while ( mm < t ) *m++ = *mm++;
×
374
                        r = m;
×
375
                        if ( t[1] == FUNHEAD+2 && t[FUNHEAD+1] <= -FUNCTION ) {
×
376
                                *m++ = -t[FUNHEAD+1];
×
377
                                tp = T->tablepointers + (ABS(T->numind)+TABLEEXTENSION)*i;
×
378
                                if ( T->numind < 0 ) {
×
379
                                        xx = tp[0]+1;
×
380
                                        *m++ = FUNHEAD+xx*2;
×
381
                                        for ( j = 2; j < FUNHEAD; j++ ) *m++ = 0;
×
382
                                        for ( j = 0; j < xx; j++ ) {
×
383
                                                *m++ = -SNUMBER; *m++ = *tp++;
×
384
                                        }
385
                                }
386
                                else {
387
                                        *m++ = FUNHEAD+T->numind*2;
×
388
                                        for ( j = 2; j < FUNHEAD; j++ ) *m++ = 0;
×
389
                                        for ( j = 0; j < T->numind; j++ ) {
×
390
                                                *m++ = -SNUMBER; *m++ = *tp++;
×
391
                                        }
392
                                }
393
                        }
394
                        else if ( T->numind < 0 ) {
×
395
                                tp = T->tablepointers + (ABS(T->numind)+TABLEEXTENSION)*i;
×
396
                                xx = tp[0]+1;
×
397
                                *m++ = SYMBOL; *m++ = 2+xx*2; mm = t + FUNHEAD+1;
×
398
                                for ( j = 0; j < xx; j++, mm += 2, tp++ ) {
×
399
                                        if ( *tp != 0 ) { *m++ = mm[1]; *m++ = *tp; }
×
400
                                }
401
                                r[1] = m-r;
×
402
                                if ( r[1] == 2 ) m = r;
×
403
                        }
404
                        else {
405
                                *m++ = SYMBOL; *m++ = 2+T->numind*2; mm = t + FUNHEAD+1;
×
406
                                tp = T->tablepointers + (T->numind+TABLEEXTENSION)*i;
×
407
                                for ( j = 0; j < T->numind; j++, mm += 2, tp++ ) {
×
408
                                        if ( *tp != 0 ) { *m++ = mm[1]; *m++ = *tp; }
×
409
                                }
410
                                r[1] = m-r;
×
411
                                if ( r[1] == 2 ) m = r;
×
412
                        }
413
/*
414
                        The next code replaces this old code
415

416
                        *m++ = SUBEXPRESSION;
417
                        *m++ = SUBEXPSIZE;
418
                        *m++ = *tp;
419
                        *m++ = 1;
420
                        *m++ = T->bufnum;
421
                        FILLSUB(m);
422
                        mm = t + t[1];
423

424
                        We had forgotten to take the parameters into account.
425
                        Hence the subexpression prototype for wildcards was missed
426
                        Now we slow things down a little bit, but we do not run
427
                        any risks. There is still one problem. We have not checked
428
                        that the prototype matches.
429
*/
430
                        tp = T->tablepointers + (ABS(T->numind)+TABLEEXTENSION)*i
×
431
                                        +ABS(T->numind);
×
432
                        numsubexp = tp[0]; numbuf = tp[1];
×
433
                        r = m;
×
434
#ifdef WITHPTHREADS
435
                        tp = T->prototype[identity];
436
#else
437
                        tp = T->prototype;
438
#endif
439
                        for ( j = 0; j < tp[1]; j++ ) *m++ = tp[j];
×
440
                        r[2] = numsubexp; r[4] = numbuf;
×
441
/*
442
                        r = m;
443
                        tp = T->tablepointers + (ABS(T->numind)+TABLEEXTENSION)*i;
444
                        *m++ = -t[FUNHEAD];
445
                        if ( T->numind < 0 ) {
446
                                xx = tp[0]+1;
447
                                *m++ = t[1] - xx - T->numind - 1;
448
                        }
449
                        else {
450
                                xx = T->numind;
451
                                *m++ = t[1] - 1;
452
                        }
453
                        for ( j = 2; j < FUNHEAD; j++ ) *m++ = t[j];
454
                        for ( j = 0; j < xx; j++ ) {
455
                                *m++ = -SNUMBER; *m++ = *tp++;
456
                        }
457
                        tp = t + FUNHEAD + 1 + 2*T->numind;
458
                        mm = t + t[1];
459
                        while ( tp < mm ) *m++ = *tp++;
460
                        r[1] = m-r;
461
*/
462
/*
463
                        From now on is old code
464
*/
465
                        mm = t + t[1];
×
466
                        while ( mm < tstop ) *m++ = *mm++;
×
467
                        *termout = m - termout;
×
468
                        AT.WorkPointer = m;
×
469
                        if ( Generator(BHEAD termout,level) ) {
×
470
                                MesCall("DoTableExpand");
×
471
                                return(-1);
×
472
                        }
473
                        AT.WorkPointer = termout;
×
474
                }
475
        }
476
        else {
477
                for ( i = 0; i < T->totind; i++ ) {
66✔
478
#if TABLEEXTENSION == 2
479
                        if ( T->tablepointers[i] < 0 ) continue;
480
#else
481
                        if ( T->tablepointers[TABLEEXTENSION*i] < 0 ) continue;
60✔
482
#endif
483
                        m = termout + 1; mm = term + 1;
60✔
484
                        while ( mm < t ) *m++ = *mm++;
60✔
485
                        r = m;
60✔
486
                        if ( t[1] == FUNHEAD+2 && t[FUNHEAD+1] <= -FUNCTION ) {
60✔
487
                                *m++ = -t[FUNHEAD+1];
×
488
                                *m++ = FUNHEAD+T->numind*2;
×
489
                                for ( j = 2; j < FUNHEAD; j++ ) *m++ = 0;
×
490
                                tp = T->tablepointers + (T->numind+TABLEEXTENSION)*i;
×
491
                                for ( j = 0; j < T->numind; j++ ) {
×
492
                                        if ( j > 0 ) {
×
493
                                                num = T->mm[j].mini + ( i % T->mm[j-1].size ) / T->mm[j].size;
×
494
                                        }
495
                                        else {
496
                                                num = T->mm[j].mini + i / T->mm[j].size;
×
497
                                        }
498
                                        *m++ = -SNUMBER; *m++ = num;
×
499
                                }
500
                        }
501
                        else {
502
                                *m++ = SYMBOL; *m++ = 2+T->numind*2; mm = t + FUNHEAD+1;
60✔
503
                                for ( j = 0; j < T->numind; j++, mm += 2 ) {
120✔
504
                                        if ( j > 0 ) {
60✔
505
                                                num = T->mm[j].mini + ( i % T->mm[j-1].size ) / T->mm[j].size;
×
506
                                        }
507
                                        else {
508
                                                num = T->mm[j].mini + i / T->mm[j].size;
60✔
509
                                        }
510
                                        if ( num != 0 ) { *m++ = mm[1]; *m++ = num; }
60✔
511
                                }
512
                                r[1] = m-r;
60✔
513
                                if ( r[1] == 2 ) m = r;
60✔
514
                        }
515
/*
516
                        The next code replaces this old code
517

518
                        *m++ = SUBEXPRESSION;
519
                        *m++ = SUBEXPSIZE;
520
                        *m++ = *tp;
521
                        *m++ = 1;
522
                        *m++ = T->bufnum;
523
                        FILLSUB(m);
524
                        mm = t + t[1];
525

526
                        We had forgotten to take the parameters into account.
527
                        Hence the subexpression prototype for wildcards was missed
528
                        Now we slow things down a little bit, but we do not run
529
                        any risks. There is still one problem. We have not checked
530
                        that the prototype matches.
531
*/
532
                        r = m;
60✔
533
                        *m++ = -t[FUNHEAD];
60✔
534
                        *m++ = t[1] - 1;
60✔
535
                        for ( j = 2; j < FUNHEAD; j++ ) *m++ = t[j];
120✔
536
                        for ( j = 0; j < T->numind; j++ ) {
120✔
537
                                if ( j > 0 ) {
60✔
538
                                        num = T->mm[j].mini + ( i % T->mm[j-1].size ) / T->mm[j].size;
×
539
                                }
540
                                else {
541
                                        num = T->mm[j].mini + i / T->mm[j].size;
60✔
542
                                }
543
                                *m++ = -SNUMBER; *m++ = num;
60✔
544
                        }
545
                        tp = t + FUNHEAD + 1 + 2*T->numind;
60✔
546
                        mm = t + t[1];
60✔
547
                        while ( tp < mm ) *m++ = *tp++;
60✔
548
                        r[1] = m - r;
60✔
549
/*
550
                        From now on is old code
551
*/
552
                        while ( mm < tstop ) *m++ = *mm++;
240✔
553
                        *termout = m - termout;
60✔
554
                        AT.WorkPointer = m;
60✔
555
                        if ( Generator(BHEAD termout,level) ) {
60✔
556
                                MesCall("DoTableExpand");
×
557
                                return(-1);
×
558
                        }
559
                }
560
        }
561
        return(0);
562
}
563

564
/*
565
          #] DoTableExpansion : 
566
          #[ TableBase :
567

568
        File with all the database related things.
569
        We have the routines for the generic database command
570
        TableBase,options;
571
        TB,options;
572
        Options are:
573
                Open "File.tbl";                   Open for R/W
574
                Open "File.tbl", readonly;         Open for R
575
                Create "File.tbl";                 Create for write
576
                Load "File.tbl", tablename;        Loads stubs of table
577
                Load "File.tbl";                   Loads stubs of all tables
578
                Enter "File.tbl", tablename;       Loads whole table
579
                Enter "File.tbl";                  Loads all tables
580
                Audit "File.tbl", options;         Print list of contents
581
                Replace "File.tbl", tablename;     Saves a table (with overwrite)
582
                Replace "File.tbl", table element; Saves a table element   ,,
583
                Cleanup "File.tbl";                Makes tables contingent
584
                AddTo "File.tbl" tablename;        Add if not yet there.
585
                AddTo "File.tbl" table element;    Add if not yet there.
586
                Delete "File.tbl" tablename;
587
                Delete "File.tbl" table element;
588

589
                On/Off substitute;
590
                On/Off compress "File.tbl";
591
        id tbl_(f?,?a) = f(?a);
592
        When a tbl_ is used, automatically the corresponding element is compiled
593
        at the start of the next module.
594
        if TB,On,substitute [tablename], use of table RHS (if loaded)
595
        if TB,Off,substitute [tablename], use of tbl_(table,...);
596

597

598
        Still needed: Something like OverLoad to allow loading parts of a table
599
        from more than one file. Date stamps needed? In that case we need a touch
600
        command as well.
601

602
        If we put all our diagrams inside, we have to go outside the concept
603
        of tables.
604

605
          #] TableBase : 
606
          #[ CoTableBase :
607

608
        To be followed by ,subkey
609
*/
610
static KEYWORD tboptions[] = {
611
         {"addto",           (TFUN)CoTBaddto,      0,    PARTEST}
612
        ,{"audit",           (TFUN)CoTBaudit,      0,    PARTEST}
613
        ,{"cleanup",         (TFUN)CoTBcleanup,    0,    PARTEST}
614
        ,{"create",          (TFUN)CoTBcreate,     0,    PARTEST}
615
        ,{"enter",           (TFUN)CoTBenter,      0,    PARTEST}
616
        ,{"help",            (TFUN)CoTBhelp,       0,    PARTEST}
617
        ,{"load",            (TFUN)CoTBload,       0,    PARTEST}
618
        ,{"off",             (TFUN)CoTBoff,        0,    PARTEST}
619
        ,{"on",              (TFUN)CoTBon,         0,    PARTEST}
620
        ,{"open",            (TFUN)CoTBopen,       0,    PARTEST}
621
        ,{"replace",         (TFUN)CoTBreplace,    0,    PARTEST}
622
        ,{"use",             (TFUN)CoTBuse,        0,    PARTEST}
623
};
624

625
static UBYTE *tablebasename = 0;
626

627
int CoTableBase(UBYTE *s)
30✔
628
{
629
        UBYTE *option, c, *t;
30✔
630
        int i,optlistsize = sizeof(tboptions)/sizeof(KEYWORD), error = 0;
30✔
631
        while ( *s == ' ' ) s++;
30✔
632
        if ( *s != '"' ) {
30✔
633
                if ( ( tolower(*s) == 'h' ) && ( tolower(s[1]) == 'e' )
×
634
                 && ( tolower(s[2]) == 'l' ) && ( tolower(s[3]) == 'p' )
×
635
                 && ( FG.cTable[s[4]] > 1 ) ) {
×
636
                        CoTBhelp(s);
×
637
                        return(0);
×
638
                }
639
proper:;
×
640
                MesPrint("&Proper syntax: TableBase \"filename\" options");
×
641
                return(1);
×
642
        }
643
        s++; tablebasename = s;
30✔
644
        while ( *s && *s != '"' ) s++;
252✔
645
        if ( *s != '"' ) goto proper;
30✔
646
        t = s; s++; *t = 0;
30✔
647
        while ( *s == ' ' || *s == '\t' || *s == ',' ) s++;
60✔
648
        option = s;
649
        while ( FG.cTable[*s] == 0 ) s++;
174✔
650
        c = *s; *s = 0;
30✔
651
        for ( i = 0; i < optlistsize; i++ ) {
156✔
652
                if ( StrICmp(option,(UBYTE *)(tboptions[i].name)) == 0 ) {
156✔
653
                        *s = c;
30✔
654
                        while ( *s == ',' ) s++;
54✔
655
                        error = (tboptions[i].func)(s);
30✔
656
                        *t = '"';
24✔
657
                        return(error);
24✔
658
                }
659
        }
660
        MesPrint("&Unrecognized option %s in TableBase statement",option);
×
661
        return(1);
×
662
}
663

664
/*
665
          #] CoTableBase : 
666
          #[ FlipTable :
667

668
        Flips the table between use as 'stub' and regular use
669
*/
670

671
int FlipTable(FUNCTIONS f, int type)
×
672
{
673
        TABLES T, TT;
×
674
        T = f->tabl;
×
675
        if ( ( TT = T->spare ) == 0 ) {
×
676
                MesPrint("Error: trying to change mode on a table that has no tablebase");
×
677
                return(-1);
×
678
        }
679
        if ( TT->mode == type ) f->tabl = TT;
×
680
        return(0);
681
}
682

683
/*
684
          #] FlipTable : 
685
          #[ SpareTable :
686

687
        Creates a spare element for a table. This is used in the table bases.
688
        It is a (thus far) empty copy of the TT table.
689
        By using FlipTable we can switch between them and alter which version of
690
        a table we will be using. Note that this also causes some extra work in the
691
        ResetVariables and the Globalize routines.
692
*/
693

694
int SpareTable(TABLES TT)
6✔
695
{
696
        TABLES T;
6✔
697
        T = (TABLES)Malloc1(sizeof(struct TaBlEs),"table");
6✔
698
        T->defined = T->mdefined = 0; T->sparse = TT->sparse; T->mm = 0; T->flags = 0;
6✔
699
        T->numtree = 0; T->rootnum = 0; T->MaxTreeSize = 0;
6✔
700
        T->boomlijst = 0;
6✔
701
    T->strict = TT->strict;
6✔
702
    T->bounds = TT->bounds;
6✔
703
        T->bufnum = inicbufs();
6✔
704
        T->argtail = TT->argtail;
6✔
705
        T->spare = TT;
6✔
706
        T->bufferssize = 8;
6✔
707
        T->buffers = (WORD *)Malloc1(sizeof(WORD)*T->bufferssize,"SpareTable buffers");
6✔
708
        T->buffersfill = 0;
6✔
709
        T->buffers[T->buffersfill++] = T->bufnum;
6✔
710
        T->mode = 0;
6✔
711
    T->numind = TT->numind;
6✔
712
    T->totind = 0;
6✔
713
        T->prototype = TT->prototype;
6✔
714
        T->pattern = TT->pattern;
6✔
715
        T->tablepointers = 0;
6✔
716
        T->reserved = 0;
6✔
717
        T->tablenum = 0;
6✔
718
        T->numdummies = 0;
6✔
719
        T->mm = (MINMAX *)Malloc1(ABS(T->numind)*sizeof(MINMAX),"table dimensions");
6✔
720
        T->flags = (WORD *)Malloc1(ABS(T->numind)*sizeof(WORD),"table flags");
6✔
721
        ClearTableTree(T);
6✔
722
        TT->spare = T;
6✔
723
        TT->mode = 1;
6✔
724
        return(0);
6✔
725
}
726

727
/*
728
          #] SpareTable : 
729
          #[ FindTB :
730

731
        Looks for a tablebase with the given name in the active tablebases.
732
*/
733

734
DBASE *FindTB(UBYTE *name)
30✔
735
{
736
        DBASE *d;
30✔
737
        int i;
30✔
738
        for ( i = 0; i < NumTableBases; i++ ) {
30✔
739
                d = tablebases+i;
12✔
740
                if ( d->name && ( StrCmp(name,(UBYTE *)(d->name)) == 0 ) ) { return(d); }
12✔
741
        }
742
        return(0);
743
}
744

745
/*
746
          #] FindTB : 
747
          #[ CoTBcreate :
748

749
        Creates a new tablebase.
750
        Error is when there is already an active tablebase by this name.
751
        If a file with the given name exists already, but it does not correspond
752
        to an active table base, its contents will be lost.
753
        Note that tablebasename is a static variable, defined in CoTableBase
754
*/
755

756
int CoTBcreate(UBYTE *s)
6✔
757
{
758
        DUMMYUSE(s);
6✔
759
        if ( FindTB(tablebasename) != 0 ) {
6✔
760
                MesPrint("&There is already an open TableBase with the name %s",tablebasename);
×
761
                return(-1);
×
762
        }
763
        NewDbase((char *)tablebasename,0);
6✔
764
        return(0);
6✔
765
}
766

767
/*
768
          #] CoTBcreate : 
769
          #[ CoTBopen :
770
*/
771

772
int CoTBopen(UBYTE *s)
12✔
773
{
774
        DBASE *d;
12✔
775
        MLONG rw = 1;
12✔
776

777
        SkipSpaces(&s);
12✔
778
        
779
        if ( *s ) {
12✔
780
                if ( ConsumeOption(&s,"readonly") != 0 ) {
12✔
781
                        rw = 0;
782
                } else {
783
                        MesPrint("&Invalid option for TableBase open: %s, ignoring", s);
×
784
                }
785
        }
786
        
787
        if ( ( d = FindTB(tablebasename) ) != 0 ) {
12✔
788
                MesPrint("&There is already an open TableBase with the name %s",tablebasename);
×
789
                return(-1);
×
790
        }
791
        d = GetDbase((char *)tablebasename, rw);
12✔
792
        if ( CheckTableDeclarations(d) ) return(-1);
6✔
793
        return(0);
794
}
795

796
/*
797
          #] CoTBopen : 
798
          #[ CoTBaddto :
799
*/
800

801
int CoTBaddto(UBYTE *s)
12✔
802
{
803
        GETIDENTITY
8✔
804
        DBASE *d;
12✔
805
        UBYTE *tablename, c, *t, elementstring[ELEMENTSIZE+20], *ss, *es;
12✔
806
        WORD type, funnum, lbrac, first, num, *expr, *w;
12✔
807
        TABLES T = 0;
12✔
808
        MLONG basenumber;
12✔
809
        LONG x;
12✔
810
        int i, j, error = 0, sum;
12✔
811
        if ( ( d = FindTB(tablebasename) ) == 0 ) {
12✔
812
                MesPrint("&No open tablebase with the name %s",tablebasename);
×
813
                return(-1);
×
814
        }
815
        
816
        if ( ( d->rwmode ) == 0 ) {
12✔
817
                MesPrint("&Tablebase with the name %s opened in read only mode",tablebasename);
6✔
818
                return(-1);
6✔
819
        }
820
        AO.DollarOutSizeBuffer = 32;
6✔
821
        AO.DollarOutBuffer = (UBYTE *)Malloc1(AO.DollarOutSizeBuffer,
6✔
822
                                                        "TableOutBuffer");
823
/*
824
        Now loop through the names and start adding
825
*/
826
        while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
6✔
827
        while ( *s ) {
12✔
828
                tablename = s;
6✔
829
                if ( ( s = SkipAName(s) ) == 0 ) goto tableabort;
6✔
830
                c = *s; *s = 0;
6✔
831
                if ( ( GetVar(tablename,&type,&funnum,CFUNCTION,NOAUTO) == NAMENOTFOUND )
6✔
832
                        || ( T = functions[funnum].tabl ) == 0 ) {
6✔
833
                        MesPrint("&%s should be a previously declared table",tablename);
×
834
                        *s = c; goto tableabort;
×
835
                }
836
                if ( T->sparse == 0 ) {
6✔
837
                        MesPrint("&%s should be a sparse table",tablename);
×
838
                        *s = c; goto tableabort;
×
839
                }
840
                basenumber = AddTableName(d,(char *)tablename,T);
6✔
841
                if ( T->spare && ( T->mode ==  1 ) ) T = T->spare;
6✔
842
                if ( basenumber < 0 ) basenumber = -basenumber;
6✔
843
                else if ( basenumber == 0 ) { *s = c; goto tableabort; }
6✔
844
                *s = c;
6✔
845
                if ( *s == '(' ) { /* Addition of single element */
6✔
846
                        s++; es = s;
×
847
                        for ( i = 0, w = AT.WorkPointer; i < ABS(T->numind); i++ ) {
×
848
                          ParseSignedNumber(x,s);
×
849
                      if ( FG.cTable[s[-1]] != 1 || ( *s != ',' && *s != ')' ) ) {
×
850
                                MesPrint("&Table arguments in TableBase addto statement should be numbers");
×
851
                                return(1);
×
852
                          }
853
                          *w++ = x;
×
854
                          if ( *s == ')' ) break;
×
855
                          s++;
×
856
                        }
857
                        if ( *s != ')' || i < ( ABS(T->numind) - 1 ) ) {
×
858
                          MesPrint("&Incorrect number of table arguments in TableBase addto statement. Should be %d"
×
859
                                ,ABS(T->numind));
×
860
                          error = 1;
×
861
                        }
862
                        c = *s; *s = 0;
×
863
                        i = FindTableTree(T,AT.WorkPointer,1);
×
864
                        if ( i < 0 ) {
×
865
                                MesPrint("&Element %s has not been defined",es);
×
866
                                error = 1;
×
867
                                *s++ = c;
×
868
                        }
869
                        else if ( ExistsObject(d,basenumber,(char *)es) ) {}
×
870
                        else {
871
                          int dict = AO.CurrentDictionary;
×
872
                          AO.CurrentDictionary = 0;
×
873
                          sum = i + ABS(T->numind);
×
874
/*
875
                          See also commentary below
876
*/
877
                          AO.DollarInOutBuffer = 1;
×
878
                          AO.PrintType = 1;
×
879
                          ss = AO.DollarOutBuffer;
×
880
                          *ss = 0;
×
881
                          AO.OutInBuffer = 1;
×
882
#if ( TABLEEXTENSION == 2 )
883
                          expr = cbuf[T->bufnum].rhs[T->tablepointers[sum]];
884
#else
885
                          expr = cbuf[T->tablepointers[sum+1]].rhs[T->tablepointers[sum]];
×
886
#endif
887
                          lbrac = 0; first = 0;
×
888
                          while ( *expr ) {
×
889
                                if ( WriteTerm(expr,&lbrac,first,PRINTON,0) ) {
×
890
                                                error = 1; break;
891
                                }
892
                                expr += *expr;
×
893
                          }
894
                          AO.OutInBuffer = 0;
×
895
                          AddObject(d,basenumber,(char *)es,(char *)(AO.DollarOutBuffer));
×
896
                          *s++ = c;
×
897
                          AO.CurrentDictionary = dict;
×
898
                        }
899
                }
900
                else {
901
/*
902
                Now we have to start looping through all defined elements of this table.
903
                We have to construct the arguments in text format.
904
*/
905
                  for ( i = 0; i < T->totind; i++ ) {
24✔
906
#if ( TABLEEXTENSION == 2 )
907
                        if ( !T->sparse && T->tablepointers[i] < 0 ) continue;
908
#else
909
                        if ( !T->sparse && T->tablepointers[TABLEEXTENSION*i] < 0 ) continue;
18✔
910
#endif
911
                        sum = i * ( ABS(T->numind) + TABLEEXTENSION );
18✔
912
                        t = elementstring;
18✔
913
                        for ( j = 0; j < ABS(T->numind); j++, sum++ ) {
36✔
914
                                if ( j > 0 ) *t++ = ',';
18✔
915
                                num = T->tablepointers[sum];
18✔
916
                                t = NumCopy(num,t);
18✔
917
                                if ( ( t - elementstring ) >= ELEMENTSIZE ) {
18✔
918
                                        MesPrint("&Table element specification takes more than %ld characters and cannot be handled",
×
919
                                                (MLONG)ELEMENTSIZE);
920
                                        goto tableabort;
×
921
                                }
922
                        }
923
                        if ( ExistsObject(d,basenumber,(char *)elementstring) ) { continue; }
18✔
924
/*
925
                        We have the number in basenumber and the element in elementstring.
926
                        Now we need the rhs. We can use the code from WriteDollarToBuffer.
927
                        Main complication: in the table compiler buffer there can be
928
                        brackets. The dollars do not have those......
929
*/
930
                        AO.DollarInOutBuffer = 1;
18✔
931
                        AO.PrintType = 1;
18✔
932
                        ss = AO.DollarOutBuffer;
18✔
933
                        *ss = 0;
18✔
934
                        AO.OutInBuffer = 1;
18✔
935
#if ( TABLEEXTENSION == 2 )
936
                        expr = cbuf[T->bufnum].rhs[T->tablepointers[sum]];
937
#else
938
                        expr = cbuf[T->tablepointers[sum+1]].rhs[T->tablepointers[sum]];
18✔
939
#endif
940
                        lbrac = 0; first = 0;
18✔
941
                        while ( *expr ) {
36✔
942
                                if ( WriteTerm(expr,&lbrac,first,PRINTON,0) ) {
18✔
943
                                        error = 1; break;
944
                                }
945
                                expr += *expr;
18✔
946
                        }
947
                        AO.OutInBuffer = 0;
18✔
948
                        AddObject(d,basenumber,(char *)elementstring,(char *)(AO.DollarOutBuffer));
18✔
949
                  }
950
                }
951
                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
6✔
952
        }
953
        if ( WriteIniInfo(d) ) goto tableabort;
6✔
954
        M_free(AO.DollarOutBuffer,"DollarOutBuffer");
6✔
955
        AO.DollarOutBuffer = 0;
6✔
956
        AO.DollarOutSizeBuffer = 0;
6✔
957
        return(error);        
6✔
958
tableabort:;
×
959
        M_free(AO.DollarOutBuffer,"DollarOutBuffer");
×
960
        AO.DollarOutBuffer = 0;
×
961
        AO.DollarOutSizeBuffer = 0;
×
962
        AO.OutInBuffer = 0;
×
963
        return(1);
×
964
}
965

966
/*
967
          #] CoTBaddto : 
968
          #[ CoTBenter :
969

970
        Loads the elements of the tables specified into memory and sends them
971
        one by one to the compiler as Fill statements.
972
*/
973

974
int CoTBenter(UBYTE *s)
×
975
{
976
        DBASE *d;
×
977
        MLONG basenumber;
×
978
        UBYTE *arguments, *rhs, *buffer, *t, *u, c, *tablename;
×
979
        LONG size;
×
980
        int i, j, error = 0, error1 = 0, printall = 0;
×
981
        TABLES T = 0;
×
982
        WORD type, funnum;
×
983
        int dict = AO.CurrentDictionary;
×
984
        AO.CurrentDictionary = 0;
×
985
        if ( ( d = FindTB(tablebasename) ) == 0 ) {
×
986
                MesPrint("&No open tablebase with the name %s, check for existence of file or try readonly mode when opening.",tablebasename);
×
987
                error = -1;
×
988
                goto Endofall;
×
989
        }
990
        while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
991
        if ( *s == '!' ) { printall = 1; s++; }
×
992
        while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
993
        if ( *s ) {
×
994
          while ( *s ) {
×
995
                tablename = s;
×
996
                if ( ( s = SkipAName(s) ) == 0 ) { error = 1; goto Endofall; }
×
997
                c = *s; *s = 0;
×
998
                if ( ( GetVar(tablename,&type,&funnum,CFUNCTION,NOAUTO) == NAMENOTFOUND )
×
999
                        || ( T = functions[funnum].tabl ) == 0 ) {
×
1000
                        MesPrint("&%s should be a previously declared table",tablename);
×
1001
                        basenumber = 0;
×
1002
                }
1003
                else if ( T->sparse == 0 ) {
×
1004
                        MesPrint("&%s should be a sparse table",tablename);
×
1005
                        basenumber = 0;
×
1006
                }
1007
                else { basenumber = GetTableName(d,(char *)tablename); }
×
1008
                if ( T->spare == 0 ) { SpareTable(T); }
×
1009
                if ( basenumber > 0 ) {
×
1010
                        for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
×
1011
                                for ( j = 0; j < NUMOBJECTS; j++ ) {
×
1012
                                        if ( basenumber != d->iblocks[i]->objects[j].tablenumber )
×
1013
                                                continue;
×
1014
                                        arguments = (UBYTE *)(d->iblocks[i]->objects[j].element);
×
1015
                                        rhs = (UBYTE *)ReadObject(d,basenumber,(char *)arguments);
×
1016
                                        if ( printall ) {
×
1017
                                                if ( rhs ) {
×
1018
                                                        MesPrint("%s(%s) = %s",tablename,arguments,rhs);
×
1019
                                                }
1020
                                                else {
1021
                                                        MesPrint("%s(%s) = 0",tablename,arguments);
×
1022
                                                }
1023
                                        }
1024
                                        if ( rhs ) {
×
1025
                                                u = rhs; while ( *u ) u++;
×
1026
                                                size = u-rhs;
×
1027
                                                u = arguments; while ( *u ) u++;
×
1028
                                                size += u-arguments;
×
1029
                                                u = tablename; while ( *u ) u++;
×
1030
                                                size += u-tablename;
×
1031
                                                size += 6;
×
1032
                                                buffer  = (UBYTE *)Malloc1(size,"TableBase copy");
×
1033
                                                t = tablename; u = buffer;
×
1034
                                                while ( *t ) *u++ = *t++;
×
1035
                                                *u++ = '(';
×
1036
                                                t = arguments;
×
1037
                                                while ( *t ) *u++ = *t++;
×
1038
                                                *u++ = ')'; *u++ = '=';
×
1039
                                                t = rhs;
×
1040
                                                while ( *t ) *u++ = *t++;
×
1041
                                                if ( t == rhs ) *u++ = '0';
×
1042
                                                *u++ = 0; *u = 0;
×
1043
                                                M_free(rhs,"rhs in TBenter");
×
1044

1045
                                                error1 = CoFill(buffer);
×
1046

1047
                                                if ( error1 < 0 ) goto Endofall;
×
1048
                                                if ( error1 != 0 ) error = error1;
×
1049
                                                M_free(buffer,"TableBase copy");
×
1050
                                        }
1051
                                }
1052
                        }
1053
                }
1054
                *s = c;
×
1055
                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
1056
          }
1057
        }
1058
        else {
1059
          s = (UBYTE *)(d->tablenames); basenumber = 0;
×
1060
          while ( *s ) {
×
1061
                basenumber++;
×
1062
                tablename = s; while ( *s ) s++; s++;
×
1063
                while ( *s ) s++;
×
1064
                s++;
×
1065
                if ( ( GetVar(tablename,&type,&funnum,CFUNCTION,NOAUTO) == NAMENOTFOUND )
×
1066
                        || ( T = functions[funnum].tabl ) == 0 ) {
×
1067
                        MesPrint("&%s should be a previously declared table",tablename);
×
1068
                }
1069
                else if ( T->sparse == 0 ) {
×
1070
                        MesPrint("&%s should be a sparse table",tablename);
×
1071
                }
1072
                if ( T->spare == 0 ) { SpareTable(T); }
×
1073
                for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
×
1074
                        for ( j = 0; j < NUMOBJECTS; j++ ) {
×
1075
                                if ( d->iblocks[i]->objects[j].tablenumber == basenumber ) {
×
1076
                                        arguments = (UBYTE *)(d->iblocks[i]->objects[j].element);
×
1077
                                        rhs = (UBYTE *)ReadObject(d,basenumber,(char *)arguments);
×
1078
                                        if ( printall ) {
×
1079
                                                if ( rhs ) {
×
1080
                                                        MesPrint("%s%s = %s",tablename,arguments,rhs);
×
1081
                                                }
1082
                                                else {
1083
                                                        MesPrint("%s%s = 0",tablename,arguments);
×
1084
                                                }
1085
                                        }
1086
                                        if ( rhs ) {
×
1087
                                                u = rhs; while ( *u ) u++;
×
1088
                                                size = u-rhs;
×
1089
                                                u = arguments; while ( *u ) u++;
×
1090
                                                size += u-arguments;
×
1091
                                                u = tablename; while ( *u ) u++;
×
1092
                                                size += u-tablename;
×
1093
                                                size += 6;
×
1094
                                                buffer  = (UBYTE *)Malloc1(size,"TableBase copy");
×
1095
                                                t = tablename; u = buffer;
×
1096
                                                while ( *t ) *u++ = *t++;
×
1097
                                                *u++ = '(';
×
1098
                                                t = arguments;
×
1099
                                                while ( *t ) *u++ = *t++;
×
1100
                                                *u++ = ')'; *u++ = '=';
×
1101
                                                t = rhs;
×
1102
                                                while ( *t ) *u++ = *t++;
×
1103
                                                if ( t == rhs ) *u++ = '0';
×
1104
                                                *u++ = 0; *u = 0;
×
1105
                                                M_free(rhs,"rhs in TBenter");
×
1106

1107
                                                error1 = CoFill(buffer);
×
1108

1109
                                                if ( error1 < 0 ) goto Endofall;
×
1110
                                                if ( error1 != 0 ) error = error1;
×
1111
                                                M_free(buffer,"TableBase copy");
×
1112
                                        }
1113
                                }
1114
                        }
1115
                }
1116
          }
1117
        }
1118
Endofall:;
×
1119
        AO.CurrentDictionary = dict;
×
1120
        return(error);
×
1121
}
1122

1123
/*
1124
          #] CoTBenter : 
1125
          #[ CoTestUse :
1126

1127
        Possibly to be followed by names of tables.
1128
        We make an array of TABLES structs to be tested in AC.usedtables.
1129
        Note: only sparse tables are allowed.
1130
        No arguments means all tables.
1131
*/
1132

1133
int CoTestUse(UBYTE *s)
×
1134
{
1135
        GETIDENTITY
1136
        UBYTE *tablename, c;
×
1137
        WORD type, funnum, *w;
×
1138
        TABLES T;
×
1139
        int error = 0;
×
1140
        w = AT.WorkPointer;
×
1141
        *w++ = TYPETESTUSE; *w++ = 2;
×
1142
        while ( *s ) {
×
1143
                tablename = s;
×
1144
                if ( ( s = SkipAName(s) ) == 0 ) return(1);
×
1145
                c = *s; *s = 0;
×
1146
                if ( ( GetVar(tablename,&type,&funnum,CFUNCTION,NOAUTO) == NAMENOTFOUND )
×
1147
                        || ( T = functions[funnum].tabl ) == 0 ) {
×
1148
                        MesPrint("&%s should be a previously declared table",tablename);
×
1149
                        error = 1;
×
1150
                }
1151
                else if ( T->sparse == 0 ) {
×
1152
                        MesPrint("&%s should be a sparse table",tablename);
×
1153
                        error = 1;
×
1154
                }
1155
                *w++ = funnum + FUNCTION;
×
1156
                *s = c;
×
1157
                while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
×
1158
        }
1159
        AT.WorkPointer[1] = w - AT.WorkPointer;
×
1160
/*
1161
        if ( AT.WorkPointer[1] > 2 ) {
1162
                AddNtoL(AT.WorkPointer[1],AT.WorkPointer);
1163
        }
1164
*/
1165
        AddNtoL(AT.WorkPointer[1],AT.WorkPointer);
×
1166
        return(error);
×
1167
}
1168

1169
/*
1170
          #] CoTestUse : 
1171
          #[ CheckTableDeclarations :
1172

1173
                Checks that all tables in a tablebase  have identical properties to
1174
                possible previous declarations. If they have not been declared
1175
                before, they are declared here.
1176
*/
1177

1178
int CheckTableDeclarations(DBASE *d)
6✔
1179
{
1180
        WORD type, funnum;
6✔
1181
        UBYTE *s, *ss, *t, *command = 0;
6✔
1182
        int k, error = 0, error1, i;
6✔
1183
        TABLES T;
6✔
1184
        LONG commandsize = 0;
6✔
1185

1186
        s = (UBYTE *)(d->tablenames);
6✔
1187
        for ( k = 0; k < d->topnumber; k++ ) {
12✔
1188
                if ( GetVar(s,&type,&funnum,ANYTYPE,NOAUTO) == NAMENOTFOUND ) {
6✔
1189
/*
1190
                        We have to declare the table
1191
*/
1192
                        ss = s; i = 0; while ( *ss ) { ss++; i++; } /* name */
48✔
1193
                        ss++; while ( *ss ) { ss++; i++; } /* tail */
18✔
1194
                        if ( commandsize == 0 ) {
6✔
1195
                                commandsize = i + 15;
6✔
1196
                                if ( commandsize < 100 ) commandsize = 100;
6✔
1197
                        }
1198
                        if ( (i+11) > commandsize ) {
6✔
1199
                                if ( command ) { M_free(command,"table command"); command = 0; }
×
1200
                                commandsize = i+10;
×
1201
                        }
1202
                        if ( command == 0 ) {
6✔
1203
                                command = (UBYTE *)Malloc1(commandsize,"table command");
6✔
1204
                        }
1205
                        t = command; ss = tablebase; while ( *ss ) *t++ = *ss++;
60✔
1206
                        *t++ = ','; while ( *s ) *t++ = *s++;
48✔
1207
                        s++; while ( *s ) *t++ = *s++;
18✔
1208
                        *t++ = ')'; *t = 0; s++;
6✔
1209
                        error1 = DoTable(command,1);
6✔
1210
                        if ( error1 ) error = error1;
6✔
1211
                }
1212
                else if ( ( type != CFUNCTION )
×
1213
                         || ( ( T = functions[funnum].tabl ) == 0 )
×
1214
                         || ( T->sparse == 0 ) ) {
×
1215
                        MesPrint("&%s has been declared previously, but not as a sparse table.",s);
×
1216
                        error = 1;
×
1217
                        while ( *s ) s++;
×
1218
                        s++;
×
1219
                        while ( *s ) s++;
×
1220
                        s++;
×
1221
                }
1222
                else {
1223
/*
1224
                        Test dimension and argtail. There should be an exact match.
1225
                        We are not going to rename arguments when reading the elements.
1226
*/
1227
                        ss = s;
×
1228
                        while ( *s ) s++;
×
1229
                        s++;
×
1230
                        if ( StrCmp(s,T->argtail) ) {
×
1231
                                MesPrint("&Declaration of table %s in %s different from previous declaration",ss,d->name);
×
1232
                                error = 1;
×
1233
                        }
1234
                        while ( *s ) s++;
×
1235
                        s++;
×
1236
                }
1237
        }
1238
        if ( command ) { M_free(command,"table command"); }
6✔
1239
        return(error);
6✔
1240
}
1241

1242
/*
1243
          #] CheckTableDeclarations : 
1244
          #[ CoTBload :
1245

1246
                Loads the table stubbs of the specified tables in the indicated
1247
                tablebase. Syntax:
1248
                TableBase "tablebasename.tbl" load [tablename(s)];
1249
                If no tables are specified all tables are taken.
1250
*/
1251

1252
int CoTBload(UBYTE *ss)
×
1253
{
1254
        DBASE *d;
×
1255
        UBYTE *s, *name, *t, *r, *command, *arguments, *tail;
×
1256
        LONG commandsize;
×
1257
        int num, cs, es, ns, ts, i, j, error = 0, error1;
×
1258
        if ( ( d = FindTB(tablebasename) ) == 0 ) {
×
1259
                MesPrint("&No open tablebase with the name %s",tablebasename);
×
1260
                return(-1);
×
1261
        }
1262
        commandsize = 120;
×
1263
        command = (UBYTE *)Malloc1(commandsize,"Fill command");
×
1264
        AC.vetofilling = 1;
×
1265
        if ( *ss ) {
×
1266
          while ( *ss == ',' || *ss == ' ' || *ss == '\t' ) ss++;
×
1267
          while ( *ss ) {
×
1268
                name = ss; ss = SkipAName(ss); *ss = 0;
×
1269
                s = (UBYTE *)(d->tablenames);
×
1270
                num = 0; ns = 0;
×
1271
                while ( *s ) {
×
1272
                        num++;
×
1273
                        if ( StrCmp(s,name) ) {
×
1274
                                while ( *s ) s++;
×
1275
                                s++; 
×
1276
                                while ( *s ) s++;
×
1277
                                s++;
×
1278
                                num++;
×
1279
                                continue;
×
1280
                        }
1281
                        name = s; while ( *s ) s++; ns = s-name; s++;
×
1282
                        tail = s; while ( *s ) s++; ts = s-tail; s++;
×
1283
                        tail++; while ( FG.cTable[*tail] == 1 ) tail++;
×
1284
/*
1285
                        Go through all elements
1286
*/
1287
                        for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
×
1288
                                for ( j = 0; j < NUMOBJECTS; j++ ) {
×
1289
                                        if ( d->iblocks[i]->objects[j].tablenumber == num ) {
×
1290
                                                t = arguments = (UBYTE *)(d->iblocks[i]->objects[j].element);
×
1291
                                                while ( *t ) t++;
×
1292
                                                es = t - arguments;
×
1293
                                                cs = 2*es + 2*ns + ts + 10;
×
1294
                                                if ( cs > commandsize )        {
×
1295
                                                        commandsize = 2*cs;
×
1296
                                                        if ( command ) M_free(command,"Fill command");
×
1297
                                                        command = (UBYTE *)Malloc1(commandsize,"Fill command");
×
1298
                                                }
1299
                                                r = command; t = name; while ( *t ) *r++ = *t++;
×
1300
                                                *r++ = '('; t = arguments; while ( *t ) *r++ = *t++;
×
1301
                                                *r++ = ')'; *r++ = '='; *r++ = 't'; *r++ = 'b'; *r++ = 'l';
×
1302
                                                *r++ = '_'; *r++ = '('; t = name; while ( *t ) *r++ = *t++;
×
1303
                                                *r++ = ','; t = arguments; while ( *t ) *r++ = *t++;
×
1304
                                                t = tail; while ( *t ) {
×
1305
                                                        if ( *t == '?' && r[-1] != ',' ) {
×
1306
                                                                t++;
×
1307
                                                                if ( FG.cTable[*t] == 0 || *t == '$' || *t == '[' ) {
×
1308
                                                                        t = SkipAName(t);
×
1309
                                                                        if ( *t == '[' ) {
×
1310
                                                                                SKIPBRA1(t);
×
1311
                                                                        }
1312
                                                                }
1313
                                                                else if ( *t == '{' ) {
×
1314
                                                                        SKIPBRA2(t);
×
1315
                                                                }
1316
                                                                else if ( *t ) { *r++ = *t++; continue; }
×
1317
                                                        }
1318
                                                        else *r++ = *t++;
×
1319
                                                }
1320
                                                *r++ = ')'; *r = 0;
×
1321
/*
1322
                                                Still to do: replacemode or no replacemode?
1323
*/
1324
                                                AC.vetotablebasefill = 1;
×
1325
                                                error1 = CoFill(command);
×
1326
                                                AC.vetotablebasefill = 0;
×
1327
                                                if ( error1 < 0 ) goto finishup;
×
1328
                                                if ( error1 != 0 ) error = error1;
×
1329
                                        }
1330
                                }
1331
                        }
1332
                        break;
1333
                }
1334
            while ( *ss == ',' || *ss == ' ' || *ss == '\t' ) ss++;
×
1335
          }
1336
        }
1337
        else {        /* do all of them */
1338
                s = (UBYTE *)(d->tablenames);
×
1339
                num = 0; ns = 0;
×
1340
                while ( *s ) {
×
1341
                        num++;
×
1342
                        name = s; while ( *s ) s++; ns = s-name; s++;
×
1343
                        tail = s; while ( *s ) s++; ts = s-tail; s++;
×
1344
                        tail++; while ( FG.cTable[*tail] == 1 ) tail++;
×
1345
/*
1346
                        Go through all elements
1347
*/
1348
                        for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
×
1349
                                for ( j = 0; j < NUMOBJECTS; j++ ) {
×
1350
                                        if ( d->iblocks[i]->objects[j].tablenumber == num ) {
×
1351
                                                t = arguments = (UBYTE *)(d->iblocks[i]->objects[j].element);
×
1352
                                                while ( *t ) t++;
×
1353
                                                es = t - arguments;
×
1354
                                                cs = 2*es + 2*ns + ts + 10;
×
1355
                                                if ( cs > commandsize )        {
×
1356
                                                        commandsize = 2*cs;
×
1357
                                                        if ( command ) M_free(command,"Fill command");
×
1358
                                                        command = (UBYTE *)Malloc1(commandsize,"Fill command");
×
1359
                                                }
1360
                                                r = command; t = name; while ( *t ) *r++ = *t++;
×
1361
                                                *r++ = '('; t = arguments; while ( *t ) *r++ = *t++;
×
1362
                                                *r++ = ')'; *r++ = '='; *r++ = 't'; *r++ = 'b'; *r++ = 'l';
×
1363
                                                *r++ = '_'; *r++ = '('; t = name; while ( *t ) *r++ = *t++;
×
1364
                                                *r++ = ','; t = arguments; while ( *t ) *r++ = *t++;
×
1365
                                                t = tail; while ( *t ) {
×
1366
                                                        if ( *t == '?' && r[-1] != ',' ) {
×
1367
                                                                t++;
×
1368
                                                                if ( FG.cTable[*t] == 0 || *t == '$' || *t == '[' ) {
×
1369
                                                                        t = SkipAName(t);
×
1370
                                                                        if ( *t == '[' ) {
×
1371
                                                                                SKIPBRA1(t);
×
1372
                                                                        }
1373
                                                                }
1374
                                                                else if ( *t == '{' ) {
×
1375
                                                                        SKIPBRA2(t);
×
1376
                                                                }
1377
                                                                else if ( *t ) { *r++ = *t++; continue; }
×
1378
                                                        }
1379
                                                        else *r++ = *t++;
×
1380
                                                }
1381
                                                *r++ = ')'; *r = 0;
×
1382
/*
1383
                                                Still to do: replacemode or no replacemode?
1384
*/
1385
                                                AC.vetotablebasefill = 1;
×
1386
                                                error1 = CoFill(command);
×
1387
                                                AC.vetotablebasefill = 0;
×
1388
                                                if ( error1 < 0 ) goto finishup;
×
1389
                                                if ( error1 != 0 ) error = error1;
×
1390
                                        }
1391
                                }
1392
                        }
1393
                }
1394
        }
1395
finishup:;
×
1396
        AC.vetofilling = 0;
×
1397
        if ( command ) M_free(command,"Fill command");
×
1398
        return(error);
1399
}
1400

1401
/*
1402
          #] CoTBload : 
1403
          #[ TestUse :
1404

1405
        Look for tbl_(tablename,arguments)
1406
        if tablename is encountered, check first whether the element is in
1407
        use already. If not, check in the tables in AC.usedtables.
1408
        If the element is not there, add it to AC.usedtables.
1409

1410

1411
        We need the arguments of TestUse to see for which tables it is to be done
1412
*/
1413

1414
WORD TestUse(WORD *term, WORD level)
×
1415
{
1416
        WORD *tstop, *t, *m, *tstart, tabnum;
×
1417
        WORD *funs, numfuns, error = 0;
×
1418
        TABLES T;
×
1419
        LONG i;
×
1420
        CBUF *C = cbuf+AM.rbufnum;
×
1421
        int isp;
×
1422

1423
        numfuns = C->lhs[level][1] - 2;
×
1424
        funs = C->lhs[level] + 2;
×
1425
        GETSTOP(term,tstop);
×
1426
        t = term+1;
×
1427
        while ( t < tstop ) {
×
1428
                if ( *t != TABLESTUB ) { t += t[1]; continue; }
×
1429
                tstart = t;
×
1430
                m = t + FUNHEAD;
×
1431
                t += t[1];
×
1432
                if ( *m >= -FUNCTION ) continue;
×
1433
                tabnum = -*m;
×
1434
                if ( ( T = functions[tabnum-FUNCTION].tabl ) == 0 ) continue;
×
1435
                if ( T->sparse == 0 ) continue;
×
1436
/*
1437
                Check whether we have to test this one
1438
*/
1439
                if ( numfuns > 0 ) {
×
1440
                        for ( i = 0; i < numfuns; i++ ) {
×
1441
                                if ( tabnum == funs[i] ) break;
×
1442
                        }
1443
                        if ( i >= numfuns && numfuns > 0 ) continue;
×
1444
                }
1445
/*
1446
                Test whether the element has been defined already.
1447
                        If not, mark it as used.
1448
                Note: we only allow sparse tables (for now)
1449
*/
1450
                m++;
×
1451
                for ( i = 0; i < ABS(T->numind); i++, m += 2 ) {
×
1452
                        if ( m >= t || *m != -SNUMBER ) break;
×
1453
                }
1454
                if ( ( i == ABS(T->numind) ) &&
×
1455
                 ( ( isp = FindTableTree(T,tstart+FUNHEAD+1,2) ) >= 0 ) ) {
×
1456
                        if ( ( T->tablepointers[isp+ABS(T->numind)+4] & ELEMENTLOADED ) == 0 ) {
×
1457
                                        T->tablepointers[isp+ABS(T->numind)+4] |= ELEMENTUSED;
×
1458
                        }
1459
                }
1460
                else {
1461
                        MesPrint("TestUse: Encountered a table element inside tbl_ that does not correspond to a tablebase element");
×
1462
                        error = -1;
×
1463
                }
1464
        }
1465
        return(error);
×
1466
}
1467

1468
/*
1469
          #] TestUse : 
1470
          #[ CoTBaudit :
1471
*/
1472

1473
int CoTBaudit(UBYTE *s)
×
1474
{
1475
        DBASE *d;
×
1476
        UBYTE *name, *tail;
×
1477
        int i, j, error = 0, num;
×
1478

1479
        if ( ( d = FindTB(tablebasename) ) == 0 ) {
×
1480
                MesPrint("&No open tablebase with the name %s",tablebasename);
×
1481
                return(-1);
×
1482
        }
1483
        while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
1484
        while ( *s ) {
×
1485
/*
1486
                Get the options here
1487
                They will mainly involve the sorting of the output.
1488
*/
1489
                s++;
×
1490
        }
1491
        s = (UBYTE *)(d->tablenames); num = 0;
×
1492
        while ( *s ) {
×
1493
                num++;
×
1494
                name = s; while ( *s ) s++; s++;
×
1495
                tail = s; while ( *s ) s++; s++;
×
1496
                MesPrint("Table,sparse,%s%s)",name,tail);
×
1497
                for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
×
1498
                        for ( j = 0; j < NUMOBJECTS; j++ ) {
×
1499
                                if ( d->iblocks[i]->objects[j].tablenumber == num ) {
×
1500
                                        MesPrint("    %s(%s)",name,d->iblocks[i]->objects[j].element);
×
1501
                                }
1502
                        }
1503
                }
1504
        }
1505
        return(error);
1506
}
1507

1508
/*
1509
          #] CoTBaudit : 
1510
          #[ CoTBon :
1511
*/
1512

1513
int CoTBon(UBYTE *s)
×
1514
{
1515
        DBASE *d;
×
1516
        UBYTE *ss, c;
×
1517
        int error = 0;
×
1518
        if ( ( d = FindTB(tablebasename) ) == 0 ) {
×
1519
                MesPrint("&No open tablebase with the name %s",tablebasename);
×
1520
                return(-1);
×
1521
        }
1522
        while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
1523
        while ( *s ) {
×
1524
                ss = SkipAName(s);
×
1525
                c = *ss; *ss = 0;
×
1526
                if ( StrICmp(s,(UBYTE *)("compress")) == 0 ) {
×
1527
                        d->mode &= ~NOCOMPRESS;
×
1528
                }
1529
                else {
1530
                        MesPrint("&subkey %s not defined in TableBase On statement");
×
1531
                        error = 1;
×
1532
                }
1533
                *ss = c; s = ss;
×
1534
                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
1535
        }
1536
        return(error);
1537
}
1538

1539
/*
1540
          #] CoTBon : 
1541
          #[ CoTBoff :
1542
*/
1543

1544
int CoTBoff(UBYTE *s)
×
1545
{
1546
        DBASE *d;
×
1547
        UBYTE *ss, c;
×
1548
        int error = 0;
×
1549
        if ( ( d = FindTB(tablebasename) ) == 0 ) {
×
1550
                MesPrint("&No open tablebase with the name %s",tablebasename);
×
1551
                return(-1);
×
1552
        }
1553
        while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
1554
        while ( *s ) {
×
1555
                ss = SkipAName(s);
×
1556
                c = *ss; *ss = 0;
×
1557
                if ( StrICmp(s,(UBYTE *)("compress")) == 0 ) {
×
1558
                        d->mode |= NOCOMPRESS;
×
1559
                }
1560
                else {
1561
                        MesPrint("&subkey %s not defined in TableBase Off statement");
×
1562
                        error = 1;
×
1563
                }
1564
                *ss = c; s = ss;
×
1565
                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
1566
        }
1567
        return(error);
1568
}
1569

1570
/*
1571
          #] CoTBoff : 
1572
          #[ CoTBcleanup :
1573
*/
1574

1575
int CoTBcleanup(UBYTE *s)
×
1576
{
1577
        DUMMYUSE(s);
×
1578
        MesPrint("&TableBase Cleanup statement not yet implemented");
×
1579
        return(1);
×
1580
}
1581

1582
/*
1583
          #] CoTBcleanup : 
1584
          #[ CoTBreplace :
1585
*/
1586

1587
int CoTBreplace(UBYTE *s)
×
1588
{
1589
        DUMMYUSE(s);
×
1590
        MesPrint("&TableBase Replace statement not yet implemented");
×
1591
        return(1);
×
1592
}
1593

1594
/*
1595
          #] CoTBreplace : 
1596
          #[ CoTBuse :
1597

1598
        Here the actual table use as determined in TestUse causes the needed
1599
        table elements to be loaded
1600
*/
1601

1602
int CoTBuse(UBYTE *s)
×
1603
{
1604
        GETIDENTITY
1605
        DBASE *d;
×
1606
        MLONG basenumber;
×
1607
        UBYTE *arguments, *rhs, *buffer, *t, *u, c, *tablename, *p;
×
1608
        LONG size, sum, x;
×
1609
        int i, j, error = 0, error1 = 0, k;
×
1610
        TABLES T = 0;
×
1611
        WORD type, funnum, mode, *w;
×
1612
        if ( ( d = FindTB(tablebasename) ) == 0 ) {
×
1613
                MesPrint("&No open tablebase with the name %s",tablebasename);
×
1614
                return(-1);
×
1615
        }
1616
        while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
1617
        if ( *s ) {
×
1618
          while ( *s ) {
×
1619
                tablename = s;
×
1620
                if ( ( s = SkipAName(s) ) == 0 ) return(1);
×
1621
                c = *s; *s = 0;
×
1622
                if ( ( GetVar(tablename,&type,&funnum,CFUNCTION,NOAUTO) == NAMENOTFOUND )
×
1623
                        || ( T = functions[funnum].tabl ) == 0 ) {
×
1624
                        MesPrint("&%s should be a previously declared table",tablename);
×
1625
                        basenumber = 0;
×
1626
                }
1627
                else if ( T->sparse == 0 ) {
×
1628
                        MesPrint("&%s should be a sparse table",tablename);
×
1629
                        basenumber = 0;
×
1630
                }
1631
                else { basenumber = GetTableName(d,(char *)tablename); }
×
1632
/*                if ( T->spare == 0 ) { SpareTable(T); } */
1633
                if ( basenumber > 0 ) {
×
1634
                        for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
×
1635
                                for ( j = 0; j < NUMOBJECTS; j++ ) {
×
1636
                                        if ( d->iblocks[i]->objects[j].tablenumber != basenumber ) continue;
×
1637
                                        arguments = p = (UBYTE *)(d->iblocks[i]->objects[j].element);
×
1638
/*
1639
                                        Now translate the arguments and see whether we need
1640
                                        this one....
1641
*/
1642
                                        for ( k = 0, w = AT.WorkPointer; k < ABS(T->numind); k++ ) {
×
1643
                                                ParseSignedNumber(x,p);
×
1644
                                                *w++ = x; p++;
×
1645
                                        }
1646
                                        sum = FindTableTree(T,AT.WorkPointer,1);
×
1647
                                        if ( sum < 0 ) {
×
1648
                                                MesPrint("Table %s in tablebase %s has not been loaded properly"
×
1649
                                                                ,tablename,tablebasename);
1650
                                                error = 1;
×
1651
                                                continue;
×
1652
                                        }
1653
                                        sum += ABS(T->numind) + 4;
×
1654
                                        mode = T->tablepointers[sum];
×
1655
                                        if ( ( mode & ELEMENTLOADED ) == ELEMENTLOADED ) {
×
1656
                                                T->tablepointers[sum] &= ~ELEMENTUSED;
×
1657
                                                continue;
×
1658
                                        }
1659
                                        if ( ( mode & ELEMENTUSED ) == 0 ) continue;
×
1660
/*
1661
                                        We need this one!
1662
*/
1663
                                        rhs = (UBYTE *)ReadijObject(d,i,j,(char *)arguments);
×
1664
                                        if ( rhs ) {
×
1665
                                                u = rhs; while ( *u ) u++;
×
1666
                                                size = u-rhs;
×
1667
                                                u = arguments; while ( *u ) u++;
×
1668
                                                size += u-arguments;
×
1669
                                                u = tablename; while ( *u ) u++;
×
1670
                                                size += u-tablename;
×
1671
                                                size += 6;
×
1672
                                                buffer  = (UBYTE *)Malloc1(size,"TableBase copy");
×
1673
                                                t = tablename; u = buffer;
×
1674
                                                while ( *t ) *u++ = *t++;
×
1675
                                                *u++ = '(';
×
1676
                                                t = arguments;
×
1677
                                                while ( *t ) *u++ = *t++;
×
1678
                                                *u++ = ')'; *u++ = '=';
×
1679
                                                t = rhs;
×
1680
                                                while ( *t ) *u++ = *t++;
×
1681
                                                if ( t == rhs ) { *u++ = '0'; }
×
1682
                                                *u++ = 0; *u = 0;
×
1683
                                                M_free(rhs,"rhs in TBuse xxx");
×
1684

1685
                                                error1 = CoFill(buffer);
×
1686

1687
                                                if ( error1 < 0 ) { return(error); }
×
1688
                                                if ( error1 != 0 ) error = error1;
×
1689
                                                M_free(buffer,"TableBase copy");
×
1690
                                        }
1691
                                        T->tablepointers[sum] &= ~ELEMENTUSED;
×
1692
                                        T->tablepointers[sum] |= ELEMENTLOADED;
×
1693
                                }
1694
                        }
1695
                }
1696
                *s = c;
×
1697
                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
1698
          }
1699
        }
1700
        else {
1701
          s = (UBYTE *)(d->tablenames); basenumber = 0;
×
1702
          while ( *s ) {
×
1703
                basenumber++;
×
1704
                tablename = s;
×
1705
                while ( *s ) s++;
×
1706
                s++;
×
1707
                while ( *s ) s++;
×
1708
                s++;
×
1709
                if ( ( GetVar(tablename,&type,&funnum,CFUNCTION,NOAUTO) == NAMENOTFOUND )
×
1710
                        || ( T = functions[funnum].tabl ) == 0 ) {
×
1711
                        MesPrint("&%s should be a previously declared table",tablename);
×
1712
                }
1713
                else if ( T->sparse == 0 ) {
×
1714
                        MesPrint("&%s should be a sparse table",tablename);
×
1715
                }
1716
        if ( T->spare && T->mode == 0 ) {
×
1717
                MesPrint("In table %s we have a problem with stubb orders in CoTBuse",tablename);
×
1718
                error = -1;
×
1719
        }
1720
/*                if ( T->spare == 0 ) { SpareTable(T); } */
1721
                for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
×
1722
                        for ( j = 0; j < NUMOBJECTS; j++ ) {
×
1723
                                if ( d->iblocks[i]->objects[j].tablenumber == basenumber ) {
×
1724
                                        arguments = p = (UBYTE *)(d->iblocks[i]->objects[j].element);
×
1725
/*
1726
                                        Now translate the arguments and see whether we need
1727
                                        this one....
1728
*/
1729
                                        for ( k = 0, w = AT.WorkPointer; k < ABS(T->numind); k++ ) {
×
1730
                                                ParseSignedNumber(x,p);
×
1731
                                                *w++ = x; p++;
×
1732
                                        }
1733
                                        sum = FindTableTree(T,AT.WorkPointer,1);
×
1734
                                        if ( sum < 0 ) {
×
1735
                                                MesPrint("Table %s in tablebase %s has not been loaded properly"
×
1736
                                                                ,tablename,tablebasename);
1737
                                                error = 1;
×
1738
                                                continue;
×
1739
                                        }
1740
                                        sum += ABS(T->numind) + 4;
×
1741
                                        mode = T->tablepointers[sum];
×
1742
                                        if ( ( mode & ELEMENTLOADED ) == ELEMENTLOADED ) {
×
1743
                                                T->tablepointers[sum] &= ~ELEMENTUSED;
×
1744
                                                continue;
×
1745
                                        }
1746
                                        if ( ( mode & ELEMENTUSED ) == 0 ) continue;
×
1747
/*
1748
                                        We need this one!
1749
*/
1750
                                        rhs = (UBYTE *)ReadijObject(d,i,j,(char *)arguments);
×
1751
                                        if ( rhs ) {
×
1752
                                                u = rhs; while ( *u ) u++;
×
1753
                                                size = u-rhs;
×
1754
                                                u = arguments; while ( *u ) u++;
×
1755
                                                size += u-arguments;
×
1756
                                                u = tablename; while ( *u ) u++;
×
1757
                                                size += u-tablename;
×
1758
                                                size += 6;
×
1759
                                                buffer  = (UBYTE *)Malloc1(size,"TableBase copy");
×
1760
                                                t = tablename; u = buffer;
×
1761
                                                while ( *t ) *u++ = *t++;
×
1762
                                                *u++ = '(';
×
1763
                                                t = arguments;
×
1764
                                                while ( *t ) *u++ = *t++;
×
1765
                                                *u++ = ')'; *u++ = '=';
×
1766

1767
                                                t = rhs;
×
1768
                                                while ( *t ) *u++ = *t++;
×
1769
                                                if ( t == rhs ) { *u++ = '0'; }
×
1770
                                                *u++ = 0; *u = 0;
×
1771
                                                M_free(rhs,"rhs in TBuse");
×
1772

1773
                                                error1 = CoFill(buffer);
×
1774

1775
                                                if ( error1 < 0 ) { return(error); }
×
1776
                                                if ( error1 != 0 ) error = error1;
×
1777
                                                M_free(buffer,"TableBase copy");
×
1778
                                        }
1779
                                        T->tablepointers[sum] &= ~ELEMENTUSED;
×
1780
                                        T->tablepointers[sum] |= ELEMENTLOADED;
×
1781
                                }
1782
                        }
1783
                }
1784
          }
1785
        }
1786
        return(error);
1787
}
1788

1789
/*
1790
          #] CoTBuse : 
1791
          #[ CoApply :
1792

1793
        Possibly to be followed by names of tables.
1794
*/
1795

1796
int CoApply(UBYTE *s)
×
1797
{
1798
        GETIDENTITY
1799
        UBYTE *tablename, c;
×
1800
        WORD type, funnum, *w;
×
1801
        TABLES T;
×
1802
        LONG maxtogo = MAXPOSITIVE;
×
1803
        int error = 0;
×
1804
        w = AT.WorkPointer;
×
1805
        if ( FG.cTable[*s] == 1 ) {
×
1806
                maxtogo = 0;
1807
                while ( FG.cTable[*s] == 1 ) {
×
1808
                        maxtogo = maxtogo*10 + (*s-'0');
×
1809
                        s++;
×
1810
                }
1811
                while ( *s == ',' ) s++;
×
1812
                if ( maxtogo > MAXPOSITIVE || maxtogo < 0 ) maxtogo = MAXPOSITIVE;
×
1813
        }
1814
        *w++ = TYPEAPPLY; *w++ = 3; *w++ = maxtogo;
×
1815
        while ( *s ) {
×
1816
                tablename = s;
×
1817
                if ( ( s = SkipAName(s) ) == 0 ) return(1);
×
1818
                c = *s; *s = 0;
×
1819
                if ( ( GetVar(tablename,&type,&funnum,CFUNCTION,NOAUTO) == NAMENOTFOUND )
×
1820
                        || ( T = functions[funnum].tabl ) == 0 ) {
×
1821
                        MesPrint("&%s should be a previously declared table",tablename);
×
1822
                        error = 1;
×
1823
                }
1824
                else if ( T->sparse == 0 ) {
×
1825
                        MesPrint("&%s should be a sparse table",tablename);
×
1826
                        error = 1;
×
1827
                }
1828
                *w++ = funnum + FUNCTION;
×
1829
                *s = c;
×
1830
                while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
×
1831
        }
1832
        AT.WorkPointer[1] = w - AT.WorkPointer;
×
1833
/*
1834
        if ( AT.WorkPointer[1] > 2 ) {
1835
                AddNtoL(AT.WorkPointer[1],AT.WorkPointer);
1836
        }
1837
*/
1838
        AddNtoL(AT.WorkPointer[1],AT.WorkPointer);
×
1839
/*
1840
        AT.WorkPointer[0] = TYPEAPPLYRESET;
1841
        AddNtoL(AT.WorkPointer[1],AT.WorkPointer);
1842
*/
1843
        return(error);
×
1844
}
1845

1846
/*
1847
          #] CoApply : 
1848
          #[ CoTBhelp :
1849
*/
1850

1851
char *helptb[] = {
1852
         "The TableBase statement is used as follows:"
1853
        ,"TableBase \"file.tbl\" keyword subkey(s)"
1854
        ,"    in which we have"
1855
        ,"Keyword   Subkey(s)   Action"
1856
        ,"open                 Opens file.tbl for R/W"
1857
        ,"create               Creates file.tbl for R/W. Old contents are lost"
1858
        ,"load                 Loads all stubs of all tables"
1859
        ,"load    tablename(s) Loads all stubs the tables mentioned"
1860
        ,"enter                Loads all stubs and rhs of all tables"
1861
        ,"enter   tablename(s) Loads all stubs and rhs of the tables mentioned"
1862
        ,"audit                Prints list of contents"
1863
/*        ,"replace tablename    saves a table (with overwrite)" */
1864
/*        ,"replace tableelement saves a table element (with overwrite)" */
1865
/*        ,"cleanup              makes tables contingent" */
1866
        ,"addto   tablename    adds all elements if not yet there"
1867
        ,"addto   tableelement adds element if not yet there"
1868
/*        ,"delete  tablename    removes table from tablebase" */
1869
/*        ,"delete  tableelement removes element from tablebase" */
1870
        ,"on      compress     elements are stored in gzip format (default)"
1871
        ,"off     compress     elements are stored in uncompressed format"
1872
        ,"use                  compiles all needed elements"
1873
        ,"use     tablename(s) compiles all needed elements of these tables"
1874
        ,""
1875
        ,"Related commands are:"
1876
        ,"testuse              marks which tbl_ elements occur for all tables"
1877
        ,"testuse tablename(s) marks which tbl_ elements occur for given tables"
1878
        ,"apply                replaces tbl_ if rhs available"
1879
        ,"apply   tablename(s) replaces tbl_ for given tables if rhs available"
1880
        ,""
1881
                };
1882

1883
int CoTBhelp(UBYTE *s)
×
1884
{
1885
        int i, ii = sizeof(helptb)/sizeof(char *);
×
1886
        DUMMYUSE(s);
×
1887
        for ( i = 0; i < ii; i++ ) MesPrint("%s",helptb[i]);
×
1888
        return(0);
×
1889
}
1890

1891
/*
1892
          #] CoTBhelp : 
1893
          #[ ReWorkT :
1894

1895
        Replaces the STUBBS of the functions in the list.
1896
        This gains one space. Hence we have to be very careful
1897
*/
1898

NEW
1899
void ReWorkT(WORD *term, WORD *funs, WORD numfuns)
×
1900
{
1901
        WORD *tstop, *tend, *m, *t, *tt, *mm, *mmm, *r, *rr;
×
1902
        int i, j;
×
1903
        tend = term + *term; tstop = tend - ABS(tend[-1]);
×
1904
        m = t = term+1;
×
1905
        while ( t < tstop ) {
×
1906
                if ( *t == TABLESTUB ) {
×
1907
                        for ( i = 0; i < numfuns; i++ ) {
×
1908
                                if ( -t[FUNHEAD] == funs[i] ) break;
×
1909
                        }
1910
                        if ( numfuns == 0 || i < numfuns ) { /* Hit */
×
1911
                                i = t[1] - 1;
×
1912
                                *m++ = -t[FUNHEAD]; *m++ = i; t += 2; i -= FUNHEAD;
×
1913
                                if ( m < t ) { for ( j = 0; j < FUNHEAD-2; j++ ) *m++ = *t++; }
×
1914
                                else { m += FUNHEAD-2; t += FUNHEAD-2; }
×
1915
                                t++;
×
1916
                                while ( i-- > 0 ) { *m++ = *t++; }
×
1917
                                tt = t; mm = m;
×
1918
                                if ( mm < tt ) {
×
1919
                                        while ( tt < tend ) *mm++ = *tt++;
×
1920
                                        *term = mm - term;
×
1921
                                        tend = term + *term; tstop = tend - ABS(tend[-1]);
×
1922
                                        t = m;
×
1923
                                }
1924
                        }
1925
                        else { goto inc; }
×
1926
                }
1927
                else if ( *t >= FUNCTION ) {
×
1928
                        tt = t + t[1];
×
1929
                        mm = m;
×
1930
                        for ( j = 0; j < FUNHEAD; j++ ) {
×
1931
                                if ( m == t ) { m++; t++; }
×
1932
                                else *m++ = *t++;
×
1933
                        }
1934
                        while ( t < tt ) {
×
1935
                                if ( *t <= -FUNCTION ) {
×
1936
                                        if ( m == t ) { m++; t++; }
×
1937
                                        else *m++ = *t++;
×
1938
                                }
1939
                                else if ( *t < 0 ) {
×
1940
                                        if ( m == t ) { m += 2; t += 2; }
×
1941
                                        else { *m++ = *t++; *m++ = *t++; }
×
1942
                                }
1943
                                else {
1944
                                        rr = t + *t; mmm = m;
×
1945
                                        for ( j = 0; j < ARGHEAD; j++ ) {
×
1946
                                                if ( m == t ) { m++; t++; }
×
1947
                                                else *m++ = *t++;
×
1948
                                        }
1949
                                        while ( t < rr ) {
×
1950
                                                r = t + *t;
×
1951
                                                ReWorkT(t,funs,numfuns);
×
1952
                                                j = *t;
×
1953
                                                if ( m == t ) { m += j; t += j; }
×
1954
                                                else { while ( j-- >= 0 ) *m++ = *t++; }
×
1955
                                                t = r;
1956
                                        }
1957
                                        *mmm = m-mmm;
×
1958
                                }
1959
                        }
1960
                        mm[1] = m - mm;
×
1961
                        t = tt;
×
1962
                }
1963
                else {
1964
inc:                j = t[1];
×
1965
                        if ( m < t ) { while ( j-- >= 0 ) *m++ = *t++; }
×
1966
                        else { m += j; t += j; }
×
1967
                }
1968
        }
1969
        if ( m < t ) {
×
1970
                while ( t < tend ) *m++ = *t++;
×
1971
                *term = m - term;
×
1972
        }
1973
}
×
1974

1975
/*
1976
          #] ReWorkT : 
1977
          #[ Apply :
1978
*/
1979

1980
WORD Apply(WORD *term, WORD level)
×
1981
{
1982
        WORD *funs, numfuns;
×
1983
        TABLES T;
×
1984
        int i, j;
×
1985
        CBUF *C = cbuf+AM.rbufnum;
×
1986
/*
1987
        Point the tables in the proper direction
1988
*/
1989
        numfuns = C->lhs[level][1] - 2;
×
1990
        funs = C->lhs[level] + 2;
×
1991
        if ( numfuns > 0 ) {
×
1992
                for ( i = MAXBUILTINFUNCTION-FUNCTION; i < AC.FunctionList.num; i++ ) {
×
1993
                        if ( ( T = functions[i].tabl ) != 0 ) {
×
1994
                                for ( j = 0; j < numfuns; j++ ) {
×
1995
                                        if ( i == (funs[j]-FUNCTION) && T->spare ) {
×
1996
                                                FlipTable(&(functions[i]),0);
×
1997
                                                break;
×
1998
                                        }
1999
                                }
2000
                        }
2001
                }
2002
        }
2003
        else {
2004
                for ( i = MAXBUILTINFUNCTION-FUNCTION; i < AC.FunctionList.num; i++ ) {
×
2005
                        if ( ( T = functions[i].tabl ) != 0 ) {
×
2006
                                if ( T->spare ) FlipTable(&(functions[i]),0);
×
2007
                        }
2008
                }
2009
        }
2010
/*
2011
        Now the replacements everywhere of
2012
                id tbl_(table,?a) = table(?a);
2013
        Actually, this has to be done recursively.
2014
        Note that we actually gain one space. 
2015
*/
2016
        ReWorkT(term,funs,numfuns);
×
2017
        return(0);
×
2018
}
2019

2020
/*
2021
          #] Apply : 
2022
          #[ ApplyExec :
2023

2024
        Replaces occurrences of tbl_(table,indices,pattern) by the proper
2025
        rhs of table(indices,pattern). It does this up to maxtogo times
2026
        in the given term. It starts with the occurrences inside the
2027
        arguments of functions. If necessary it finishes at groundlevel.
2028
        An infinite number of tries is indicated by maxtogo = 2^15-1 or 2^31-1.
2029
        The occurrences are replaced by subexpressions. This allows TestSub
2030
        to finish the job properly.
2031

2032
        The main trick here is T = T->spare which turns to the proper rhs.
2033

2034
        The return value is the number of substitutions that can still be made
2035
        based on maxtogo. Hence, if the returnvalue is different from maxtogo
2036
        there was a substitution.
2037
*/
2038

2039
int ApplyExec(WORD *term, int maxtogo, WORD level)
×
2040
{
2041
        GETIDENTITY
2042
        WORD rhsnumber, *Tpattern, *funs, numfuns, funnum;
×
2043
        WORD ii, *t, *t1, *w, *p, *m, *m1, *u, *r, tbufnum, csize, wilds;
×
2044
        NESTING NN;
×
2045
        int i, j, isp, stilltogo;
×
2046
        CBUF *C;
×
2047
        TABLES T;
×
2048
/*
2049
        Startup. We need NestPoin for when we have to replace something deep down.
2050
*/
2051
        t = term;
×
2052
        m = t + *t;
×
2053
        csize = ABS(m[-1]);
×
2054
        m -= csize;
×
2055
        AT.NestPoin->termsize = t;
×
2056
        if ( AT.NestPoin == AT.Nest ) AN.EndNest = t + *t;
×
2057
        t++;
×
2058
/*
2059
        First we look inside function arguments. Also when clean!
2060
*/
2061
        while ( t < m ) {
×
2062
                if ( *t < FUNCTION ) { t += t[1]; continue; }
×
2063
                if ( functions[*t-FUNCTION].spec > 0 ) { t += t[1]; continue; }
×
2064
                AT.NestPoin->funsize = t;
×
2065
                r = t + t[1];
×
2066
                t += FUNHEAD;
×
2067
                while ( t < r ) {
×
2068
                        if ( *t < 0 ) { NEXTARG(t); continue; }
×
2069
                        AT.NestPoin->argsize = t1 = t;
×
2070
                        u = t + *t;
×
2071
                        t += ARGHEAD;
×
2072
                        AT.NestPoin++;
×
2073
                        while ( t < u ) {
×
2074
/*
2075
                                Now we loop over the terms inside a function argument
2076
                                This defines a recursion and we have to call ApplyExec again.
2077
                                The real problem is when we catch something and we have
2078
                                to insert a subexpression pointer. This may use more or
2079
                                less space and the whole term has to be readjusted.
2080
                                This is why we have the NestPoin variables. They tell us
2081
                                where the sizes of the term, the function and the arguments
2082
                                are sitting, and also where the dirty flags are.
2083
                                This readjusting is of course done in the groundlevel code.
2084
                                Here we worry abound the maxtogo count.
2085
*/
2086
                                stilltogo = ApplyExec(t,maxtogo,level);
×
2087
                                if ( stilltogo != maxtogo ) {
×
2088
                                        if ( stilltogo <= 0 ) {
×
2089
                                                AT.NestPoin--;
×
2090
                                                return(stilltogo);
×
2091
                                        }
2092
                                        maxtogo = stilltogo;
×
2093
                                        u = t1 + *t1;
×
2094
                                        m = term + *term - csize;
×
2095
                                }
2096
                                t += *t;
×
2097
                        }
2098
                        AT.NestPoin--;
×
2099
                }
2100
        }
2101
/*
2102
        Now we look at the ground level
2103
*/
2104
        C = cbuf+AM.rbufnum;
×
2105
        t = term + 1;
×
2106
        while ( t < m ) {
×
2107
                if ( *t != TABLESTUB ) { t += t[1]; continue; }
×
2108
                funnum = -t[FUNHEAD];
×
2109
                if ( ( funnum < FUNCTION )
×
2110
                  || ( funnum >= FUNCTION+WILDOFFSET )
2111
                  || ( ( T = functions[funnum-FUNCTION].tabl ) == 0 )
×
2112
                  || ( T->sparse == 0 )
×
2113
                  || ( T->spare == 0 ) ) { t += t[1]; continue; }
×
2114
                numfuns = C->lhs[level][1] - 3;
×
2115
                funs = C->lhs[level] + 3;
×
2116
                if ( numfuns > 0 ) {
×
2117
                        for ( i = 0; i < numfuns; i++ ) {
×
2118
                                if ( funs[i] == funnum ) break;
×
2119
                        }
2120
                        if ( i >= numfuns ) { t += t[1]; continue; }
×
2121
                }
2122
                r = t + t[1];
×
2123
                AT.NestPoin->funsize = t + 1;
×
2124
                t1 = t;
×
2125
                t += FUNHEAD + 1;
×
2126
/*
2127
                Test whether the table catches
2128
                Test 1: index arguments and range. isp will be the number
2129
                        of the element in the table.
2130
*/
2131
                T = T->spare;
×
2132
#ifdef WITHPTHREADS
2133
                Tpattern = T->pattern[identity];
2134
#else
2135
                Tpattern = T->pattern;
2136
#endif
2137
                p = Tpattern+FUNHEAD+1;
×
2138
                for ( i = 0; i < ABS(T->numind); i++, t += 2 ) {
×
2139
                        if ( *t != -SNUMBER ) break;
×
2140
                }
2141
                if ( i < ABS(T->numind) ) { t = r; continue; }
×
2142
                isp = FindTableTree(T,t1+FUNHEAD+1,2);
×
2143
                if ( isp < 0 ) { t = r; continue; }
×
2144
                rhsnumber = T->tablepointers[isp+ABS(T->numind)];
×
2145
#if ( TABLEEXTENSION == 2 )
2146
                tbufnum = T->bufnum;
2147
#else
2148
                tbufnum = T->tablepointers[isp+ABS(T->numind)+1];
×
2149
#endif
2150
                t = t1+FUNHEAD+2;
×
2151
                ii = ABS(T->numind);
×
2152
                while ( --ii >= 0 ) {
×
2153
                        *p = *t; t += 2; p += 2;
×
2154
                }
2155
/*
2156
                If there are more arguments we have to do some
2157
                pattern matching. This should be easy. We adapted the
2158
                pattern, so that the array indices match already.
2159
*/
2160
#ifdef WITHPTHREADS
2161
                AN.FullProto = T->prototype[identity];
2162
#else
2163
                AN.FullProto = T->prototype;
2164
#endif
2165
                AN.WildValue = AN.FullProto + SUBEXPSIZE;
×
2166
                AN.WildStop = AN.FullProto+AN.FullProto[1];
×
2167
                ClearWild(BHEAD0);
×
2168
                AN.RepFunNum = 0;
×
2169
                AN.RepFunList = AN.EndNest;
×
2170
            AT.WorkPointer = (WORD *)(((UBYTE *)(AN.EndNest)) + AM.MaxTer/2);
×
2171
/*
2172
                The RepFunList is after the term but not very relevant.
2173
                We need because MatchFunction uses it
2174
*/
2175
                if ( AT.WorkPointer + t1[1] >= AT.WorkTop ) { MesWork(); }
×
2176
                wilds = 0;
×
2177
                w = AT.WorkPointer;
×
2178
                *w++ = -t1[FUNHEAD];
×
2179
                *w++ = t1[1] - 1;
×
2180
                for ( i = 2; i < FUNHEAD; i++ ) *w++ = t1[i];
×
2181
                t = t1 + FUNHEAD+1;
2182
                while ( t < r ) *w++ = *t++;
×
2183
                t = AT.WorkPointer;
×
2184
                AT.WorkPointer = w;
×
2185
                if ( MatchFunction(BHEAD Tpattern,t,&wilds) > 0 ) {
×
2186
/*
2187
                        Here we caught one. Now we should worry about:
2188
                        1: inserting the subexpression pointer with its wildcards
2189
                        2: NestPoin because we may not be at the lowest level
2190
                        The function starts at t1.
2191
*/
2192
#ifdef WITHPTHREADS
2193
                        m1 = T->prototype[identity];
2194
#else
2195
                        m1 = T->prototype;
2196
#endif
2197
                        m1[2] = rhsnumber;
×
2198
                        m1[4] = tbufnum;
×
2199
                        t = t1;
×
2200
                        j = t[1];
×
2201
                        i = m1[1];
×
2202
                        if ( j > i ) {
×
2203
                                j = i - j;
×
2204
                                NCOPY(t,m1,i);
×
2205
                                m1 = AN.EndNest;
×
2206
                                while ( r < m1 ) *t++ = *r++;
×
2207
                                AN.EndNest = t;
×
2208
                                *term += j;
×
2209
                                NN = AT.NestPoin;
×
2210
                                while ( NN > AT.Nest ) {
×
2211
                                        NN--;
×
2212
                                        NN->termsize[0] += j;
×
2213
                                        NN->funsize[1] += j;
×
2214
                                        NN->argsize[0] += j;
×
2215
                                        NN->funsize[2] |= DIRTYFLAG;
×
2216
                                        NN->argsize[1] |= DIRTYFLAG;
×
2217
                                }
2218
                                m += j;
×
2219
                        }
2220
                        else if ( j < i ) {
×
2221
                                j = i-j;
×
2222
                                t = AN.EndNest;
×
2223
                                while ( t >= r ) { t[j] = *t; t--; }
×
2224
                                t = t1;
2225
                                NCOPY(t,m1,i);
×
2226
                                AN.EndNest += j;
×
2227
                                *term += j;
×
2228
                                NN = AT.NestPoin;
×
2229
                                while ( NN > AT.Nest ) {
×
2230
                                        NN--;
×
2231
                                        NN->termsize[0] += j;
×
2232
                                        NN->funsize[1] += j;
×
2233
                                        NN->argsize[0] += j;
×
2234
                                        NN->funsize[2] |= DIRTYFLAG;
×
2235
                                        NN->argsize[1] |= DIRTYFLAG;
×
2236
                                }
2237
                                m += j;
×
2238
                        }
2239
                        else {
2240
                                NCOPY(t,m1,j);
×
2241
                        }
2242
                        r = t1 + t1[1];
×
2243
                        maxtogo--;
×
2244
                        if ( maxtogo <= 0 ) return(maxtogo);
×
2245
                }
2246
                t = r;
2247
        }
2248
        return(maxtogo);
2249
}
2250

2251
/*
2252
          #] ApplyExec : 
2253
          #[ ApplyReset :
2254
*/
2255

2256
WORD ApplyReset(WORD level)
×
2257
{
2258
        WORD *funs, numfuns;
×
2259
        TABLES T;
×
2260
        int i, j;
×
2261
        CBUF *C = cbuf+AM.rbufnum;
×
2262

2263
        numfuns = C->lhs[level][1] - 2;
×
2264
        funs = C->lhs[level] + 2;
×
2265
        if ( numfuns > 0 ) {
×
2266
                for ( i = MAXBUILTINFUNCTION-FUNCTION; i < AC.FunctionList.num; i++ ) {
×
2267
                        if ( ( T = functions[i].tabl ) != 0 ) {
×
2268
                                for ( j = 0; j < numfuns; j++ ) {
×
2269
                                        if ( i == (funs[j]-FUNCTION) && T->spare ) {
×
2270
                                                FlipTable(&(functions[i]),1);
×
2271
                                                break;
×
2272
                                        }
2273
                                }
2274
                        }
2275
                }
2276
        }
2277
        else {
2278
                for ( i = MAXBUILTINFUNCTION-FUNCTION; i < AC.FunctionList.num; i++ ) {
×
2279
                        if ( ( T = functions[i].tabl ) != 0 ) {
×
2280
                                if ( T->spare ) FlipTable(&(functions[i]),1);
×
2281
                        }
2282
                }
2283
        }
2284
        return(0);
×
2285
}
2286

2287
/*
2288
          #] ApplyReset : 
2289
          #[ TableReset :
2290
*/
2291

2292
WORD TableReset(void)
3,710✔
2293
{
2294
        TABLES T;
3,710✔
2295
        int i;
3,710✔
2296

2297
        for ( i = MAXBUILTINFUNCTION-FUNCTION; i < AC.FunctionList.num; i++ ) {
109,044✔
2298
                if ( ( T = functions[i].tabl ) != 0 && T->spare && T->mode == 0 ) {
105,334✔
2299
                        functions[i].tabl = T->spare;
×
2300
                }
2301
        }
2302
        return(0);
3,710✔
2303
}
2304

2305
/*
2306
          #] TableReset : 
2307
          #[ LoadTableElement :
2308
?????
2309
int LoadTableElement(DBASE *d, TABLE *T, WORD num)
2310
{
2311
}
2312

2313
          #] LoadTableElement : 
2314
          #[ ReleaseTB :
2315

2316
        Releases all TableBases
2317
*/
2318

NEW
2319
int ReleaseTB(void)
×
2320
{
2321
        DBASE *d;
×
2322
        int i;
×
2323
        for ( i = NumTableBases - 1; i >= 0; i-- ) {
×
2324
                d = tablebases+i;
×
2325
                fclose(d->handle);
×
2326
                FreeTableBase(d);
×
2327
        }
2328
        return(0);
×
2329
}
2330

2331
/*
2332
          #] ReleaseTB : 
2333
*/
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