• 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

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

35
#include "form3.h"
36

37
/*
38
          #] Includes : 
39
          #[ If statement :
40
                 #[ Syntax :
41

42
                The `if' is a conglomerate of statements: if,else,endif
43

44
                The if consists in principle of:
45

46
                if ( number );
47
                        statements
48
                else;
49
                        statements
50
                endif;
51

52
                The first set is taken when number != 0.
53
                The else is not mandatory.
54
                TRUE = 1 and FALSE = 0
55

56
                The number can be built up via a logical expression:
57

58
                                        expr1 condition expr2
59

60
                each expression can be a subexpression again. It has to be
61
                enclosed in parentheses in that case.
62
                Conditions are:
63
                        >, >=, <, <=, ==, !=, ||, &&
64

65
                When Expressions are chained evaluation is from left to right,
66
                independent of whether this indicates nonsense.
67
                if ( a || b || c || d ); is a perfectly normal statement.
68
                if ( a >= b || c == d ); would be messed up. This should be:
69
                if ( ( a >= b ) || ( c == d ) );
70

71
                The building blocks of the Expressions are:
72

73
                        Match(option,pattern)        The number of times pattern fits in term_
74
                        Count(....)                                The count value of term_
75
                        Coeff[icient]                        The coefficient of term_
76
                        FindLoop(options)                Are there loops (as in ReplaceLoop).
77

78
                Implementation for internal notation:
79

80
                TYPEIF,length,gotolevel(if fail),EXPRTYPE,length,......
81

82
                EXPRTYPE can be:
83
                        SHORTNUMBER                        ->,4,sign,size
84
                        LONGNUMBER                        ->,|ncoef+2|,ncoef,numer,denom
85
                        MATCH                                ->,patternsiz+3,keyword,pattern
86
                        MULTIPLEOF                        ->,3,thenumber
87
                        COUNT                                ->,countsiz+2,countinfo
88
                        TYPEFINDLOOP                ->,7 (findloop info)
89
                        COEFFICIENT                        ->,2
90
                        IFDOLLAR                        ->,3,dollarnumber
91
                        SUBEXPR                                ->,size,dummy,size1,EXPRTYPE,length,...
92
                                                                  ,2,condition1,size2,...
93
                                                                This is like functions.
94

95
                Note that there must be a restriction to the number of nestings
96
                of parentheses in an if statement. It has been set to 10.
97

98
                The syntax of match corresponds to the syntax of the left side
99
                of an id statement. The only difference is the keyword
100
                MATCH vs TYPEIDNEW.
101

102
                 #] Syntax : 
103
                 #[ GetIfDollarNum :
104
*/
105

106
WORD GetIfDollarNum(WORD *ifp, WORD *ifstop)
×
107
{
108
        DOLLARS d;
×
109
        WORD num, *w;
×
110
        if ( ifp[2] < 0 ) { return(-ifp[2]-1); }
×
111
        d = Dollars+ifp[2];
×
112
        if ( ifp+3 < ifstop && ifp[3] == IFDOLLAREXTRA ) {
×
113
                if ( d->nfactors == 0 ) {
×
114
                        MLOCK(ErrorMessageLock);
×
115
                        MesPrint("Attempt to use a factor of an unfactored $-variable");
×
116
                        MUNLOCK(ErrorMessageLock);
×
NEW
117
                        TERMINATE(-1);
×
118
                }
119
                num = GetIfDollarNum(ifp+3,ifstop);
×
120
                if ( num > d->nfactors ) {
×
121
                        MLOCK(ErrorMessageLock);
×
122
                        MesPrint("Dollar factor number %s out of range",num);
×
123
                        MUNLOCK(ErrorMessageLock);
×
NEW
124
                        TERMINATE(-1);
×
125
                }
126
                if ( num == 0 ) {
×
127
                        return(d->nfactors);
×
128
                }
129
                w = d->factors[num-1].where;
×
130
                if ( w == 0 ) return(d->factors[num].value);
×
131
getnumber:;
×
132
                if ( *w == 0 ) return(0);
×
133
                if ( *w == 4 && w[3] == 3 && w[2] == 1 && w[1] < MAXPOSITIVE && w[4] == 0 ) {
×
134
                        return(w[1]);
135
                }
136
                if ( ( w[w[0]] != 0 ) || ( ABS(w[w[0]-1]) != w[0]-1 ) ) {
×
137
                        MLOCK(ErrorMessageLock);
×
138
                        MesPrint("Dollar factor number expected but found expression");
×
139
                        MUNLOCK(ErrorMessageLock);
×
NEW
140
                        TERMINATE(-1);
×
141
                }
142
                else {
143
                        MLOCK(ErrorMessageLock);
×
144
                        MesPrint("Dollar factor number out of range");
×
145
                        MUNLOCK(ErrorMessageLock);
×
NEW
146
                        TERMINATE(-1);
×
147
                }
148
                return(0);
×
149
        }
150
/*
151
        Now we have just a dollar and should evaluate that into a short number
152
*/
153
        if ( d->type == DOLZERO ) {
×
154
                return(0);
155
        }
156
        else if ( d->type == DOLNUMBER || d->type == DOLTERMS ) {
×
157
                w = d->where; goto getnumber;
×
158
        }
159
        else {
160
                MLOCK(ErrorMessageLock);
×
161
                MesPrint("Dollar factor number is wrong type");
×
162
                MUNLOCK(ErrorMessageLock);
×
NEW
163
                TERMINATE(-1);
×
164
                return(0);
×
165
        }
166
}
167

168
/*
169
                 #] GetIfDollarNum : 
170
                 #[ FindVar :
171
*/
172

173
int FindVar(WORD *v, WORD *term)
1,220✔
174
{
175
        WORD *t, *tstop, *m, *mstop, *f, *fstop, *a, *astop;
1,220✔
176
        GETSTOP(term,tstop);
1,220✔
177
        t = term+1;
1,220✔
178
        while ( t < tstop ) {
2,432✔
179
                if ( *v == *t && *v < FUNCTION ) {        /* VECTOR, INDEX, SYMBOL, DOTPRODUCT */
1,648✔
180
                        switch ( *v ) {
72✔
181
                                case SYMBOL:
28✔
182
                                        m = t+2; mstop = t+t[1];
28✔
183
                                        while ( m < mstop ) {
32✔
184
                                                if ( *m == v[1] ) return(1);
28✔
185
                                                m += 2;
4✔
186
                                        }
187
                                        break;
188
                                case INDEX:
189
                                case VECTOR:
190
InVe:
88✔
191
                                        m = t+2; mstop = t+t[1];
88✔
192
                                        while ( m < mstop ) {
144✔
193
                                                if ( *m == v[1] ) return(1);
108✔
194
                                                m++;
56✔
195
                                        }
196
                                        break;
197
                                case DOTPRODUCT:
×
198
                                        m = t+2; mstop = t+t[1];
×
199
                                        while ( m < mstop ) {
×
200
                                                if ( *m == v[1] && m[1] == v[2] ) return(1);
×
201
                                                if ( *m == v[2] && m[1] == v[1] ) return(1);
×
202
                                                m += 3;
×
203
                                        }
204
                                        break;
205
                        }
206
                }
207
                else if ( *v == VECTOR && *t == INDEX ) goto InVe;
1,576✔
208
                else if ( *v == INDEX && *t == VECTOR ) goto InVe;
1,552✔
209
                else if ( ( *v == VECTOR || *v == INDEX ) && *t == DOTPRODUCT ) {
1,532✔
210
                        m = t+2; mstop = t+t[1];
32✔
211
                        while ( m < mstop ) {
48✔
212
                                if ( v[1] == m[0] || v[1] == m[1] ) return(1);
32✔
213
                                m += 3;
16✔
214
                        }
215
                }
216
                else if ( *t >= FUNCTION ) {
1,500✔
217
                        if ( *v == FUNCTION && v[1] == *t ) return(1);
1,264✔
218
                        if ( functions[*t-FUNCTION].spec > 0 ) {
1,144✔
219
                          if ( *v == VECTOR || *v == INDEX ) { /* we need to check arguments */
140✔
220
                                int i;
221
                                for ( i = FUNHEAD; i < t[1]; i++ ) {
104✔
222
                                        if ( v[1] == t[i] ) return(1);
76✔
223
                                }
224
                          }
225
                        }
226
                        else {
227
                          fstop = t + t[1]; f = t + FUNHEAD;
1,004✔
228
                          while ( f < fstop ) { /* Do the arguments one by one */
1,848✔
229
                                if ( *f <= 0 ) {
1,028✔
230
                                        switch ( *f ) {
672✔
231
                                                case -SYMBOL:
36✔
232
                                                        if ( *v == SYMBOL && v[1] == f[1] ) return(1);
36✔
233
                                                        f += 2;
24✔
234
                                                        break;
24✔
235
                                                case -VECTOR:
80✔
236
                                                case -MINVECTOR:
237
                                                case -INDEX:
238
                                                        if ( ( *v == VECTOR || *v == INDEX )
80✔
239
                                                         && ( v[1] == f[1] ) ) return(1);
40✔
240
                                                        f += 2;
60✔
241
                                                        break;
60✔
242
                                                case -SNUMBER:
504✔
243
                                                        f += 2;
504✔
244
                                                        break;
504✔
245
                                                default:
52✔
246
                                                        if ( *v == FUNCTION && v[1] == -*f && *f <= -FUNCTION ) return(1);
52✔
247
                                                        if ( *f <= -FUNCTION ) f++;
40✔
248
                                                        else f += 2;
×
249
                                                        break;
250
                                        }
251
                                }
252
                                else {
253
                                        a = f + ARGHEAD; astop = f + *f;
356✔
254
                                        while ( a < astop ) {
632✔
255
                                                if ( FindVar(v,a) == 1 ) return(1);
416✔
256
                                                a += *a;
276✔
257
                                        }
258
                                        f = astop;
259
                                }
260
                          }
261
                        }
262
                }
263
                t += t[1];
1,212✔
264
        }
265
        return(0);
266
}
267

268
/*
269
                 #] FindVar : 
270
                 #[ DoIfStatement :                                WORD DoIfStatement(PHEAD ifcode,term)
271

272
                The execution time part of the if-statement.
273
                The arguments are a pointer to the TYPEIF and a pointer to the term.
274
                The answer is either 1 (success) or 0 (fail).
275
                The calling routine can figure out where to go in case of failure
276
                by picking up gotolevel.
277
                Note that the whole setup asks for recursions.
278
*/
279

280
WORD DoIfStatement(PHEAD WORD *ifcode, WORD *term)
57,480✔
281
{
282
        GETBIDENTITY
283
        WORD *ifstop, *ifp;
57,480✔
284
        UWORD *coef1 = 0, *coef2, *coef3, *cc;
57,480✔
285
        WORD ncoef1, ncoef2, ncoef3, i = 0, first, *r, acoef, ismul1, ismul2, j;
57,480✔
286
        UWORD *Spac1, *Spac2;
57,480✔
287
        ifstop = ifcode + ifcode[1];
57,480✔
288
        ifp = ifcode + 3;
57,480✔
289
        if ( ifp >= ifstop ) return(1);
57,480✔
290
        if ( ( ifp + ifp[1] ) >= ifstop ) {
57,480✔
291
                switch ( *ifp ) {
2,336✔
292
                        case LONGNUMBER:
×
293
                                if ( ifp[2] ) return(1);
×
294
                                else return(0);
×
295
                        case MATCH:
1,532✔
296
                        case TYPEIF:
297
                                if ( HowMany(BHEAD ifp,term) ) return(1);
1,532✔
298
                                else return(0);
1,528✔
299
                        case TYPEFINDLOOP:
×
300
                                if ( Lus(term,ifp[3],ifp[4],ifp[5],ifp[6],ifp[2]) ) return(1);
×
301
                                else return(0);
×
302
                        case TYPECOUNT:
×
303
                                if ( CountDo(term,ifp) ) return(1);
×
304
                                else return(0);
×
305
                        case COEFFI:
306
                        case MULTIPLEOF:
307
                                return(1);
308
                        case IFDOLLAR:
×
309
                                {
310
                                        DOLLARS d = Dollars + ifp[2];
×
311
#ifdef WITHPTHREADS
312
                                        int nummodopt, dtype = -1;
313
                                        if ( AS.MultiThreaded ) {
314
                                                for ( nummodopt = 0; nummodopt < NumModOptdollars; nummodopt++ ) {
315
                                                        if ( ifp[2] == ModOptdollars[nummodopt].number ) break;
316
                                                }
317
                                                if ( nummodopt < NumModOptdollars ) {
318
                                                        dtype = ModOptdollars[nummodopt].type;
319
                                                        if ( dtype == MODLOCAL ) {
320
                                                                d = ModOptdollars[nummodopt].dstruct+AT.identity;
321
                                                        }
322
                                                }
323
                                        }
324
                                        dtype = d->type;
325
#else
326
                                        int dtype = d->type;  /* We use dtype to make the operation atomic */
327
#endif
328
                                        if ( dtype == DOLZERO ) return(0);
×
329
                                        if ( dtype == DOLUNDEFINED ) {
×
330
                                                if ( AC.UnsureDollarMode == 0 ) {
×
331
                                                        MesPrint("$%s is undefined",AC.dollarnames->namebuffer+d->name);
×
NEW
332
                                                        TERMINATE(-1);
×
333
                                                }
334
                                        }
335
                                }
336
                                return(1);
×
337
                        case IFEXPRESSION:
×
338
                                r = ifp+2; j = ifp[1] - 2;
×
339
                                while ( --j >= 0 ) {
×
340
                                        if ( *r == AR.CurExpr ) return(1);
×
341
                                        r++;
×
342
                                }
343
                                return(0);
344
                        case IFISFACTORIZED:
×
345
                                r = ifp+2; j = ifp[1] - 2;
×
346
                                if ( j == 0 ) {
×
347
                                        if ( ( Expressions[AR.CurExpr].vflags & ISFACTORIZED ) != 0 )
×
348
                                                return(1);
349
                                        else
350
                                                return(0);
×
351
                                }
352
                                while ( --j >= 0 ) {
×
353
                                        if ( ( Expressions[*r].vflags & ISFACTORIZED ) == 0 ) return(0);
×
354
                                        r++;
×
355
                                }
356
                                return(1);
357
                        case IFOCCURS:
804✔
358
                                {
359
                                        WORD *OccStop = ifp + ifp[1];
804✔
360
                                        ifp += 2;
804✔
361
                                        while ( ifp < OccStop ) {
1,312✔
362
                                                if ( FindVar(ifp,term) == 1 ) return(1);
804✔
363
                                                if ( *ifp == DOTPRODUCT ) ifp += 3;
508✔
364
                                                else ifp += 2;
508✔
365
                                        }
366
                                }
367
                                return(0);
368
                        case IFUSERFLAG:
×
369
                                if ( ( Expressions[AR.CurExpr].uflags & (1 << ifp[2]) ) != 0 )
×
370
                                        return(1);
371
                                return(0);
×
372
                        default:
×
373
/*
374
                                Now we have a subexpression. Test first for one with a single item.
375
*/
376
                                if ( ifp[3] == ( ifp[1] + 3 ) ) return(DoIfStatement(BHEAD ifp,term));
×
377
                                ifstop = ifp + ifp[1];
×
378
                                ifp += 3;
×
379
                                break;
×
380
                }
381
        }
55,144✔
382
/*
383
        Here is the composite condition.
384
*/
385
        coef3 = NumberMalloc("DoIfStatement");
55,144✔
386
        Spac1 = NumberMalloc("DoIfStatement");
55,144✔
387
        Spac2 = (UWORD *)(TermMalloc("DoIfStatement"));
55,144✔
388
        ncoef1 = 0; first = 1; ismul1 = 0;
55,144✔
389
        do {
110,288✔
390
                if ( !first ) {
110,288✔
391
                        ifp += 2;
55,144✔
392
                        if ( ifp[-2] == ORCOND && ncoef1 ) {
55,144✔
393
                                coef1 = Spac1;
×
394
                                ncoef1 = 1; coef1[0] = coef1[1] = 1;
×
395
                                goto SkipCond;
×
396
                        }
397
                        if ( ifp[-2] == ANDCOND && !ncoef1 ) goto SkipCond;
55,144✔
398
                }
399
                coef2 = Spac2;
110,288✔
400
                ncoef2 = 1;
110,288✔
401
                ismul2 = 0;
110,288✔
402
                switch ( *ifp ) {
110,288✔
403
                        case LONGNUMBER:
33,044✔
404
                                ncoef2 = ifp[2];
33,044✔
405
                                j = 2*(ABS(ncoef2));
33,044✔
406
                                cc = (UWORD *)(ifp + 3);
33,044✔
407
                                for ( i = 0; i < j; i++ ) coef2[i] = cc[i];
72,844✔
408
                                break;
409
#ifdef WITHFLOAT
410
                        case IFFLOATNUMBER:
×
411
/*
412
                                The sloppy solution is: Convert to rational.
413
                                This way we can write it over coef2,ncoef2
414
*/
415
                                ncoef2 = FloatFunToRat(BHEAD coef2,ifp);
×
416
                                break;
×
417
#endif
418
                        case MATCH:
3,200✔
419
                        case TYPEIF:
420
                                coef2[0] = HowMany(BHEAD ifp,term);
3,200✔
421
                                coef2[1] = 1;
3,200✔
422
                                if ( coef2[0] == 0 ) ncoef2 = 0;
3,200✔
423
                                break;
424
                        case TYPECOUNT:
50,304✔
425
                                acoef = CountDo(term,ifp);
50,304✔
426
                                coef2[0] = ABS(acoef);
50,304✔
427
                                coef2[1] = 1;
50,304✔
428
                                if ( acoef == 0 ) ncoef2 = 0;
50,304✔
429
                                else if ( acoef < 0 ) ncoef2 = -1;
32,836✔
430
                                break;
431
                        case TYPEFINDLOOP:
×
432
                                acoef = Lus(term,ifp[3],ifp[4],ifp[5],ifp[6],ifp[2]);
×
433
                                coef2[0] = ABS(acoef);
×
434
                                coef2[1] = 1;
×
435
                                if ( acoef == 0 ) ncoef2 = 0;
×
436
                                else if ( acoef < 0 ) ncoef2 = -1;
×
437
                                break;
438
                        case COEFFI:
×
439
                                r = term + *term;
×
440
                                ncoef2 = r[-1];
×
441
                                i = ABS(ncoef2);
×
442
                                cc = (UWORD *)(r - i);
×
443
                                if ( ncoef2 < 0 ) ncoef2 = (ncoef2+1)>>1;
×
444
                                else ncoef2 = (ncoef2-1)>>1;
×
445
                                i--; for ( j = 0; j < i; j++ ) coef2[j] = cc[j];
×
446
                                break;
447
                        case SUBEXPR:
×
448
                                ncoef2 = coef2[0] = DoIfStatement(BHEAD ifp,term);
×
449
                                coef2[1] = 1;
×
450
                                break;
×
451
                        case MULTIPLEOF:
×
452
                                ncoef2 = 1;
×
453
                                coef2[0] = ifp[2];
×
454
                                coef2[1] = 1;
×
455
                                ismul2 = 1;
×
456
                                break;
×
457
                        case IFDOLLAREXTRA:
458
                                break;
459
                        case IFDOLLAR:
23,740✔
460
                                {
461
/*
462
                                        We need to abstract a long rational in coef2
463
                                        with length ncoef2. What if that cannot be done?
464
*/
465
                                        DOLLARS d = Dollars + ifp[2];
23,740✔
466
#ifdef WITHPTHREADS
467
                                        int nummodopt, dtype = -1;
11,870✔
468
                                        if ( AS.MultiThreaded ) {
11,870✔
469
                                                for ( nummodopt = 0; nummodopt < NumModOptdollars; nummodopt++ ) {
14,414✔
470
                                                        if ( ifp[2] == ModOptdollars[nummodopt].number ) break;
14,414✔
471
                                                }
472
                                                if ( nummodopt < NumModOptdollars ) {
11,834✔
473
                                                        dtype = ModOptdollars[nummodopt].type;
11,834✔
474
                                                        if ( dtype == MODLOCAL ) {
11,834✔
475
                                                                d = ModOptdollars[nummodopt].dstruct+AT.identity;
8,624✔
476
                                                        }
477
                                                        else {
478
                                                                LOCK(d->pthreadslockread);
3,210✔
479
                                                        }
480
                                                }
481
                                        }
482
#endif
483
/*
484
                                        We have to pick up the IFDOLLAREXTRA pieces for [1], [$y] etc.
485
*/
486
                                        if ( ifp+3 < ifstop && ifp[3] == IFDOLLAREXTRA ) {
23,740✔
487
                                                if ( d->nfactors == 0 ) {
×
488
                                                        MLOCK(ErrorMessageLock);
×
489
                                                        MesPrint("Attempt to use a factor of an unfactored $-variable");
×
490
                                                        MUNLOCK(ErrorMessageLock);
×
NEW
491
                                                        TERMINATE(-1);
×
492
                                                } {
493
                                                WORD num = GetIfDollarNum(ifp+3,ifstop);
×
494
                                                WORD *w;
×
495
                                                while ( ifp+3 < ifstop && ifp[3] == IFDOLLAREXTRA ) ifp += 3;
×
496
                                                if ( num > d->nfactors ) {
×
497
                                                        MLOCK(ErrorMessageLock);
×
498
                                                        MesPrint("Dollar factor number %s out of range",num);
×
499
                                                        MUNLOCK(ErrorMessageLock);
×
NEW
500
                                                        TERMINATE(-1);
×
501
                                                }
502
                                                if ( num == 0 ) {
×
503
                                                        ncoef2 = 1; coef2[0] = d->nfactors; coef2[1] = 1;
×
504
                                                        break;
×
505
                                                }
506
                                                w = d->factors[num-1].where;
×
507
                                                if ( w == 0 ) {
×
508
                                                        if ( d->factors[num-1].value < 0 ) {
×
509
                                                                ncoef2 = -1; coef2[0] = -d->factors[num-1].value; coef2[1] = 1;
×
510
                                                        }
511
                                                        else {
512
                                                                ncoef2 = 1; coef2[0] = d->factors[num-1].value; coef2[1] = 1;
×
513
                                                        }
514
                                                        break;
515
                                                }
516
                                                if ( w[*w] == 0 ) {
×
517
                                                        r = w + *w - 1;
×
518
                                                        i = ABS(*r);
×
519
                                                        if ( i == ( *w-1 ) ) {
×
520
                                                                ncoef2 = (i-1)/2;
×
521
                                                                if ( *r < 0 ) ncoef2 = -ncoef2;
×
522
                                                                i--; cc = coef2; r = w + 1;
×
523
                                                                while ( --i >= 0 ) *cc++ = (UWORD)(*r++);
×
524
                                                                break;
525
                                                        }
526
                                                }
527
                                                goto generic;
×
528
                                                }
529
                                        }
530
                                        else {
531
                                          switch ( d->type ) {
23,740✔
532
                                                case DOLUNDEFINED:
×
533
                                                        if ( AC.UnsureDollarMode == 0 ) {
×
534
#ifdef WITHPTHREADS
535
                                                                if ( dtype > 0 && dtype != MODLOCAL ) { UNLOCK(d->pthreadslockread); }
536
#endif
537
                                                                MLOCK(ErrorMessageLock);
×
538
                                                                MesPrint("$%s is undefined",AC.dollarnames->namebuffer+d->name);
×
539
                                                                MUNLOCK(ErrorMessageLock);
×
NEW
540
                                                                TERMINATE(-1);
×
541
                                                        }
542
                                                        ncoef2 = 0; coef2[0] = 0; coef2[1] = 1;
×
543
                                                        break;
×
544
                                                case DOLZERO:
8,521✔
545
                                                        ncoef2 = coef2[0] = 0; coef2[1] = 1;
8,521✔
546
                                                        break;
8,521✔
547
                                                case DOLSUBTERM:
×
548
                                                        if ( d->where[0] != INDEX || d->where[1] != 3
×
549
                                                        || d->where[2] < 0 || d->where[2] >= AM.OffsetIndex ) {
×
550
                                                                if ( AC.UnsureDollarMode == 0 ) {
×
551
#ifdef WITHPTHREADS
552
                                                                        if ( dtype > 0 && dtype != MODLOCAL ) { UNLOCK(d->pthreadslockread); }
553
#endif
554
                                                                        MLOCK(ErrorMessageLock);
×
555
                                                                        MesPrint("$%s is of wrong type",AC.dollarnames->namebuffer+d->name);
×
556
                                                                        MUNLOCK(ErrorMessageLock);
×
NEW
557
                                                                        TERMINATE(-1);
×
558
                                                                }
559
                                                                ncoef2 = 0; coef2[0] = 0; coef2[1] = 1;
×
560
                                                                break;
×
561
                                                        }
562
                                                        d->index = d->where[2];
×
563
                                                        /* fall through */
564
                                                case DOLINDEX:
×
565
                                                        if ( d->index == 0 ) {
×
566
                                                                ncoef2 = coef2[0] = 0; coef2[1] = 1;
×
567
                                                        }
568
                                                        else if ( d->index > 0 && d->index < AM.OffsetIndex ) {
×
569
                                                                ncoef2 = 1; coef2[0] = d->index; coef2[1] = 1;
×
570
                                                        }
571
                                                        else if ( AC.UnsureDollarMode == 0 ) {
×
572
#ifdef WITHPTHREADS
573
                                                                if ( dtype > 0 && dtype != MODLOCAL ) { UNLOCK(d->pthreadslockread); }
574
#endif
575
                                                                MLOCK(ErrorMessageLock);
×
576
                                                                MesPrint("$%s is of wrong type",AC.dollarnames->namebuffer+d->name);
×
577
                                                                MUNLOCK(ErrorMessageLock);
×
NEW
578
                                                                TERMINATE(-1);
×
579
                                                        }
580
                                                        ncoef2 = coef2[0] = 0; coef2[1] = 1;
×
581
                                                        break;
×
582
                                                case DOLWILDARGS:
×
583
                                                        if ( d->where[0] <= -FUNCTION ||
×
584
                                                        ( d->where[0] < 0 && d->where[2] != 0 )
×
585
                                                        || ( d->where[0] > 0 && d->where[d->where[0]] != 0 )
×
586
                                                        ) {
587
                                                                if ( AC.UnsureDollarMode == 0 ) {
×
588
#ifdef WITHPTHREADS
589
                                                                        if ( dtype > 0 && dtype != MODLOCAL ) { UNLOCK(d->pthreadslockread); }
590
#endif
591
                                                                        MLOCK(ErrorMessageLock);
×
592
                                                                        MesPrint("$%s is of wrong type",AC.dollarnames->namebuffer+d->name);
×
593
                                                                        MUNLOCK(ErrorMessageLock);
×
NEW
594
                                                                        TERMINATE(-1);
×
595
                                                                }
596
                                                                ncoef2 = coef2[0] = 0; coef2[1] = 1;
×
597
                                                                break;
×
598
                                                        }
599
                                                        /* fall through */
600
                                                case DOLARGUMENT:
601
                                                        if ( d->where[0] == -SNUMBER ) {
×
602
                                                                if ( d->where[1] == 0 ) {
×
603
                                                                        ncoef2 = coef2[0] = 0;
×
604
                                                                }
605
                                                                else if ( d->where[1] < 0 ) {
×
606
                                                                        ncoef2 = -1;
×
607
                                                                        coef2[0] = -d->where[1];
×
608
                                                                }
609
                                                                else {
610
                                                                        ncoef2 = 1;
×
611
                                                                        coef2[0] = d->where[1];
×
612
                                                                }
613
                                                                coef2[1] = 1;
×
614
                                                        }
615
                                                        else if ( d->where[0] == -INDEX
×
616
                                                        && d->where[1] >= 0 && d->where[1] < AM.OffsetIndex ) {
×
617
                                                                if ( d->where[1] == 0 ) {
×
618
                                                                        ncoef2 = coef2[0] = 0; coef2[1] = 1;
×
619
                                                                }
620
                                                                else {
621
                                                                        ncoef2 = 1; coef2[0] = d->where[1];
×
622
                                                                        coef2[1] = 1;
×
623
                                                                }
624
                                                        }
625
                                                        else if ( d->where[0] > 0
×
626
                                                        && d->where[ARGHEAD] == (d->where[0]-ARGHEAD)
×
627
                                                        && ABS(d->where[d->where[0]-1]) ==
×
628
                                                                                (d->where[0] - ARGHEAD-1) ) {
×
629
                                                                i = d->where[d->where[0]-1];
×
630
                                                                ncoef2 = (ABS(i)-1)/2;
×
631
                                                                if ( i < 0 ) { ncoef2 = -ncoef2; i = -i; }
×
632
                                                                i--; cc = coef2; r = d->where + ARGHEAD+1;
×
633
                                                                while ( --i >= 0 ) *cc++ = (UWORD)(*r++);
×
634
                                                        }
635
                                                        else {
636
                                                                if ( AC.UnsureDollarMode == 0 ) {
×
637
#ifdef WITHPTHREADS
638
                                                                        if ( dtype > 0 && dtype != MODLOCAL ) { UNLOCK(d->pthreadslockread); }
639
#endif
640
                                                                        MLOCK(ErrorMessageLock);
×
641
                                                                        MesPrint("$%s is of wrong type",AC.dollarnames->namebuffer+d->name);
×
642
                                                                        MUNLOCK(ErrorMessageLock);
×
NEW
643
                                                                        TERMINATE(-1);
×
644
                                                                }
645
                                                                ncoef2 = 0; coef2[0] = 0; coef2[1] = 1;
×
646
                                                        }
647
                                                        break;
648
                                                   case DOLNUMBER:
15,219✔
649
                                                case DOLTERMS:
650
                                                        if ( d->where[d->where[0]] == 0 ) {
15,219✔
651
                                                                r = d->where + d->where[0]-1;
15,219✔
652
                                                                i = ABS(*r);
15,219✔
653
                                                                if ( i == ( d->where[0]-1 ) ) {
15,219✔
654
                                                                        ncoef2 = (i-1)/2;
15,219✔
655
                                                                        if ( *r < 0 ) ncoef2 = -ncoef2;
15,219✔
656
                                                                        i--; cc = coef2; r = d->where + 1;
15,219✔
657
                                                                        while ( --i >= 0 ) *cc++ = (UWORD)(*r++);
45,657✔
658
                                                                        break;
659
                                                                }
660
                                                        }
661
generic:;
×
662
                                                        if ( AC.UnsureDollarMode == 0 ) {
×
663
#ifdef WITHPTHREADS
664
                                                                if ( dtype > 0 && dtype != MODLOCAL ) { UNLOCK(d->pthreadslockread); }
665
#endif
666
                                                                MLOCK(ErrorMessageLock);
×
667
                                                                MesPrint("$%s is of wrong type",AC.dollarnames->namebuffer+d->name);
×
668
                                                                MUNLOCK(ErrorMessageLock);
×
NEW
669
                                                                TERMINATE(-1);
×
670
                                                        }
671
                                                        ncoef2 = 0; coef2[0] = 0; coef2[1] = 1;
×
672
                                                        break;
×
673
                                          }
674
                                        }
11,870✔
675
#ifdef WITHPTHREADS
676
                                        if ( dtype > 0 && dtype != MODLOCAL ) { UNLOCK(d->pthreadslockread); }
11,870✔
677
#endif
678
                                }
679
                                break;
680
                        case IFEXPRESSION:
×
681
                                r = ifp+2; j = ifp[1] - 2; ncoef2 = 0;
×
682
                                while ( --j >= 0 ) {
×
683
                                        if ( *r == AR.CurExpr ) { ncoef2 = 1; break; }
×
684
                                        r++;
×
685
                                }
686
                                coef2[0] = ncoef2;
×
687
                                coef2[1] = 1;
×
688
                                break;
×
689
                        case IFISFACTORIZED:
×
690
                                r = ifp+2; j = ifp[1] - 2;
×
691
                                if ( j == 0 ) {
×
692
                                        ncoef2 = 0;
×
693
                                        if ( ( Expressions[AR.CurExpr].vflags & ISFACTORIZED ) != 0 ) {
×
694
                                                ncoef2 = 1;
×
695
                                        }
696
                                }
697
                                else {
698
                                        ncoef2 = 1;
×
699
                                        while ( --j >= 0 ) {
×
700
                                                if ( ( Expressions[*r].vflags & ISFACTORIZED ) == 0 ) {
×
701
                                                        ncoef2 = 0;
702
                                                        break;
703
                                                }
704
                                                r++;
×
705
                                        }
706
                                }
707
                                coef2[0] = ncoef2;
×
708
                                coef2[1] = 1;
×
709
                                break;
×
710
                        case IFOCCURS:
×
711
                                {
712
                                        WORD *OccStop = ifp + ifp[1], *ifpp = ifp+2;
×
713
                                        ncoef2 = 0;
×
714
                                        while ( ifpp < OccStop ) {
×
715
                                                if ( FindVar(ifpp,term) == 1 ) {
×
716
                                                        ncoef2 = 1; break;
717
                                                }
718
                                                if ( *ifpp == DOTPRODUCT ) ifp += 3;
×
719
                                                else ifpp += 2;
×
720
                                        }
721
                                        coef2[0] = ncoef2;
×
722
                                        coef2[1] = 1;
×
723
                                }
724
                                break;
×
725
                        case IFUSERFLAG:
×
726
                                {
727
                                        ncoef2 = 0;
×
728
                                        if ( ( Expressions[AR.CurExpr].uflags & (1 << ifp[2]) ) != 0 )
×
729
                                                ncoef2 = 1;
×
730
                                        coef2[0] = ncoef2;
×
731
                                        coef2[1] = 1;
×
732
                                }
733
                                break;
×
734
                        default:
735
                                break;
736
                }
737
                if ( !first ) {
110,288✔
738
                        if ( ifp[-2] != ORCOND && ifp[-2] != ANDCOND ) {
55,144✔
739
                                if ( ( ifp[-2] == EQUAL || ifp[-2] == NOTEQUAL ) &&
55,144✔
740
                                ( ismul2 || ismul1 ) ) {
741
                                        if ( ismul1 && ismul2 ) {
×
742
                                                if ( coef1[0] == coef2[0] ) i = 1;
743
                                                else i = 0;
744
                                        }
745
                                        else {
746
                                                if ( ismul1 ) {
×
747
                                                        if ( ncoef2 )
748
                                                                Divvy(BHEAD coef2,&ncoef2,coef1,ncoef1);
749
                                                        cc = coef2; ncoef3 = ncoef2;
750
                                                }
751
                                                else {
752
                                                        if ( ncoef1 )
×
753
                                                                Divvy(BHEAD coef1,&ncoef1,coef2,ncoef2);
×
754
                                                        cc = coef1; ncoef3 = ncoef1;
×
755
                                                }
756
                                                if ( ncoef3 < 0 ) ncoef3 = -ncoef3;
×
757
                                                if ( ncoef3 == 0 ) {
×
758
                                                        if ( ifp[-2] == EQUAL ) i = 1;
×
759
                                                        else i = 0;
×
760
                                                }
761
                                                else if ( cc[ncoef3] != 1 ) {
×
762
                                                        if ( ifp[-2] == EQUAL ) i = 0;
×
763
                                                        else i = 1;
×
764
                                                }
765
                                                else {
766
                                                        for ( j = 1; j < ncoef3; j++ ) {
×
767
                                                                if ( cc[ncoef3+j] != 0 ) break;
×
768
                                                        }
769
                                                        if ( j < ncoef3 ) {
×
770
                                                                if ( ifp[-2] == EQUAL ) i = 0;
×
771
                                                                else i = 1;
×
772
                                                        }
773
                                                        else if ( ifp[-2] == EQUAL ) i = 1;
×
774
                                                        else i = 0;
×
775
                                                }
776
                                        }
777
                                        goto donemul;
×
778
                                }
779
                                else if ( AddRat(BHEAD coef1,ncoef1,coef2,-ncoef2,coef3,&ncoef3) ) {
55,144✔
780
                                        NumberFree(coef3,"DoIfStatement"); NumberFree(Spac1,"DoIfStatement"); TermFree(Spac2,"DoIfStatement");
×
781
                                        MesCall("DoIfStatement"); return(-1);
×
782
                                }
783
                                switch ( ifp[-2] ) {
55,144✔
784
                                        case GREATER:
37,588✔
785
                                                if ( ncoef3 > 0 ) i = 1;
37,588✔
786
                                                else i = 0;
787
                                                break;
788
                                        case GREATEREQUAL:
×
789
                                                if ( ncoef3 >= 0 ) i = 1;
×
790
                                                else i = 0;
791
                                                break;
792
                                        case LESS:
3,560✔
793
                                                if ( ncoef3 < 0 ) i = 1;
3,560✔
794
                                                else i = 0;
795
                                                break;
796
                                        case LESSEQUAL:
×
797
                                                if ( ncoef3 <= 0 ) i = 1;
×
798
                                                else i = 0;
799
                                                break;
800
                                        case EQUAL:
10,780✔
801
                                                if ( ncoef3 == 0 ) i = 1;
10,780✔
802
                                                else i = 0;
803
                                                break;
804
                                        case NOTEQUAL:
3,216✔
805
                                                if ( ncoef3 != 0 ) i = 1;
3,216✔
806
                                                else i = 0;
807
                                                break;
808
                                }
809
donemul:                if ( i ) { ncoef2 = 1; coef2 = Spac2; coef2[0] = coef2[1] = 1; }
13,915✔
810
                                else ncoef2 = 0;
811
                                ismul1 = ismul2 = 0;
110,288✔
812
                        }
813
                }
814
                else {
815
                        first = 0;
816
                }
817
                coef1 = Spac1;
110,288✔
818
                i = 2*ABS(ncoef2);
110,288✔
819
                for ( j = 0; j < i; j++ ) coef1[j] = coef2[j];
203,870✔
820
                ncoef1 = ncoef2;
110,288✔
821
SkipCond:
110,288✔
822
                ifp += ifp[1];
110,288✔
823
        } while ( ifp < ifstop );
110,288✔
824

825
        NumberFree(coef3,"DoIfStatement"); NumberFree(Spac1,"DoIfStatement"); TermFree(Spac2,"DoIfStatement");
55,144✔
826
        if ( ncoef1 ) return(1);
55,144✔
827
        else return(0);
41,229✔
828
}
829

830
/*
831
                 #] DoIfStatement : 
832
                 #[ HowMany :                                        WORD HowMany(ifcode,term)
833

834
                Returns the number of times that the pattern in ifcode
835
                can be taken out from term. There is a subkey in ifcode[2];
836
                The notation is identical to the lhs of an id statement.
837
                Most of the code comes from TestMatch.
838
*/
839

840
WORD HowMany(PHEAD WORD *ifcode, WORD *term)
4,732✔
841
{
842
        GETBIDENTITY
843
        WORD *m, *t, *r, *w, power, RetVal, i, topje, *newterm;
4,732✔
844
        WORD *OldWork, *ww, *mm;
4,732✔
845
        int *RepSto, RepVal;
4,732✔
846
        int numdollars = 0;
4,732✔
847
        m = ifcode + IDHEAD;
4,732✔
848
        AN.FullProto = m;
4,732✔
849
        AN.WildValue = w = m + SUBEXPSIZE;
4,732✔
850
        m += m[1];
4,732✔
851
        AN.WildStop = m;
4,732✔
852
        OldWork = AT.WorkPointer;
4,732✔
853
        if ( ( ifcode[4] & 1 ) != 0 ) {        /* We have at least one dollar in the pattern */
4,732✔
854
                AR.Eside = LHSIDEX;
×
855
                ww = AT.WorkPointer; i = m[0]; mm = m;
×
856
                NCOPY(ww,mm,i);
×
857
                *OldWork += 3;
×
858
                *ww++ = 1; *ww++ = 1; *ww++ = 3;
×
859
                AT.WorkPointer = ww;
×
860
                RepSto = AN.RepPoint;
×
861
                RepVal = *RepSto;
×
862
                NewSort(BHEAD0);
×
863
                if ( Generator(BHEAD OldWork,AR.Cnumlhs) ) {
×
864
                        LowerSortLevel();
×
865
                        *RepSto = RepVal;
×
866
                        AN.RepPoint = RepSto;
×
867
                        AT.WorkPointer = OldWork;
×
868
                        return(-1);
×
869
                }
870
                AT.WorkPointer = ww;
×
871
                if ( EndSort(BHEAD ww,0) < 0 ) {}
×
872
                *RepSto = RepVal;
×
873
                AN.RepPoint = RepSto;
×
874
                if ( *ww == 0 || *(ww+*ww) != 0 ) {
×
875
                        if ( AP.lhdollarerror == 0 ) {
×
876
                                MLOCK(ErrorMessageLock);
×
877
                                MesPrint("&LHS must be one term");
×
878
                                MUNLOCK(ErrorMessageLock);
×
879
                                AP.lhdollarerror = 1;
×
880
                        }
881
                        AT.WorkPointer = OldWork;
×
882
                        return(-1);
×
883
                }
884
                m = ww; AT.WorkPointer = ww = m + *m;
×
885
                if ( m[*m-1] < 0 ) { m[*m-1] = -m[*m-1]; }
×
886
                *m -= m[*m-1];
×
887
                AR.Eside = RHSIDE;
×
888
        }
889
        else {
890
                ww = term + *term;
4,732✔
891
                if ( AT.WorkPointer < ww ) AT.WorkPointer = ww;
4,732✔
892
        }
893
        ClearWild(BHEAD0);
4,732✔
894
        while ( w < AN.WildStop ) {
12,964✔
895
                if ( *w == LOADDOLLAR ) numdollars++;
8,232✔
896
                w += w[1];
8,232✔
897
        }
898
        AN.RepFunNum = 0;
4,732✔
899
        AN.RepFunList = AT.WorkPointer;
4,732✔
900
    AT.WorkPointer = (WORD *)(((UBYTE *)(AT.WorkPointer)) + AM.MaxTer);
4,732✔
901
        topje = cbuf[AT.ebufnum].numrhs;
4,732✔
902
        if ( AT.WorkPointer >= AT.WorkTop ) {
4,732✔
903
                MLOCK(ErrorMessageLock);
×
904
                MesWork();
×
905
                MUNLOCK(ErrorMessageLock);
×
906
                return(-1);
×
907
        }
908
        AN.DisOrderFlag = ifcode[2] & SUBDISORDER;
4,732✔
909
        switch ( ifcode[2] & (~SUBDISORDER) ) {
4,732✔
910
                case SUBONLY :
×
911
                        /* Must be an exact match */
912
                        AN.UseFindOnly = 1; AN.ForFindOnly = 0;
×
913
/*
914
                Copy the term first to scratchterm. This is needed
915
                because of the Substitute.
916
*/
917
                        i = *term;
×
918
                        t = term; newterm = r = AT.WorkPointer;
×
919
                        NCOPY(r,t,i); AT.WorkPointer = r;
×
920
                        RetVal = 0;
×
921
                        if ( FindRest(BHEAD newterm,m) && ( AN.UsedOtherFind ||
×
922
                                FindOnly(BHEAD newterm,m) ) ) {
×
923
                                Substitute(BHEAD newterm,m,1);
×
924
                                if ( numdollars ) {
×
925
                                        WildDollars(BHEAD (WORD *)0);
×
926
                                        numdollars = 0;
×
927
                                }
928
                                ClearWild(BHEAD0);
×
929
                                RetVal = 1;
×
930
                        }
931
                        else RetVal = 0;
932
                        break;
933
                case SUBMANY :
4,732✔
934
/*
935
                Copy the term first to scratchterm. This is needed
936
                because of the Substitute.
937
*/
938
                        i = *term;
4,732✔
939
                        t = term; newterm = r = AT.WorkPointer;
4,732✔
940
                        NCOPY(r,t,i); AT.WorkPointer = r;
231,708✔
941
                        RetVal = 0;
4,732✔
942
                        AN.UseFindOnly = 0;
4,732✔
943
                        if ( ( power = FindRest(BHEAD newterm,m) ) > 0 ) {
4,732✔
944
                                if ( ( power = FindOnce(BHEAD newterm,m) ) > 0 ) {
4✔
945
                                        AN.UseFindOnly = 0;
×
946
                                        do {
×
947
                                                Substitute(BHEAD newterm,m,1);
×
948
                                                if ( numdollars ) {
×
949
                                                        WildDollars(BHEAD (WORD *)0);
×
950
                                                        numdollars = 0;
×
951
                                                }
952
                                                ClearWild(BHEAD0);
×
953
                                                RetVal++;
×
954
                                        } while ( FindRest(BHEAD newterm,m) && (
×
955
                                                AN.UsedOtherFind || FindOnce(BHEAD newterm,m) ) );
×
956
                                }
957
                                else if ( power < 0 ) {
4✔
958
                                        do {
4✔
959
                                                Substitute(BHEAD newterm,m,1);
4✔
960
                                                if ( numdollars ) {
4✔
961
                                                        WildDollars(BHEAD (WORD *)0);
×
962
                                                        numdollars = 0;
×
963
                                                }
964
                                                ClearWild(BHEAD0);
4✔
965
                                                RetVal++;
4✔
966
                                        } while ( FindRest(BHEAD newterm,m) );
4✔
967
                                }
968
                        }
969
                        else if ( power < 0 ) {
4,728✔
970
                                if ( FindOnce(BHEAD newterm,m) ) {
×
971
                                        do {
×
972
                                                Substitute(BHEAD newterm,m,1);
×
973
                                                if ( numdollars ) {
×
974
                                                        WildDollars(BHEAD (WORD *)0);
×
975
                                                        numdollars = 0;
×
976
                                                }
977
                                                ClearWild(BHEAD0);
×
978
                                        } while ( FindOnce(BHEAD newterm,m) );
×
979
                                        RetVal = 1;
980
                                }
981
                        }
982
                        break;
983
                case SUBONCE :
×
984
/*
985
                Copy the term first to scratchterm. This is needed
986
                because of the Substitute.
987
*/
988
                        i = *term;
×
989
                        t = term; newterm = r = AT.WorkPointer;
×
990
                        NCOPY(r,t,i); AT.WorkPointer = r;
×
991
                        RetVal = 0;
×
992
                        AN.UseFindOnly = 0;
×
993
                        if ( FindRest(BHEAD newterm,m) && ( AN.UsedOtherFind || FindOnce(BHEAD newterm,m) ) ) {
×
994
                                Substitute(BHEAD newterm,m,1);
×
995
                                if ( numdollars ) {
×
996
                                        WildDollars(BHEAD (WORD *)0);
×
997
                                        numdollars = 0;
×
998
                                }
999
                                ClearWild(BHEAD0);
×
1000
                                RetVal = 1;
×
1001
                        }
1002
                        else RetVal = 0;
1003
                        break;
1004
                case SUBMULTI :
×
1005
                        RetVal = FindMulti(BHEAD term,m);
×
1006
                        break;
×
1007
                case SUBVECTOR :
1008
                        RetVal = 0;
×
1009
                        for ( i = 0; i < *term; i++ ) ww[i] = term[i];                        
×
1010
                        while ( ( power = FindAll(BHEAD ww,m,AR.Cnumlhs,ifcode) ) != 0 ) { RetVal += power; }
×
1011
                        break;
1012
                case SUBSELECT :
×
1013
                        ifcode += IDHEAD;        ifcode += ifcode[1];        ifcode += *ifcode;
×
1014
                        AN.UseFindOnly = 1; AN.ForFindOnly = ifcode;
×
1015
                        if ( FindRest(BHEAD term,m) && ( AN.UsedOtherFind ||
×
1016
                                        FindOnly(BHEAD term,m) ) ) RetVal = 1;
×
1017
                        else RetVal = 0;
1018
                        break;
1019
                default :
1020
                        RetVal = 0;
1021
                        break;
1022
        }
1023
        AT.WorkPointer = AN.RepFunList;
4,732✔
1024
        cbuf[AT.ebufnum].numrhs = topje;
4,732✔
1025
        return(RetVal);
4,732✔
1026
}
1027

1028
/*
1029
                 #] HowMany : 
1030
                 #[ DoubleIfBuffers :
1031
*/
1032

1033
VOID DoubleIfBuffers(VOID)
56✔
1034
{
1035
        int newmax, i;
56✔
1036
        WORD *newsumcheck;
56✔
1037
        LONG *newheap, *newifcount;
56✔
1038
        if ( AC.MaxIf == 0 ) newmax = 10;
56✔
1039
        else                newmax = 2*AC.MaxIf;
×
1040
        newheap = (LONG *)Malloc1(sizeof(LONG)*(newmax+1),"IfHeap");
56✔
1041
        newsumcheck = (WORD *)Malloc1(sizeof(WORD)*(newmax+1),"IfSumCheck");
56✔
1042
        newifcount = (LONG *)Malloc1(sizeof(LONG)*(newmax+1),"IfCount");
56✔
1043
        if ( AC.MaxIf ) {
56✔
1044
                for ( i = 0; i < AC.MaxIf; i++ ) {
×
1045
                        newheap[i] = AC.IfHeap[i];
×
1046
                        newsumcheck[i] = AC.IfSumCheck[i];
×
1047
                        newifcount[i] = AC.IfCount[i];
×
1048
                }
1049
                AC.IfStack = (AC.IfStack-AC.IfHeap) + newheap;
×
1050
                M_free(AC.IfHeap,"AC.IfHeap");
×
1051
                M_free(AC.IfCount,"AC.IfCount");
×
1052
                M_free(AC.IfSumCheck,"AC.IfSumCheck");
×
1053
        }
1054
        else {
1055
                AC.IfStack = newheap;
56✔
1056
        }
1057
        AC.IfHeap = newheap;
56✔
1058
        AC.IfSumCheck = newsumcheck;
56✔
1059
        AC.IfCount = newifcount;
56✔
1060
        AC.MaxIf = newmax;
56✔
1061
}
56✔
1062

1063
/*
1064
                 #] DoubleIfBuffers : 
1065
          #] If statement : 
1066
          #[ Switch statement :
1067
                 #[ DoSwitch :
1068
*/
1069

1070
int DoSwitch(PHEAD WORD *term, WORD *lhs)
×
1071
{
1072
/*
1073
        For the moment we ignore the compiler buffer problems.
1074
*/
1075
        WORD numdollar = lhs[2];
×
1076
        WORD ncase = DolToNumber(BHEAD numdollar);
×
1077
        SWITCHTABLE *swtab = FindCase(lhs[3],ncase);
×
1078
        return(Generator(BHEAD term,swtab->value));
×
1079
}
1080

1081
/*
1082
                 #] DoSwitch : 
1083
                 #[ DoEndSwitch :
1084
*/
1085

1086
int DoEndSwitch(PHEAD WORD *term, WORD *lhs)
×
1087
{
1088
        SWITCH *sw = AC.SwitchArray+lhs[2];
×
1089
        return(Generator(BHEAD term,sw->endswitch.value+1));
×
1090
}
1091

1092
/*
1093
                 #] DoEndSwitch : 
1094
                 #[ FindCase :
1095
*/
1096

1097
SWITCHTABLE *FindCase(WORD nswitch, WORD ncase)
×
1098
{
1099
/*
1100
        First find the switch table and determine how we have to search.
1101
*/
1102
        SWITCH *sw = AC.SwitchArray+nswitch;
×
1103
        WORD hi, lo, med;
×
1104
        if ( sw->typetable == DENSETABLE ) {
×
1105
                med = ncase - sw->caseoffset;
×
1106
                if ( med >= sw->numcases || med < 0 ) return(&sw->defaultcase);
×
1107
        }
1108
        else {
1109
/*
1110
                We need a binary search in the table.
1111
*/
1112
                if ( ncase > sw->maxcase || ncase < sw->mincase ) return(&sw->defaultcase);
×
1113
                hi = sw->numcases-1; lo = 0;
×
1114
                for(;;) {
×
1115
                        med = (hi+lo)/2;
×
1116
                        if ( ncase == sw->table[med].ncase ) break;
×
1117
            else if ( ncase > sw->table[med].ncase ) {
×
1118
                                lo = med+1;
×
1119
                                if ( lo > hi ) return(&sw->defaultcase);
×
1120
                        }
1121
                        else {
1122
                                hi = med-1;
×
1123
                                if ( hi < lo ) return(&sw->defaultcase);
×
1124
                        }
1125
                }
1126
        }
1127
        return(&sw->table[med]);
×
1128
}
1129

1130
/*
1131
                 #] FindCase : 
1132
                 #[ DoubleSwitchBuffers :
1133
*/
1134

1135
int DoubleSwitchBuffers(VOID)
×
1136
{
1137
        int newmax, i;
×
1138
        SWITCH *newarray;
×
1139
        WORD *newheap;
×
1140
        if ( AC.MaxSwitch == 0 ) newmax = 10;
×
1141
        else                     newmax = 2*AC.MaxSwitch;
×
1142
        newarray = (SWITCH *)Malloc1(sizeof(SWITCH)*(newmax+1),"SwitchArray");
×
1143
        newheap = (WORD *)Malloc1(sizeof(WORD)*(newmax+1),"SwitchHeap");
×
1144
        if ( AC.MaxSwitch ) {
×
1145
                for ( i = 0; i < AC.MaxSwitch; i++ ) {
×
1146
                        newarray[i] = AC.SwitchArray[i];
×
1147
                        newheap[i] = AC.SwitchHeap[i];
×
1148
                }
1149
                M_free(AC.SwitchHeap,"AC.SwitchHeap");
×
1150
                M_free(AC.SwitchArray,"AC.SwitchArray");
×
1151
        }
1152
        for ( i = AC.MaxSwitch; i <= newmax; i++ ) {
×
1153
                newarray[i].table = 0;
×
1154
                newarray[i].tablesize = 0;
×
1155
                newarray[i].defaultcase.ncase = 0;
×
1156
                newarray[i].defaultcase.value = 0;
×
1157
                newarray[i].defaultcase.compbuffer = 0;
×
1158
                newarray[i].endswitch.ncase = 0;
×
1159
                newarray[i].endswitch.value = 0;
×
1160
                newarray[i].endswitch.compbuffer = 0;
×
1161
                newarray[i].typetable = 0;
×
1162
                newarray[i].mincase = 0;
×
1163
                newarray[i].maxcase = 0;
×
1164
                newarray[i].numcases = 0;
×
1165
                newarray[i].caseoffset = 0;
×
1166
                newarray[i].iflevel = 0;
×
1167
                newarray[i].whilelevel = 0;
×
1168
                newarray[i].nestingsum = 0;
×
1169
                newheap[i] = 0;
×
1170
        }
1171
        AC.SwitchArray = newarray;
×
1172
        AC.SwitchHeap = newheap;
×
1173
        AC.MaxSwitch = newmax;
×
1174
        return(0);
×
1175
}
1176

1177
/*
1178
                 #] DoubleSwitchBuffers : 
1179
                 #[ SwitchSplitMerge :
1180

1181
                Sorts an array of WORDs. No adding of equal objects.
1182
*/
1183

1184
VOID SwitchSplitMergeRec(SWITCHTABLE *array,WORD num,SWITCHTABLE *auxarray)
×
1185
{
1186
        WORD n1,n2,i,j,k;
×
1187
        SWITCHTABLE *t1,*t2, t;
×
1188
        if ( num < 2 ) return;
×
1189
        if ( num == 2 ) {
×
1190
                if ( array[0].ncase > array[1].ncase ) {
×
1191
                        t = array[0]; array[0] = array[1]; array[1] = t;
×
1192
                }
1193
                return;
×
1194
        }
1195
        n1 = num/2;
×
1196
        n2 = num - n1;
×
1197
        SwitchSplitMergeRec(array,n1,auxarray);
×
1198
        SwitchSplitMergeRec(array+n1,n2,auxarray);
×
1199
        if ( array[n1-1].ncase <= array[n1].ncase ) return;
×
1200

1201
        t1 = array; t2 = auxarray; i = n1; NCOPY(t2,t1,i);
×
1202
        i = 0; j = n1; k = 0;
1203
        while ( i < n1 && j < num ) {
×
1204
                if ( auxarray[i].ncase <= array[j].ncase ) { array[k++] = auxarray[i++]; }
×
1205
                else { array[k++] = array[j++]; }
×
1206
        }
1207
        while ( i < n1 ) array[k++] = auxarray[i++];
×
1208
/*
1209
        Remember: remnants of j are still in place!
1210
*/
1211
}
1212

1213
VOID SwitchSplitMerge(SWITCHTABLE *array,WORD num)
×
1214
{
1215
        SWITCHTABLE *auxarray = (SWITCHTABLE *)Malloc1(sizeof(SWITCHTABLE)*num/2,"SwitchSplitMerge");
×
1216
        SwitchSplitMergeRec(array,num,auxarray);
×
1217
        M_free(auxarray,"SwitchSplitMerge");
×
1218
}
×
1219

1220
/*
1221
                 #] SwitchSplitMerge : 
1222
          #] Switch statement : 
1223
*/
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