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

vermaseren / form / 9364948935

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

Pull #526

github

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

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

32 existing lines in 2 files now uncovered.

41391 of 82816 relevant lines covered (49.98%)

878690.77 hits per line

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

59.0
/sources/names.c
1
/** @file names.c
2
 * 
3
 *  The complete names administration.
4
 *  All variables with a name have to pass here to be properly registered,
5
 *        have structs of the proper type assigned to them etc.
6
 *        The file also contains the utility routines for maintaining the
7
 *        balanced trees that make searching for names rather fast.
8
 */
9
/* #[ License : */
10
/*
11
 *   Copyright (C) 1984-2023 J.A.M. Vermaseren
12
 *   When using this file you are requested to refer to the publication
13
 *   J.A.M.Vermaseren "New features of FORM" math-ph/0010025
14
 *   This is considered a matter of courtesy as the development was paid
15
 *   for by FOM the Dutch physics granting agency and we would like to
16
 *   be able to track its scientific use to convince FOM of its value
17
 *   for the community.
18
 *
19
 *   This file is part of FORM.
20
 *
21
 *   FORM is free software: you can redistribute it and/or modify it under the
22
 *   terms of the GNU General Public License as published by the Free Software
23
 *   Foundation, either version 3 of the License, or (at your option) any later
24
 *   version.
25
 *
26
 *   FORM is distributed in the hope that it will be useful, but WITHOUT ANY
27
 *   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
28
 *   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
29
 *   details.
30
 *
31
 *   You should have received a copy of the GNU General Public License along
32
 *   with FORM.  If not, see <http://www.gnu.org/licenses/>.
33
 */
34
/* #] License : */ 
35
/*
36
          #[ Includes :
37
*/
38

39
#include "form3.h"
40

41
/* EXTERNLOCK(dummylock) */
42

43
/*
44
          #] Includes : 
45

46
          #[ GetNode :
47
*/
48

49
NAMENODE *GetNode(NAMETREE *nametree, UBYTE *name)
×
50
{
51
        NAMENODE *n;
×
52
        int node, newnode, i;
×
53
        if ( nametree->namenode == 0 ) return(0);
×
54
        newnode = nametree->headnode;
×
55
        do {
×
56
                node = newnode;
×
57
                n = nametree->namenode+node;
×
58
                if ( ( i = StrCmp(name,nametree->namebuffer+n->name) ) < 0 )
×
59
                        newnode = n->left;
×
60
                else if ( i > 0 ) newnode = n->right;
×
61
                else { return(n); }
62
        } while ( newnode >= 0 );
×
63
        return(0);
64
}
65

66
/*
67
          #] GetNode : 
68
          #[ AddName :
69
*/
70

71
int AddName(NAMETREE *nametree, UBYTE *name, WORD type, WORD number, int *nodenum)
322,320✔
72
{
73
        NAMENODE *n, *nn, *nnn;
322,320✔
74
        UBYTE *s, *ss, *sss;
322,320✔
75
        LONG *c1,*c2, j, newsize;
322,320✔
76
        int node, newnode, node3, r, rr = 0, i, retval = 0;
322,320✔
77
        if ( nametree->namenode == 0 ) {
322,320✔
78
                s = name; i = 1; while ( *s ) { i++; s++; }
14,560✔
79
                j = INITNAMESIZE;
5,352✔
80
                if ( i > j ) j = i;
5,352✔
81
                nametree->namenode = (NAMENODE *)Malloc1(INITNODESIZE*sizeof(NAMENODE),
5,352✔
82
                        "new nametree in AddName");
83
                nametree->namebuffer = (UBYTE *)Malloc1(j,
5,352✔
84
                        "new namebuffer in AddName");
85
                nametree->nodesize = INITNODESIZE;
5,352✔
86
                nametree->namesize = j;
5,352✔
87
                nametree->namefill = i;
5,352✔
88
                nametree->nodefill = 1;
5,352✔
89
                nametree->headnode = 0;
5,352✔
90
                n = nametree->namenode;
5,352✔
91
                n->parent = n->left = n->right = -1;
5,352✔
92
                n->balance = 0;
5,352✔
93
                n->type = type;
5,352✔
94
                n->number = number;
5,352✔
95
                n->name = 0;
5,352✔
96
                s = name;
5,352✔
97
                ss = nametree->namebuffer;
5,352✔
98
                while ( *s ) *ss++ = *s++;
14,560✔
99
                *ss = 0;
5,352✔
100
                *nodenum = 0;
5,352✔
101
                return(retval);
5,352✔
102
        }
103
        newnode = nametree->headnode;
316,968✔
104
        do {
2,094,743✔
105
                node = newnode;
2,094,743✔
106
                n = nametree->namenode+node;
2,094,743✔
107
                if ( StrCmp(name,nametree->namebuffer+n->name) < 0 ) {
2,094,743✔
108
                        newnode = n->left; r = -1;
968,424✔
109
                }
110
                else {
111
                        newnode = n->right; r = 1;
1,126,322✔
112
                }
113
        } while ( newnode >= 0 );
2,094,743✔
114
/*
115
        We are at the insertion point. Add the node.
116
*/
117
        if ( nametree->nodefill >= nametree->nodesize ) {        /* Double allocation */
316,968✔
118
                newsize = nametree->nodesize * 2;
9,126✔
119
                if ( newsize > MAXINNAMETREE ) newsize = MAXINNAMETREE;
9,126✔
120
                if ( nametree->nodefill >= MAXINNAMETREE ) {
9,126✔
121
                        MesPrint("!!!More than %l names in one object",(LONG)MAXINNAMETREE);
×
NEW
122
                        TERMINATE(-1);
×
123
                }
124
                nnn = (NAMENODE *)Malloc1(2*((LONG)newsize*sizeof(NAMENODE)),
9,126✔
125
                        "extra names in AddName");
126
                c1 = (LONG *)nnn; c2 = (LONG *)nametree->namenode;
9,126✔
127
                i = (nametree->nodefill * sizeof(NAMENODE))/sizeof(LONG);
9,126✔
128
                while ( --i >= 0 ) *c1++ = *c2++;
2,859,281✔
129
                M_free(nametree->namenode,"nametree->namenode");
9,126✔
130
                nametree->namenode = nnn;
9,126✔
131
                nametree->nodesize = newsize;
9,126✔
132
                n = nametree->namenode+node;
9,126✔
133
        }
134
        *nodenum = newnode = nametree->nodefill++;
316,968✔
135
        nn = nametree->namenode+newnode;
316,968✔
136
        nn->parent = node;
316,968✔
137
        if ( r < 0 ) n->left = newnode; else n->right = newnode;
316,968✔
138
        nn->left = nn->right = -1;
316,968✔
139
        nn->type = type;
316,968✔
140
        nn->number = number;
316,968✔
141
        nn->balance = 0;
316,968✔
142
        i = 1; s = name; while ( *s ) { i++; s++; }
2,183,151✔
143
        while ( nametree->namefill + i >= nametree->namesize ) { /* Double alloc */
324,219✔
144
                sss = (UBYTE *)Malloc1(2*nametree->namesize,
7,251✔
145
                        "extra names in AddName");
146
                s = sss; ss = nametree->namebuffer; j = nametree->namefill;
7,251✔
147
                while ( --j >= 0 ) *s++ = *ss++;
2,717,267✔
148
                M_free(nametree->namebuffer,"nametree->namebuffer");
7,251✔
149
                nametree->namebuffer = sss;
7,251✔
150
                nametree->namesize *= 2;
7,251✔
151
        }
152
        s = nametree->namebuffer+nametree->namefill;
316,968✔
153
        nn->name = nametree->namefill;
316,968✔
154
        retval = nametree->namefill;
316,968✔
155
        nametree->namefill += i;
316,968✔
156
        while ( *name ) *s++ = *name++;
2,183,151✔
157
        *s = 0;
316,968✔
158
/*
159
        Adjust the balance factors
160
*/
161
        while ( node >= 0 ) {
916,159✔
162
                n = nametree->namenode + node;
900,285✔
163
                if ( newnode == n->left ) rr = -1;
900,285✔
164
                else rr = 1;
472,282✔
165
                if ( n->balance == -rr ) { n->balance = 0; return(retval); }
900,285✔
166
                else if ( n->balance == rr ) break;
807,449✔
167
                n->balance = rr;
599,191✔
168
                newnode = node;
599,191✔
169
                node = n->parent;
599,191✔
170
        }
171
        if ( node < 0 ) return(retval);
224,132✔
172
/*
173
        We have to rebalance the tree. There are two basic operations.
174
        n/node is the unbalanced node. newnode is its child.
175
        rr is the old balance of n/node.
176
*/
177
        nn = nametree->namenode + newnode;
208,258✔
178
        if ( nn->balance == -rr ) {        /* The difficult case */
208,258✔
179
                if ( rr > 0 ) {
99,337✔
180
                        node3 = nn->left;
32,367✔
181
                        nnn = nametree->namenode + node3;
32,367✔
182
                        nnn->parent = n->parent;
32,367✔
183
                        n->parent = nn->parent = node3;
32,367✔
184
                        if ( nnn->right >= 0 ) nametree->namenode[nnn->right].parent = newnode;
32,367✔
185
                        if ( nnn->left >= 0 ) nametree->namenode[nnn->left].parent = node;
32,367✔
186
                        n->right = nnn->left; nnn->left = node;
32,367✔
187
                        nn->left = nnn->right; nnn->right = newnode;
32,367✔
188
                        if ( nnn->balance > 0 ) { n->balance = -1; nn->balance = 0; }
32,367✔
189
                        else if ( nnn->balance == 0 ) { n->balance = nn->balance = 0; }
24,997✔
190
                        else                    { nn->balance = 1; n->balance = 0; }
12,474✔
191
                }
192
                else {
193
                        node3 = nn->right;
66,970✔
194
                        nnn = nametree->namenode + node3;
66,970✔
195
                        nnn->parent = n->parent;
66,970✔
196
                        n->parent = nn->parent = node3;
66,970✔
197
                        if ( nnn->right >= 0 ) nametree->namenode[nnn->right].parent = node;
66,970✔
198
                        if ( nnn->left >= 0 ) nametree->namenode[nnn->left].parent = newnode;
66,970✔
199
                        n->left = nnn->right; nnn->right = node;
66,970✔
200
                        nn->right = nnn->left; nnn->left = newnode;
66,970✔
201
                        if ( nnn->balance < 0 ) { n->balance = 1; nn->balance = 0; }
66,970✔
202
                        else if ( nnn->balance == 0 ) { n->balance = nn->balance = 0; }
57,422✔
203
                        else                    { nn->balance = -1; n->balance = 0; }
14,877✔
204
                }
205
                nnn->balance = 0;
99,337✔
206
                if ( nnn->parent >= 0 ) {
99,337✔
207
                        nn = nametree->namenode + nnn->parent;
97,428✔
208
                        if ( node == nn->left ) nn->left = node3;
97,428✔
209
                        else nn->right = node3;
52,859✔
210
                }
211
                if ( node == nametree->headnode ) nametree->headnode = node3;
99,337✔
212
        }
213
        else if ( nn->balance == rr ) {        /* The easy case */
108,921✔
214
                nn->parent = n->parent; n->parent = newnode;
108,921✔
215
                if ( rr > 0 ) {
108,921✔
216
                        if ( nn->left >= 0 ) nametree->namenode[nn->left].parent = node;
69,111✔
217
                        n->right = nn->left; nn->left = node;
69,111✔
218
                }
219
                else {
220
                        if ( nn->right >= 0 ) nametree->namenode[nn->right].parent = node;
39,810✔
221
                        n->left = nn->right; nn->right = node;
39,810✔
222
                }
223
                if ( nn->parent >= 0 ) {
108,921✔
224
                        nnn = nametree->namenode + nn->parent;
106,546✔
225
                        if ( node == nnn->left ) nnn->left = newnode;
106,546✔
226
                        else nnn->right = newnode;
56,377✔
227
                }
228
                nn->balance = n->balance = 0;
108,921✔
229
                if ( node == nametree->headnode ) nametree->headnode = newnode;
108,921✔
230
        }
231
#ifdef DEBUGON
232
        else {        /* Cannot be. Code here for debugging only */
233
                MesPrint("We ran into an impossible case in AddName\n");
234
                DumpTree(nametree);
235
                TERMINATE(-1);
236
        }
237
#endif
238
        return(retval);
239
}
240

241
/*
242
          #] AddName : 
243
          #[ GetName :
244

245
        When AutoDeclare is an active statement.
246
        If par == WITHAUTO and the variable is not found we have to check:
247
    1: that nametree != AC.exprnames && nametree != AC.dollarnames
248
        2: check that the variable is not in AC.exprnames after all.
249
        3: call GetAutoName and return its values.
250
*/
251

252
int GetName(NAMETREE *nametree, UBYTE *namein, WORD *number, int par)
2,473,588✔
253
{
254
        NAMENODE *n;
2,473,588✔
255
        int node, newnode, i;
2,473,588✔
256
        UBYTE *s, *t, *u, *name;
2,473,588✔
257
/*        name = ConstructName(namein,0); */
258
        name = namein;
2,473,588✔
259
        if ( nametree->namenode == 0 || nametree->namefill == 0 ) goto NotFound;
2,473,588✔
260
        newnode = nametree->headnode;
2,464,307✔
261
        do {
19,329,720✔
262
                node = newnode;
19,329,720✔
263
                n = nametree->namenode+node;
19,329,720✔
264
                if ( ( i = StrCmp(name,nametree->namebuffer+n->name) ) < 0 )
19,329,720✔
265
                        newnode = n->left;
7,819,400✔
266
                else if ( i > 0 ) newnode = n->right;
11,510,280✔
267
                else {
268
                        *number = n->number;
2,379,365✔
269
                        return(n->type);
2,379,365✔
270
                }
271
        } while ( newnode >= 0 );
16,950,330✔
272
        s = name;
273
        while ( *s ) s++;
371,459✔
274
        if ( s > name && s[-1] == '_' && nametree == AC.varnames ) {
84,944✔
275
/*
276
                        The Kronecker delta d_ is very special. It is not really a function.
277
*/
278
                if ( s == name+2 && ( *name == 'd' || *name == 'D' ) ) {
63✔
279
                        *number = DELTA-FUNCTION;
35✔
280
                        return(CDELTA);
35✔
281
                }
282
/*
283
                        Test for N#_? type variables (summed indices)
284
*/
285
                if ( s > name+2 && *name == 'N' ) {
28✔
286
                        t = name+1; i = 0;
21✔
287
                        while ( FG.cTable[*t] == 1 ) i = 10*i + *t++ -'0';
56✔
288
                        if ( s == t+1 ) {
21✔
289
                                *number = i + AM.IndDum - AM.OffsetIndex;
21✔
290
                                return(CINDEX);
21✔
291
                        }
292
                }
293
/*
294
                        Now test for any built in object
295
*/
296
                newnode = nametree->headnode;
7✔
297
                do {
56✔
298
                        node = newnode;
56✔
299
                        n = nametree->namenode+node;
56✔
300
                        if ( ( i = StrHICmp(name,nametree->namebuffer+n->name) ) < 0 )
56✔
301
                                newnode = n->left;
28✔
302
                        else if ( i > 0 ) newnode = n->right;
28✔
303
                        else {
304
                                *number = n->number; return(n->type);
7✔
305
                        }
306
                } while ( newnode >= 0 );
49✔
307
/*
308
                        Now we test for the extra symbols of the type STR###_
309
                        The string sits in AC.extrasym and is followed by digits.
310
                        The name is only legal if the number is in the
311
                        range 1,...,cbuf[AM.sbufnum].numrhs
312
*/
313
                t = name; u = AC.extrasym;
×
314
                while ( *t == *u ) { t++; u++; }
×
315
                if ( *u == 0 && *t != 0 ) {        /* potential hit */
×
316
                        WORD x = 0;
317
                        while ( FG.cTable[*t] == 1 ) {
×
318
                                x = 10*x + (*t++ - '0');
×
319
                        }
320
                        if ( *t == '_' && x > 0 && x <= cbuf[AM.sbufnum].numrhs ) { /* Hit */
×
321
                                *number = MAXVARIABLES-x;
×
322
                                return(CSYMBOL);
×
323
                        }
324
                }
325
        }
326
NotFound:;
84,881✔
327
        if ( par != WITHAUTO || nametree == AC.autonames ) return(NAMENOTFOUND);
94,156✔
328
        return(GetAutoName(name,number));
15,687✔
329
}
330

331
/*
332
          #] GetName : 
333
          #[ GetFunction :
334

335
        Gets either a function or a $ that should expand into a function
336
        during runtime. In the case of the $ the value in funnum is -dolnum-1.
337
        The return value is the position after the name of the function or the $.
338
*/
339
 
340
static WORD one = 1;
341

342
UBYTE *GetFunction(UBYTE *s,WORD *funnum)
×
343
{
344
        int type;
×
345
        WORD numfun;
×
346
        UBYTE *t1, c;
×
347
        if ( *s == '$' ) {
×
348
                t1 = s+1; while ( FG.cTable[*t1] < 2 ) t1++;
×
349
                c = *t1; *t1 = 0;
×
350
                if ( ( type = GetName(AC.dollarnames,s+1,&numfun,NOAUTO) ) == CDOLLAR ) {
×
351
                        *funnum = -numfun-2;
×
352
                }
353
                else {
354
                        MesPrint("&%s is undefined",s);
×
355
                        numfun = AddDollar(s+1,DOLINDEX,&one,1);
×
356
                        *funnum = 0;
×
357
                }
358
        }
359
        else {
360
                t1 = SkipAName(s);
×
361
                c = *t1; *t1 = 0;
×
362
                if ( ( ( type = GetName(AC.varnames,s,&numfun,WITHAUTO) ) != CFUNCTION )
×
363
                        || ( functions[numfun].spec > 0 ) ) {
×
364
                        MesPrint("&%s should be a regular function",s);
×
365
                        *funnum = 0;
×
366
                        if ( type < 0 ) {
×
367
                                if ( GetName(AC.exprnames,s,&numfun,NOAUTO) == NAMENOTFOUND )
×
368
                                AddFunction(s,0,0,0,0,0,-1,-1);
×
369
                        }
370
                        *t1 = c;
×
371
                        return(t1);
×
372
                }
373
                *funnum = numfun+FUNCTION;
×
374
        }
375
        *t1 = c;
×
376
        return(t1);
×
377
}
378

379
/*
380
          #] GetFunction : 
381
          #[ GetNumber :
382

383
        Gets either a number or a $ that should expand into a number
384
        during runtime. In the case of the $ the value in num is -dolnum-2.
385
        The return value is the position after the number or the $.
386
*/
387

388
UBYTE *GetNumber(UBYTE *s,WORD *num)
×
389
{
390
        int type;
×
391
        WORD numfun;
×
392
        UBYTE *t1, c;
×
393
        while ( *s == '+' ) s++;
×
394
        if ( *s == '$' ) {
×
395
                t1 = s+1; while ( FG.cTable[*t1] < 2 ) t1++;
×
396
                c = *t1; *t1 = 0;
×
397
                if ( ( type = GetName(AC.dollarnames,s+1,&numfun,NOAUTO) ) == CDOLLAR ) {
×
398
                        *num = -numfun-2;
×
399
                }
400
                else {
401
                        MesPrint("&%s is undefined",s);
×
402
                        numfun = AddDollar(s+1,DOLINDEX,&one,1);
×
403
                        *num = -1;
×
404
                }
405
        }
406
        else if ( *s >= '0' && *s <= '9' ) {
×
407
                ULONG x = *s++ - '0';
×
408
                while ( *s >= '0' && *s <= '9' ) { x = 10*x + (*s++-'0'); }
×
409
                t1 = s;
×
410
                if ( x >= MAXPOSITIVE ) goto illegal;
×
411
                *num = (WORD)x;
×
412
                return(t1);
×
413
        }
414
        else {
415
                if ( *s == '-' ) { s++; }
×
416
                if ( *s >= '0' && *s <= '9' ) { while ( *s >= '0' && *s <= '9' ) s++; t1 = s; }
×
417
                else { t1 = SkipAName(s); }
×
418
illegal:
×
419
                *num = -1;
×
420
                MesPrint("&Illegal option in Canonicalize statement. Should be a nonnegative number or $ variable.");
×
421
                return(t1);
×
422
        }
423
        *t1 = c;
×
424
        return(t1);
×
425
}
426

427
/*
428
          #] GetNumber : 
429
          #[ GetLastExprName :
430

431
        When AutoDeclare is an active statement.
432
        If par == WITHAUTO and the variable is not found we have to check:
433
    1: that nametree != AC.exprnames && nametree != AC.dollarnames
434
        2: check that the variable is not in AC.exprnames after all.
435
        3: call GetAutoName and return its values.
436
*/
437

438
int GetLastExprName(UBYTE *name, WORD *number)
7✔
439
{
440
        int i;
7✔
441
        EXPRESSIONS e;
7✔
442
        for ( i = NumExpressions; i > 0; i-- ) {
7✔
443
                e = Expressions+i-1;
7✔
444
                if ( StrCmp(AC.exprnames->namebuffer+e->name,name) == 0 ) {
7✔
445
                        *number = i-1;
7✔
446
                        return(1);
7✔
447
                }
448
        }
449
        return(0);
450
}
451

452
/*
453
          #] GetLastExprName : 
454
          #[ GetOName :
455

456
        Adds the proper offsets, so we do not have to do that in the calling
457
        routine.
458
*/
459

460
int GetOName(NAMETREE *nametree, UBYTE *name, WORD *number, int par)
973✔
461
{
462
        int retval = GetName(nametree,name,number,par);
973✔
463
        switch ( retval ) {
973✔
464
                case CVECTOR: *number += AM.OffsetVector; break;
259✔
465
                case CINDEX:  *number += AM.OffsetIndex;  break;
392✔
466
                case CFUNCTION: *number += FUNCTION; break;
56✔
467
                default: break;
468
        }
469
        return(retval);
973✔
470
}
471

472
/*
473
          #] GetOName : 
474
          #[ GetAutoName :
475

476
        This routine gets the automatic declarations
477
*/
478

479
int GetAutoName(UBYTE *name, WORD *number)
15,687✔
480
{
481
        UBYTE *s, c;
15,687✔
482
        int type;
15,687✔
483
        if ( GetName(AC.exprnames,name,number,NOAUTO) != NAMENOTFOUND )
15,687✔
484
                                return(NAMENOTFOUND);
485
        s = name;
486
        while ( *s ) { s++; }
61,128✔
487
        if ( s[-1] == '_' ) {
12,746✔
488
                return(NAMENOTFOUND);
489
        }
490
        while ( s > name ) {
48,235✔
491
                c = *s; *s = 0;
48,214✔
492
                type = GetName(AC.autonames,name,number,NOAUTO);
48,214✔
493
                *s = c;
48,214✔
494
                switch(type) {
48,214✔
495
                        case CSYMBOL: {
12,347✔
496
                                SYMBOLS sym = ((SYMBOLS)(AC.AutoSymbolList.lijst)) + *number;
12,347✔
497
                                *number = AddSymbol(name,sym->minpower,sym->maxpower,sym->complex,sym->dimension);
12,347✔
498
                                return(type); }
12,347✔
499
                        case CVECTOR: {
357✔
500
                                VECTORS vec = ((VECTORS)(AC.AutoVectorList.lijst)) + *number;
357✔
501
                                *number = AddVector(name,vec->complex,vec->dimension);
357✔
502
                                return(type); }
357✔
503
                        case CINDEX: {
21✔
504
                                INDICES ind = ((INDICES)(AC.AutoIndexList.lijst)) + *number;
21✔
505
                                *number = AddIndex(name,ind->dimension,ind->nmin4);
21✔
506
                                return(type); }
21✔
507
                        case CFUNCTION: {
×
508
                                FUNCTIONS fun = ((FUNCTIONS)(AC.AutoFunctionList.lijst)) + *number;
×
509
                                *number = AddFunction(name,fun->commute,fun->spec,fun->complex,fun->symmetric,fun->dimension,fun->maxnumargs,fun->minnumargs);
×
510
                                return(type); }
×
511
                        default:
512
                                break;
35,489✔
513
                }
514
                s--;
35,489✔
515
        }
516
        return(NAMENOTFOUND);
517
}
518

519
/*
520
          #] GetAutoName : 
521
          #[ GetVar :
522
*/
523

524
int GetVar(UBYTE *name, WORD *type, WORD *number, int wantedtype, int par)
7,701✔
525
{
526
        WORD funnum;
7,701✔
527
        int typ;
7,701✔
528
        if ( ( typ = GetName(AC.varnames,name,number,par) ) != wantedtype ) {
7,701✔
529
                if ( typ != NAMENOTFOUND ) {
7,428✔
530
                        if ( wantedtype == -1 ) {
7✔
531
                                *type = typ;
7✔
532
                                return(1);
7✔
533
                        }
534
                        NameConflict(typ,name);
×
535
                        MakeDubious(AC.varnames,name,&funnum);
×
536
                        return(-1);
×
537
                }
538
                if ( ( typ = GetName(AC.exprnames,name,&funnum,par) ) != NAMENOTFOUND ) {
7,421✔
539
                        if ( typ == wantedtype || wantedtype == -1 ) {
274✔
540
                                *number = funnum; *type = typ; return(1);
274✔
541
                        }
542
                        NameConflict(typ,name);
×
543
                        return(-1);
×
544
                }
545
                return(NAMENOTFOUND);
546
        }
547
        if ( typ == -1 ) { return(0); }
273✔
548
        *type = typ;
273✔
549
        return(1);
273✔
550
}
551

552
/*
553
          #] GetVar : 
554
          #[ EntVar :
555
*/
556

557
WORD EntVar(WORD type, UBYTE *name, WORD x, WORD y, WORD z, WORD d)
7,308✔
558
{
559
        switch ( type ) {
7,308✔
560
                case CSYMBOL:
×
561
                        return(AddSymbol(name,y,z,x,d));
×
562
                        break;
×
563
                case CINDEX:
×
564
                        return(AddIndex(name,x,z));
×
565
                        break;
×
566
                case CVECTOR:
×
567
                        return(AddVector(name,x,d));
×
568
                        break;
115✔
569
                case CFUNCTION:
115✔
570
                        return(AddFunction(name,y,z,x,0,d,-1,-1));
115✔
571
                        break;
×
572
                case CSET:
×
573
                        AC.SetList.numtemp++;
×
574
                        return(AddSet(name,d));
×
575
                        break;
7,193✔
576
                case CEXPRESSION:
7,193✔
577
                        return(AddExpression(name,x,y));
7,193✔
578
                        break;
579
                default:
580
                        break;
581
        }
582
        return(-1);
583
}
584

585
/*
586
          #] EntVar : 
587
          #[ GetDollar :
588
*/
589

590
int GetDollar(UBYTE *name)
2,892✔
591
{
592
        WORD number;
2,892✔
593
        if ( GetName(AC.dollarnames,name,&number,NOAUTO) == NAMENOTFOUND ) return(-1);
2,892✔
594
        return((int)number);
2,582✔
595
}
596

597
/*
598
          #] GetDollar : 
599
          #[ DumpTree :
600
*/
601

602
VOID DumpTree(NAMETREE *nametree)
×
603
{
604
        if ( nametree->headnode >= 0
×
605
                && nametree->namebuffer && nametree->namenode ) {
×
606
                DumpNode(nametree,nametree->headnode,0);
×
607
        }
608
}
×
609

610
/*
611
          #] DumpTree : 
612
          #[ DumpNode :
613
*/
614

615
VOID DumpNode(NAMETREE *nametree, WORD node, WORD depth)
×
616
{
617
        NAMENODE *n;
×
618
        int i;
×
619
        char *name;
×
620
        n = nametree->namenode + node;
×
621
        if ( n->left >= 0 ) DumpNode(nametree,n->left,depth+1);
×
622
        for ( i = 0; i < depth; i++ ) printf(" ");
×
623
        name = (char *)(nametree->namebuffer+n->name);
×
624
        printf("%s(%d): {%d}(%d)(%d)[%d]\n",
×
625
                name,node,n->parent,n->left,n->right,n->balance);
626
        if ( n->right >= 0 ) DumpNode(nametree,n->right,depth+1);
×
627
}
×
628

629
/*
630
          #] DumpNode : 
631
          #[ CompactifyTree :
632
*/
633

634
int CompactifyTree(NAMETREE *nametree,WORD par)
283✔
635
{
636
        NAMETREE newtree;
283✔
637
        NAMENODE *n;
283✔
638
        LONG i, j, ns, k;
283✔
639
        UBYTE *s;
283✔
640

641
        for ( i = 0, j = 0, k = 0, n = nametree->namenode, ns = 0;
283✔
642
        i < nametree->nodefill; i++, n++ ) {
8,979✔
643
                if ( n->type != CDELETE ) {
8,696✔
644
                        s = nametree->namebuffer+n->name;
5,981✔
645
                        while ( *s ) { s++; ns++; }
39,927✔
646
                        j++;
5,981✔
647
                }
648
                else k++;
2,715✔
649
        }
650
        if ( k == 0 ) return(0);
283✔
651
        if ( j == 0 ) {
234✔
652
                if ( nametree->namebuffer ) M_free(nametree->namebuffer,"nametree->namebuffer");
56✔
653
                if ( nametree->namenode ) M_free(nametree->namenode,"nametree->namenode");
56✔
654
                nametree->namebuffer = 0;
56✔
655
                nametree->namenode = 0;
56✔
656
                nametree->namesize = nametree->namefill =
56✔
657
                nametree->nodesize = nametree->nodefill =
56✔
658
                nametree->oldnamefill = nametree->oldnodefill = 0;
56✔
659
                nametree->globalnamefill = nametree->globalnodefill =
56✔
660
                nametree->clearnamefill = nametree->clearnodefill = 0;
56✔
661
                nametree->headnode = -1;
56✔
662
                return(0);
56✔
663
        }
664
        ns += j;
178✔
665
        if ( j < 10 ) j = 10;
178✔
666
        if ( ns < 100 ) ns = 100;
178✔
667
        newtree.namenode = (NAMENODE *)Malloc1(2*j*sizeof(NAMENODE),"compactify namestree");
178✔
668
        newtree.nodefill = 0; newtree.nodesize = 2*j;
178✔
669
        newtree.namebuffer = (UBYTE *)Malloc1(2*ns,"compactify namestree");
178✔
670
        newtree.namefill = 0; newtree.namesize = 2*ns;
178✔
671
        CopyTree(&newtree,nametree,nametree->headnode,par);
178✔
672
        newtree.namenode[newtree.nodefill>>1].parent = -1;
178✔
673
        LinkTree(&newtree,(WORD)0,newtree.nodefill);
178✔
674
        newtree.headnode = newtree.nodefill >> 1;
178✔
675
        M_free(nametree->namebuffer,"nametree->namebuffer");
178✔
676
        M_free(nametree->namenode,"nametree->namenode");
178✔
677
        nametree->namebuffer  = newtree.namebuffer;
178✔
678
        nametree->namenode    = newtree.namenode;
178✔
679
        nametree->namesize    = newtree.namesize;
178✔
680
        nametree->namefill    = newtree.namefill;
178✔
681
        nametree->nodesize    = newtree.nodesize;
178✔
682
        nametree->nodefill    = newtree.nodefill;
178✔
683
        nametree->oldnamefill = newtree.namefill;
178✔
684
        nametree->oldnodefill = newtree.nodefill;
178✔
685
        nametree->headnode    = newtree.headnode;
178✔
686

687
/*        DumpTree(nametree); */
688
        return(0);
178✔
689
}
690

691
/*
692
          #] CompactifyTree : 
693
          #[ CopyTree :
694
*/
695

696
VOID CopyTree(NAMETREE *newtree, NAMETREE *oldtree, WORD node, WORD par)
4,605✔
697
{
698
        NAMENODE *n, *m;
4,605✔
699
        UBYTE *s, *t;
4,605✔
700
        n = oldtree->namenode+node;
4,605✔
701
        if ( n->left >= 0 ) CopyTree(newtree,oldtree,n->left,par);
4,605✔
702
        if ( n->type != CDELETE ) {
4,605✔
703
                m = newtree->namenode+newtree->nodefill;
2,516✔
704
                m->type = n->type;
2,516✔
705
                m->number = n->number;
2,516✔
706
                m->name = newtree->namefill;
2,516✔
707
                m->left = m->right = -1;
2,516✔
708
                m->balance = 0;
2,516✔
709
                switch ( n->type ) {
2,516✔
710
                        case CSYMBOL:
140✔
711
                                if ( par == AUTONAMES ) {
140✔
712
                                        autosymbols[n->number].name = newtree->namefill;
×
713
                                        autosymbols[n->number].node = newtree->nodefill;
×
714
                                }
715
                                else {
716
                                        symbols[n->number].name = newtree->namefill;
140✔
717
                                        symbols[n->number].node = newtree->nodefill;
140✔
718
                                }
719
                                break;
720
                        case CINDEX :
7✔
721
                                if ( par == AUTONAMES ) {
7✔
722
                                        autoindices[n->number].name = newtree->namefill;
×
723
                                        autoindices[n->number].node = newtree->nodefill;
×
724
                                }
725
                                else {
726
                                        indices[n->number].name = newtree->namefill;
7✔
727
                                        indices[n->number].node = newtree->nodefill;
7✔
728
                                }
729
                                break;
730
                        case CVECTOR:
7✔
731
                                if ( par == AUTONAMES ) {
7✔
732
                                        autovectors[n->number].name = newtree->namefill;
×
733
                                        autovectors[n->number].node = newtree->nodefill;
×
734
                                }
735
                                else {
736
                                        vectors[n->number].name = newtree->namefill;
7✔
737
                                        vectors[n->number].node = newtree->nodefill;
7✔
738
                                }
739
                                break;
740
                        case CFUNCTION:
910✔
741
                                if ( par == AUTONAMES ) {
910✔
742
                                        autofunctions[n->number].name = newtree->namefill;
×
743
                                        autofunctions[n->number].node = newtree->nodefill;
×
744
                                }
745
                                else {
746
                                        functions[n->number].name = newtree->namefill;
910✔
747
                                        functions[n->number].node = newtree->nodefill;
910✔
748
                                }
749
                                break;
750
                        case CSET:
91✔
751
                                Sets[n->number].name = newtree->namefill;
91✔
752
                                Sets[n->number].node = newtree->nodefill;
91✔
753
                                break;
91✔
754
                        case CEXPRESSION:
1,361✔
755
                                Expressions[n->number].name = newtree->namefill;
1,361✔
756
                                Expressions[n->number].node = newtree->nodefill;
1,361✔
757
                                break;
1,361✔
758
                        case CDUBIOUS:
×
759
                                Dubious[n->number].name = newtree->namefill;
×
760
                                Dubious[n->number].node = newtree->nodefill;
×
761
                                break;
×
762
                        case CDOLLAR:
×
763
                                Dollars[n->number].name = newtree->namefill;
×
764
                                Dollars[n->number].node = newtree->nodefill;
×
765
                                break;
×
766
                        default:
×
767
                                MesPrint("Illegal variable type in CopyTree: %d",n->type);
×
768
                                break;
×
769
                }
770
                newtree->nodefill++;
2,516✔
771
                s = newtree->namebuffer + newtree->namefill;
2,516✔
772
                t = oldtree->namebuffer + n->name;
2,516✔
773
                while ( *t ) { *s++ = *t++; newtree->namefill++; }
15,399✔
774
                *s = 0; newtree->namefill++;
2,516✔
775
        }
776
        if ( n->right >= 0 ) CopyTree(newtree,oldtree,n->right,par);
4,605✔
777
}
4,605✔
778

779
/*
780
          #] CopyTree : 
781
          #[ LinkTree :
782
*/
783

784
VOID LinkTree(NAMETREE *tree, WORD offset, WORD numnodes)
2,516✔
785
{
786
/*
787
        Makes the tree into a binary tree
788
*/
789
        int med,numleft,numright,medleft,medright;
2,516✔
790
        med = numnodes >> 1;
2,516✔
791
        numleft = med;
2,516✔
792
        numright = numnodes - med - 1;
2,516✔
793
        medleft = numleft >> 1;
2,516✔
794
        medright = ( numright >> 1 ) + med + 1;
2,516✔
795
        if ( numleft > 0 ) {
2,516✔
796
                tree->namenode[offset+med].left = offset+medleft;
1,400✔
797
                tree->namenode[offset+medleft].parent = offset+med;
1,400✔
798
        }
799
        if ( numright > 0 ) {
2,516✔
800
                tree->namenode[offset+med].right = offset+medright;
938✔
801
                tree->namenode[offset+medright].parent = offset+med;
938✔
802
        }
803
        if ( numleft  > 0 ) LinkTree(tree,offset,numleft);
2,516✔
804
        if ( numright > 0 ) LinkTree(tree,offset+med+1,numright);
2,516✔
805
        while ( numleft && numright ) { numleft >>= 1; numright >>= 1; }
4,567✔
806
        if ( numleft ) tree->namenode[offset+med].balance = -1;
2,516✔
807
        else if ( numright ) tree->namenode[offset+med].balance = 1;
1,830✔
808
}
2,516✔
809

810
/*
811
          #] LinkTree : 
812
          #[ MakeNameTree :
813
*/
814

815
NAMETREE *MakeNameTree(VOID)
7,104✔
816
{
817
        NAMETREE *n;
7,104✔
818
        n = (NAMETREE *)Malloc1(sizeof(NAMETREE),"new nametree");
7,104✔
819
        n->namebuffer = 0;
7,104✔
820
        n->namenode = 0;
7,104✔
821
        n->namesize = n->namefill = n->nodesize = n->nodefill =
7,104✔
822
        n->oldnamefill = n->oldnodefill = 0;
7,104✔
823
        n->globalnamefill = n->globalnodefill =
7,104✔
824
        n->clearnamefill = n->clearnodefill = 0;
7,104✔
825
        n->headnode = -1;
7,104✔
826
        return(n);
7,104✔
827
}
828

829
/*
830
          #] MakeNameTree : 
831
          #[ FreeNameTree :
832
*/
833

834
VOID FreeNameTree(NAMETREE *n)
×
835
{
836
        if ( n ) {
×
837
                if ( n->namebuffer ) M_free(n->namebuffer,"nametree->namebuffer");
×
838
                if ( n->namenode ) M_free(n->namenode,"nametree->namenode");
×
839
                M_free(n,"nametree");
×
840
        }
841
}
×
842

843
/*
844
          #] FreeNameTree : 
845

846
          #[ WildcardNames :
847
*/
848

849
void ClearWildcardNames(VOID)
14,858✔
850
{
851
        AC.NumWildcardNames = 0;
14,858✔
852
}
14,858✔
853

854
int AddWildcardName(UBYTE *name)
1,379✔
855
{
856
        GETIDENTITY
394✔
857
        int size = 0, tocopy, i;
1,379✔
858
        UBYTE *s = name, *t, *newbuffer;
1,379✔
859
        while ( *s ) { s++; size++; }
2,814✔
860
        for ( i = 0, t = AC.WildcardNames; i < AC.NumWildcardNames; i++ ) {
2,072✔
861
                s = name;
862
                while ( ( *s == *t ) && *s ) { s++; t++; }
903✔
863
                if ( *s == 0 && *t == 0 ) return(i+1);
784✔
864
                while ( *t ) t++;
1,386✔
865
                t++;
693✔
866
        }
867
        tocopy = t - AC.WildcardNames;
1,288✔
868
        if ( tocopy + size + 1 > AC.WildcardBufferSize ) {
1,288✔
869
                if ( AC.WildcardBufferSize == 0 ) {
×
870
                        AC.WildcardBufferSize = size+1;
×
871
                        if ( AC.WildcardBufferSize < 100 ) AC.WildcardBufferSize = 100;
×
872
                }
873
                else if ( size+1 >= AC.WildcardBufferSize ) {
×
874
                        AC.WildcardBufferSize += size+1;
×
875
                }
876
                else {
877
                        AC.WildcardBufferSize *= 2;
×
878
                }
879
                newbuffer = (UBYTE *)Malloc1((LONG)AC.WildcardBufferSize,"argument list names");
×
880
                t = newbuffer;
×
881
                if ( AC.WildcardNames ) {
×
882
                        s = AC.WildcardNames;
883
                        while ( tocopy > 0 ) { *t++ = *s++; tocopy--; }
×
884
                        M_free(AC.WildcardNames,"AC.WildcardNames");
×
885
                }
886
                AC.WildcardNames = newbuffer;
×
887
                M_free(AT.WildArgTaken,"AT.WildArgTaken");
×
888
                AT.WildArgTaken = (WORD *)Malloc1((LONG)AC.WildcardBufferSize*sizeof(WORD)/2
×
889
                                ,"argument list names");
890
        }
891
        s = name;
892
        while ( *s ) *t++ = *s++;
2,632✔
893
        *t = 0;
1,288✔
894
        AC.NumWildcardNames++;
1,288✔
895
        return(AC.NumWildcardNames);
1,288✔
896
}
897

898
int GetWildcardName(UBYTE *name)
1,330✔
899
{
900
        UBYTE *s, *t;
1,330✔
901
        int i;
1,330✔
902
        for ( i = 0, t = AC.WildcardNames; i < AC.NumWildcardNames; i++ ) {
2,030✔
903
                s = name;
904
                while ( ( *s == *t ) && *s ) { s++; t++; }
3,346✔
905
                if ( *s == 0 && *t == 0 ) return(i+1);
2,023✔
906
                while ( *t ) t++;
1,400✔
907
                t++;
700✔
908
        }
909
        return(0);
910
}
911

912
/*
913
          #] WildcardNames : 
914

915
          #[ AddSymbol :
916

917
        The actual addition. Special routine for additions 'on the fly'
918
*/
919

920
int AddSymbol(UBYTE *name, int minpow, int maxpow, int cplx, int dim)
51,227✔
921
{
922
        int nodenum, numsymbol = AC.Symbols->num;
51,227✔
923
        UBYTE *s = name;
51,227✔
924
        SYMBOLS sym = (SYMBOLS)FromVarList(AC.Symbols);
51,227✔
925
        bzero(sym,sizeof(struct SyMbOl));
51,227✔
926
        sym->name = AddName(*AC.activenames,name,CSYMBOL,numsymbol,&nodenum);
51,227✔
927
        sym->minpower = minpow;
51,227✔
928
        sym->maxpower = maxpow;
51,227✔
929
        sym->complex  = cplx;
51,227✔
930
        sym->flags    = 0;
51,227✔
931
        sym->node     = nodenum;
51,227✔
932
        sym->dimension= dim;
51,227✔
933
        while ( *s ) s++;
260,633✔
934
        sym->namesize = (s-name)+1;
51,227✔
935
        return(numsymbol);
51,227✔
936
}
937

938
/*
939
          #] AddSymbol : 
940
          #[ CoSymbol :
941

942
        Symbol declarations.   name[#{R|I|C}][([min]:[max])]
943
        Note that we know already that the parentheses match properly
944
*/
945

946
int CoSymbol(UBYTE *s)
1,292✔
947
{
948
        int type, error = 0, minpow, maxpow, cplx, sgn, dim;
1,292✔
949
        WORD numsymbol;
3,381✔
950
        UBYTE *name, *oldc, c, cc;
3,381✔
951
        do {
3,381✔
952
                minpow = -MAXPOWER;
3,381✔
953
                maxpow =  MAXPOWER;
3,381✔
954
                cplx = 0;
3,381✔
955
                dim = 0;
3,381✔
956
                name = s;
3,381✔
957
                if ( ( s = SkipAName(s) ) == 0 ) {
3,381✔
958
IllForm:        MesPrint("&Illegally formed name in symbol statement");
×
959
                        error = 1;
×
960
                        s = SkipField(name,0);
×
961
                        goto eol;
×
962
                }
963
                oldc = s; cc = c = *s; *s = 0;
3,381✔
964
                if ( TestName(name) ) { *s = c; goto IllForm; }
3,381✔
965
                if ( cc == '#' ) {
3,381✔
966
                        s++;
14✔
967
                             if ( tolower(*s) == 'r' ) cplx = VARTYPENONE;
14✔
968
                        else if ( tolower(*s) == 'c' ) cplx = VARTYPECOMPLEX;
14✔
969
                        else if ( tolower(*s) == 'i' ) cplx = VARTYPEIMAGINARY;
×
970
                        else if ( ( ( *s == '-' || *s == '+' || *s == '=' )
×
971
                                 && ( s[1] >= '0' && s[1] <= '9' ) )
×
972
                                 || ( *s >= '0' && *s <= '9' ) ) {
×
973
                                LONG x;
×
974
                                sgn = 0;
×
975
                                if ( *s == '-' ) { sgn = VARTYPEMINUS; s++; }
×
976
                                else if ( *s == '+' || *s == '=' ) { sgn = 0; s++; }
×
977
                                x = *s -'0';
×
978
                                while ( s[1] >= '0' && s[1] <= '9' ) {
×
979
                                        x = 10*x + (s[1] - '0'); s++;
×
980
                                }
981
                                if ( x >= MAXPOWER || x <= 1 ) {
×
982
                                        MesPrint("&Illegal value for root of unity %s",name);
×
983
                                        error = 1;
×
984
                                }
985
                                else {
986
                                        maxpow = x;
×
987
                                }
988
                                cplx = VARTYPEROOTOFUNITY | sgn;
×
989
                        }
990
                        else {
991
                                MesPrint("&Illegal specification for complexity of symbol %s",name);
×
992
                                *oldc = c;
×
993
                                error = 1;
×
994
                                s = SkipField(s,0);
×
995
                                goto eol;
×
996
                        }
997
                        s++; cc = *s;
14✔
998
                }
999
                if ( cc == '{' ) {
3,381✔
1000
                        s++;
×
1001
                        if ( ( *s == 'd' || *s == 'D' ) && s[1] == '=' ) {
×
1002
                                s += 2;
×
1003
                                if ( *s == '-' || *s == '+' || FG.cTable[*s] == 1 ) {
×
1004
                                        ParseSignedNumber(dim,s)
×
1005
                                        if ( dim < -HALFMAX || dim > HALFMAX ) {
×
1006
                                                MesPrint("&Warning: dimension of %s (%d) out of range"
×
1007
                                                ,name,dim);
1008
                                        }
1009
                                }
1010
                                if ( *s != '}' ) goto IllDim;
×
1011
                                else s++;
×
1012
                        }
1013
                        else {
1014
IllDim:                        MesPrint("&Error: Illegal dimension field for variable %s",name);
×
1015
                                error = 1;
×
1016
                                s = SkipField(s,0);
×
1017
                                goto eol;
×
1018
                        }
1019
                        cc = *s;
×
1020
                }
1021
                if ( cc == '(' ) {
3,381✔
1022
                        if ( ( cplx & VARTYPEROOTOFUNITY ) == VARTYPEROOTOFUNITY ) {
35✔
1023
                                MesPrint("&Root of unity property for %s cannot be combined with power restrictions",name);
×
1024
                                error = 1;
×
1025
                        }
1026
                        s++;
35✔
1027
                        if ( *s == '-' || *s == '+' || FG.cTable[*s] == 1 ) {
35✔
1028
                                ParseSignedNumber(minpow,s)
×
1029
                                if ( minpow < -MAXPOWER ) {
×
1030
                                        minpow = -MAXPOWER;
×
1031
                                        if ( AC.WarnFlag )
×
1032
                                        MesPrint("&Warning: minimum power of %s corrected to %d"
×
1033
                                        ,name,-MAXPOWER);
1034
                                }
1035
                        }
1036
                        if ( *s != ':' ) {
35✔
1037
skippar:                error = 1;
×
1038
                                s = SkipField(s,1);
×
1039
                                goto eol;
×
1040
                        }
1041
                        else s++;
35✔
1042
                        if ( *s == '-' || *s == '+' || FG.cTable[*s] == 1 ) {
35✔
1043
                                ParseSignedNumber(maxpow,s)
84✔
1044
                                if ( maxpow > MAXPOWER ) {
35✔
1045
                                        maxpow = MAXPOWER;
×
1046
                                        if ( AC.WarnFlag )
×
1047
                                        MesPrint("&Warning: maximum power of %s corrected to %d"
×
1048
                                        ,name,MAXPOWER);
1049
                                }
1050
                        }
1051
                        if ( *s != ')' ) goto skippar;
35✔
1052
                        s++;
35✔
1053
                }
1054
                if ( ( AC.AutoDeclareFlag == 0 && 
3,381✔
1055
                 ( ( type = GetName(AC.exprnames,name,&numsymbol,NOAUTO) )
3,273✔
1056
                                 != NAMENOTFOUND ) )
1057
                || ( ( type = GetName(*(AC.activenames),name,&numsymbol,NOAUTO) ) != NAMENOTFOUND ) ) {
3,381✔
1058
                        if ( type != CSYMBOL ) error = NameConflict(type,name);
35✔
1059
                        else {
1060
                                SYMBOLS sym = (SYMBOLS)(AC.Symbols->lijst) + numsymbol;
35✔
1061
                                if ( ( numsymbol == AC.lPolyFunVar ) && ( AC.lPolyFunType > 0 )
35✔
1062
                                         && ( AC.lPolyFun != 0 ) && ( minpow > -MAXPOWER || maxpow < MAXPOWER ) ) {
×
1063
                                        MesPrint("&The symbol %s is used by power expansions in the PolyRatFun!",name);
×
1064
                                        error = 1;
×
1065
                                }
1066
                                sym->complex  = cplx;
35✔
1067
                                sym->minpower = minpow;
35✔
1068
                                sym->maxpower = maxpow;
35✔
1069
                                sym->dimension= dim;
35✔
1070
                        }
1071
                }
1072
                else {
1073
                        AddSymbol(name,minpow,maxpow,cplx,dim);
3,346✔
1074
                }
1075
                *oldc = c;
3,381✔
1076
eol:        while ( *s == ',' ) s++;
5,470✔
1077
        } while ( *s );
3,381✔
1078
        return(error);
1,292✔
1079
}
1080

1081
/*
1082
          #] CoSymbol : 
1083
          #[ AddIndex :
1084

1085
        The actual addition. Special routine for additions 'on the fly'
1086
*/
1087

1088
int AddIndex(UBYTE *name, int dim, int dim4)
2,798✔
1089
{
1090
        int nodenum, numindex = AC.Indices->num;
2,798✔
1091
        INDICES ind = (INDICES)FromVarList(AC.Indices);
2,798✔
1092
        UBYTE *s = name;
2,798✔
1093
        bzero(ind,sizeof(struct InDeX));
2,798✔
1094
        ind->name      = AddName(*AC.activenames,name,CINDEX,numindex,&nodenum);
2,798✔
1095
        ind->type      = 0;
2,798✔
1096
        ind->dimension = dim;
2,798✔
1097
        ind->flags     = 0;
2,798✔
1098
        ind->nmin4     = dim4;
2,798✔
1099
        ind->node      = nodenum;
2,798✔
1100
        while ( *s ) s++;
14,310✔
1101
        ind->namesize = (s-name)+1;
2,798✔
1102
        return(numindex);
2,798✔
1103
}
1104

1105
/*
1106
          #] AddIndex : 
1107
          #[ CoIndex :
1108

1109
        Index declarations. name[={number|symbol[:othersymbol]}]
1110
*/
1111

1112
int CoIndex(UBYTE *s)
231✔
1113
{
1114
        int type, error = 0, dim, dim4;
231✔
1115
        WORD numindex;
1,001✔
1116
        UBYTE *name, *oldc, c;
1,001✔
1117
        do {
1,001✔
1118
                dim = AC.lDefDim;
1,001✔
1119
                dim4 = AC.lDefDim4;
1,001✔
1120
                name = s;
1,001✔
1121
                if ( ( s = SkipAName(s) ) == 0 ) {
1,001✔
1122
IllForm:        MesPrint("&Illegally formed name in index statement");
×
1123
                        error = 1;
×
1124
                        s = SkipField(name,0);
×
1125
                        goto eol;
×
1126
                }
1127
                oldc = s; c = *s; *s = 0;
1,001✔
1128
                if ( TestName(name) ) { *s = c; goto IllForm; }
1,001✔
1129
                if ( c == '=' ) {
1,001✔
1130
                        s++;
42✔
1131
                        if ( ( s = DoDimension(s,&dim,&dim4) ) == 0 ) {
42✔
1132
                                *oldc = c;
×
1133
                                error = 1;
×
1134
                                s = SkipField(name,0);
×
1135
                                goto eol;
×
1136
                        }
1137
                }
1138
                if ( ( AC.AutoDeclareFlag == 0 && 
1,001✔
1139
                ( ( type = GetName(AC.exprnames,name,&numindex,NOAUTO) )
980✔
1140
                 != NAMENOTFOUND ) )
1141
                || ( ( type = GetName(*(AC.activenames),name,&numindex,NOAUTO) ) != NAMENOTFOUND ) ) {
1,001✔
1142
                        if ( type != CINDEX ) error = NameConflict(type,name);
×
1143
                        else { /* reset the dimensions */
1144
                                indices[numindex].dimension = dim;
×
1145
                                indices[numindex].nmin4     = dim4;
×
1146
                        }
1147
                }
1148
                else AddIndex(name,dim,dim4);
1,001✔
1149
                *oldc = c;
1,001✔
1150
eol:        while ( *s == ',' ) s++;
1,771✔
1151
        } while ( *s );
1,001✔
1152
        return(error);
231✔
1153
}
1154

1155
/*
1156
          #] CoIndex : 
1157
          #[ DoDimension :
1158
*/
1159

1160
UBYTE *DoDimension(UBYTE *s, int *dim, int *dim4)
49✔
1161
{
1162
        UBYTE c, *t = s;
49✔
1163
        int type, error = 0;
49✔
1164
        WORD numsymbol;
49✔
1165
        NAMETREE **oldtree = AC.activenames;
49✔
1166
        LIST* oldsymbols = AC.Symbols;
49✔
1167
        *dim4 = -NMIN4SHIFT;
49✔
1168
        if ( FG.cTable[*s] == 1 ) {
49✔
1169
retry:
21✔
1170
                ParseNumber(*dim,s)
42✔
1171
#if ( BITSINWORD/8 < 4 )
1172
                if ( *dim >= (1 << (BITSINWORD-1)) ) goto illeg;
1173
#endif
1174
                *dim4 = *dim - 4;
21✔
1175
                return(s);
21✔
1176
        }
1177
        else if ( ( (FG.cTable[*s] == 0 ) || ( *s == '[' ) )
28✔
1178
                && ( s = SkipAName(s) ) != 0 ) {
21✔
1179
                AC.activenames = &(AC.varnames);
21✔
1180
                AC.Symbols = &(AC.SymbolList);
21✔
1181
                c = *s; *s = 0;
21✔
1182
                if ( ( ( type = GetName(AC.exprnames,t,&numsymbol,NOAUTO) ) != NAMENOTFOUND )
21✔
1183
                || ( ( type = GetName(AC.varnames,t,&numsymbol,WITHAUTO) ) != NAMENOTFOUND ) ) {
21✔
1184
                        if ( type != CSYMBOL ) error = NameConflict(type,t);
14✔
1185
                }
1186
                else {
1187
                        numsymbol = AddSymbol(t,-MAXPOWER,MAXPOWER,0,0);
7✔
1188
                        if ( AC.WarnFlag )
7✔
1189
                        MesPrint("&Warning: Implicit declaration of %s as a symbol",t);
7✔
1190
                }
1191
                *dim = -numsymbol;
21✔
1192
                if ( ( *s = c ) == ':' ) {
21✔
1193
                        s++;
×
1194
                        t = s;
×
1195
                        if ( ( s = SkipAName(s) ) == 0 ) goto illeg;
×
1196
                        if ( ( ( type = GetName(AC.exprnames,t,&numsymbol,NOAUTO) ) != NAMENOTFOUND )
×
1197
                        || ( ( type = GetName(AC.varnames,t,&numsymbol,WITHAUTO) ) != NAMENOTFOUND ) ) {
×
1198
                                if ( type != CSYMBOL ) error = NameConflict(type,t);
×
1199
                        }
1200
                        else {
1201
                                numsymbol = AddSymbol(t,-MAXPOWER,MAXPOWER,0,0);
×
1202
                                if ( AC.WarnFlag )
×
1203
                                MesPrint("&Warning: Implicit declaration of %s as a symbol",t);
×
1204
                        }
1205
                        *dim4 = -numsymbol-NMIN4SHIFT;
×
1206
                }
1207
        } 
1208
        else if ( *s == '+' && FG.cTable[s[1]] == 1 ) {
7✔
1209
                s++; goto retry;
×
1210
        }
1211
        else {
1212
illeg:        MesPrint("&Illegal dimension specification. Should be number >= 0, symbol or symbol:symbol");
7✔
1213
                return(0);
7✔
1214
        }
1215
        AC.Symbols = oldsymbols;
21✔
1216
        AC.activenames = oldtree;
21✔
1217
        if ( error ) return(0);
21✔
1218
        return(s);
1219
}
1220

1221
/*
1222
          #] DoDimension : 
1223
          #[ CoDimension :
1224
*/
1225

1226
int CoDimension(UBYTE *s)
7✔
1227
{
1228
        s = DoDimension(s,&AC.lDefDim,&AC.lDefDim4);
7✔
1229
        if ( s == 0 ) return(1);
7✔
1230
        if ( *s != 0 ) {
×
1231
                MesPrint("&Argument of dimension statement should be number >= 0, symbol or symbol:symbol");
×
1232
                return(1);
×
1233
        }
1234
        return(0);
1235
}
1236

1237
/*
1238
          #] CoDimension : 
1239
          #[ AddVector :
1240

1241
        The actual addition. Special routine for additions 'on the fly'
1242
*/
1243

1244
int AddVector(UBYTE *name, int cplx, int dim)
2,913✔
1245
{
1246
        int nodenum, numvector = AC.Vectors->num;
2,913✔
1247
        VECTORS v = (VECTORS)FromVarList(AC.Vectors);
2,913✔
1248
        UBYTE *s = name;
2,913✔
1249
        bzero(v,sizeof(struct VeCtOr));
2,913✔
1250
        v->name = AddName(*AC.activenames,name,CVECTOR,numvector,&nodenum);
2,913✔
1251
        v->complex = cplx;
2,913✔
1252
        v->node    = nodenum;
2,913✔
1253
        v->dimension = dim;
2,913✔
1254
        v->flags = 0;
2,913✔
1255
        while ( *s ) s++;
14,232✔
1256
        v->namesize = (s-name)+1;
2,913✔
1257
        return(numvector);
2,913✔
1258
}
1259

1260
/*
1261
          #] AddVector : 
1262
          #[ CoVector :
1263

1264
        Vector declarations. The descriptor string is "(,%n)"
1265
*/
1266

1267
int CoVector(UBYTE *s)
227✔
1268
{
1269
        int type, error = 0, dim;
227✔
1270
        WORD numvector;
780✔
1271
        UBYTE *name, c, *endname;
780✔
1272
        do {
780✔
1273
                name = s;
780✔
1274
                dim = 0;
780✔
1275
                if ( ( s = SkipAName(s) ) == 0 ) {
780✔
1276
IllForm:        MesPrint("&Illegally formed name in vector statement");
×
1277
                        error = 1;
×
1278
                        s = SkipField(s,0);
×
1279
                }
1280
                else {
1281
                        c = *s; *s = 0, endname = s;
780✔
1282
                        if ( TestName(name) ) { *s = c; goto IllForm; }
780✔
1283
                        if ( c == '{' ) {
780✔
1284
                                s++;
×
1285
                                if ( ( *s == 'd' || *s == 'D' ) && s[1] == '=' ) {
×
1286
                                        s += 2;
×
1287
                                        if ( *s == '-' || *s == '+' || FG.cTable[*s] == 1 ) {
×
1288
                                                ParseSignedNumber(dim,s)
×
1289
                                                if ( dim < -HALFMAX || dim > HALFMAX ) {
×
1290
                                                        MesPrint("&Warning: dimension of %s (%d) out of range"
×
1291
                                                        ,name,dim);
1292
                                                }
1293
                                        }
1294
                                        if ( *s != '}' ) goto IllDim;
×
1295
                                        else s++;
×
1296
                                }
1297
                                else {
1298
IllDim:                                MesPrint("&Error: Illegal dimension field for variable %s",name);
×
1299
                                        error = 1;
×
1300
                                        s = SkipField(s,0);
×
1301
                                        while ( *s == ',' ) s++;
×
1302
                                        continue;
×
1303
                                }
1304
                        }
1305
                        if ( ( AC.AutoDeclareFlag == 0 &&
780✔
1306
                         ( ( type = GetName(AC.exprnames,name,&numvector,NOAUTO) )
773✔
1307
                         != NAMENOTFOUND ) )
1308
                        || ( ( type = GetName(*(AC.activenames),name,&numvector,NOAUTO) ) != NAMENOTFOUND ) ) {
780✔
1309
                                if ( type != CVECTOR ) error = NameConflict(type,name);
×
1310
                        }
1311
                        else AddVector(name,0,dim);
780✔
1312
                        *endname = c;
780✔
1313
                }
1314
                while ( *s == ',' ) s++;
1,333✔
1315
        } while ( *s );
780✔
1316
        return(error);
227✔
1317
}
1318

1319
/*
1320
          #] CoVector : 
1321
          #[ AddFunction :
1322

1323
        The actual addition. Special routine for additions 'on the fly'
1324
*/
1325

1326
int AddFunction(UBYTE *name, int comm, int istensor, int cplx, int symprop, int dim, int argmax, int argmin)
232,783✔
1327
{
1328
        int nodenum, numfunction = AC.Functions->num;
232,783✔
1329
        FUNCTIONS fun = (FUNCTIONS)FromVarList(AC.Functions);
232,783✔
1330
        UBYTE *s = name;
232,783✔
1331
        bzero(fun,sizeof(struct FuNcTiOn));
232,783✔
1332
        fun->name = AddName(*AC.activenames,name,CFUNCTION,numfunction,&nodenum);
232,783✔
1333
        fun->commute = comm;
232,783✔
1334
        fun->spec = istensor;
232,783✔
1335
        fun->complex  = cplx;
232,783✔
1336
        fun->tabl = 0;
232,783✔
1337
        fun->flags = 0;
232,783✔
1338
        fun->node = nodenum;
232,783✔
1339
        fun->symminfo = 0;
232,783✔
1340
        fun->symmetric = symprop;
232,783✔
1341
        fun->dimension = dim;
232,783✔
1342
        fun->maxnumargs = argmax;
232,783✔
1343
        fun->minnumargs = argmin;
232,783✔
1344
        while ( *s ) s++;
1,707,858✔
1345
        fun->namesize = (s-name)+1;
232,783✔
1346
        return(numfunction);
232,783✔
1347
}
1348

1349
/*
1350
          #] AddFunction : 
1351
          #[ CoCommuteInSet :
1352

1353
        Commuting,f1,...,fn;
1354
*/
1355

1356
int CoCommuteInSet(UBYTE *s)
7✔
1357
{
1358
        UBYTE *name, *ss, c, *start = s;
7✔
1359
        WORD number, type, *g, *gg;
7✔
1360
        int error = 0, i, len = StrLen(s), len2 = 0;
7✔
1361
        if ( AC.CommuteInSet != 0 ) {
7✔
1362
                g = AC.CommuteInSet;
1363
                while ( *g ) g += *g;
×
1364
                len2 = g - AC.CommuteInSet;
×
1365
                if ( len2+len+3 > AC.SizeCommuteInSet ) {
×
1366
                        gg = (WORD *)Malloc1((len2+len+3)*sizeof(WORD),"CommuteInSet");
×
1367
                        for ( i = 0; i < len2; i++ ) gg[i] = AC.CommuteInSet[i];
×
1368
                        gg[len2] = 0;
×
1369
                        M_free(AC.CommuteInSet,"CommuteInSet");
×
1370
                        AC.CommuteInSet = gg;
×
1371
                        AC.SizeCommuteInSet = len+len2+3;
×
1372
                        g = AC.CommuteInSet+len2;
×
1373
                }
1374
        }
1375
        else {
1376
                AC.SizeCommuteInSet = len+2;
7✔
1377
                g = AC.CommuteInSet = (WORD *)Malloc1((len+3)*sizeof(WORD),"CommuteInSet");
7✔
1378
                *g = 0;
7✔
1379
        }
1380
        gg = g++;
7✔
1381
        ss = s-1;
7✔
1382
        for(;;) {
1383
                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
119✔
1384
                if ( *s == 0 ) {
77✔
1385
                        if ( s - start >= len ) break;
28✔
1386
                        *s = '}'; s++;
21✔
1387
                        *g = 0;
21✔
1388
                        *gg = g-gg;
21✔
1389
                        if ( *gg < 2 ) {
21✔
1390
                                MesPrint("&There should be at least two noncommuting functions or tensors in a commuting statement.");
×
1391
                                error = 1;                
×
1392
                        }
1393
                        else if ( *gg == 2 ) {
21✔
1394
                                gg[2] = gg[1]; gg[3] = 0; gg[0] = 3;
×
1395
                        }
1396
                        gg = g++;
21✔
1397
                        continue;
21✔
1398
                }
1399
                if ( s > ss ) {
49✔
1400
                        if ( *s != '{' ) {
21✔
1401
                                MesPrint("&The CommuteInSet statement should have sets enclosed in {}.");
×
1402
                                error = 1;
×
1403
                                break;
×
1404
                        }
1405
                        ss = s;
21✔
1406
                        SKIPBRA2(ss) /* Note that parentheses were tested before */
147✔
1407
                        *ss = 0;
21✔
1408
                        s++;
21✔
1409
                }
1410
                name = s;
49✔
1411
                s = SkipAName(s);
49✔
1412
                c = *s; *s = 0;
49✔
1413
                if ( ( type = GetName(AC.varnames,name,&number,NOAUTO) ) != CFUNCTION ) {
49✔
1414
                        MesPrint("&%s is not a function or tensor",name);
×
1415
                        error = 1;
×
1416
                }
1417
                else if ( functions[number].commute == 0 ){
49✔
1418
                        MesPrint("&%s is not a noncommuting function or tensor",name);
×
1419
                        error = 1;
×
1420
                }
1421
                else {
1422
                        *g++ = number+FUNCTION;
49✔
1423
                        functions[number].flags |= COULDCOMMUTE;
49✔
1424
                        if ( number+FUNCTION >= GAMMA && number+FUNCTION <= GAMMASEVEN ) {
49✔
1425
                                functions[GAMMA-FUNCTION].flags |= COULDCOMMUTE;
7✔
1426
                                functions[GAMMAI-FUNCTION].flags |= COULDCOMMUTE;
7✔
1427
                                functions[GAMMAFIVE-FUNCTION].flags |= COULDCOMMUTE;
7✔
1428
                                functions[GAMMASIX-FUNCTION].flags |= COULDCOMMUTE;
7✔
1429
                                functions[GAMMASEVEN-FUNCTION].flags |= COULDCOMMUTE;
7✔
1430
                        }
1431
                }
1432
                *s = c;
49✔
1433
        }
1434
        return(error);
7✔
1435
}
1436

1437
/*
1438
          #] CoCommuteInSet : 
1439
          #[ CoFunction + ...:
1440

1441
        Function declarations.
1442
        The second parameter indicates commutation properties.
1443
        The third parameter tells whether we have a tensor.
1444
*/
1445

1446
int CoFunction(UBYTE *s, int comm, int istensor)
1,040✔
1447
{
1448
        int type, error = 0, cplx, symtype, dim, argmax, argmin;
1,040✔
1449
        WORD numfunction, reverseorder = 0, addone;
1,040✔
1450
        UBYTE *name, *oldc, *par, c, cc;
1,781✔
1451
        do {
1,781✔
1452
                symtype = cplx = 0, argmin = argmax = -1;
1,781✔
1453
                dim = 0;
1,781✔
1454
                name = s;
1,781✔
1455
                if ( ( s = SkipAName(s) ) == 0 ) {
1,781✔
1456
IllForm:        MesPrint("&Illegally formed function/tensor name");
×
1457
                        error = 1;
×
1458
                        s = SkipField(name,0);
×
1459
                        goto eol;
×
1460
                }
1461
                oldc = s; cc = c = *s; *s = 0;
1,781✔
1462
                if ( TestName(name) ) { *s = c; goto IllForm; }
1,781✔
1463
                if ( c == '#' ) {
1,781✔
1464
                        s++;
×
1465
                             if ( tolower(*s) == 'r' ) cplx = VARTYPENONE;
×
1466
                        else if ( tolower(*s) == 'c' ) cplx = VARTYPECOMPLEX;
×
1467
                        else if ( tolower(*s) == 'i' ) cplx = VARTYPEIMAGINARY;
×
1468
                        else {
1469
                                MesPrint("&Illegal specification for complexity of %s",name);
×
1470
                                *oldc = c;
×
1471
                                error = 1;
×
1472
                                s = SkipField(s,0);
×
1473
                                goto eol;
×
1474
                        }
1475
                        s++; cc = *s;
×
1476
                }
1477
                if ( cc == '{' ) {
1,781✔
1478
                        s++;
×
1479
                        if ( ( *s == 'd' || *s == 'D' ) && s[1] == '=' ) {
×
1480
                                s += 2;
×
1481
                                if ( *s == '-' || *s == '+' || FG.cTable[*s] == 1 ) {
×
1482
                                        ParseSignedNumber(dim,s)
×
1483
                                        if ( dim < -HALFMAX || dim > HALFMAX ) {
×
1484
                                                MesPrint("&Warning: dimension of %s (%d) out of range"
×
1485
                                                ,name,dim);
1486
                                        }
1487
                                }
1488
                                if ( *s != '}' ) goto IllDim;
×
1489
                                else s++;
×
1490
                        }
1491
                        else {
1492
IllDim:                        MesPrint("&Error: Illegal dimension field for variable %s",name);
×
1493
                                error = 1;
×
1494
                                s = SkipField(s,0);
×
1495
                                goto eol;
×
1496
                        }
1497
                        cc = *s;
×
1498
                }
1499
                if ( cc == '(' ) {
1,781✔
1500
                        s++;
147✔
1501
                        if ( *s == '-' ) {
147✔
1502
                                reverseorder = REVERSEORDER;
×
1503
                                s++;
×
1504
                        }
1505
                        else {
1506
                                reverseorder = 0;
1507
                        }
1508
                        par = s;
147✔
1509
                        while ( FG.cTable[*s] == 0 ) s++;
854✔
1510
                        cc = *s; *s = 0;
147✔
1511
                        if ( s <= par ) {
147✔
1512
illegsym:                *s = cc;
×
1513
                                MesPrint("&Illegal specification for symmetry of %s",name);
×
1514
                                *oldc = c;
×
1515
                                error = 1;
×
1516
                                s = SkipField(s,1);
×
1517
                                goto eol;
×
1518
                        }
1519
                        if ( StrICont(par,(UBYTE *)"symmetric") == 0 ) symtype = SYMMETRIC;
147✔
1520
                        else if ( StrICont(par,(UBYTE *)"antisymmetric") == 0 ) symtype = ANTISYMMETRIC;
91✔
1521
                        else if ( ( StrICont(par,(UBYTE *)"cyclesymmetric") == 0 )
56✔
1522
                        || ( StrICont(par,(UBYTE *)"cyclic") == 0 ) ) symtype = CYCLESYMMETRIC;
28✔
1523
                        else if ( ( StrICont(par,(UBYTE *)"rcyclesymmetric") == 0 )
14✔
1524
                        || ( StrICont(par,(UBYTE *)"rcyclic") == 0 )
×
1525
                        || ( StrICont(par,(UBYTE *)"reversecyclic") == 0 ) ) symtype = RCYCLESYMMETRIC;
×
1526
                        else goto illegsym;
×
1527
                        *s = cc;
147✔
1528
                        if ( *s != ')' || ( s[1] && s[1] != ',' && s[1] != '<' ) ) {
147✔
1529
                                Warning("&Excess information in symmetric properties currently ignored");
×
1530
                                s = SkipField(s,1);
×
1531
                        }
1532
                        else s++;
147✔
1533
                        symtype |= reverseorder;
147✔
1534
                        cc = *s;
147✔
1535
                }
1536
retry:;
1,781✔
1537
                if ( cc == '<' ) {
1,781✔
1538
                        s++; addone = 0;
×
1539
                        if ( *s == '=' ) { addone++; s++; }
×
1540
                        argmax = 0;
×
1541
                        while ( FG.cTable[*s] == 1 ) { argmax = 10*argmax + *s++ - '0'; }
×
1542
                        argmax += addone;
×
1543
                        par = s;
×
1544
                        while ( FG.cTable[*s] == 0 ) s++;
×
1545
                        if ( s > par ) {
×
1546
                                cc = *s; *s = 0;
×
1547
                                if ( ( StrICont(par,(UBYTE *)"arguments") == 0 )
×
1548
                                || ( StrICont(par,(UBYTE *)"args") == 0 ) ) {}
×
1549
                                else {
1550
                                        Warning("&Illegal information in number of arguments properties currently ignored");
×
1551
                                        error = 1;
×
1552
                                }
1553
                                *s = cc;
×
1554
                        }
1555
                        if ( argmax <= 0 ) {
×
1556
                                MesPrint("&Error: Cannot have fewer than 0 arguments for variable %s",name);
×
1557
                                error = 1;
×
1558
                        }
1559
                        cc = *s;
×
1560
                }
1561
                if ( cc == '>' ) {
1,781✔
1562
                        s++; addone = 1;
×
1563
                        if ( *s == '=' ) { addone = 0; s++; }
×
1564
                        argmin = 0;
×
1565
                        while ( FG.cTable[*s] == 1 ) { argmin = 10*argmin + *s++ - '0'; }
×
1566
                        argmin += addone;
×
1567
                        par = s;
×
1568
                        while ( FG.cTable[*s] == 0 ) s++;
×
1569
                        if ( s > par ) {
×
1570
                                cc = *s; *s = 0;
×
1571
                                if ( ( StrICont(par,(UBYTE *)"arguments") == 0 )
×
1572
                                || ( StrICont(par,(UBYTE *)"args") == 0 ) ) {}
×
1573
                                else {
1574
                                        Warning("&Illegal information in number of arguments properties currently ignored");
×
1575
                                        error = 1;
×
1576
                                }
1577
                                *s = cc;
×
1578
                        }
1579
                        cc = *s;
×
1580
                }
1581
                if ( cc == '<' ) goto retry;
1,781✔
1582
                if ( ( AC.AutoDeclareFlag == 0 &&
1,781✔
1583
                 ( ( type = GetName(AC.exprnames,name,&numfunction,NOAUTO) )
1,781✔
1584
                 != NAMENOTFOUND ) )
1585
                || ( ( type = GetName(*(AC.activenames),name,&numfunction,NOAUTO) ) != NAMENOTFOUND ) ) {
1,781✔
1586
                        if ( type != CFUNCTION ) error = NameConflict(type,name);
×
1587
                        else {
1588
/*                                FUNCTIONS fun = (FUNCTIONS)(AC.Functions->lijst) + numfunction-FUNCTION; */
1589
                                FUNCTIONS fun = (FUNCTIONS)(AC.Functions->lijst) + numfunction;
×
1590

1591
                                if ( fun->tabl != 0 ) {
×
1592
                                        MesPrint("&Illegal attempt to change table into function");
×
1593
                                        error = 1;
×
1594
                                }
1595

1596
                                fun->complex = cplx;
×
1597
                                fun->commute = comm;
×
1598
                                if ( istensor && fun->spec == 0 ) {
×
1599
                                        MesPrint("&Function %s changed to tensor",name);
×
1600
                                        error = 1;
×
1601
                                }
1602
                                else if ( istensor == 0 && fun->spec > 0 ) {
×
1603
                                        MesPrint("&Tensor %s changed to function",name);
×
1604
                                        error = 1;
×
1605
                                }
1606
                                fun->spec = istensor;
×
1607
                                if ( fun->symmetric != symtype ) {
×
1608
                                        fun->symmetric = symtype;
×
1609
                                        AC.SymChangeFlag = 1;
×
1610
                                }
1611
                                fun->maxnumargs = argmax;
×
1612
                                fun->minnumargs = argmin;
×
1613
                        }
1614
                }
1615
                else {
1616
                        AddFunction(name,comm,istensor,cplx,symtype,dim,argmax,argmin);
1,781✔
1617
                }
1618
                *oldc = c;
1,781✔
1619
eol:        while ( *s == ',' ) s++;
2,522✔
1620
        } while ( *s );
1,781✔
1621
        return(error);
1,040✔
1622
}
1623

1624
int CoNFunction(UBYTE *s) { return(CoFunction(s,1,0)); }
63✔
1625
int CoCFunction(UBYTE *s) { return(CoFunction(s,0,0)); }
900✔
1626
int CoNTensor(UBYTE *s) { return(CoFunction(s,1,2)); }
×
1627
int CoCTensor(UBYTE *s) { return(CoFunction(s,0,2)); }
77✔
1628

1629
/*
1630
          #] CoFunction + ...: 
1631
          #[ DoTable :
1632

1633
        Syntax:
1634
        Table [check] [strict|relax] [zerofill] name(:1:2,...,regular arguments);
1635
        name must be the name of a regular function.
1636
        the table indices must be the first arguments.
1637
                The parenthesis indicates 'name' as opposed to the options.
1638

1639
                We leave behind:
1640
                a struct tabl in the FUNCTION struct
1641
                Regular table:
1642
                        an array tablepointers for the pointers to elements of rhs
1643
                        in the compiler struct cbuf[T->bufnum]
1644
                        an array MINMAX T->mm with the minima and maxima 
1645
                        a prototype array
1646
                        an offset in the compiler buffer for the pattern to be matched
1647
                Sparse table:
1648
                        Just the number of dimensions
1649
                        We will keep track of the number of defined elements in totind
1650
                        and in tablepointers we will have numind+1 positions for each
1651
                        element. The first numind elements for the indices and the
1652
                        last one for the element in cbuf[T->bufnum].rhs
1653

1654
                        If the number of dimensions is *<number>, there is not a fixed
1655
                        number of dimensions. Just a maximum. In that case the first
1656
                        index should be the number of other dimensions. This first index
1657
                        does not count in <number>.
1658

1659
                Complication: to preserve speed we need a prototype and a pattern
1660
                for each thread when we use WITHPTHREADS. This is because we write
1661
                into those when looking for the pattern.
1662
*/
1663

1664
static int nwarntab = 1;
1665

1666
int DoTable(UBYTE *s, int par)
115✔
1667
{
1668
        GETIDENTITY
34✔
1669
        UBYTE *name, *p, *inp, c;
115✔
1670
        int i, j, k, sparseflag = 0, rflag = 0, checkflag = 0;
115✔
1671
        int error = 0, ret, oldcbufnum, oldEside;
115✔
1672
        WORD funnum, type, *OldWork, *w, *ww, *t, *tt, *flags1, oldnumrhs,oldnumlhs;
115✔
1673
        LONG oldcpointer;
115✔
1674
        MINMAX *mm, *mm1;
115✔
1675
        LONG x, y;
115✔
1676
        TABLES T;
115✔
1677
        CBUF *C;
115✔
1678
        
1679
        while ( *s == ',' ) s++;
115✔
1680
        do {
122✔
1681
                name = s;
122✔
1682
                if ( ( s = SkipAName(s) ) == 0 ) {
122✔
1683
IllForm:        MesPrint("&Illegal name or option in table declaration");
×
1684
                        return(1);
×
1685
                }
1686
                c = *s; *s = 0;
122✔
1687
                if ( TestName(name) ) { *s = c; goto IllForm; }
122✔
1688
                *s = c;
122✔
1689
                if ( *s == '(' ) break;
122✔
1690
                if ( *s != ',' ) {
7✔
1691
                        MesPrint("&Illegal definition of table");
×
1692
                        return(1);
×
1693
                }
1694
                *s = 0;
7✔
1695
/*
1696
                Secondary options
1697
*/
1698
                if      ( StrICmp(name,(UBYTE *)("check" )) == 0 ) checkflag = 1;
7✔
1699
                else if ( StrICmp(name,(UBYTE *)("zero"  )) == 0 ) checkflag = 2;
7✔
1700
                else if ( StrICmp(name,(UBYTE *)("one"   )) == 0 ) checkflag = 3;
7✔
1701
                else if ( StrICmp(name,(UBYTE *)("strict")) == 0 ) rflag = 1;
7✔
1702
                else if ( StrICmp(name,(UBYTE *)("relax" )) == 0 ) rflag = -1;
7✔
1703
                else if ( StrICmp(name,(UBYTE *)("zerofill" )) == 0 ) { rflag = -2; checkflag = 2; }
7✔
1704
                else if ( StrICmp(name,(UBYTE *)("onefill" )) == 0 ) { rflag = -3; checkflag = 3; }
7✔
1705
                else if ( StrICmp(name,(UBYTE *)("sparse")) == 0 ) sparseflag |= 1;
7✔
1706
                else if ( StrICmp(name,(UBYTE *)("base")) == 0 ) sparseflag |= 3;
×
1707
                else if ( StrICmp(name,(UBYTE *)("tablebase")) == 0 ) sparseflag |= 3;
×
1708
                else {
1709
                        MesPrint("&Illegal option in table definition: '%s'",name);
×
1710
                        error = 1;
×
1711
                }
1712
                *s++ = ',';
7✔
1713
                while ( *s == ',' ) s++;
7✔
1714
        } while ( *s );
7✔
1715
        if ( name == s || *s == 0 ) {
115✔
1716
                MesPrint("&Illegal name or option in table declaration");
×
1717
                return(1);
×
1718
        }
1719
        *s = 0;                /* *s could only have been a parenthesis */
115✔
1720
        if ( sparseflag ) {
115✔
1721
                if ( checkflag == 1 ) rflag = 0;
7✔
1722
                else if ( checkflag == 2 ) rflag = -2;
7✔
1723
                else if ( checkflag == 3 ) rflag = -3;
7✔
1724
                else rflag = -1;
7✔
1725
        }
1726
        if ( ( ret = GetVar(name,&type,&funnum,CFUNCTION,NOAUTO) ) ==
115✔
1727
                                        NAMENOTFOUND ) {
1728
                if ( par == 0 ) {
115✔
1729
                        funnum = EntVar(CFUNCTION,name,0,1,0,0);
×
1730
                }
1731
                else if ( par == 1 || par == 2 ) {
115✔
1732
                        funnum = EntVar(CFUNCTION,name,0,0,0,0);
115✔
1733
                }
1734
        }
1735
        else if ( ret <= 0 ) {
×
1736
                funnum = EntVar(CFUNCTION,name,0,0,0,0);
×
1737
                error = 1;
×
1738
        }
1739
        else {
1740
                if ( par == 2 ) {
×
1741
                        if ( nwarntab ) {
×
1742
                                Warning("Table now declares its (commuting) function.");
×
1743
                                Warning("Earlier definition in Function statement obsolete. Please remove.");
×
1744
                                nwarntab = 0;
×
1745
                        }
1746
                }
1747
                else {
1748
                        error = 1;
×
1749
                        MesPrint("&(N)(C)Tables should not be declared previously");
×
1750
                }
1751
        }
1752
        if ( functions[funnum].spec > 0 ) {
115✔
1753
                MesPrint("&Tensors cannot become tables");
×
1754
                return(1);
×
1755
        }
1756
        if ( functions[funnum].symmetric > 0 ) {
115✔
1757
                MesPrint("&Functions with nontrivial symmetrization properties cannot become tables");
×
1758
                return(1);
×
1759
        }
1760
        if ( functions[funnum].tabl ) {
115✔
1761
                MesPrint("&Redefinition of an existing table is not allowed.");
×
1762
                return(1);
×
1763
        }
1764
        functions[funnum].tabl = T = (TABLES)Malloc1(sizeof(struct TaBlEs),"table");
115✔
1765
/*
1766
        Next we find the size of the table (if it is not sparse)
1767
*/
1768
        T->defined = T->mdefined = 0; T->sparse = sparseflag; T->mm = 0; T->flags = 0;
115✔
1769
        T->numtree = 0; T->rootnum = 0; T->MaxTreeSize = 0;
115✔
1770
        T->boomlijst = 0;
115✔
1771
    T->strict = rflag;
115✔
1772
    T->bounds = checkflag;
115✔
1773
        T->bufnum = inicbufs();
115✔
1774
        T->argtail = 0;
115✔
1775
        T->spare = 0;
115✔
1776
        T->bufferssize = 8;
115✔
1777
        T->buffers = (WORD *)Malloc1(sizeof(WORD)*T->bufferssize,"Table buffers");
115✔
1778
        T->buffersfill = 0;
115✔
1779
        T->buffers[T->buffersfill++] = T->bufnum;
115✔
1780
        T->mode = 0;
115✔
1781
        T->numdummies = 0;
115✔
1782
    mm = T->mm;
115✔
1783
    T->numind = 0;
115✔
1784
    if ( rflag > 0 ) AC.MustTestTable++;
115✔
1785
    T->totind = 0;      /* Table hasn't been checked */
115✔
1786

1787
        p = s; *s = '(';
115✔
1788
        if ( sparseflag ) {
115✔
1789
/*
1790
                First copy the tail, just in case we will construct a tablebase
1791
                Note that we keep the ( to indicate a tail
1792
                The actual arguments can be found after the comma. Before we have
1793
                the dimension which the tablebase will need for consistency checking.
1794
*/
1795
                inp = p+1;
7✔
1796
                SKIPBRA3(inp)
7✔
1797
                c = *inp; *inp = 0;
7✔
1798
                T->argtail = strDup1(p,"argtail");
7✔
1799
                *inp = c;
7✔
1800
/*
1801
                Now the regular compilation
1802
*/
1803
                inp = p++;
7✔
1804
                if ( *p == '<' ) {
7✔
1805
                        WORD inc = 1;
×
1806
                        p++;
×
1807
                        if ( *p == '=' ) { inc++; p++; }
×
1808
/*
1809
                        We will use one extra number for telling how many there really are.
1810
*/
1811
                        x = 0;
×
1812
                        while ( *p <= '9' && *p >= '0' ) x = 10*x + (*p++-'0');
×
1813
                        x = -x-inc;
×
1814
                        if ( x == -1 ) {
×
1815
                                MesPrint("&Maximum number of dimensions in *-table should be at least one.");
×
1816
                                error = 1;
×
1817
                                goto FinishUp2;
×
1818
                        }
1819
                }
1820
                else {
1821
                        ParseNumber(x,p)
14✔
1822
                        if ( FG.cTable[p[-1]] != 1 || ( *p != ',' && *p != ')' ) ) {
7✔
1823
                                p = inp;
×
1824
                                MesPrint("&First argument in a sparse table must be a number of dimensions");
×
1825
                                error = 1;
×
1826
                                x = 1;
×
1827
                        }
1828
                }
1829
                T->numind = x;
7✔
1830
                T->mm = (MINMAX *)Malloc1(ABS(x)*sizeof(MINMAX),"table dimensions");
7✔
1831
                T->flags = (WORD *)Malloc1(ABS(x)*sizeof(WORD),"table flags");
7✔
1832
                mm = T->mm;
7✔
1833
                inp = p;
7✔
1834
                if ( *inp != ')' ) inp++;
7✔
1835
                T->totind = 0;                        /* At the moment there are this many */
7✔
1836
                T->tablepointers = 0;
7✔
1837
                T->reserved = 0;
7✔
1838
        }
1839
        else {
1840
                T->numind = 0;
108✔
1841
                T->totind = 1;
108✔
1842
                for(;;) {        /* Read the dimensions as far as they can be recognized */
108✔
1843
                        inp = ++p;
108✔
1844
                        if ( FG.cTable[*p] != 1 && *p != '+' && *p != '-' ) break;
108✔
1845
                        ParseSignedNumber(x,p)
62✔
1846
                        if ( FG.cTable[p[-1]] != 1 || *p != ':' ) break;
31✔
1847
                        p++;
31✔
1848
                        ParseSignedNumber(y,p)
76✔
1849
                        if ( FG.cTable[p[-1]] != 1 || ( *p != ',' && *p != ')' ) ) {
31✔
1850
                                MesPrint("&Illegal dimension field in table declaration");
×
1851
                                return(1);
×
1852
                        }
1853
                        mm1 = (MINMAX *)Malloc1((T->numind+1)*sizeof(MINMAX),"table dimensions");
31✔
1854
                        flags1 = (WORD *)Malloc1((T->numind+1)*sizeof(WORD),"table flags");
31✔
1855
                        for ( i = 0; i < T->numind; i++ ) { mm1[i] = T->mm[i]; flags1[i] = T->flags[i]; }
62✔
1856
                        if ( T->mm ) M_free(T->mm,"table dimensions");
31✔
1857
                        if ( T->flags ) M_free(T->flags,"table flags");
31✔
1858
                        T->mm = mm1;
31✔
1859
                        T->flags = flags1;
31✔
1860
                        mm = T->mm + T->numind;
31✔
1861
                        mm->mini = x; mm->maxi = y;
31✔
1862
                        T->totind *= mm->maxi-mm->mini+1;
31✔
1863
                        T->numind++;
31✔
1864
                        if ( *p == ')' ) { inp = p; break; }
31✔
1865
                }
1866
                w = T->tablepointers
216✔
1867
                  = (WORD *)Malloc1(TABLEEXTENSION*sizeof(WORD)*(T->totind),"table pointers");
108✔
1868
                i = T->totind;
108✔
1869
                for ( i = TABLEEXTENSION*T->totind; i > 0; i-- ) *w++ = -1; /* means: undefined */
1,512✔
1870
                for ( i = T->numind-1, x = 1; i >= 0; i-- ) {
139✔
1871
                        T->mm[i].size = x;        /* Defines increment in this dimension */
31✔
1872
                        x *= T->mm[i].maxi - T->mm[i].mini + 1;
31✔
1873
                }
1874
        }
1875
/*
1876
        Now we redo the 'function part' and send it to the compiler.
1877
        The prototype has to be picked up properly.
1878
*/
1879
        AT.WorkPointer++; /* We need one extra word later */
115✔
1880
        OldWork = AT.WorkPointer;
115✔
1881
        oldcbufnum = AC.cbufnum;
115✔
1882
        AC.cbufnum = T->bufnum;
115✔
1883
        C = cbuf+AC.cbufnum;
115✔
1884
        oldcpointer = C->Pointer - C->Buffer;
115✔
1885
        oldnumlhs = C->numlhs;
115✔
1886
        oldnumrhs = C->numrhs;
115✔
1887
        AddLHS(AC.cbufnum);
115✔
1888
        while ( s >= name ) *--inp = *s--;
709✔
1889
        w = AT.WorkPointer;
115✔
1890
        AC.ProtoType = w;
115✔
1891
        *w++ = SUBEXPRESSION;
115✔
1892
        *w++ = SUBEXPSIZE;
115✔
1893
        *w++ = 0;
115✔
1894
        *w++ = 1;
115✔
1895
        *w++ = AC.cbufnum;
115✔
1896
        FILLSUB(w)
1897
        AC.WildC = w;
115✔
1898
        AC.NwildC = 0;
115✔
1899
        AT.WorkPointer = w + 4*AM.MaxWildcards;
115✔
1900
        if ( ( ret = CompileAlgebra(inp,LHSIDE,AC.ProtoType) ) < 0 ) {
115✔
1901
                error = 1; goto FinishUp;
×
1902
        }
1903
        if ( AC.NwildC && SortWild(w,AC.NwildC) ) error = 1;
115✔
1904
        w += AC.NwildC;
115✔
1905
        i = w-OldWork;
115✔
1906
        OldWork[1] = i;
115✔
1907
/*
1908
        Basically we have to pull this pattern through Generator in case
1909
        there are functions inside functions, or parentheses.
1910
        We have to temporarily disable the .tabl to avoid problems with
1911
        TestSub.
1912
        Essential: we need to start NewSort twice to avoid the PutOut routines.
1913
        The ground pattern is sitting in C->numrhs, but it could be that it
1914
        has subexpressions in it. Hence it has to be worked out as the lhs in
1915
        id statements (in comexpr.c).
1916
*/
1917
        OldWork[2] = C->numrhs;
115✔
1918
        *w++ = 1; *w++ = 1; *w++ = 3;
115✔
1919
        OldWork[-1] = w-OldWork+1;
115✔
1920
        AT.WorkPointer = w;
115✔
1921
        ww = C->rhs[C->numrhs];
115✔
1922
        for ( j = 0; j < *ww; j++ ) w[j] = ww[j];
2,019✔
1923
        AT.WorkPointer = w+*w;
115✔
1924
        if ( *ww == 0 || ww[*ww] != 0 ) {
115✔
1925
                MesPrint("&Illegal table pattern definition");
×
1926
                AC.lhdollarflag = 0;
×
1927
                error = 1;
×
1928
        }
1929
        if ( error ) goto FinishUp;
115✔
1930

1931
        if ( NewSort(BHEAD0) || NewSort(BHEAD0) ) { error = 1; goto FinishUp; }
115✔
1932
        AN.RepPoint = AT.RepCount + 1;
115✔
1933
        AC.lhdollarflag = 0; oldEside = AR.Eside; AR.Eside = LHSIDE;
115✔
1934
        AR.Cnumlhs = C->numlhs;
115✔
1935
        functions[funnum].tabl = 0;
115✔
1936
        if ( Generator(BHEAD w,C->numlhs) ) {
115✔
1937
                functions[funnum].tabl = T;
×
1938
                AR.Eside = oldEside;
×
1939
                LowerSortLevel(); LowerSortLevel(); goto FinishUp;
×
1940
        }
1941
        functions[funnum].tabl = T;
115✔
1942
        AR.Eside = oldEside;
115✔
1943
        AT.WorkPointer = w;
115✔
1944
        if ( EndSort(BHEAD w,0) < 0 ) { LowerSortLevel(); goto FinishUp; }
115✔
1945
        if ( *w == 0 || *(w+*w) != 0 ) {
115✔
1946
                MesPrint("&Irregular pattern in table definition");
×
1947
                error = 1;
×
1948
                goto FinishUp;
×
1949
        }
1950
        LowerSortLevel();
115✔
1951
        if ( AC.lhdollarflag ) {
115✔
1952
                MesPrint("&Unexpanded dollar variables are not allowed in table definition");
×
1953
                error = 1;
×
1954
                goto FinishUp;
×
1955
        }
1956
        AT.WorkPointer = ww = w + *w;
115✔
1957
        if ( ww[-1] != 3 || ww[-2] != 1 || ww[-3] != 1 ) {
115✔
1958
                MesPrint("&Coefficient of pattern in table definition should be 1.");
×
1959
                error = 1;
×
1960
                goto FinishUp;
×
1961
        }
1962
        AC.DumNum = 0;
115✔
1963
/*
1964
        Now we have to allocate space for prototype+pattern
1965
        In the case of TFORM we need extra pointers, because each worker has its own
1966
*/
1967
        j = *w + ABS(T->numind)*2-3;
115✔
1968
#ifdef WITHPTHREADS
1969
        { int n;
34✔
1970
        T->prototypeSize = ((i+j)*sizeof(WORD)+2*sizeof(WORD *)) * AM.totalnumberofthreads;
34✔
1971
        T->prototype = (WORD **)Malloc1(T->prototypeSize,"table prototype");
34✔
1972
        T->pattern = T->prototype + AM.totalnumberofthreads;
34✔
1973
        t = (WORD *)(T->pattern + AM.totalnumberofthreads);
34✔
1974
        for ( n = 0; n < AM.totalnumberofthreads; n++ ) {
170✔
1975
                T->prototype[n] = t;
136✔
1976
                for ( k = 0; k < i; k++ ) *t++ = OldWork[k];
2,192✔
1977
        }
1978
        T->pattern[0] = t;
34✔
1979
        j--; w++;
34✔
1980
        w[1] += ABS(T->numind)*2;
34✔
1981
        for ( k = 0; k < FUNHEAD; k++ ) *t++ = *w++;
136✔
1982
        j -= FUNHEAD;
34✔
1983
        for ( k = 0; k < ABS(T->numind); k++ ) { *t++ = -SNUMBER; *t++ = 0; j -= 2; }
46✔
1984
        for ( k = 0; k < j; k++ ) *t++ = *w++;
368✔
1985
        if ( sparseflag ) T->pattern[0][1] = t - T->pattern[0];
34✔
1986
        k = t - T->pattern[0];
34✔
1987
        for ( n = 1; n < AM.totalnumberofthreads; n++ ) {
136✔
1988
                T->pattern[n] = t; tt = T->pattern[0];
102✔
1989
                for ( i = 0; i < k; i++ ) *t++ = *tt++;
1,482✔
1990
        }
1991
        }
1992
#else
1993
        T->prototypeSize = (i+j)*sizeof(WORD);
81✔
1994
        T->prototype = (WORD *)Malloc1(T->prototypeSize, "table prototype");
81✔
1995
        T->pattern = T->prototype + i;
81✔
1996
        for ( k = 0; k < i; k++ ) T->prototype[k] = OldWork[k];
1,346✔
1997
        t = T->pattern;
81✔
1998
        j--; w++;
81✔
1999
        w[1] += ABS(T->numind)*2;
81✔
2000
        for ( k = 0; k < FUNHEAD; k++ ) *t++ = *w++;
324✔
2001
        j -= FUNHEAD;
81✔
2002
        for ( k = 0; k < ABS(T->numind); k++ ) { *t++ = -SNUMBER; *t++ = 0; j -= 2; }
107✔
2003
        for ( k = 0; k < j; k++ ) *t++ = *w++;
916✔
2004
        if ( sparseflag ) T->pattern[1] = t - T->pattern;
81✔
2005
#endif
2006
/*
2007
        At this point we can pop the compilerbuffer.
2008
*/
2009
        C->Pointer = C->Buffer + oldcpointer;
115✔
2010
        C->numrhs = oldnumrhs;
115✔
2011
        C->numlhs = oldnumlhs;
115✔
2012
/*
2013
        Now check whether wildcards get converted to dollars (for PARALLEL)
2014
        We give a warning!
2015
*/
2016
#ifdef WITHPTHREADS
2017
        t = T->prototype[0];
34✔
2018
#else
2019
        t = T->prototype;
81✔
2020
#endif
2021
        tt = t + t[1]; t += SUBEXPSIZE;
115✔
2022
        while ( t < tt ) {
416✔
2023
                if ( *t == LOADDOLLAR ) {
301✔
2024
                        Warning("The use of $-variable assignments in tables disables parallel\
×
2025
 execution for the whole program.");
2026
                        AM.hparallelflag |= NOPARALLEL_TBLDOLLAR;
×
2027
                        AC.mparallelflag |= NOPARALLEL_TBLDOLLAR;
×
2028
                        AddPotModdollar(t[2]);
×
2029
                }
2030
                t += t[1];
301✔
2031
        }
2032
FinishUp:;
115✔
2033
        AT.WorkPointer = OldWork - 1;
115✔
2034
        AC.cbufnum = oldcbufnum;
115✔
2035
FinishUp2:;
115✔
2036
        if ( T->sparse ) ClearTableTree(T);
115✔
2037
        if ( ( sparseflag & 2 ) != 0 ) {
115✔
2038
                if ( T->spare == 0 ) { SpareTable(T); }
×
2039
        }
2040
        return(error);
2041
}
2042

2043
/*
2044
          #] DoTable : 
2045
          #[ CoTable :
2046
*/
2047

2048
int CoTable(UBYTE *s)
94✔
2049
{
2050
        return(DoTable(s,2));
94✔
2051
}
2052

2053
/*
2054
          #] CoTable : 
2055
          #[ CoNTable :
2056
*/
2057

2058
int CoNTable(UBYTE *s)
×
2059
{
2060
        return(DoTable(s,0));
×
2061
}
2062

2063
/*
2064
          #] CoNTable : 
2065
          #[ CoCTable :
2066
*/
2067

2068
int CoCTable(UBYTE *s)
21✔
2069
{
2070
        return(DoTable(s,1));
21✔
2071
}
2072

2073
/*
2074
          #] CoCTable : 
2075
          #[ EmptyTable :
2076
*/
2077

2078
void EmptyTable(TABLES T)
×
2079
{
2080
        int j;
×
2081
        if ( T->sparse ) ClearTableTree(T);
×
2082
        if ( T->boomlijst ) M_free(T->boomlijst,"TableTree");
×
2083
        T->boomlijst = 0;
×
2084
        for (j = 0; j < T->buffersfill; j++ ) { /* was <= */
×
2085
                finishcbuf(T->buffers[j]);
×
2086
        }
2087
        if ( T->buffers ) M_free(T->buffers,"Table buffers");
×
2088
        finishcbuf(T->bufnum);
×
2089
        T->bufnum = inicbufs();
×
2090
        T->bufferssize = 8;
×
2091
        T->buffers = (WORD *)Malloc1(sizeof(WORD)*T->bufferssize,"Table buffers");
×
2092
        T->buffersfill = 0;
×
2093
        T->buffers[T->buffersfill++] = T->bufnum;
×
2094
        T->defined = T->mdefined = 0; T->flags = 0;
×
2095
        T->numtree = 0; T->rootnum = 0; T->MaxTreeSize = 0;
×
2096
        T->spare = 0; T->reserved = 0;
×
2097
        if ( T->spare ) {
×
2098
                TABLES TT = T->spare;
2099
                if ( TT->mm ) M_free(TT->mm,"tableminmax");
2100
                if ( TT->flags ) M_free(TT->flags,"tableflags");
2101
                if ( TT->tablepointers ) M_free(TT->tablepointers,"tablepointers");
2102
                for (j = 0; j < TT->buffersfill; j++ ) {
2103
                        finishcbuf(TT->buffers[j]);
2104
                }
2105
                if ( TT->boomlijst ) M_free(TT->boomlijst,"TableTree");
2106
                if ( TT->buffers ) M_free(TT->buffers,"Table buffers");
2107
                M_free(TT,"table");
2108
                SpareTable(T);
2109
        }
2110
        else {
2111
                WORD *w = T->tablepointers;
×
2112
                j = T->totind;
×
2113
                for ( j = TABLEEXTENSION*T->totind; j > 0; j-- ) *w++ = -1; /* means: undefined */
×
2114
        }
2115
}
×
2116

2117
/*
2118
          #] EmptyTable : 
2119
          #[ AddSet :
2120
*/
2121

2122
int AddSet(UBYTE *name, WORD dim)
25,384✔
2123
{
2124
        int nodenum, numset = AC.SetList.num;
25,384✔
2125
        SETS set = (SETS)FromVarList(&AC.SetList);
25,384✔
2126
        UBYTE *s;
25,384✔
2127
        if ( name ) {
25,384✔
2128
                set->name = AddName(AC.varnames,name,CSET,numset,&nodenum);
23,200✔
2129
                s = name;
23,200✔
2130
                while ( *s ) s++;
160,463✔
2131
                set->namesize = (s-name)+1;
23,200✔
2132
                set->node  = nodenum;
23,200✔
2133
        }
2134
        else {
2135
                set->name = 0;
2,184✔
2136
                set->namesize = 0;
2,184✔
2137
                set->node  = -1;
2,184✔
2138
        }
2139
        set->first =
25,384✔
2140
        set->last  = AC.SetElementList.num;        /* set has no elements yet */
25,384✔
2141
        set->type  = -1;                                        /* undefined as of yet */
25,384✔
2142
        set->dimension = dim;
25,384✔
2143
        set->flags = 0;
25,384✔
2144
        return(numset);
25,384✔
2145
}
2146

2147
/*
2148
          #] AddSet : 
2149
          #[ DoElements :
2150

2151
        Remark (25-mar-2011): If the dimension has been set (dim != MAXPOSITIVE)
2152
        we want to test dimensions. Numbers count as dimension zero?
2153
*/
2154

2155
int DoElements(UBYTE *s, SETS set, UBYTE *name)
266✔
2156
{
2157
        int type, error = 0, x, sgn, i;
266✔
2158
        WORD numset, *e;
266✔
2159
        UBYTE c, *cname;
266✔
2160
        while ( *s ) {
1,561✔
2161
                if ( *s == ',' ) { s++; continue; }
1,295✔
2162
                sgn = 0;
2163
                while ( *s == '-' || *s == '+' ) { sgn ^= 1; s++; }
805✔
2164
                cname = s;
770✔
2165
                if ( FG.cTable[*s] == 0 || *s == '_' || *s == '[' ) {
770✔
2166
                        if ( ( s = SkipAName(s) ) == 0 ) {
693✔
2167
                                MesPrint("&Illegal name in set definition");
×
2168
                                return(1);
×
2169
                        }
2170
                        c = *s; *s = 0;
693✔
2171
                        if ( ( ( type = GetName(AC.exprnames,cname,&numset,NOAUTO) ) == NAMENOTFOUND )
693✔
2172
                        && ( ( type = GetOName(AC.varnames,cname,&numset,WITHAUTO) ) == NAMENOTFOUND ) ) {
693✔
2173
                                DUBIOUSV dv;
×
2174
                                int nodenum;
×
2175
                                MesPrint("&%s has not been declared",cname);
×
2176
/*
2177
                                We enter a 'dubious' declaration to cut down on errors
2178
*/
2179
                                numset = AC.DubiousList.num;
×
2180
                                dv = (DUBIOUSV)FromVarList(&AC.DubiousList);
×
2181
                                dv->name = AddName(AC.varnames,cname,CDUBIOUS,numset,&nodenum);
×
2182
                                dv->node = nodenum;
×
2183
                                set->type = type = CDUBIOUS;
×
2184
                                set->dimension = 0;
×
2185
                                error = 1;
×
2186
                        }
2187
                        if ( set->type == -1 ) {
693✔
2188
                                if ( type == CSYMBOL ) {
231✔
2189
                                        for ( i = set->first; i < set->last; i++ ) {
84✔
2190
                                                SetElements[i] += 2*MAXPOWER;
×
2191
                                        }
2192
                                }
2193
                                set->type = type;
231✔
2194
                        }
2195
                        if ( set->type != type && set->type != CDUBIOUS
693✔
2196
                        && type != CDUBIOUS ) {
×
2197
                                if ( set->type != CNUMBER || ( type != CSYMBOL
×
2198
                                && type != CINDEX ) ) {
×
2199
                                        MesPrint(
×
2200
                                        "&%s has not the same type as the other members of the set"
2201
                                        ,cname);
2202
                                        error = 1;
×
2203
                                        set->type = CDUBIOUS;
×
2204
                                }
2205
                                else {
2206
                                        if ( type == CSYMBOL ) {
×
2207
                                                for ( i = set->first; i < set->last; i++ ) {
×
2208
                                                        SetElements[i] += 2*MAXPOWER;
×
2209
                                                }
2210
                                        }
2211
                                        set->type = type;
×
2212
                                }
2213
                        }
2214
                        if ( set->dimension != MAXPOSITIVE ) { /* Dimension check */
693✔
2215
                                switch ( set->type ) {
×
2216
                                        case CSYMBOL:
×
2217
                                                if ( symbols[numset].dimension != set->dimension ) {
×
2218
                                                        MesPrint("&Dimension check failed in set %s, symbol %s",
×
2219
                                                                VARNAME(Sets,(set-Sets)),
×
2220
                                                                VARNAME(symbols,numset));
×
2221
                                                        error = 1;
×
2222
                                                        set->dimension = MAXPOSITIVE;
×
2223
                                                }
2224
                                                break;
2225
                                        case CVECTOR:
×
2226
                                                if ( vectors[numset-AM.OffsetVector].dimension != set->dimension ) {
×
2227
                                                        MesPrint("&Dimension check failed in set %s, vector %s",
×
2228
                                                                VARNAME(Sets,(set-Sets)),
×
2229
                                                                VARNAME(vectors,(numset-AM.OffsetVector)));
×
2230
                                                        error = 1;
×
2231
                                                        set->dimension = MAXPOSITIVE;
×
2232
                                                }
2233
                                                break;
2234
                                        case CFUNCTION:
×
2235
                                                if ( functions[numset-FUNCTION].dimension != set->dimension ) {
×
2236
                                                        MesPrint("&Dimension check failed in set %s, function %s",
×
2237
                                                                VARNAME(Sets,(set-Sets)),
×
2238
                                                                VARNAME(functions,(numset-FUNCTION)));
×
2239
                                                        error = 1;
×
2240
                                                }
2241
                                                break;
2242
                                                        set->dimension = MAXPOSITIVE;
2243
                                }
2244
                        }
693✔
2245
                        if ( sgn ) {
693✔
2246
                                if ( type != CVECTOR ) {
28✔
2247
                                        MesPrint("&Illegal use of - sign in set. Can use only with vector or number");
×
2248
                                        error = 1;
×
2249
                                }
2250
/*
2251
                                numset = AM.OffsetVector - numset;
2252
                                numset |= SPECMASK;
2253
                                numset = AM.OffsetVector - numset;
2254
*/
2255
                                numset -= WILDMASK;
28✔
2256
                        }
2257
                        *s = c;
693✔
2258
                        if ( name == 0 && *s == '?' ) {
693✔
2259
                                s++;
56✔
2260
                                switch ( set->type ) {
56✔
2261
                                        case CSYMBOL:
56✔
2262
                                                numset = -numset; break;
56✔
2263
                                        case CVECTOR:
×
2264
                                                numset += WILDOFFSET; break;
×
2265
                                        case CINDEX:
×
2266
                                                numset |= WILDMASK; break;
×
2267
                                        case CFUNCTION:
×
2268
                                                numset |= WILDMASK; break;
×
2269
                                }
2270
                                AC.wildflag = 1;
56✔
2271
                        }
2272
/*
2273
                        Now add the element to the set.
2274
*/
2275
                        e = (WORD *)FromVarList(&AC.SetElementList);
693✔
2276
                        *e = numset;
693✔
2277
                        (set->last)++;
693✔
2278
                }
2279
                else if ( FG.cTable[*s] == 1 ) {
77✔
2280
                        ParseNumber(x,s)
210✔
2281
                        if ( sgn ) x = -x;
77✔
2282
                        if ( x >= MAXPOWER || x <= -MAXPOWER ||
77✔
2283
                        ( set->type == CINDEX && ( x < 0 || x >= AM.OffsetIndex ) ) ) {
77✔
2284
                                MesPrint("&Illegal value for set element: %d",x);
×
2285
                                if ( AC.firstconstindex ) {
×
2286
                                MesPrint("&0 <= Fixed indices < ConstIndex(which is %d)",
×
2287
                                        AM.OffsetIndex-1);
×
2288
                                MesPrint("&For setting ConstIndex, read the chapter on the setup file");
×
2289
                                AC.firstconstindex = 0;
×
2290
                                }
2291
                                error = 1;
2292
                                x = 0;
2293
                        }
2294
/*
2295
                        Check what is allowed with the type.
2296
*/
2297
                        if ( set->type == -1 ) {
77✔
2298
                                if ( x < 0 || x >= AM.OffsetIndex ) {
28✔
2299
                                        for ( i = set->first; i < set->last; i++ ) {
×
2300
                                                SetElements[i] += 2*MAXPOWER;
×
2301
                                        }
2302
                                        set->type = CSYMBOL;
×
2303
                                }
2304
                                else set->type = CNUMBER;
28✔
2305
                        }
2306
                        else if ( set->type == CDUBIOUS ) {}
49✔
2307
                        else if ( set->type == CNUMBER && x < 0 ) {
49✔
2308
                                for ( i = set->first; i < set->last; i++ ) {
21✔
2309
                                        SetElements[i] += 2*MAXPOWER;
14✔
2310
                                }
2311
                                set->type = CSYMBOL;
7✔
2312
                        }
2313
                        else if ( set->type != CSYMBOL && ( x < 0 ||
42✔
2314
                        ( set->type != CINDEX && set->type != CNUMBER ) ) ) {
42✔
2315
                                MesPrint("&Illegal mixture of element types in set");
×
2316
                                error = 1;
×
2317
                                set->type = CDUBIOUS;                                        
×
2318
                        }
2319
/*
2320
                        Allocate an element
2321
*/
2322
                        e = (WORD *)FromVarList(&AC.SetElementList);
77✔
2323
                        (set->last)++;
77✔
2324
                        if ( set->type == CSYMBOL ) *e = x + 2*MAXPOWER;
77✔
2325
/*                        else if ( set->type == CINDEX ) *e = x; */
2326
                        else *e = x;
70✔
2327
                }
2328
                else {
2329
                        MesPrint("&Illegal object in list of set elements");
×
2330
                        return(1);
×
2331
                }
2332
        }
2333
        if ( error == 0 && ( ( set->flags & ORDEREDSET ) == ORDEREDSET ) ) {
266✔
2334
/*
2335
                The set->last-set->first list of numbers must be sorted.
2336
                Because we plan here potentially thousands of elements we use
2337
                a simple version of splitmerge. In ordered sets we can search
2338
                later with a binary search.
2339
*/
2340
                SimpleSplitMerge(SetElements+set->first,set->last-set->first);
×
2341
        }
2342
        return(error);
2343
}
2344

2345
/*
2346
          #] DoElements : 
2347
          #[ CoSet :
2348

2349
        Set declarations.
2350
*/
2351

2352
int CoSet(UBYTE *s)
105✔
2353
{
2354
        int type, error = 0, ordered = 0;
105✔
2355
        UBYTE *name = s, c, *ss;
105✔
2356
        SETS set;
105✔
2357
        WORD numberofset, dim = MAXPOSITIVE;
105✔
2358
#ifdef WITHFLOAT
2359
/*----------------------------------------------------------------*/
2360
        {
2361
                WORD numeq = 0;
105✔
2362
                LONG x;
105✔
2363
                ss = s;
105✔
2364
                while ( *ss && *ss != ':' ) { if ( *ss == '=' ) numeq++; ss++; }
588✔
2365
                if ( *ss == 0 && numeq == 1 ) { /* We have the Set var = value; variety */
105✔
2366
                        while ( FG.cTable[*s] == 0 ) s++;
×
2367
                        ss = s; c = *s; *s = 0;
×
2368
                        if ( c != '=' ) {
×
2369
Proper:
×
2370
                                MesPrint("&Proper syntax for value-set is `Set name = value'");
×
2371
                                return(1);
×
2372
                        }
2373
                        x = 0; s++;
×
2374
                        while ( *s >= '0' && *s <= '9' ) x = 10*x + (*s++-'0');
×
2375
                        if ( *s ) goto Proper;
×
2376
                        if ( StrICmp(name,(UBYTE *)"maxweight") == 0 ) {
×
2377
                                AC.tMaxWeight = x;   /* Temporary. Made permanent later */
×
2378
                        }
2379
                        else if ( StrICmp(name,(UBYTE *)"defaultprecision") == 0 ) {
×
2380
                                AC.tDefaultPrecision = x;   /* Temporary. Made permanent later */
×
2381
                        }
2382
                        else {
2383
                                MesPrint("&Illegal subkey in value set: %s",name);
×
2384
                                return(1);
×
2385
                        }
2386
                }                
2387
        }
2388
/*----------------------------------------------------------------*/
2389
#endif
2390
        if ( ( s = SkipAName(s) ) == 0 ) {
105✔
2391
IllForm:MesPrint("&Illegal name for set");
×
2392
                return(1);
×
2393
        }
2394
        c = *s; *s = 0;
105✔
2395
        if ( TestName(name) ) goto IllForm;
105✔
2396
        if ( ( ( type = GetName(AC.exprnames,name,&numberofset,NOAUTO) ) != NAMENOTFOUND )
105✔
2397
        || ( ( type = GetName(AC.varnames,name,&numberofset,NOAUTO) ) != NAMENOTFOUND ) ) {
105✔
2398
                if ( type != CSET ) NameConflict(type,name);
×
2399
                else {
2400
                        MesPrint("&There is already a set with the name %s",name);
×
2401
                }
2402
                return(1);
×
2403
        }
2404
        if ( c == 0 ) {
105✔
2405
                numberofset = AddSet(name,0);
7✔
2406
                set = Sets + numberofset;
7✔
2407
                return(0);                /* empty set */
7✔
2408
        }
2409
        *s = c; ss = s;     /* ss marks the end of the name */
98✔
2410
        if ( *s == '(' ) {
98✔
2411
                UBYTE *sss, cc;
×
2412
                s++; sss = s;   /* Beginning of option */
×
2413
                while ( *s != ',' && *s != ')' && *s ) s++;
×
2414
                cc = *s; *s = 0;
×
2415
                if ( StrICont(sss,(UBYTE *)"ordered") == 0 ) {
×
2416
                        ordered = ORDEREDSET;
2417
                }
2418
                else {
2419
                        MesPrint("&Error: Illegal option in set definition: %s",sss);
×
2420
                        error = 1;
×
2421
                }
2422
                *s = cc;
×
2423
                if ( *s != ')' ) {
×
2424
                        MesPrint("&Error: Currently only one option allowed in set definition.");
×
2425
                        error = 1;
×
2426
                        while ( *s && *s != ')' ) s++;
×
2427
                }
2428
                s++;
×
2429
        }
2430
        if ( *s == '{' ) {
98✔
2431
                s++;
×
2432
                if ( ( *s == 'd' || *s == 'D' ) && s[1] == '=' ) {
×
2433
                        s += 2;
×
2434
                        if ( *s == '-' || *s == '+' || FG.cTable[*s] == 1 ) {
×
2435
                                ParseSignedNumber(dim,s)
×
2436
                                if ( dim < -HALFMAX || dim > HALFMAX ) {
×
2437
                                        MesPrint("&Warning: dimension of %s (%d) out of range"
×
2438
                                        ,name,dim);
2439
                                }
2440
                        }
2441
                        if ( *s != '}' ) goto IllDim;
×
2442
                        else s++;
×
2443
                }
2444
                else {
2445
IllDim:                MesPrint("&Error: Illegal dimension field for set %s",name);
×
2446
                        error = 1;
×
2447
                        s = SkipField(s,0);
×
2448
                }
2449
                while ( *s == ',' ) s++;
×
2450
        }
2451
        c = *ss; *ss = 0;
98✔
2452
        numberofset = AddSet(name,dim);
98✔
2453
        *ss = c;
98✔
2454
        set = Sets + numberofset;
98✔
2455
        set->flags |= ordered;
98✔
2456
        if ( *s != ':' ) {
98✔
2457
                MesPrint("&Proper syntax is `Set name:elements'");
×
2458
                return(1);
×
2459
        }
2460
        s++;
98✔
2461
        error = DoElements(s,set,name);
98✔
2462
        AC.SetList.numtemp = AC.SetList.num;
98✔
2463
        AC.SetElementList.numtemp = AC.SetElementList.num;
98✔
2464
        return(error);
98✔
2465
}
2466

2467
/*
2468
          #] CoSet : 
2469
          #[ DoTempSet :
2470

2471
                Gets a {} set definition and returns a set number if the set is
2472
                properly structured. This number refers either to an already
2473
                existing set, or to a set that is defined here.
2474
                From and to refer to the contents. They exclude the {}.
2475
*/
2476

2477
int DoTempSet(UBYTE *from, UBYTE *to)
2,184✔
2478
{
2479
        int i, num, j, sgn;
2,184✔
2480
        WORD *e, *ep;
2,184✔
2481
        UBYTE c;
2,184✔
2482
        int setnum = AddSet(0,MAXPOSITIVE);
2,184✔
2483
        SETS set = Sets + setnum, setp;
2,184✔
2484
        set->name = -1;
2,184✔
2485
        set->type = -1;
2,184✔
2486
        c = *to; *to = 0;
2,184✔
2487
        AC.wildflag = 0;
2,184✔
2488
        while ( *from == ',' ) from++;
4,200✔
2489
        if ( *from == '<' || *from == '>' ) {
2,184✔
2490
                set->type = CRANGE;
2,016✔
2491
                set->first = 3*MAXPOWER;
2,016✔
2492
                set->last = -3*MAXPOWER;
2,016✔
2493
                while ( *from == '<' || *from == '>' ) {
4,032✔
2494
                        if ( *from == '<' ) {
2,016✔
2495
                                j = 1; from++;
×
2496
                                if ( *from == '=' ) { from++; j++; }
×
2497
                        }
2498
                        else {
2499
                                j = -1; from++;
2,016✔
2500
                                if ( *from == '=' ) { from++; j--; }
2,016✔
2501
                        }
2502
                        sgn = 1;
2,016✔
2503
                        while ( *from == '-' || *from == '+' ) {
2,016✔
2504
                                if ( *from == '-' ) sgn = -sgn;
×
2505
                                from++;
×
2506
                        }
2507
                        ParseNumber(num,from)
4,032✔
2508
                        if ( *from && *from != ',' ) {
2,016✔
2509
                                MesPrint("&Illegal number in ranged set definition");
×
2510
                                return(-1);
×
2511
                        }
2512
                        if ( sgn < 0 ) num = -num;
2,016✔
2513
                        if ( num >= MAXPOWER || num <= -MAXPOWER ) {
2,016✔
2514
                                Warning("Value in ranged set too big. Adjusted to infinity.");
×
2515
                                if ( num > 0 ) num =  3*MAXPOWER;
×
2516
                                else           num = -3*MAXPOWER;
×
2517
                        }
2518
                        else if ( j ==  2 ) num += 2*MAXPOWER;
2,016✔
2519
                        else if ( j == -2 ) num -= 2*MAXPOWER;
2,016✔
2520
                        if ( j > 0 ) set->first = num;
2,016✔
2521
                        else set->last = num;
2,016✔
2522
                        while ( *from == ',' ) from++;
2,016✔
2523
                }
2524
                if ( *from ) {
2,016✔
2525
                        MesPrint("&Definition of ranged set contains illegal objects");
×
2526
                        return(-1);
×
2527
                }
2528
        }
2529
        else if ( DoElements(from,set,(UBYTE *)0) != 0 ) {
168✔
2530
                AC.SetElementList.num = set->first;
×
2531
                AC.SetList.num--; *to = c;
×
2532
                return(-1);
×
2533
        }
2534
        *to = c;
2,184✔
2535
/*
2536
        Now we have to test whether this set exists already.
2537
*/
2538
        num = set->last - set->first;
2,184✔
2539
        for ( setp = Sets, i = 0; i < AC.SetList.num-1; i++, setp++ ) {
34,328✔
2540
                if ( num != setp->last - setp->first ) continue;
34,153✔
2541
                if ( set->type != setp->type ) continue;
2,079✔
2542
                if ( set->type == CRANGE ) {
2,058✔
2543
                        if ( set->first == setp->first ) return(setp-Sets);
1,988✔
2544
                }
2545
                else {
2546
                        e = SetElements + set->first;
70✔
2547
                        ep = SetElements + setp->first;
70✔
2548
                        j = num;
70✔
2549
                        while ( --j >= 0 ) if ( *e++ != *ep++ ) break;
98✔
2550
                        if ( j < 0 ) {
70✔
2551
                                AC.SetElementList.num = set->first;
21✔
2552
                                AC.SetList.num--;
21✔
2553
                                return(setp - Sets);
21✔
2554
                        }
2555
                }
2556
        }
2557
        return(setnum);
2558
}
2559

2560
/*
2561
          #] DoTempSet : 
2562
          #[ CoAuto :
2563

2564
        To prepare first:
2565
                Use of the proper pointers in the various declaration routines
2566
                Proper action in .store and .clear
2567
*/
2568

2569
int CoAuto(UBYTE *inp)
115✔
2570
{
2571
        int retval;
115✔
2572

2573
        AC.Symbols = &(AC.AutoSymbolList);
115✔
2574
        AC.Vectors = &(AC.AutoVectorList);
115✔
2575
        AC.Indices = &(AC.AutoIndexList);
115✔
2576
        AC.Functions = &(AC.AutoFunctionList);
115✔
2577
        AC.activenames = &(AC.autonames);
115✔
2578
        AC.AutoDeclareFlag = WITHAUTO;
115✔
2579

2580
        while ( *inp == ',' ) inp++;
115✔
2581
        retval = CompileStatement(inp);
115✔
2582

2583
        AC.AutoDeclareFlag = 0;
115✔
2584
        AC.Symbols = &(AC.SymbolList);
115✔
2585
        AC.Vectors = &(AC.VectorList);
115✔
2586
        AC.Indices = &(AC.IndexList);
115✔
2587
        AC.Functions = &(AC.FunctionList);
115✔
2588
        AC.activenames = &(AC.varnames);
115✔
2589
        return(retval);
115✔
2590
}
2591

2592
/*
2593
          #] CoAuto : 
2594
          #[ AddDollar :
2595

2596
        The actual addition. Special routine for additions 'on the fly'
2597
*/
2598

2599
int AddDollar(UBYTE *name, WORD type, WORD *start, LONG size)
2,381✔
2600
{
2601
        int nodenum, numdollar = AP.DollarList.num;
2,381✔
2602
        WORD *s, *t;
2,381✔
2603
        DOLLARS dol = (DOLLARS)FromVarList(&AP.DollarList);
2,381✔
2604
        dol->name = AddName(AC.dollarnames,name,CDOLLAR,numdollar,&nodenum);
2,381✔
2605
        dol->type = type;
2,381✔
2606
        dol->node = nodenum;
2,381✔
2607
        dol->zero = 0;
2,381✔
2608
        dol->numdummies = 0;
2,381✔
2609
#ifdef WITHPTHREADS
2610
        dol->pthreadslockread = dummylock;
706✔
2611
        dol->pthreadslockwrite = dummylock;
706✔
2612
#endif
2613
        dol->nfactors = 0;
2,381✔
2614
        dol->factors = 0;
2,381✔
2615
        AddRHS(AM.dbufnum,1);
2,381✔
2616
        AddLHS(AM.dbufnum);
2,381✔
2617
        if ( start && size > 0 ) {
2,381✔
2618
                dol->size = size;
×
2619
                dol->where =
×
2620
                s = (WORD *)Malloc1((size+1)*sizeof(WORD),"$-variable contents");
×
2621
                t = start;
×
2622
                while ( --size >= 0 ) *s++ = *t++;
×
2623
                *s = 0;
×
2624
        }
2625
        else { dol->where = &(AM.dollarzero); dol->size = 0; }
2,381✔
2626
        cbuf[AM.dbufnum].rhs[numdollar] = dol->where;
2,381✔
2627
        cbuf[AM.dbufnum].CanCommu[numdollar] = 0;
2,381✔
2628
        cbuf[AM.dbufnum].NumTerms[numdollar] = 0;
2,381✔
2629

2630
        return(numdollar);
2,381✔
2631
}
2632

2633
/*
2634
          #] AddDollar : 
2635
          #[ ReplaceDollar :
2636

2637
        Replacements of dollar variables can happen at any time.
2638
        For debugging purposes we should have a tracing facility.
2639

2640
        Not in use????
2641
*/
2642

2643
int ReplaceDollar(WORD number, WORD newtype, WORD *newstart, LONG newsize)
×
2644
{
2645
        int error = 0;
×
2646
        DOLLARS dol = Dollars + number;
×
2647
        WORD *s, *t;
×
2648
        LONG i;
×
2649
        dol->type = newtype;
×
2650
        if ( dol->size == newsize && newsize > 0 && newstart ) {
×
2651
                s = dol->where; t = newstart; i = newsize;
×
2652
                while ( --i >= 0 ) { if ( *s++ != *t++ ) break; }
×
2653
                if ( i < 0 ) return(0);
×
2654
        }
2655
        if ( dol->where && dol->where != &(dol->zero) ) {
×
2656
                M_free(dol->where,"dollar->where"); dol->where = &(dol->zero); dol->size = 0;
×
2657
        }
2658
        if ( newstart && newsize > 0 ) {
×
2659
                dol->size = newsize;
×
2660
                dol->where =
×
2661
                s = (WORD *)Malloc1((newsize+1)*sizeof(WORD),"$-variable contents");
×
2662
                t = newstart; i = newsize;
×
2663
                while ( --i >= 0 ) *s++ = *t++;
×
2664
                *s = 0;
×
2665
        }
2666
        return(error);
2667
}
2668

2669
/*
2670
          #] ReplaceDollar : 
2671
          #[ AddDubious :
2672

2673
        This adds a variable of which we do not know the proper type.
2674
*/
2675

2676
int AddDubious(UBYTE *name)
×
2677
{
2678
        int nodenum, numdubious = AC.DubiousList.num;
×
2679
        DUBIOUSV dub = (DUBIOUSV)FromVarList(&AC.DubiousList);
×
2680
        dub->name = AddName(AC.varnames,name,CDUBIOUS,numdubious,&nodenum);
×
2681
        dub->node = nodenum;
×
2682
        return(numdubious);
×
2683
}
2684

2685
/*
2686
          #] AddDubious : 
2687
          #[ MakeDubious :
2688
*/
2689

2690
int MakeDubious(NAMETREE *nametree, UBYTE *name, WORD *number)
×
2691
{
2692
        NAMENODE *n;
×
2693
        int node, newnode, i;
×
2694
        if ( nametree->namenode == 0 ) return(-1);
×
2695
        newnode = nametree->headnode;
×
2696
        do {
×
2697
                node = newnode;
×
2698
                n = nametree->namenode+node;
×
2699
                if ( ( i = StrCmp(name,nametree->namebuffer+n->name) ) < 0 )
×
2700
                        newnode = n->left;
×
2701
                else if ( i > 0 ) newnode = n->right;
×
2702
                else {
2703
                        if ( n->type != CDUBIOUS ) {
×
2704
                                int numdubious = AC.DubiousList.num;
×
2705
                                FUNCTIONS dub = (FUNCTIONS)FromVarList(&AC.DubiousList);
×
2706
                                dub->name = n->name;
×
2707
                                n->number = numdubious;
×
2708
                        }
2709
                        *number = n->number;
×
2710
                        return(CDUBIOUS);
×
2711
                }
2712
        } while ( newnode >= 0 );
×
2713
        return(-1);
2714
}
2715

2716
/*
2717
          #] MakeDubious : 
2718
          #[ NameConflict :
2719
*/
2720

2721
static char *nametype[] = { "symbol", "index", "vector", "function",
2722
                "set", "expression" };
2723
static char *plural[] = { "","n","","","","n" };
2724

2725
int NameConflict(int type, UBYTE *name)
×
2726
{
2727
        if ( type == NAMENOTFOUND ) {
×
2728
                MesPrint("&%s has not been declared",name);
×
2729
        }
2730
        else if ( type != CDUBIOUS )
×
2731
                MesPrint("&%s has been declared as a%s %s already"
×
2732
                        ,name,plural[type],nametype[type]);
2733
        return(1);
×
2734
}
2735

2736
/*
2737
          #] NameConflict : 
2738
          #[ AddExpression :
2739
*/
2740

2741
int AddExpression(UBYTE *name, int x, int y)
7,193✔
2742
{
2743
        int nodenum, numexpr = AC.ExpressionList.num;
7,193✔
2744
        EXPRESSIONS expr = (EXPRESSIONS)FromVarList(&AC.ExpressionList);
7,193✔
2745
        UBYTE *s;
7,193✔
2746
        expr->status = x;
7,193✔
2747
        expr->printflag = y;
7,193✔
2748
        PUTZERO(expr->onfile);
7,193✔
2749
        PUTZERO(expr->size);
7,193✔
2750
        expr->renum = 0;
7,193✔
2751
        expr->renumlists = 0;
7,193✔
2752
        expr->hidelevel = 0;
7,193✔
2753
        expr->inmem = 0;
7,193✔
2754
        expr->bracketinfo = expr->newbracketinfo = 0;
7,193✔
2755
        if ( name ) {
7,193✔
2756
                expr->name = AddName(AC.exprnames,name,CEXPRESSION,numexpr,&nodenum);
7,018✔
2757
                expr->node = nodenum;
7,018✔
2758
                expr->replace = NEWLYDEFINEDEXPRESSION ;
7,018✔
2759
                s = name;
7,018✔
2760
                while ( *s ) s++;
34,748✔
2761
                expr->namesize = (s-name)+1;
7,018✔
2762
        }
2763
        else {
2764
                expr->replace = REDEFINEDEXPRESSION;
175✔
2765
                expr->name = AC.TransEname;
175✔
2766
                expr->node = -1;
175✔
2767
                expr->namesize = 0;
175✔
2768
        }
2769
        expr->vflags = 0;
7,193✔
2770
        expr->numdummies = 0;
7,193✔
2771
        expr->numfactors = 0;
7,193✔
2772
#ifdef PARALLELCODE
2773
        expr->partodo = 0;
6,134✔
2774
#endif
2775
        expr->uflags = 0;
7,193✔
2776
        return(numexpr);
7,193✔
2777
}
2778

2779
/*
2780
          #] AddExpression : 
2781
          #[ GetLabel :
2782
*/
2783

2784
int GetLabel(UBYTE *name)
3,052✔
2785
{
2786
        int i;
3,052✔
2787
        LONG newnum;
3,052✔
2788
        UBYTE **NewLabelNames;
3,052✔
2789
        int *NewLabel;
3,052✔
2790
        for ( i = 0; i < AC.NumLabels; i++ ) {
8,344✔
2791
                if ( StrCmp(name,AC.LabelNames[i]) == 0 ) return(i);
8,113✔
2792
        }
2793
        if ( AC.NumLabels >= AC.MaxLabels ) {
231✔
2794
                newnum = 2*AC.MaxLabels;
35✔
2795
                if ( newnum == 0 ) newnum = 10;
35✔
2796
                if ( newnum > 32765 ) newnum = 32765;
14✔
2797
                if ( newnum == AC.MaxLabels ) {
35✔
2798
                        MesPrint("&More than 32765 labels in one module. Please simplify.");
×
NEW
2799
                        TERMINATE(-1);
×
2800
                }
2801
                NewLabelNames = (UBYTE **)Malloc1((sizeof(UBYTE *)+sizeof(int))
70✔
2802
                                *newnum,"Labels");
35✔
2803
                NewLabel = (int *)(NewLabelNames+newnum);
35✔
2804
                for ( i = 0; i< AC.MaxLabels; i++ ) {
245✔
2805
                        NewLabelNames[i] = AC.LabelNames[i];
210✔
2806
                        NewLabel[i] = AC.Labels[i];
210✔
2807
                }
2808
                if ( AC.LabelNames ) M_free(AC.LabelNames,"Labels");
35✔
2809
                AC.LabelNames = NewLabelNames;
35✔
2810
                AC.Labels = NewLabel;
35✔
2811
                AC.MaxLabels = newnum;
35✔
2812
        }
2813
        i = AC.NumLabels++;
231✔
2814
        AC.LabelNames[i] = strDup1(name,"Labels");
231✔
2815
        AC.Labels[i] = -1;
231✔
2816
        return(i);
231✔
2817
}
2818

2819
/*
2820
          #] GetLabel : 
2821
          #[ ResetVariables :
2822

2823
        Resets the variables.
2824
        par = 0  The list of temporary sets (after each .sort)
2825
        par = 1  The list of local variables (after each .store)
2826
        par = 2  All variables (after each .clear)
2827
*/
2828

2829
void ResetVariables(int par)
3,405✔
2830
{
2831
        int i, j;
3,405✔
2832
        TABLES T;
3,405✔
2833
        switch ( par ) {
3,405✔
2834
        case 0 : /* Only the sets without a name */
3,377✔
2835
                AC.SetList.num        = AC.SetList.numtemp;
3,377✔
2836
                AC.SetElementList.num = AC.SetElementList.numtemp;
3,377✔
2837
                break;
3,377✔
2838
        case 2 :
×
2839
                for ( i = AC.SymbolList.numclear; i < AC.SymbolList.num; i++ )
×
2840
                        AC.varnames->namenode[symbols[i].node].type = CDELETE;
×
2841
                AC.SymbolList.num = AC.SymbolList.numglobal = AC.SymbolList.numclear;
×
2842
                for ( i = AC.VectorList.numclear; i < AC.VectorList.num; i++ )
×
2843
                        AC.varnames->namenode[vectors[i].node].type = CDELETE;
×
2844
                AC.VectorList.num = AC.VectorList.numglobal = AC.VectorList.numclear;
×
2845
                for ( i = AC.IndexList.numclear; i < AC.IndexList.num; i++ )
×
2846
                        AC.varnames->namenode[indices[i].node].type = CDELETE;
×
2847
                AC.IndexList.num = AC.IndexList.numglobal = AC.IndexList.numclear;
×
2848
                for ( i = AC.FunctionList.numclear; i < AC.FunctionList.num; i++ ) {
×
2849
                        AC.varnames->namenode[functions[i].node].type = CDELETE;
×
2850
                        if ( ( T = functions[i].tabl ) != 0 ) {
×
2851
                                if ( T->tablepointers ) M_free(T->tablepointers,"tablepointers");
×
2852
                                if ( T->prototype ) M_free(T->prototype,"tableprototype");
×
2853
                                if ( T->mm ) M_free(T->mm,"tableminmax");
×
2854
                                if ( T->flags ) M_free(T->flags,"tableflags");
×
2855
                                if ( T->argtail ) M_free(T->argtail,"table arguments");
×
2856
                                if ( T->boomlijst ) M_free(T->boomlijst,"TableTree");
×
2857
                                for (j = 0; j < T->buffersfill; j++ ) { /* was <= */
×
2858
                                        finishcbuf(T->buffers[j]);
×
2859
                                }
2860
                                /*[07apr2004 mt]:*/ /*memory leak*/
2861
                                if ( T->buffers ) M_free(T->buffers,"Table buffers");
×
2862
                                /*:[07apr2004 mt]*/ 
2863
                                finishcbuf(T->bufnum);
×
2864
                                if ( T->spare ) {
×
2865
                                        TABLES TT = T->spare;
×
2866
                                        if ( TT->mm ) M_free(TT->mm,"tableminmax");
×
2867
                                        if ( TT->flags ) M_free(TT->flags,"tableflags");
×
2868
                                        if ( TT->tablepointers ) M_free(TT->tablepointers,"tablepointers");
×
2869
                                        for (j = 0; j < TT->buffersfill; j++ ) { /* was <= */
×
2870
                                                finishcbuf(TT->buffers[j]);
×
2871
                                        }
2872
                                        if ( TT->boomlijst ) M_free(TT->boomlijst,"TableTree");
×
2873
                                        /*[07apr2004 mt]:*/ /*memory leak*/
2874
                                        if ( TT->buffers )M_free(TT->buffers,"Table buffers");
×
2875
                                        /*:[07apr2004 mt]*/
2876
                                        M_free(TT,"table");
×
2877
                                }
2878
                                M_free(T,"table");
×
2879
                        }
2880
                }
2881
                AC.FunctionList.num = AC.FunctionList.numglobal = AC.FunctionList.numclear;
×
2882
                for ( i = AC.SetList.numclear; i < AC.SetList.num; i++ ) {
×
2883
                        if ( Sets[i].node >= 0 )
×
2884
                                AC.varnames->namenode[Sets[i].node].type = CDELETE;
×
2885
                }
2886
                AC.SetList.numtemp = AC.SetList.num = AC.SetList.numglobal = AC.SetList.numclear;
×
2887
                for ( i = AC.DubiousList.numclear; i < AC.DubiousList.num; i++ )
×
2888
                        AC.varnames->namenode[Dubious[i].node].type = CDELETE;
×
2889
                AC.DubiousList.num = AC.DubiousList.numglobal = AC.DubiousList.numclear;
×
2890
                AC.SetElementList.numtemp = AC.SetElementList.num =
×
2891
                        AC.SetElementList.numglobal = AC.SetElementList.numclear;
×
2892
                CompactifyTree(AC.varnames,VARNAMES);
×
2893
                AC.varnames->namefill = AC.varnames->globalnamefill = AC.varnames->clearnamefill;
×
2894
                AC.varnames->nodefill = AC.varnames->globalnodefill = AC.varnames->clearnodefill;
×
2895

2896
                for ( i = AC.AutoSymbolList.numclear; i < AC.AutoSymbolList.num; i++ )
×
2897
                        AC.autonames->namenode[
×
2898
                                        ((SYMBOLS)(AC.AutoSymbolList.lijst))[i].node].type = CDELETE;
×
2899
                AC.AutoSymbolList.num = AC.AutoSymbolList.numglobal
×
2900
                                                         = AC.AutoSymbolList.numclear;
×
2901
                for ( i = AC.AutoVectorList.numclear; i < AC.AutoVectorList.num; i++ )
×
2902
                        AC.autonames->namenode[
×
2903
                                        ((VECTORS)(AC.AutoVectorList.lijst))[i].node].type = CDELETE;
×
2904
                AC.AutoVectorList.num = AC.AutoVectorList.numglobal
×
2905
                                                         = AC.AutoVectorList.numclear;
×
2906
                for ( i = AC.AutoIndexList.numclear; i < AC.AutoIndexList.num; i++ )
×
2907
                        AC.autonames->namenode[
×
2908
                                        ((INDICES)(AC.AutoIndexList.lijst))[i].node].type = CDELETE;
×
2909
                AC.AutoIndexList.num = AC.AutoIndexList.numglobal
×
2910
                                                    = AC.AutoIndexList.numclear;
×
2911
                for ( i = AC.AutoFunctionList.numclear; i < AC.AutoFunctionList.num; i++ ) {
×
2912
                        AC.autonames->namenode[
×
2913
                                        ((FUNCTIONS)(AC.AutoFunctionList.lijst))[i].node].type = CDELETE;
×
2914
                        if ( ( T = ((FUNCTIONS)(AC.AutoFunctionList.lijst))[i].tabl ) != 0 ) {
×
2915
                                if ( T->tablepointers ) M_free(T->tablepointers,"tablepointers");
×
2916
                                if ( T->prototype ) M_free(T->prototype,"tableprototype");
×
2917
                                if ( T->mm ) M_free(T->mm,"tableminmax");
×
2918
                                if ( T->flags ) M_free(T->flags,"tableflags");
×
2919
                                if ( T->argtail ) M_free(T->argtail,"table arguments");
×
2920
                                if ( T->boomlijst ) M_free(T->boomlijst,"TableTree");
×
2921
                                for (j = 0; j < T->buffersfill; j++ ) { /* was <= */
×
2922
                                        finishcbuf(T->buffers[j]);
×
2923
                                }
2924
                                if ( T->spare ) {
×
2925
                                        TABLES TT = T->spare;
×
2926
                                        if ( TT->mm ) M_free(TT->mm,"tableminmax");
×
2927
                                        if ( TT->flags ) M_free(TT->flags,"tableflags");
×
2928
                                        if ( TT->tablepointers ) M_free(TT->tablepointers,"tablepointers");
×
2929
                                        for (j = 0; j < TT->buffersfill; j++ ) { /* was <= */
×
2930
                                                finishcbuf(TT->buffers[j]);
×
2931
                                        }
2932
                                        if ( TT->boomlijst ) M_free(TT->boomlijst,"TableTree");
×
2933
                                        M_free(TT,"table");
×
2934
                                }
2935
                                M_free(T,"table");
×
2936
                        }
2937
                }
2938
                AC.AutoFunctionList.num = AC.AutoFunctionList.numglobal
×
2939
                                                           = AC.AutoFunctionList.numclear;
×
2940
                CompactifyTree(AC.autonames,AUTONAMES);
×
2941
                AC.autonames->namefill = AC.autonames->globalnamefill
×
2942
                                                          = AC.autonames->clearnamefill;
×
2943
                AC.autonames->nodefill = AC.autonames->globalnodefill
×
2944
                                                          = AC.autonames->clearnodefill;
×
2945
                ReleaseTB();
×
2946
                break;
×
2947
        case 1 :
28✔
2948
                for ( i = AC.SymbolList.numglobal; i < AC.SymbolList.num; i++ )
35✔
2949
                        AC.varnames->namenode[symbols[i].node].type = CDELETE;
7✔
2950
                AC.SymbolList.num = AC.SymbolList.numglobal;
28✔
2951
                for ( i = AC.VectorList.numglobal; i < AC.VectorList.num; i++ )
28✔
2952
                        AC.varnames->namenode[vectors[i].node].type = CDELETE;
×
2953
                AC.VectorList.num = AC.VectorList.numglobal;
28✔
2954
                for ( i = AC.IndexList.numglobal; i < AC.IndexList.num; i++ )
28✔
2955
                        AC.varnames->namenode[indices[i].node].type = CDELETE;
×
2956
                AC.IndexList.num = AC.IndexList.numglobal;
28✔
2957
                for ( i = AC.FunctionList.numglobal; i < AC.FunctionList.num; i++ ) {
28✔
2958
                        AC.varnames->namenode[functions[i].node].type = CDELETE;
×
2959
                        if ( ( T = functions[i].tabl ) != 0 ) {
×
2960
                                if ( T->tablepointers ) M_free(T->tablepointers,"tablepointers");
×
2961
                                if ( T->prototype ) M_free(T->prototype,"tableprototype");
×
2962
                                if ( T->mm ) M_free(T->mm,"tableminmax");
×
2963
                                if ( T->flags ) M_free(T->flags,"tableflags");
×
2964
                                if ( T->argtail ) M_free(T->argtail,"table arguments");
×
2965
                                if ( T->boomlijst ) M_free(T->boomlijst,"TableTree");
×
2966
                                for (j = 0; j < T->buffersfill; j++ ) { /* was <= */
×
2967
                                        finishcbuf(T->buffers[j]);
×
2968
                                }
2969
                                /*[07apr2004 mt]:*/  /*memory leak*/
2970
                                if ( T->buffers ) M_free(T->buffers,"Table buffers");
×
2971
                                /*:[07apr2004 mt]*/
2972
                                finishcbuf(T->bufnum);
×
2973
                                if ( T->spare ) {
×
2974
                                        TABLES TT = T->spare;
×
2975
                                        if ( TT->mm ) M_free(TT->mm,"tableminmax");
×
2976
                                        if ( TT->flags ) M_free(TT->flags,"tableflags");
×
2977
                                        if ( TT->tablepointers ) M_free(TT->tablepointers,"tablepointers");
×
2978
                                        for (j = 0; j < TT->buffersfill; j++ ) { /* was <= */
×
2979
                                                finishcbuf(TT->buffers[j]);
×
2980
                                        }
2981
                                        if ( TT->boomlijst ) M_free(TT->boomlijst,"TableTree");
×
2982
                                        /*[07apr2004 mt]:*/ /*memory leak*/
2983
                                        if ( TT->buffers ) M_free(TT->buffers,"Table buffers");
×
2984
                                        /*:[07apr2004 mt]*/
2985
                                        M_free(TT,"table");
×
2986
                                }
2987
                                M_free(T,"table");
×
2988
                        }
2989
                }
2990
#ifdef TABLECLEANUP
2991
                {
2992
                int j;
2993
                WORD *tp;
2994
                for ( i = 0; i < AC.FunctionList.numglobal; i++ ) {
2995
/*
2996
                        Now, if the table definition is from after the .global
2997
                        while the function is from before, there is a problem.
2998
                        This could be resolved by defining CTable (=Table), Ntable
2999
                        and do away with the previous function definition.
3000
*/
3001
                        if ( ( T = functions[i].tabl ) != 0 ) {
3002
/*
3003
                                First restore overwritten definitions.
3004
*/
3005
                                if ( T->sparse ) {
3006
                                        T->totind = T->mdefined;
3007
                                        for ( j = 0, tp = T->tablepointers; j < T->totind; j++ ) {
3008
                                                tp += ABS(T->numind);
3009
#if TABLEEXTENSION == 2
3010
                                                tp[0] = tp[1];
3011
#else
3012
                                                tp[0] = tp[2];
3013
                                                tp[1] = tp[3];
3014
                                                tp[4] = tp[5];
3015
#endif
3016
                                                tp += TABLEEXTENSION;
3017
                                        }
3018
                                        RedoTableTree(T,T->totind);
3019
                                        if ( T->spare ) {
3020
                                                TABLES TT = T->spare;
3021
                                                TT->totind = TT->mdefined;
3022
                                                for ( j = 0, tp = TT->tablepointers; j < TT->totind; j++ ) {
3023
                                                        tp += ABS(TT->numind);
3024
#if TABLEEXTENSION == 2
3025
                                                        tp[0] = tp[1];
3026
#else
3027
                                                        tp[0] = tp[2];
3028
                                                        tp[1] = tp[3];
3029
                                                        tp[4] = tp[5];
3030
#endif
3031
                                                        tp += TABLEEXTENSION;
3032
                                                }
3033
                                                RedoTableTree(TT,TT->totind);
3034
                                                cbuf[TT->bufnum].numlhs = cbuf[TT->bufnum].mnumlhs;
3035
                                                cbuf[TT->bufnum].numrhs = cbuf[TT->bufnum].mnumrhs;
3036
                                        }
3037
                                }
3038
                                else {
3039
                                        for ( j = 0, tp = T->tablepointers; j < T->totind; j++ ) {
3040
#if TABLEEXTENSION == 2
3041
                                                tp[0] = tp[1];
3042
#else
3043
                                                tp[0] = tp[2];
3044
                                                tp[1] = tp[3];
3045
                                                tp[4] = tp[5];
3046
#endif
3047
                                        }
3048
                                        T->defined = T->mdefined;
3049
                                }
3050
                                cbuf[T->bufnum].numlhs = cbuf[T->bufnum].mnumlhs;
3051
                                cbuf[T->bufnum].numrhs = cbuf[T->bufnum].mnumrhs;
3052
                        }
3053
                }
3054
                }
3055
#endif
3056
                AC.FunctionList.num = AC.FunctionList.numglobal;
28✔
3057
                for ( i = AC.SetList.numglobal; i < AC.SetList.num; i++ ) {
28✔
3058
                        if ( Sets[i].node >= 0 )
×
3059
                                AC.varnames->namenode[Sets[i].node].type = CDELETE;
×
3060
                }
3061
                AC.SetList.numtemp = AC.SetList.num = AC.SetList.numglobal;
28✔
3062
                for ( i = AC.DubiousList.numglobal; i < AC.DubiousList.num; i++ )
28✔
3063
                        AC.varnames->namenode[Dubious[i].node].type = CDELETE;
×
3064
                AC.DubiousList.num = AC.DubiousList.numglobal;
28✔
3065
                AC.SetElementList.numtemp = AC.SetElementList.num =
28✔
3066
                        AC.SetElementList.numglobal;
28✔
3067
                CompactifyTree(AC.varnames,VARNAMES);
28✔
3068
                AC.varnames->namefill = AC.varnames->globalnamefill;
28✔
3069
                AC.varnames->nodefill = AC.varnames->globalnodefill;
28✔
3070

3071
                for ( i = AC.AutoSymbolList.numglobal; i < AC.AutoSymbolList.num; i++ )
28✔
3072
                        AC.autonames->namenode[
×
3073
                                        ((SYMBOLS)(AC.AutoSymbolList.lijst))[i].node].type = CDELETE;
×
3074
                AC.AutoSymbolList.num = AC.AutoSymbolList.numglobal;
28✔
3075
                for ( i = AC.AutoVectorList.numglobal; i < AC.AutoVectorList.num; i++ )
28✔
3076
                        AC.autonames->namenode[
×
3077
                                        ((VECTORS)(AC.AutoVectorList.lijst))[i].node].type = CDELETE;
×
3078
                AC.AutoVectorList.num = AC.AutoVectorList.numglobal;
28✔
3079
                for ( i = AC.AutoIndexList.numglobal; i < AC.AutoIndexList.num; i++ )
28✔
3080
                        AC.autonames->namenode[
×
3081
                                        ((INDICES)(AC.AutoIndexList.lijst))[i].node].type = CDELETE;
×
3082
                AC.AutoIndexList.num = AC.AutoIndexList.numglobal;
28✔
3083
                for ( i = AC.AutoFunctionList.numglobal; i < AC.AutoFunctionList.num; i++ ) {
28✔
3084
                        AC.autonames->namenode[
×
3085
                                        ((FUNCTIONS)(AC.AutoFunctionList.lijst))[i].node].type = CDELETE;
×
3086
                        if ( ( T = ((FUNCTIONS)(AC.AutoFunctionList.lijst))[i].tabl ) != 0 ) {
×
3087
                                if ( T->tablepointers ) M_free(T->tablepointers,"tablepointers");
×
3088
                                if ( T->prototype ) M_free(T->prototype,"tableprototype");
×
3089
                                if ( T->mm ) M_free(T->mm,"tableminmax");
×
3090
                                if ( T->flags ) M_free(T->flags,"tableflags");
×
3091
                                if ( T->argtail ) M_free(T->argtail,"table arguments");
×
3092
                                if ( T->boomlijst ) M_free(T->boomlijst,"TableTree");
×
3093
                                for (j = 0; j < T->buffersfill; j++ ) { /* was <= */
×
3094
                                        finishcbuf(T->buffers[j]);
×
3095
                                }
3096
                                if ( T->spare ) {
×
3097
                                        TABLES TT = T->spare;
×
3098
                                        if ( TT->mm ) M_free(TT->mm,"tableminmax");
×
3099
                                        if ( TT->flags ) M_free(TT->flags,"tableflags");
×
3100
                                        if ( TT->tablepointers ) M_free(TT->tablepointers,"tablepointers");
×
3101
                                        for (j = 0; j < TT->buffersfill; j++ ) { /* was <= */
×
3102
                                                finishcbuf(TT->buffers[j]);
×
3103
                                        }
3104
                                        if ( TT->boomlijst ) M_free(TT->boomlijst,"TableTree");
×
3105
                                        M_free(TT,"table");
×
3106
                                }
3107
                                M_free(T,"table");
×
3108
                        }
3109
                }
3110
                AC.AutoFunctionList.num = AC.AutoFunctionList.numglobal;
28✔
3111

3112
                CompactifyTree(AC.autonames,AUTONAMES);
28✔
3113

3114
                AC.autonames->namefill = AC.autonames->globalnamefill;
28✔
3115
                AC.autonames->nodefill = AC.autonames->globalnodefill;
28✔
3116
                break;
28✔
3117
        }
3118
}
3,405✔
3119

3120
/*
3121
          #] ResetVariables : 
3122
          #[ RemoveDollars :
3123
*/
3124

3125
void RemoveDollars(VOID)
×
3126
{
3127
        DOLLARS d;
×
3128
        CBUF *C = cbuf + AM.dbufnum;
×
3129
        int numdollar = AP.DollarList.num;
×
3130
        if ( numdollar > 0 ) {
×
3131
          while ( numdollar > AM.gcNumDollars ) {
×
3132
                numdollar--;
×
3133
                d = Dollars + numdollar;
×
3134
                if ( d->where && d->where != &(d->zero) && d->where != &(AM.dollarzero) ) {
×
3135
                        M_free(d->where,"dollar->where"); d->where = &(d->zero); d->size = 0;
×
3136
                }
3137
                AC.dollarnames->namenode[d->node].type = CDELETE;
×
3138
          }
3139
          AP.DollarList.num = AM.gcNumDollars;
×
3140
          CompactifyTree(AC.dollarnames,DOLLARNAMES);
×
3141

3142
          C->numrhs = C->mnumrhs;
×
3143
          C->numlhs = C->mnumlhs;
×
3144
        }
3145
}
×
3146

3147
/*
3148
          #] RemoveDollars : 
3149
          #[ Globalize :
3150
*/
3151

3152
void Globalize(int par)
1,776✔
3153
{
3154
        int i, j;
1,776✔
3155
        WORD *tp;
1,776✔
3156
        if ( par == 1 ) {
1,776✔
3157
                AC.SymbolList.numclear     = AC.SymbolList.num;
1,776✔
3158
                AC.VectorList.numclear     = AC.VectorList.num;
1,776✔
3159
                AC.IndexList.numclear      = AC.IndexList.num;
1,776✔
3160
                AC.FunctionList.numclear   = AC.FunctionList.num;
1,776✔
3161
                AC.SetList.numclear        = AC.SetList.num;
1,776✔
3162
                AC.DubiousList.numclear    = AC.DubiousList.num;
1,776✔
3163
                AC.SetElementList.numclear = AC.SetElementList.num;
1,776✔
3164
                AC.varnames->clearnamefill = AC.varnames->namefill;
1,776✔
3165
                AC.varnames->clearnodefill = AC.varnames->nodefill;
1,776✔
3166

3167
                AC.AutoSymbolList.numclear   = AC.AutoSymbolList.num;
1,776✔
3168
                AC.AutoVectorList.numclear   = AC.AutoVectorList.num;
1,776✔
3169
                AC.AutoIndexList.numclear    = AC.AutoIndexList.num;
1,776✔
3170
                AC.AutoFunctionList.numclear = AC.AutoFunctionList.num;
1,776✔
3171
                AC.autonames->clearnamefill  = AC.autonames->namefill;
1,776✔
3172
                AC.autonames->clearnodefill  = AC.autonames->nodefill;
1,776✔
3173
        }
3174
/*        for ( i = AC.FunctionList.numglobal; i < AC.FunctionList.num; i++ ) { */
3175
        for ( i = MAXBUILTINFUNCTION-FUNCTION; i < AC.FunctionList.num; i++ ) {
49,728✔
3176
/*
3177
                We need here not only the not-yet-global functions. The already
3178
                global ones may have obtained extra elements.
3179
*/
3180
                if ( functions[i].tabl ) {
47,952✔
3181
                        TABLES T = functions[i].tabl;
×
3182
                        if ( T->sparse ) {
×
3183
                                T->mdefined = T->totind;
×
3184
                                for ( j = 0, tp = T->tablepointers; j < T->totind; j++ ) {
×
3185
                                        tp += ABS(T->numind);
×
3186
#if TABLEEXTENSION == 2
3187
                                        tp[1] = tp[0];
3188
#else
3189
                                        tp[2] = tp[0]; tp[3] = tp[1]; tp[5] = tp[4] & (~ELEMENTUSED);
×
3190
#endif
3191
                                        tp += TABLEEXTENSION;
×
3192
                                }
3193
                                if ( T->spare ) {
×
3194
                                        TABLES TT = T->spare;
×
3195
                                        TT->mdefined = TT->totind;
×
3196
                                        for ( j = 0, tp = TT->tablepointers; j < TT->totind; j++ ) {
×
3197
                                                tp += ABS(TT->numind);
×
3198
#if TABLEEXTENSION == 2
3199
                                                tp[1] = tp[0];
3200
#else
3201
                                                tp[2] = tp[0]; tp[3] = tp[1]; tp[5] = tp[4] & (~ELEMENTUSED);
×
3202
#endif
3203
                                                tp += TABLEEXTENSION;
×
3204
                                        }
3205
                                        cbuf[TT->bufnum].mnumlhs = cbuf[TT->bufnum].numlhs;
×
3206
                                        cbuf[TT->bufnum].mnumrhs = cbuf[TT->bufnum].numrhs;
×
3207
                                }
3208
                        }
3209
                        else {
3210
                                T->mdefined = T->defined;
×
3211
                                for ( j = 0, tp = T->tablepointers; j < T->totind; j++ ) {
×
3212
#if TABLEEXTENSION == 2
3213
                                        tp[1] = tp[0];
3214
#else
3215
                                        tp[2] = tp[0]; tp[3] = tp[1]; tp[5] = tp[4] & (~ELEMENTUSED);
×
3216
#endif
3217
                                }
3218
                        }
3219
                        cbuf[T->bufnum].mnumlhs = cbuf[T->bufnum].numlhs;
×
3220
                        cbuf[T->bufnum].mnumrhs = cbuf[T->bufnum].numrhs;
×
3221
                }
3222
        }
3223
        for ( i = AC.AutoFunctionList.numglobal; i < AC.AutoFunctionList.num; i++ ) {
1,776✔
3224
                if ( ((FUNCTIONS)(AC.AutoFunctionList.lijst))[i].tabl )
×
3225
                        ((FUNCTIONS)(AC.AutoFunctionList.lijst))[i].tabl->mdefined =
×
3226
                                ((FUNCTIONS)(AC.AutoFunctionList.lijst))[i].tabl->defined;
×
3227
        }
3228
        AC.SymbolList.numglobal     = AC.SymbolList.num;
1,776✔
3229
        AC.VectorList.numglobal     = AC.VectorList.num;
1,776✔
3230
        AC.IndexList.numglobal      = AC.IndexList.num;
1,776✔
3231
        AC.FunctionList.numglobal   = AC.FunctionList.num;
1,776✔
3232
        AC.SetList.numglobal        = AC.SetList.num;
1,776✔
3233
        AC.DubiousList.numglobal    = AC.DubiousList.num;
1,776✔
3234
        AC.SetElementList.numglobal = AC.SetElementList.num;
1,776✔
3235
        AC.varnames->globalnamefill = AC.varnames->namefill;
1,776✔
3236
        AC.varnames->globalnodefill = AC.varnames->nodefill;
1,776✔
3237

3238
        AC.AutoSymbolList.numglobal   = AC.AutoSymbolList.num;
1,776✔
3239
        AC.AutoVectorList.numglobal   = AC.AutoVectorList.num;
1,776✔
3240
        AC.AutoIndexList.numglobal    = AC.AutoIndexList.num;
1,776✔
3241
        AC.AutoFunctionList.numglobal = AC.AutoFunctionList.num;
1,776✔
3242
        AC.autonames->globalnamefill  = AC.autonames->namefill;
1,776✔
3243
        AC.autonames->globalnodefill  = AC.autonames->nodefill;
1,776✔
3244
}
1,776✔
3245

3246
/*
3247
          #] Globalize : 
3248
          #[ TestName :
3249
*/
3250

3251
int TestName(UBYTE *name)
7,170✔
3252
{
3253
        if ( *name == '[' ) {
7,170✔
3254
                while ( *name ) name++;
266✔
3255
                if ( name[-1] == ']' ) return(0);
28✔
3256
                return(-1);
×
3257
        }
3258
        while ( *name ) {
21,951✔
3259
                if ( *name == '_' ) return(-1);
14,809✔
3260
                name++;
14,809✔
3261
        }
3262
        return(0);
3263
}
3264

3265
/*
3266
          #] TestName : 
3267
*/
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