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

tueda / form / 15241916852

25 May 2025 08:59PM UTC coverage: 47.908% (-2.8%) from 50.743%
15241916852

push

github

tueda
ci: build arm64-windows binaries

39009 of 81425 relevant lines covered (47.91%)

1079780.1 hits per line

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

46.6
/sources/pre.c
1
/** @file pre.c
2
 *
3
 *  This is the preprocessor and all its routines.
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 :
33
*/
34
#include "form3.h"
35

36
static UBYTE pushbackchar = 0;
37
static int oldmode = 0;
38
static int stopdelay = 0;
39
static STREAM *oldstream = 0;
40
static UBYTE underscore[2] = {'_',0};
41
static PREVAR *ThePreVar = 0;
42

43
static KEYWORD precommands[] = {
44
         {"add"          , DoPreAdd       , 0, 0}
45
        ,{"addseparator" , DoPreAddSeparator,0,0}
46
        ,{"append"       , DoPreAppend    , 0, 0}
47
        ,{"appendpath"   , DoPreAppendPath, 0, 0}
48
        ,{"assign"       , DoPreAssign    , 0, 0}
49
        ,{"break"        , DoPreBreak     , 0, 0}
50
        ,{"breakdo"      , DoBreakDo      , 0, 0}
51
        ,{"call"         , DoCall         , 0, 0}
52
        ,{"case"         , DoPreCase      , 0, 0}
53
        ,{"clearflag"    , DoClearUserFlag, 0, 0}
54
        ,{"clearoptimize", DoClearOptimize, 0, 0}
55
        ,{"close"        , DoPreClose     , 0, 0}
56
        ,{"closedictionary", DoPreCloseDictionary,0,0}
57
        ,{"commentchar"  , DoCommentChar  , 0, 0}
58
        ,{"continuedo"  ,  DoContinueDo   , 0, 0}
59
        ,{"create"       , DoPreCreate    , 0, 0}
60
        ,{"debug"        , DoDebug        , 0, 0}
61
        ,{"default"      , DoPreDefault   , 0, 0}
62
        ,{"define"       , DoDefine       , 0, 0}
63
        ,{"do"           , DoDo           , 0, 0}
64
        ,{"else"         , DoElse         , 0, 0}
65
        ,{"elseif"       , DoElseif       , 0, 0}
66
        ,{"enddo"        , DoEnddo        , 0, 0}
67
#ifdef WITHFLOAT
68
    ,{"endfloat"     , DoEndFloat     , 0, 0}
69
#endif
70
        ,{"endif"        , DoEndif        , 0, 0}
71
        ,{"endinside"    , DoEndInside    , 0, 0}
72
        ,{"endnamespace" , DoEndNamespace , 0, 0}
73
        ,{"endprocedure" , DoEndprocedure , 0, 0}
74
        ,{"endswitch"    , DoPreEndSwitch , 0, 0}
75
        ,{"exchange"     , DoPreExchange  , 0, 0}
76
        ,{"external"     , DoExternal     , 0, 0}
77
        ,{"factdollar"   , DoFactDollar   , 0, 0}
78
        ,{"fromexternal" , DoFromExternal , 0, 0}
79
        ,{"if"           , DoIf           , 0, 0}
80
        ,{"ifdef"        , DoIfydef       , 0, 0}
81
        ,{"ifndef"       , DoIfndef       , 0, 0}
82
        ,{"include"      , DoInclude      , 0, 0}
83
        ,{"inside"       , DoInside       , 0, 0}
84
        ,{"message"      , DoMessage      , 0, 0}
85
        ,{"namespace"    , DoNamespace    , 0, 0}
86
        ,{"opendictionary", DoPreOpenDictionary,0,0}
87
        ,{"optimize"     , DoOptimize     , 0, 0}
88
        ,{"pipe"         , DoPipe         , 0, 0}
89
        ,{"preout"       , DoPreOut       , 0, 0}
90
        ,{"prependpath"  , DoPrePrependPath,0, 0}
91
        ,{"printtimes"   , DoPrePrintTimes, 0, 0}
92
        ,{"procedure"    , DoProcedure    , 0, 0}
93
        ,{"procedureextension" , DoPrcExtension   , 0, 0}
94
        ,{"prompt"       , DoPrompt       , 0, 0}
95
        ,{"redefine"     , DoRedefine     , 0, 0}
96
        ,{"remove"       , DoPreRemove    , 0, 0}
97
        ,{"reset"        , DoPreReset     , 0, 0}
98
        ,{"reverseinclude"   , DoReverseInclude   , 0, 0}
99
        ,{"rmexternal"   , DoRmExternal   , 0, 0}
100
        ,{"rmseparator"  , DoPreRmSeparator,0, 0}
101
        ,{"setexternal"  , DoSetExternal  , 0, 0}
102
        ,{"setexternalattr"  , DoSetExternalAttr  , 0, 0}
103
        ,{"setflag"      , DoSetUserFlag  , 0, 0}
104
        ,{"setrandom"    , DoSetRandom    , 0, 0}
105
        ,{"show"         , DoPreShow      , 0, 0}
106
        ,{"skipextrasymbols" , DoSkipExtraSymbols , 0, 0}
107
        ,{"sortreallocate", DoPreSortReallocate , 0, 0}
108
#ifdef WITHFLOAT
109
    ,{"startfloat"   , DoStartFloat   , 0, 0}
110
#endif
111
        ,{"switch"       , DoPreSwitch    , 0, 0}
112
        ,{"system"       , DoSystem       , 0, 0}
113
        ,{"terminate"    , DoTerminate    , 0, 0}
114
        ,{"timeoutafter" , DoTimeOutAfter , 0, 0}
115
        ,{"toexternal"   , DoToExternal   , 0, 0}
116
        ,{"undefine"     , DoUndefine     , 0, 0}
117
        ,{"use"          , DoUse          , 0, 0}
118
        ,{"usedictionary", DoPreUseDictionary,0,0}
119
        ,{"write"        , DoPreWrite     , 0, 0}
120
};
121

122
/*
123
          #] Includes : 
124
         # [ PreProcessor :
125
                 #[ GetInput :
126

127
                Gets one input character. If we reach the end of a stream
128
                we pop to the previous stream and try again.
129
                If there are no more streams we let this be known.
130
*/
131

132
UBYTE GetInput(VOID)
71,296,191✔
133
{
134
        UBYTE c;
71,296,191✔
135
        while ( AC.CurrentStream ) {
71,448,723✔
136
                c = GetFromStream(AC.CurrentStream);
71,448,723✔
137
                if ( c != ENDOFSTREAM ) {
71,448,722✔
138
#ifdef WITHMPI
139
                        if ( PF.me == MASTER 
140
                                 && AC.NoShowInput <= 0
141
                                 && AC.CurrentStream->type != PREVARSTREAM )
142
#else
143
                        if ( AC.NoShowInput <= 0 && AC.CurrentStream->type != PREVARSTREAM )
71,296,190✔
144
#endif
145
                                CharOut(c);
206,172✔
146
                        return(c);
71,296,190✔
147
                }
148
                AC.CurrentStream = CloseStream(AC.CurrentStream);
152,532✔
149
                if ( stopdelay && AC.CurrentStream == oldstream ) {
152,532✔
150
                        stopdelay = 0; AP.AllowDelay = 1;
9✔
151
                }
152
        }
153
        return(ENDOFINPUT);
154
}
155

156
/*
157
                 #] GetInput : 
158
                 #[ ClearPushback :
159
*/
160

161
VOID ClearPushback(VOID)
886✔
162
{
163
        pushbackchar = 0;
886✔
164
}
886✔
165

166
/*
167
                 #] ClearPushback : 
168
                 #[ GetChar :
169

170
                Reads one character. If it encounters a quote it immediately
171
                takes the whole preprocessor variable and opens a stream
172
                for it and starts reading the stream.
173
                Note that we have to take special precautions for escaped quotes.
174
                That is why we remember the previous character. We allow the
175
                (dubious?) construction of ending a stream with a backslash and
176
                then using it to escape an object in the parent stream.
177
*/
178

179
UBYTE GetChar(int level)
69,670,313✔
180
{
181
        UBYTE namebuf[MAXPRENAMESIZE+2], c, *s, *t;
69,670,313✔
182
        static UBYTE lastchar, charinbuf = 0;
69,670,313✔
183
        int i, j, raiselow, olddelay;
69,670,313✔
184
        STREAM *stream;
69,670,313✔
185
        if ( level > 0 ) {
69,670,313✔
186
                lastchar = '`';
1,554✔
187
                goto higherlevel;
1,554✔
188
        }
189
        if ( pushbackchar ) { c = pushbackchar; pushbackchar = 0; return(c); }
69,668,759✔
190
        if ( charinbuf ) { c = charinbuf; charinbuf = 0; return(c); }
69,638,991✔
191
        c = GetInput();
69,638,991✔
192
        for(;;) {
69,787,426✔
193
                if ( c == '\\' ) {
69,787,426✔
194
                        charinbuf = GetInput();
81✔
195
                        if ( charinbuf != LINEFEED ) {
81✔
196
                                pushbackchar = charinbuf;
75✔
197
                                charinbuf = 0;
75✔
198
                                break;
75✔
199
                        }
200
                        charinbuf = 0;  /* Escaped linefeed -> skip leading blanks */
6✔
201
                        while ( ( c = GetInput() ) == ' ' || c == '\t' ) {}
225✔
202
                }
203
                else if ( c == '\'' || c == '`' ) {
69,787,345✔
204
                        if ( AP.DelayPrevar == 1 && c == '\'' ) {
146,949✔
205
                                AP.DelayPrevar = 0;
33✔
206
                                break;
33✔
207
                        }
208
                        lastchar = c;
146,916✔
209
higherlevel:
148,470✔
210
                        c = GetInput();
148,470✔
211
                        if ( c == '!' && lastchar == '`' ) {
148,470✔
212
                                if ( stopdelay == 0 ) oldstream = AC.CurrentStream;
9✔
213
                                AP.AllowDelay = 0;
9✔
214
                                stopdelay = 1;
9✔
215
                                c = GetInput();
9✔
216
                        }
217
                        if ( c == '~' && lastchar == '`' ) {
148,470✔
218
                                if ( AP.AllowDelay ) {
1,224✔
219
                                        pushbackchar = c;
33✔
220
                                        c = lastchar;
33✔
221
                                        AP.DelayPrevar = 1;
33✔
222
                                        break;
33✔
223
                                }
224
                        }
225
                        else {
226
                                pushbackchar = c;
147,246✔
227
                        }
228
                        olddelay = AP.DelayPrevar;
148,437✔
229
                        AP.DelayPrevar = 0;
148,437✔
230
                        i = 0; lastchar = 0;
148,437✔
231
                        for (;;) {
311,739✔
232
                                if ( pushbackchar ) { c = pushbackchar; pushbackchar = 0; }
311,739✔
233
                                else { c = GetInput(); }
164,493✔
234
                                if ( c == ENDOFINPUT || ( ( c == '\'' || c == LINEFEED )
311,739✔
235
                                && lastchar != '\\' ) ) {
148,437✔
236
                                        break;
237
                                }
238
                                if ( c == '{' ) { /* Try the preprocessor calculator */
163,302✔
239
                                        if ( PreCalc() == 0 ) Terminate(-1);
×
240
                                        c = GetInput();    /* This is either a { or a number */
×
241
                                        if ( c == '{' ) {
×
242
                                                MesPrint("@Illegal set inside preprocessor variable name");
×
243
                                                Terminate(-1);
×
244
                                        }
245
                                }
246
                                if ( c == '`' && lastchar != '\\' ) {
163,302✔
247
                                        c = GetChar(1);
1,554✔
248
                                        if ( c == ENDOFINPUT || ( ( c == '\'' || c == LINEFEED )
1,554✔
249
                                        && lastchar != '\\' ) ) {
×
250
                                                break;
251
                                        }
252
                                }
253
                                if ( lastchar == '\\' ) { i--; lastchar = 0; }
163,302✔
254
                                else lastchar = c;
163,302✔
255
                                namebuf[i++] = c;
163,302✔
256
                                if ( i > MAXPRENAMESIZE ) {
163,302✔
257
                                        namebuf[i] = 0;
×
258
                                        Error1("Preprocessor variable name too long: ",namebuf);
×
259
                                }
260
                        }
261
                        namebuf[i++] = 0;
148,437✔
262
                        if ( c != '\'' ) {
148,437✔
263
                                Error1("Unmatched quotes for preprocessor variable",namebuf);
×
264
                        }
265
                        AP.DelayPrevar = olddelay;
148,437✔
266
                        if ( namebuf[0] == '$' ) {
148,437✔
267
                                raiselow = PRENOACTION;
387✔
268
                                if ( AP.PreproFlag && *AP.preStart) {
387✔
269
                                        s = EndOfToken(AP.preStart);
84✔
270
                                        c = *s; *s = 0;
84✔
271
                                        if ( ( StrICmp(AP.preStart,(UBYTE *)"ifdef") == 0
84✔
272
                                        || StrICmp(AP.preStart,(UBYTE *)"ifndef") == 0 )
84✔
273
                                        && GetDollar(namebuf+1) < 0 ) {
×
274
                                                *s = c; c = ' ';
×
275
                                                break;
×
276
                                        }
277
                                        *s = c; 
84✔
278
                                }
279
                                else {
280
                                        s = EndOfToken(namebuf+1);
303✔
281
                                        if ( *s == '[' ) { while ( *s ) s++; }
981✔
282
                                }
283
                                if ( *s == '-' && s[1] == '-' && s[2] == 0 )
387✔
284
                                        raiselow = PRELOWERAFTER;
285
                                else if ( *s == '+' && s[1] == '+' && s[2] == 0 )
387✔
286
                                        raiselow = PRERAISEAFTER;
×
287
                                c = *s; *s = 0;
387✔
288
                                if ( OpenStream(namebuf+1,DOLLARSTREAM,0,raiselow) == 0 ) {
387✔
289
                                        *s = c;
×
290
                                        MesPrint("@Undefined variable %s used as preprocessor variable",
×
291
                                                namebuf);
292
                                        Terminate(-1);
×
293
                                }
294
                                *s = c;
387✔
295
                        }
296
                        else {
297
                                raiselow = PRENOACTION;
148,050✔
298
                                if ( AP.PreproFlag && *AP.preStart) {
148,050✔
299
                                        s = EndOfToken(AP.preStart);
4,278✔
300
                                        c = *s; *s = 0;
4,278✔
301
                                        if ( ( StrICmp(AP.preStart,(UBYTE *)"ifdef") == 0
4,278✔
302
                                        || StrICmp(AP.preStart,(UBYTE *)"ifndef") == 0 )
4,266✔
303
                                        && GetPreVar(namebuf,WITHOUTERROR) == 0 ) {
18✔
304
                                                *s = c; c = ' ';
6✔
305
                                                break;
6✔
306
                                        }
307
                                        *s = c; 
4,272✔
308
                                }
309
                                s = EndOfToken(namebuf);
148,044✔
310
                                if ( *s == '_' ) s++;
148,044✔
311
                                if ( *s == '-' && s[1] == '-' && s[2] == 0 )
148,044✔
312
                                        raiselow = PRELOWERAFTER;
313
                                else if ( *s == '+' && s[1] == '+' && s[2] == 0 )
148,044✔
314
                                        raiselow = PRERAISEAFTER;
315
                                else if ( *s == '(' && namebuf[i-2] == ')' ) {
148,044✔
316
/*
317
                                        Now count the arguments and separate them by zeroes
318
                                        Check on the ?var construction and if present, reset
319
                                        some comma's.
320
                                        Make the assignments of the variables
321
                                        Run the macro.
322
                                        Undefine the variables
323
*/
324
                                        int nargs = 1;
1,158✔
325
                                        PREVAR *p;
1,158✔
326
                                        size_t p_offset;
1,158✔
327
                                        *s++ = 0; namebuf[i-2] = 0;
1,158✔
328
                                        if ( StrICmp(namebuf,(UBYTE *)"random_") == 0 ) {
1,158✔
329
                                                UBYTE *ranvalue;
×
330
                                                ranvalue = PreRandom(s);
×
331
                                                PutPreVar(namebuf,ranvalue,(UBYTE *)"?a",1);
×
332
                                                M_free(ranvalue,"PreRandom");
×
333
                                                goto dostream;
×
334
                                        }
335
                                        else if ( StrICmp(namebuf,(UBYTE *)"tolower_") == 0 ) {
1,158✔
336
                                                UBYTE *ss = s;
337
                                                while ( *ss ) { *ss = (UBYTE)(tolower(*ss)); ss++; }
×
338
                                                PutPreVar(namebuf,s,(UBYTE *)"?a",1);
×
339
                                                goto dostream;
×
340
                                        }
341
                                        else if ( StrICmp(namebuf,(UBYTE *)"toupper_") == 0 ) {
1,158✔
342
                                                UBYTE *ss = s;
343
                                                while ( *ss ) { *ss = (UBYTE)(toupper(*ss)); ss++; }
×
344
                                                PutPreVar(namebuf,s,(UBYTE *)"?a",1);
×
345
                                                goto dostream;
×
346
                                        }
347
                                        else if ( StrICmp(namebuf,(UBYTE *)"takeleft_") == 0 ) {
1,158✔
348
                                                UBYTE *ss = s;
349
                                                int x = 0, nsize;
×
350
                                                while ( *ss != ',' && *ss ) ss++;
×
351
                                                nsize = ss-s;
×
352
                                                if ( *ss ) {
×
353
                                                        *ss++ = 0;
×
354
                                                        while ( FG.cTable[*ss] == 1 ) x = 10*x + (*ss++ - '0');
×
355
                                                        if ( x > nsize ) x = nsize;
×
356
                                                }
357
                                                else x = 0;
358
                                                PutPreVar(namebuf,s+x,(UBYTE *)"?a",1);
×
359
                                                goto dostream;
×
360
                                        }
361
                                        else if ( StrICmp(namebuf,(UBYTE *)"takeright_") == 0 ) {
1,158✔
362
                                                UBYTE *ss = s;
363
                                                int x = 0, nsize;
×
364
                                                while ( *ss != ',' && *ss ) ss++;
×
365
                                                nsize = ss-s;
×
366
                                                if ( *ss ) {
×
367
                                                        *ss++ = 0;
×
368
                                                        while ( FG.cTable[*ss] == 1 ) x = 10*x + (*ss++ - '0');
×
369
                                                        if ( x > nsize ) x = nsize;
×
370
                                                }
371
                                                else x = 0;
372
                                                x = nsize - x;
×
373
                                                s[x] = 0;
×
374
                                                PutPreVar(namebuf,s,(UBYTE *)"?a",1);
×
375
                                                goto dostream;
×
376
                                        }
377
                                        else if ( StrICmp(namebuf,(UBYTE *)"keepleft_") == 0 ) {
1,158✔
378
                                                UBYTE *ss = s;
379
                                                int x = 0, nsize;
×
380
                                                while ( *ss != ',' && *ss ) ss++;
×
381
                                                nsize = ss-s;
×
382
                                                if ( *ss ) {
×
383
                                                        *ss++ = 0;
×
384
                                                        while ( FG.cTable[*ss] == 1 ) x = 10*x + (*ss++ - '0');
×
385
                                                        if ( x > nsize ) x = nsize;
×
386
                                                }
387
                                                else x = nsize;
388
                                                s[x] = 0;
×
389
                                                PutPreVar(namebuf,s,(UBYTE *)"?a",1);
×
390
                                                goto dostream;
×
391
                                        }
392
                                        else if ( StrICmp(namebuf,(UBYTE *)"keepright_") == 0 ) {
1,158✔
393
                                                UBYTE *ss = s;
394
                                                int x = 0, nsize;
×
395
                                                while ( *ss != ',' && *ss ) ss++;
×
396
                                                nsize = ss-s;
×
397
                                                if ( *ss ) {
×
398
                                                        *ss++ = 0;
×
399
                                                        while ( FG.cTable[*ss] == 1 ) x = 10*x + (*ss++ - '0');
×
400
                                                        if ( x > nsize ) x = nsize;
×
401
                                                }
402
                                                else x = nsize;
403
                                                x = nsize-x;
×
404
                                                PutPreVar(namebuf,s+x,(UBYTE *)"?a",1);
×
405
                                                goto dostream;
×
406
                                        }
407
                                        while ( *s ) {
4,308✔
408
                                                if ( *s == '\\' ) s++;
3,150✔
409
                                                if ( *s == ',' ) { *s = 0; nargs++; }
3,150✔
410
                                                s++;
3,150✔
411
                                        }
412
                                        GetPreVar(namebuf,WITHERROR);
1,158✔
413
                                        p = ThePreVar;
1,158✔
414
                                        if ( p == 0 ) {
1,158✔
415
                                                MesPrint("@Illegal use of arguments in preprocessor variable %s",namebuf);
×
416
                                                Terminate(-1);
×
417
                                        }
418
                                        if ( p->nargs <= 0 || ( p->wildarg == 0 && nargs != p->nargs )
1,158✔
419
                                                || ( p->wildarg > 0 && nargs < p->nargs-1 ) ) {
1,158✔
420
                                                MesPrint("@Arguments of macro %s do not match",namebuf);
×
421
                                                Terminate(-1);
×
422
                                        }
423
                                        if ( p->wildarg > 0 ) {
1,158✔
424
/*
425
                                                Change some zeroes into commas
426
*/
427
                                                s = namebuf;
428
                                                for ( j = 0; j < p->wildarg; j++ ) {
×
429
                                                        while ( *s ) s++;
×
430
                                                        s++;
×
431
                                                }
432
                                                for ( j = 0; j < nargs-p->nargs; j++ ) {
×
433
                                                        while ( *s ) s++;
×
434
                                                        *s++ = ',';
×
435
                                                }
436
                                        }
437
/*
438
                                                Now we can make the assignments
439
*/
440
                                        s = namebuf;
1,158✔
441
                                        while ( *s ) s++;
4,638✔
442
                                        s++;
1,158✔
443
                                        t = p->argnames;
1,158✔
444
                                        p_offset = p - PreVar;
1,158✔
445
                                        for ( j = 0; j < p->nargs; j++ ) {
2,322✔
446
                                                if ( ( nargs == p->nargs-1 ) && ( *t == '?' ) ) {
1,164✔
447
                                                        PutPreVar(t,0,0,0);
×
448
                                                }
449
                                                else {
450
                                                        PutPreVar(t,s,0,0);
1,164✔
451
                                                        while ( *s ) s++;
4,308✔
452
                                                        s++;
1,164✔
453
                                                }
454
                                                p = PreVar + p_offset;
1,164✔
455
                                                while ( *t ) t++;
2,328✔
456
                                                t++;
1,164✔
457
                                        }
458
                                }
459
dostream:;
148,044✔
460
                                if ( ( stream = OpenStream(namebuf,PREVARSTREAM,0,raiselow) ) == 0 ) {
148,044✔
461
/*
462
                                        Eat comma before or after. This is `no value'
463
*/
464
                                }
465
                                else if ( stream->inbuffer == 0 ) {
148,044✔
466
                                        c = GetInput();
×
467
                                        if ( level > 0 && c == '\'' ) return(c);
×
468
                                        goto endofloop;
×
469
                                }
470
                        }
471
                        c = GetInput();
148,431✔
472
                }
473
                else if ( c == '{' ) { /* Try the preprocessor calculator */
69,640,396✔
474
                        if ( PreCalc() == 0 ) Terminate(-1);
4,092✔
475
                        c = GetInput();    /* This is either a { or a number */
4,092✔
476
                        break;
4,092✔
477
                }
478
                else break;
479
endofloop:;
480
        }
481
        return(c);        
482
}
483

484
/*
485
                 #] GetChar : 
486
                 #[ CharOut :
487
*/
488

489
VOID CharOut(UBYTE c)
206,172✔
490
{
491
        if ( c == LINEFEED ) {
206,172✔
492
                AM.OutBuffer[AP.InOutBuf++] = c;
10,507✔
493
                WriteString(INPUTOUT,AM.OutBuffer,AP.InOutBuf);
10,507✔
494
                AP.InOutBuf = 0;
10,507✔
495
        }
496
        else {
497
                if ( AP.InOutBuf >= AM.OutBufSize || c == LINEFEED ) {
195,665✔
498
                        WriteString(INPUTOUT,AM.OutBuffer,AP.InOutBuf);
75✔
499
                        AP.InOutBuf = 0;
75✔
500
                }
501
                AM.OutBuffer[AP.InOutBuf++] = c;
195,665✔
502
        }
503
}
206,172✔
504

505
/*
506
                 #] CharOut : 
507
                 #[ UnsetAllowDelay :
508
*/
509

510
VOID UnsetAllowDelay(VOID)
148,044✔
511
{
512
        if ( ThePreVar != 0 ) {
148,044✔
513
                if ( ThePreVar->nargs > 0 ) AP.AllowDelay = 0;
147,822✔
514
        }
515
}
148,044✔
516

517
/*
518
                 #] UnsetAllowDelay : 
519
                 #[ GetPreVar :
520

521
                We use the model of a heap. If the same name has been used more
522
                than once the last definition is used. This gives the impression
523
                of local variables.
524

525
                There are two types: The regular ones and the expression variables.
526
                The last ones are like UNCHANGED_exprname and ZERO_exprname or
527
                UNCHANGED_ and ZERO_.
528
*/
529

530
static UBYTE *yes = (UBYTE *)"1";
531
static UBYTE *no  = (UBYTE *)"0";
532
static UBYTE numintopolynomial[12];
533
#include "vector.h"
534
static Vector(UBYTE, exprstr);  /* Used for numactiveexprs_ and activeexprnames_. */
535

536
UBYTE *GetPreVar(UBYTE *name, int flag)
2,389,794✔
537
{
538
        GETIDENTITY
1,255,413✔
539
        int i, mode;
2,389,794✔
540
        WORD number;
2,389,794✔
541
        UBYTE *t, c = 0, *tt = 0;
2,389,794✔
542
        t = name; while ( *t ) t++;
4,814,541✔
543
        if ( t[-1] == '-' && t[-2] == '-' && t-2 > name && t[-3] != '_' ) {
2,389,794✔
544
                t -= 2; c = *t; *t = 0; tt = t;
×
545
        }
546
        else if ( t[-1] == '+' && t[-2] == '+' && t-2 > name && t[-3] != '_' ) {
2,389,794✔
547
                t -= 2; c = *t; *t = 0; tt = t;
×
548
        }
549
        else if ( StrICmp(name,(UBYTE *)"time_") == 0 ) {
2,389,794✔
550
                UBYTE millibuf[24];
×
551
                LONG millitime, timepart;
×
552
                int timepart1, timepart2;
×
553
                static char timestring[40];
×
554
/*                millitime = TimeCPU(1); */
555
                millitime = GetRunningTime();
×
556
                timepart = millitime%1000;
×
557
                millitime /= 1000;
×
558
                timepart /= 10;
×
559
                timepart1 = timepart / 10;
×
560
                timepart2 = timepart % 10;
×
561
                NumToStr(millibuf,millitime);
×
562
            snprintf(timestring,40,"%s.%1d%1d",millibuf,timepart1,timepart2);
×
563
                return((UBYTE *)timestring);
×
564
        }
565
        else if ( ( StrICmp(name,(UBYTE *)"timer_") == 0 )
2,389,794✔
566
               || ( StrICmp(name,(UBYTE *)"stopwatch_") == 0 ) ) {
2,389,794✔
567
                static char timestring[40];
×
568
            snprintf(timestring,40,"%ld",(GetRunningTime() - AP.StopWatchZero));
×
569
                return((UBYTE *)timestring);
×
570
        }
571
        else if ( StrICmp(name, (UBYTE *)"numactiveexprs_") == 0 ) {
2,389,794✔
572
                /* the number of active expressions */
573
                int n = 0;
574
                for ( i = 0; i < NumExpressions; i++ ) {
60✔
575
                        EXPRESSIONS e = Expressions + i;
48✔
576
                        switch ( e->status ) {
48✔
577
                                case LOCALEXPRESSION:
33✔
578
                                case GLOBALEXPRESSION:
579
                                case UNHIDELEXPRESSION:
580
                                case UNHIDEGEXPRESSION:
581
                                case INTOHIDELEXPRESSION:
582
                                case INTOHIDEGEXPRESSION:
583
                                        n++;
33✔
584
                                        break;
33✔
585
                        }
586
                }
587
                VectorReserve(exprstr, 41);  /* up to 128-bit */
12✔
588
                LongCopy(n, (char *)VectorPtr(exprstr));
12✔
589
                return VectorPtr(exprstr);
12✔
590
        }
591
        else if ( StrICmp(name, (UBYTE *)"activeexprnames_") == 0 ) {
2,389,782✔
592
                /* the list of active expressions separated by commas */
593
                int j = 0;
36✔
594
                VectorReserve(exprstr, 16);  /* at least 1 character for '\0' */
36✔
595
                for ( i = 0; i < NumExpressions; i++ ) {
150✔
596
                        UBYTE *p, *s;
114✔
597
                        int len, k;
114✔
598
                        EXPRESSIONS e = Expressions + i;
114✔
599
                        switch ( e->status ) {
114✔
600
                                case LOCALEXPRESSION:
102✔
601
                                case GLOBALEXPRESSION:
602
                                case UNHIDELEXPRESSION:
603
                                case UNHIDEGEXPRESSION:
604
                                case INTOHIDELEXPRESSION:
605
                                case INTOHIDEGEXPRESSION:
606
                                        s = AC.exprnames->namebuffer + e->name;
102✔
607
                                        len = StrLen(s);
102✔
608
                                        VectorSize(exprstr) = j;  /* j bytes must be copied in extending the buffer. */
102✔
609
                                        VectorReserve(exprstr, j + len * 2 + 1);
102✔
610
                                        p = VectorPtr(exprstr);
102✔
611
                                        if ( j > 0 ) p[j++] = ',';
102✔
612
                                        for ( k = 0; k < len; k++ ) {
618✔
613
                                                if ( s[k] == ',' || s[k] == '|' ) p[j++] = '\\';
516✔
614
                                                p[j++] = s[k];
516✔
615
                                        }
616
                                        break;
617
                        }
618
                }
619
                VectorPtr(exprstr)[j] = '\0';
36✔
620
                return VectorPtr(exprstr);
36✔
621
        }
622
        else if ( StrICmp(name, (UBYTE *)"path_") == 0 ) {
2,389,746✔
623
                /* the current FORM path (for debugging both in .c and .frm) */
624
                if ( AM.Path ) {
×
625
                        return(AM.Path);
626
                }
627
                else {
628
                        return((UBYTE *)"");
×
629
                }
630
        }
631
        t = name;
2,389,746✔
632
        while ( *t && *t != '_' ) t++;
4,810,739✔
633
        for ( i = NumPre-1; i >= 0; i-- ) {
3,630,373✔
634
                if ( *t == '_' && ( StrICmp(name,PreVar[i].name) == 0 ) ) {
3,628,134✔
635
                        if ( c ) *tt = c;
39✔
636
                        ThePreVar = PreVar+i;
39✔
637
                        return(PreVar[i].value);
39✔
638
                }
639
                else if ( StrCmp(name,PreVar[i].name) == 0 ) {
3,628,095✔
640
                        if ( c ) *tt = c;
2,387,468✔
641
                        ThePreVar = PreVar+i;
2,387,468✔
642
                        return(PreVar[i].value);
2,387,468✔
643
                }
644
        }
645
        if ( *t == '_' ) {
2,239✔
646
                if ( StrICmp(name,(UBYTE *)"EXTRASYMBOLS_") == 0 ) goto extrashort;
2,233✔
647
                *t = 0;
189✔
648
                if ( StrICmp(name,(UBYTE *)"UNCHANGED") == 0 ) mode = 1;
189✔
649
                else if ( StrICmp(name,(UBYTE *)"ZERO") == 0 ) mode = 0;
93✔
650
                else if ( StrICmp(name,(UBYTE *)"SHOWINPUT") == 0 ) {
×
651
                        *t++ = '_';
×
652
                        if ( c ) *tt = c;
×
653
                        if ( AC.NoShowInput > 0 ) return(no);
×
654
                        else return(yes);
×
655
                }
656
                else if ( StrICmp(name,(UBYTE *)"EXTRASYMBOLS") == 0 ) {
×
657
                        *t++ = '_';
×
658
extrashort:;
2,044✔
659
                        number = cbuf[AM.sbufnum].numrhs;
2,044✔
660
                        t = numintopolynomial;
2,044✔
661
                        NumCopy(number,t);
2,044✔
662
                        return(numintopolynomial);
2,044✔
663
                }
664
                else mode = -1;
665
                *t++ = '_';
189✔
666
                if ( mode >= 0 ) {
189✔
667
                        ThePreVar = 0;
189✔
668
                        if ( *t ) {
189✔
669
                                if ( GetName(AC.exprnames,t,&number,NOAUTO) == CEXPRESSION ) {
147✔
670
                                        if ( c ) *tt = c;
147✔
671
                                        if ( ( Expressions[number].vflags & ( 1 << mode ) ) != 0 )
147✔
672
                                                 return(yes);
108✔
673
                                        else return(no);
39✔
674
                                }
675
                        }
676
                        else {
677
/*
678
                                Here we have to test all active results.
679
                                These are in `negative' so the flags have to be zero.
680
*/
681
                                if ( c ) *tt = c;
42✔
682
                                if ( ( AR.expflags & ( 1 << mode ) ) == 0 ) return(yes);
42✔
683
                                else return(no);
24✔
684
                        }
685
                }
686
        }
687
        if ( ( t = (UBYTE *)(getenv((char *)(name))) ) != 0 ) {
6✔
688
                if ( c ) *tt = c;
×
689
                ThePreVar = 0;
×
690
                return(t);
×
691
        }
692
        if ( c ) *tt = c;
6✔
693
        if ( flag == WITHERROR ) {
6✔
694
                Error1("Undefined preprocessor variable",name);
×
695
        }
696
        return(0);
697
}
698

699
/*
700
                 #] GetPreVar : 
701
                 #[ PutPreVar :
702
*/
703

704
/**
705
 *  Inserts/Updates a preprocessor variable in the name administration.
706
 * 
707
 *  @param   name    Character string with the variable name.
708
 *  @param   value   Character string with a possible value.
709
 *                   Special case: if this argument is zero, then we have no
710
 *                   value. Note: This is different from having an empty
711
 *                   argument! This should only occur when the name starts
712
 *                   with a ?
713
 *  @param   args    Character string with possible arguments.
714
 *  @param   mode    =0: always create a new name entry, =1: try to do a
715
 *                   redefinition if possible.
716
 *  @return          Index of used entry in name list.
717
 */
718
int PutPreVar(UBYTE *name, UBYTE *value, UBYTE *args, int mode)
4,493,220✔
719
{
720
        int i, ii, num = 2, nnum = 2, numargs = 0;
4,493,220✔
721
        UBYTE *s, *t, *u = 0;
4,493,220✔
722
        PREVAR *p;
4,493,220✔
723
        if ( value == 0 && name[0] != '?' ) {
4,493,220✔
724
                MesPrint("@Illegal empty value for preprocessor variable %s",name);
×
725
                Terminate(-1);
×
726
        }
727
        if ( args ) {
4,493,220✔
728
                s = args; num++;
729
                while ( *s ) {
18,636✔
730
                        if ( *s != ' ' && *s != '\t' ) num++;
12,425✔
731
                        s++;
12,425✔
732
                }
733
        }
734
        if ( mode == 1 ) {
4,493,220✔
735
                i = NumPre;
4,463,017✔
736
                while ( --i >= 0 ) {
4,803,092✔
737
                        if ( StrCmp(name,PreVar[i].name) == 0 ) {
4,801,326✔
738
                                u = PreVar[i].name;
4,461,251✔
739
                                break;
4,461,251✔
740
                        }
741
                }
742
        }
743
        else i = -1;
744
        if ( i < 0 ) { p = (PREVAR *)FromList(&AP.PreVarList); ii = p - PreVar; }
4,493,220✔
745
        else         { p = &(PreVar[i]);            ii = i; }
4,461,251✔
746
        if ( value ) {
4,493,220✔
747
                s = value; while ( *s ) { s++; num++; }
9,083,462✔
748
        }
749
        else num = 1;
750
        if ( i >= 0 ) {
4,493,220✔
751
                if ( p->value ) {
4,461,251✔
752
                        s = p->value;
753
                        while ( *s ) { s++; nnum++; }
8,970,541✔
754
                }
755
                else nnum = 1;
756
                if ( nnum >= num ) {
4,461,251✔
757
/*
758
                        We can keep this in place
759
*/
760
                        if ( value && p->value ) {
4,461,077✔
761
                                s = value;
762
                                t = p->value;
763
                                while ( *s ) *t++ = *s++;
8,969,809✔
764
                                *t = 0;
4,461,077✔
765
                        }
766
                        else p->value = 0;
×
767
                        return(i);
4,461,077✔
768
                }
769
        }
770
        s = name;  while ( *s ) { s++; num++; }
337,547✔
771
        t = (UBYTE *)Malloc1(num,"PreVariable");
32,143✔
772
        p->name = t;
32,143✔
773
        s = name;  while ( *s ) *t++ = *s++; *t++ = 0;
337,547✔
774
        if ( value ) {
32,143✔
775
                p->value = t;
32,143✔
776
                s = value; while ( *s ) *t++ = *s++; *t = 0;
113,653✔
777
                if ( AM.atstartup && t[-1] == '\n' ) t[-1] = 0;
32,143✔
778
        }
779
        else p->value = 0;
×
780
        p->wildarg = 0;
32,143✔
781
        if ( args ) {
32,143✔
782
                int first = 1;
6,211✔
783
                t++; p->argnames = t;
6,211✔
784
                s = args;
6,211✔
785
                while ( *s ) {
18,636✔
786
                        if ( *s == ' ' || *s == '\t' ) { s++; continue; }
12,425✔
787
                        if ( *s == ',' ) {
12,425✔
788
                                s++; *t++ = 0; numargs++;
6✔
789
                                while ( *s == ' ' || *s == '\t' ) s++;
6✔
790
                                if ( *s == '?' ) {
6✔
791
                                        if ( p->wildarg > 0 ) {
×
792
                                                Error0("More than one ?var in #define");
×
793
                                        }
794
                                        p->wildarg = numargs;
×
795
                                }
796
                        }
797
                        else if ( *s == '?' && first ) {
12,419✔
798
                                p->wildarg = 1; *t++ = *s++;
6,202✔
799
                        }
800
                        else { *t++ = *s++; }
6,217✔
801
                        first = 0;
802
                }
803
                *t = 0;
6,211✔
804
                numargs++;
6,211✔
805
                p->nargs = numargs;
6,211✔
806
        }
807
        else {
808
                p->nargs = 0;
25,932✔
809
                p->argnames = 0;
25,932✔
810
        }
811
        if ( u ) M_free(u,"replace PreVar value");
32,143✔
812
        return(ii);
813
}
814

815
/*
816
                 #] PutPreVar : 
817
                 #[ PopPreVars :
818
*/
819

820
VOID PopPreVars(int tonumber)
×
821
{
822
        PREVAR *p = &(PreVar[NumPre]);
×
823
        while ( NumPre > tonumber ) {
×
824
                NumPre--; p--;
×
825
                M_free(p->name,"popping PreVar");
×
826
                p->name = p->value = 0;
×
827
        }
828
}
×
829

830
/*
831
                 #] PopPreVars : 
832
                 #[ IniModule :
833
*/
834

835
VOID IniModule(int type)
1,631✔
836
{
837
        GETIDENTITY
1,086✔
838
        WORD **w, i;
1,631✔
839
        CBUF *C = cbuf+AC.cbufnum;
1,631✔
840
        /*[05nov2003 mt]:*/ 
841
#ifdef WITHMPI
842
        /* To prevent
843
         *   (1) FlushOut() and PutOut() on the slaves to send a mess to the master
844
         *       compiling a module,
845
         *   (2) EndSort() called from poly_factorize_expression() on the master
846
         *       waits for the slaves.
847
         */
848
        PF.parallel=0;
849
        /*BTW, this was the bug preventing usage of more than 1 expression!*/
850
#endif
851

852
        AR.BracketOn = 0;
1,631✔
853
        AR.StoreData.dirtyflag = 0;
1,631✔
854
        AC.bracketindexflag = 0;
1,631✔
855
        AT.bracketindexflag = 0;
1,631✔
856

857
/*[06nov2003 mt]:*/
858
#ifdef WITHMPI
859
        /* This flag may be set in the procedure tokenize(). */
860
        AC.RhsExprInModuleFlag = 0;
861
/*[20oct2009 mt]:*/
862
        PF.mkSlaveInfile=0;
863
        PF.slavebuf.PObuffer=NULL;
864
        for(i=0; i<NumExpressions; i++)
865
                Expressions[i].vflags &= ~ISINRHS;
866
/*:[20oct2009 mt]*/
867
#endif
868
/*:[06nov2003 mt]*/
869

870
        /*[19nov2003 mt]:*/
871
        /*The module counter:*/
872
        (AC.CModule)++;
1,631✔
873
        /*:[19nov2003 mt]*/
874

875
        if ( !type ) {
1,631✔
876
                if ( C->rhs ) {
×
877
                        w = C->rhs; i = C->maxrhs;
×
878
                        do { *w++ = 0; } while ( --i > 0 );
×
879
                }
880
                if ( C->lhs ) {
×
881
                        w = C->lhs; i = C->maxlhs;
×
882
                        do { *w++ = 0; } while ( --i > 0 );
×
883
                }
884
        }
885
        C->numlhs = C->numrhs = 0;
1,631✔
886
        ClearTree(AC.cbufnum);
1,631✔
887
        while ( AC.NumLabels > 0 ) {
3,358✔
888
                AC.NumLabels--;
96✔
889
                if ( AC.LabelNames[AC.NumLabels] ) M_free(AC.LabelNames[AC.NumLabels],"LabelName");
96✔
890
        }
891

892
        C->Pointer = C->Buffer;
1,631✔
893

894
        AC.Commercial[0] = 0;
1,631✔
895

896
        AC.IfStack = AC.IfHeap;
1,631✔
897
        AC.arglevel = 0;
1,631✔
898
        AC.termlevel = 0;
1,631✔
899
        AC.IfLevel = 0;
1,631✔
900
        AC.WhileLevel = 0;
1,631✔
901
        AC.RepLevel = 0;
1,631✔
902
        AC.insidelevel = 0;
1,631✔
903
        AC.dolooplevel = 0;
1,631✔
904
        AC.MustTestTable = 0;
1,631✔
905
        AO.PrintType = 0;                                /* Otherwise statistics can get spoiled */
1,631✔
906
        AC.ComDefer = 0;
1,631✔
907
        AC.CollectFun = 0;
1,631✔
908
        AM.S0->PolyWise = 0;
1,631✔
909
        AC.SymChangeFlag = 0;
1,631✔
910
        AP.lhdollarerror = 0;
1,631✔
911
        AR.PolyFun = AC.lPolyFun;
1,631✔
912
        AR.PolyFunInv = AC.lPolyFunInv;
1,631✔
913
        AR.PolyFunType = AC.lPolyFunType;
1,631✔
914
        AR.PolyFunExp = AC.lPolyFunExp;
1,631✔
915
        AR.PolyFunVar = AC.lPolyFunVar;
1,631✔
916
        AR.PolyFunPow = AC.lPolyFunPow;
1,631✔
917
        AC.mparallelflag = AC.parallelflag | AM.hparallelflag;
1,631✔
918
        AC.inparallelflag = 0;
1,631✔
919
        AC.mProcessBucketSize = AC.ProcessBucketSize;
1,631✔
920
        NumPotModdollars = 0;
1,631✔
921
        AC.topolynomialflag = 0;
1,631✔
922
#ifdef WITHPTHREADS
923
        if ( AM.totalnumberofthreads > 1 ) AS.MultiThreaded = 1;
1,086✔
924
        else AS.MultiThreaded = 0;
4✔
925
        for ( i = 1; i < AM.totalnumberofthreads; i++ ) {
4,332✔
926
                AB[i]->T.S0->PolyWise = 0;
3,246✔
927
        }
928
#endif
929
        OpenTemp();
1,631✔
930
}
1,631✔
931

932
/*
933
                 #] IniModule : 
934
                 #[ IniSpecialModule :
935
*/
936

937
VOID IniSpecialModule(int type)
×
938
{
939
        DUMMYUSE(type);
×
940
}
×
941

942
/*
943
                 #] IniSpecialModule : 
944
                 #[ PreProcessor :
945
*/
946

947
VOID PreProcessor(VOID)
883✔
948
{
949
        int moduletype = FIRSTMODULE;
883✔
950
        int specialtype = 0;
883✔
951
        int error1 = 0, error2 = 0, retcode, retval;
883✔
952
        UBYTE c, *t, *s;
883✔
953
        AP.StopWatchZero = GetRunningTime();
883✔
954
        AC.compiletype = 0;
883✔
955
        AP.PreContinuation = 0;
883✔
956
        AP.PreAssignLevel = 0;
883✔
957
        AP.gNumPre = NumPre;
883✔
958
        AC.iPointer = AC.iBuffer;
883✔
959
        AC.iPointer[0] = 0;
883✔
960

961
        if ( AC.CheckpointFlag == -1 ) DoRecovery(&moduletype);
883✔
962
        AC.CheckpointStamp = Timer(0);
883✔
963

964
        for(;;) {
1,631✔
965
/*                if ( A.StatisticsFlag ) CharOut(LINEFEED); */
966

967
                IniModule(moduletype);
1,631✔
968

969
                /*Re-define preprocessor variable CMODULE_ as a current module number, starting from 1*/
970
                /*The module counter is AC.CModule, it is incremented in IniModule*/
971
                {
972
                        UBYTE buf[24];/*64/Log_2[10] = 19.3, this is enough for any integer*/
1,631✔
973
                        NumToStr(buf,AC.CModule);
1,631✔
974
                        PutPreVar((UBYTE *)"CMODULE_",buf,0,1);
1,631✔
975
                }
976

977
                if ( specialtype ) IniSpecialModule(specialtype);
1,631✔
978

979
                for(;;) {        /* Read a single line/statement */
4,496,153✔
980
                        c = GetChar(0);
4,496,153✔
981
                        if ( c == AP.ComChar ) {  /* This line is commentary */
4,496,153✔
982
                                LoadInstruction(5);
1,125✔
983
                                if ( AC.CurrentStream->FoldName ) {
1,125✔
984
                                        t = AP.preStart;
×
985
                                        if ( *t && t[1] && t[2] == '#' && t[3] == ']' ) {
×
986
                                                t += 4;
×
987
                                                while ( *t == ' ' || *t == '\t' ) t++;
×
988
                                                s = AC.CurrentStream->FoldName;
989
                                                while ( *s == *t ) { s++; t++; }
×
990
                                                if ( *s == 0 && ( *t == ' ' || *t == '\t'
×
991
                                                || *t == ':' ) ) {
992
                                                        while ( *t == ' ' || *t == '\t' ) t++;
×
993
                                                        if ( *t == ':' ) {
×
994
                                                                AC.CurrentStream = CloseStream(AC.CurrentStream);
×
995
                                                        }
996
                                                }
997
                                        }
998
                                }
999
                                *AP.preStart = 0;
1,125✔
1000
                                continue;
1,125✔
1001
                        }
1002
                        while ( c == ' ' || c == '\t' ) c = GetChar(0);
17,853,398✔
1003
                        if ( c == LINEFEED ) continue;
1,356✔
1004
                        if ( c == ENDOFINPUT ) {
1005
/*                                CharOut(LINEFEED); */
1006
                                Warning(".end instruction generated");
×
1007
                                moduletype = ENDMODULE; specialtype = 0;
×
1008
                                goto endmodule; /* Fake one */
×
1009
                        }
1010
                        if ( c == '#' ) {
1011
                                if ( PreProInstruction() ) { error1++; error2++; AP.preError++; }
4,462,735✔
1012
                                *AP.preStart = 0;
4,462,729✔
1013
                        }
1014
                        else if ( c == '.' ) {
1015
                                if ( ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) ||
1,628✔
1016
                                ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) ) {
1,625✔
1017
                                        LoadInstruction(1);
3✔
1018
                                        continue;
3✔
1019
                                }
1020
                                if ( ModuleInstruction(&moduletype,&specialtype) ) { error2++; AP.preError++; }
1,625✔
1021
                                if ( specialtype ) SetSpecialMode(moduletype,specialtype);
1,625✔
1022
                                if ( AP.PreInsideLevel != 0 ) {
1,625✔
1023
                                        MesPrint("@end of module instructions may not be used inside");
×
1024
                                        MesPrint("@the scope of a %#inside %#endinside construction.");
×
1025
                                        Terminate(-1);
×
1026
                                }
1027
                                if ( AC.RepLevel > 0 ) {
1,625✔
1028
                                        MesPrint("&EndRepeat statement(s) missing");
×
1029
                                        error2++; AP.preError++;
×
1030
                                }
1031
                                if ( AC.tablecheck == 0 ) {
1,625✔
1032
                                        AC.tablecheck = 1;
739✔
1033
                                        if ( TestTables() ) { error2++; AP.preError++; }
739✔
1034
                                }
1035
                                if ( AP.PreContinuation ) {
1,625✔
1036
                                        error1++; error2++;
3✔
1037
                                        MesPrint("&Unfinished statement. Missing ;?");
3✔
1038
                                }
1039
                                if ( moduletype == GLOBALMODULE ) MakeGlobal();
1,625✔
1040
                                else {
1041
endmodule:                        if ( error2 == 0 && AM.qError == 0 ) {
1,625✔
1042
                                                retcode = ExecModule(moduletype);
1,598✔
1043
#ifdef WITHMPI
1044
                                                if(PF.slavebuf.PObuffer!=NULL){
1045
                                                        M_free(PF.slavebuf.PObuffer,"PF inbuf");
1046
                                                        PF.slavebuf.PObuffer=NULL;
1047
                                                }
1048
#endif
1049
                                                UpdatePositions();
1,540✔
1050
                                                if ( retcode < 0 ) error1++;
1,540✔
1051
                                                if ( retcode ) { error2++; AP.preError++; }
1,540✔
1052
                                        }
1053
                                        else {
1054
                                                EXPRESSIONS e;
27✔
1055
                                                WORD j;
27✔
1056
                                                for ( j = 0, e = Expressions; j < NumExpressions; j++, e++ ) {
48✔
1057
                                                        if ( e->replace == NEWLYDEFINEDEXPRESSION ) e->replace = REGULAREXPRESSION;
21✔
1058
                                                }
1059
                                        }
1060
                                        switch ( moduletype ) {
1,567✔
1061
                                                case STOREMODULE:
15✔
1062
                                                        if ( ExecStore() ) error1++;
15✔
1063
                                                        break;
1064
                                                case CLEARMODULE:
×
1065
                                                        FullCleanUp();
×
1066
                                                        error1 = error2 = AP.preError = 0;
×
1067
                                                        AM.atstartup = 1;
×
1068
                                                        PutPreVar((UBYTE *)"DATE_",(UBYTE *)MakeDate(),0,1);
×
1069
                                                        AM.atstartup = 0;
×
1070
                                                        if ( AM.resetTimeOnClear ) {
×
1071
#ifdef WITHPTHREADS
1072
                                                                ClearAllThreads();
1073
#endif
1074
                                                                AM.SumTime += TimeCPU(1);
×
1075
                                                                TimeCPU(0);
×
1076
                                                        }
1077
                                                        AP.StopWatchZero = GetRunningTime();
×
1078
                                                        break;
×
1079
                                                case ENDMODULE:
819✔
1080
                                                        Terminate( -( error1 | error2 ) );
819✔
1081
                                        }
1082
                                }
1083
                                AC.tablecheck = 0;
748✔
1084
                                AC.compiletype = 0;
748✔
1085
                                if ( AC.exprfillwarning > 0 ) {
748✔
1086
                                        AC.exprfillwarning = 0;
93✔
1087
                                }
1088
                                if ( AC.CheckpointFlag && error1 == 0 && error2 == 0 ) DoCheckpoint(moduletype);
748✔
1089
                                break;  /* start a new module */
1090
                        }
1091
                        else {
1092
                                if ( ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) ||
29,309✔
1093
                                ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) ) {
29,303✔
1094
                                        pushbackchar = c;
6✔
1095
                                        LoadInstruction(5);
6✔
1096
                                        continue;
6✔
1097
                                }
1098
                                UngetChar(c);
29,303✔
1099
                                if ( AP.PreContinuation ) {
29,303✔
1100
                                        retval = LoadStatement(OLDSTATEMENT);
18,285✔
1101
                                }
1102
                                else {
1103
                                        AC.CurrentStream->prevline = AC.CurrentStream->linenumber;
11,018✔
1104
                                        retval = LoadStatement(NEWSTATEMENT);
11,018✔
1105
                                }
1106
                                if ( retval < 0 ) {
29,303✔
1107
                                        error1++;
×
1108
                                        if ( retval == -1 ) AP.PreContinuation = 0;
×
1109
                                        else AP.PreContinuation = 1;
×
1110
                                        TryRecover(0);
×
1111
                                }
1112
                                else if ( retval > 0 ) AP.PreContinuation = 0;
29,303✔
1113
                                else AP.PreContinuation = 1;
18,288✔
1114
                                if ( error1 == 0 && !AP.PreContinuation ) {
29,303✔
1115
                                        if ( ( AP.PreDebug & PREPROONLY ) == 0 ) {
11,015✔
1116
                                                int onpmd = NumPotModdollars;
11,015✔
1117
#ifdef WITHMPI
1118
                                                WORD oldRhsExprInModuleFlag = AC.RhsExprInModuleFlag;
1119
                                                if ( AP.PreAssignFlag ) AC.RhsExprInModuleFlag = 0;
1120
#endif
1121
                                                if ( AP.PreOut || ( AP.PreDebug & DUMPTOCOMPILER )
11,015✔
1122
                                                                == DUMPTOCOMPILER )
1123
                                                                        MesPrint(" %s",AC.iBuffer+AP.PreAssignStack[AP.PreAssignLevel]);
9✔
1124
                                                retcode = CompileStatement(AC.iBuffer+AP.PreAssignStack[AP.PreAssignLevel]);
11,015✔
1125
                                                if ( retcode < 0 ) error1++;
11,015✔
1126
                                                if ( retcode ) { error2++; AP.preError++; }
11,015✔
1127
                                                if ( AP.PreAssignFlag ) {
11,015✔
1128
                                                        if ( retcode == 0 ) {
327✔
1129
                                                                if ( ( retcode = CatchDollar(0) ) < 0 ) error1++;
327✔
1130
                                                                else if ( retcode > 0 ) { error2++; AP.preError++; }
327✔
1131
                                                        }
1132
                                                        else CatchDollar(-1);
×
1133
                                                        POPPREASSIGNLEVEL;
327✔
1134
                                                        if ( AP.PreAssignLevel <=0 )
327✔
1135
                                                                AP.PreAssignFlag = 0;
327✔
1136
                                                        NumPotModdollars = onpmd;
327✔
1137
#ifdef WITHMPI
1138
                                                        AC.RhsExprInModuleFlag = oldRhsExprInModuleFlag;
1139
#endif
1140
                                                }
1141
                                        }
1142
                                        else {
1143
                                                MesPrint(" %s",AC.iBuffer+AP.PreAssignStack[AP.PreAssignLevel]);
×
1144
                                        }
1145
                                }
1146
                                else if ( !AP.PreContinuation ) {
18,288✔
1147
                                        if ( AP.PreAssignLevel > 0 ) {
×
1148
                                                POPPREASSIGNLEVEL;
×
1149
                                                if ( AP.PreAssignLevel <=0 )
×
1150
                                                        AP.PreAssignFlag = 0;
×
1151
                                        }
1152
                                }
1153
/*
1154
                                if ( !AP.PreContinuation ) AP.PreAssignFlag = 0;
1155
*/
1156
                        }
1157
                }
1158
        }
1159
}
1160

1161
/*
1162
                 #] PreProcessor : 
1163
                 #[ PreProInstruction :
1164
*/
1165

1166
int PreProInstruction(VOID)
4,462,735✔
1167
{
1168
        UBYTE *s, *t;
4,462,735✔
1169
        KEYWORD *key;
4,462,735✔
1170
        AP.PreproFlag = 1;
4,462,735✔
1171
        AP.preFill = 0;
4,462,735✔
1172
        AP.AllowDelay = 0;
4,462,735✔
1173
        AP.DelayPrevar = 0;
4,462,735✔
1174

1175
        oldmode = 0;
4,462,735✔
1176
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) {
4,462,735✔
1177
                LoadInstruction(3);
×
1178
                if ( ( StrICmp(AP.preStart,(UBYTE *)"case") == 0
×
1179
                || StrICmp(AP.preStart,(UBYTE *)"default") == 0 )
×
1180
                && AP.PreSwitchModes[AP.PreSwitchLevel] == SEARCHINGPRECASE ) {
×
1181
                        LoadInstruction(0);
×
1182
                }
1183
                else if ( StrICmp(AP.preStart,(UBYTE *)"assign ") == 0 ) {}
×
1184
                else { LoadInstruction(1); }
×
1185
        }
1186
        else if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) {
4,462,735✔
1187
                LoadInstruction(3);
153✔
1188
                if ( ( StrICmp(AP.preStart,(UBYTE *)"else") == 0
153✔
1189
                || StrICmp(AP.preStart,(UBYTE *)"elseif") == 0 )
150✔
1190
                && AP.PreIfStack[AP.PreIfLevel] == LOOKINGFORELSE ) {
3✔
1191
                        LoadInstruction(0);
3✔
1192
                }
1193
                else if ( StrICmp(AP.preStart,(UBYTE *)"assign ") == 0 ) {}
150✔
1194
                else {
1195
                        LoadInstruction(1);
150✔
1196
                }
1197
        }
1198
        else {
1199
                LoadInstruction(0);
4,462,582✔
1200
        }
1201
        AP.PreproFlag = 0;
4,462,733✔
1202
        t = AP.preStart;
4,462,733✔
1203
        if ( *t == '-' ) {
4,462,733✔
1204
                if ( AP.PreSwitchModes[AP.PreSwitchLevel] == EXECUTINGPRESWITCH 
94✔
1205
                        && AP.PreIfStack[AP.PreIfLevel] == EXECUTINGIF ) 
94✔
1206
                        AC.NoShowInput = 1;
94✔
1207
        }
1208
        else if ( *t == '+' ) {
4,462,639✔
1209
                if ( AP.PreSwitchModes[AP.PreSwitchLevel] == EXECUTINGPRESWITCH 
×
1210
                        && AP.PreIfStack[AP.PreIfLevel] == EXECUTINGIF ) 
×
1211
                        AC.NoShowInput = 0;
×
1212
        }
1213
        else if ( *t == ':' ) {}
4,462,639✔
1214
        else {
1215
retry:;
4,462,464✔
1216
                key = FindKeyWord(t,precommands,sizeof(precommands)/sizeof(KEYWORD));
4,462,464✔
1217
                s = EndOfToken(t);
4,462,464✔
1218
                if ( key == 0 ) {
4,462,464✔
1219
                        if ( *s == ';' ) {
×
1220
                                *s = 0; goto retry;
×
1221
                        }
1222
                        else {
1223
                                *s = 0;
×
1224
                                MesPrint("@Unrecognized preprocessor instruction: %s",t);
×
1225
                                return(-1);
×
1226
                        }
1227
                }
1228
                while ( *s == ' ' || *s == '\t' || *s == ',' ) s++;
6,685,510✔
1229
                t = s;
1230
                while ( *t ) t++;
15,581,622✔
1231
                while ( ( t[-1] == ';' ) && ( t[-2] != '\\' ) ) {
4,462,479✔
1232
                        t--; *t = 0;
15✔
1233
                }
1234
                return((key->func)(s));
4,462,464✔
1235
        }
1236
        return(0);
1237
}
1238

1239
/*
1240
                 #] PreProInstruction : 
1241
                 #[ LoadInstruction :
1242

1243
                0:  preprocessor instruction that may involve matching of brackets
1244
                1:  runs straight to end-of-line
1245
                2:        runs to ;
1246
                3:        only gets one word without `' interpretation.
1247
                5:        with pushbackchar, but inside commentary. -> 1
1248

1249
To be added:
1250
        In define, redefine, call and listed do we may have delayed substitution
1251
        of preprocessor variables.
1252
*/
1253

1254
int LoadInstruction(int mode)
4,465,647✔
1255
{
1256
        UBYTE *s, *sstart, *t, c, cp;
4,465,647✔
1257
        LONG position, fillpos = 0;
4,465,647✔
1258
        int bralevel = 0, parlevel = 0, first = 1;
4,465,647✔
1259
        int quotelevel = 0;
4,465,647✔
1260
        if ( AP.preFill ) {
4,465,647✔
1261
                s = AP.preFill;
153✔
1262
                AP.preFill = 0;
153✔
1263
                if ( s[1] != LINEFEED && s[1] != ENDOFINPUT ) {
153✔
1264
                        s[0] = s[1]; s++;
60✔
1265
                }
1266
                else { oldmode = mode; return(0); }
93✔
1267
        }
1268
        else { s = AP.preStart; }
4,465,494✔
1269
        sstart = s; *s = 0;
4,465,554✔
1270
        for(;;) {
46,833,711✔
1271
                if ( ( mode & 1 ) == 1 ) {
46,833,711✔
1272
                        if ( pushbackchar && ( mode == 3 || mode == 5 ) ) {
46,594✔
1273
                                c = pushbackchar; pushbackchar = 0;
6✔
1274
                        }
1275
                        else c = GetInput();
46,588✔
1276
                }
1277
                else {
1278
                        c = GetChar(0);
46,787,117✔
1279
                }
1280

1281
                if ( mode == 2 && c == ';' ) break;
46,833,709✔
1282
                if ( ( mode == 1 || mode == 5 ) && c == LINEFEED ) break;
46,833,709✔
1283
                if ( mode == 3 && FG.cTable[c] != 0 ) {
46,832,515✔
1284
                        if ( c == '$' ) {
153✔
1285
                                pushbackchar = '$';
×
1286
                                *s++ = 'a'; *s++ = 's'; *s++ = 's'; *s++ = 'i';
×
1287
                                *s++ = 'g'; *s++ = 'n'; *s++ = ' '; *s = 0;
×
1288
                        }
1289
                        if ( c == '\'' || c == '`' ) { /* we do not expand preprocessor variables */
153✔
1290
                                mode = 1;
1291
                        }
1292
                        else {
1293
                                AP.preFill = s; *s++ = 0; *s = c;
153✔
1294
                                oldmode = mode;
153✔
1295
                                return(0);
153✔
1296
                        }
1297
                }
1298
                if ( mode == 0 && first ) {
46,832,362✔
1299
                        if ( c == '$' ) {
4,464,207✔
1300
dodollar:                s = sstart;
327✔
1301
                                *s++ = 'a'; *s++ = 's'; *s++ = 's'; *s++ = 'i';
327✔
1302
                                *s++ = 'g'; *s++ = 'n'; *s = 0;
327✔
1303
                                pushbackchar = c;
327✔
1304
                                oldmode = mode;
327✔
1305
                                return(0);
327✔
1306
                        }
1307
                        if ( c == ' ' || c == '\t' || c == ',' ) {}
4,463,880✔
1308
                        else first = 0;
1309
                }
1310
                else if ( mode == 1 && first && c == '$' && oldmode == 3 ) goto dodollar;
42,368,155✔
1311
                if ( c == ENDOFINPUT || ( c == LINEFEED
46,832,035✔
1312
/*                && bralevel == 0  */
1313
                && quotelevel == 0 ) ) {
46,832,035✔
1314
                        if ( mode == 2 && c == ENDOFINPUT ) {
4,463,878✔
1315
                                MesPrint("@Unexpected end of instruction");
×
1316
                                oldmode = mode;
×
1317
                                return(-1);
×
1318
                        }
1319
/*
1320
                        if ( mode == 0 && bralevel ) {
1321
                                MesPrint("@Unmatched brackets");
1322
                                oldmode = mode;
1323
                                return(-1);
1324
                        }
1325
*/
1326
                        if ( mode != 2 ) break;
4,463,878✔
1327
                }
1328
                if ( quotelevel ) {
42,368,157✔
1329
                        if ( c == '\\' ) {
4,443,805✔
1330
                                if ( ( mode == 1 ) || ( mode == 5 ) ) c = GetInput();
27✔
1331
                                else {
1332
                                        c = GetChar(0);
27✔
1333
                                }
1334
                                if ( c == ENDOFINPUT ) {
27✔
1335
                                        MesPrint("@Unmatched \"");
×
1336
                                        if ( mode == 2 && c == ENDOFINPUT ) {
×
1337
                                                MesPrint("@Unexpected end of instruction");
×
1338
                                        }
1339
/*
1340
                                        if ( mode == 0 && bralevel ) {
1341
                                                MesPrint("@Unmatched brackets");
1342
                                        }
1343
*/
1344
                                        oldmode = mode;
×
1345
                                        return(-1);
×
1346
                                }
1347
                                else if ( c == LINEFEED ) {} 
27✔
1348
                                else if ( c == '"' ) { *s++ = '\\'; }
27✔
1349
                                else {
1350
                                        *s++ = '\\';
27✔
1351
                                }
1352
                        }
1353
                        else if ( c == '"' ) {
4,443,778✔
1354
                                quotelevel = 0;
2,219,779✔
1355
                                AP.AllowDelay = 0;
2,219,779✔
1356
                        }
1357
                }
1358
                else if ( c == '\\' ) {
37,924,352✔
1359
                        if ( ( mode == 1 ) || ( mode == 5 ) ) cp = GetInput();
45✔
1360
                        else {
1361
                                cp = GetChar(0);
45✔
1362
                        }
1363
                        if ( cp == LINEFEED ) continue;
45✔
1364
                        if ( mode != 2 || cp != ';' ) *s++ = c;
45✔
1365
                        c = cp;
1366
                }
1367
                else if ( c == '"' ) {
37,924,307✔
1368
/*
1369
                        Now look back in the buffer and determine what the keyword is.
1370
                        If it is define or redefine, put AllowDelay to 1.
1371
*/
1372
                        t = AP.preStart;
2,219,779✔
1373
                        while ( FG.cTable[*t] <= 1 ) t++;
19,976,059✔
1374
                        cp = *t; *t = 0;
2,219,779✔
1375
                        if ( ( StrICmp(AP.preStart,(UBYTE *)"define") == 0 )
2,219,779✔
1376
                                || ( StrICmp(AP.preStart,(UBYTE *)"redefine") == 0 ) ) {
2,219,664✔
1377
                                AP.AllowDelay = 1;
2,219,395✔
1378
                                oldstream = AC.CurrentStream;
2,219,395✔
1379
                        }
1380
                        *t = cp;
2,219,779✔
1381
                        quotelevel = 1;
2,219,779✔
1382
                }
1383
                else if ( quotelevel == 0 && bralevel == 0 && c == '(' ) {
35,704,528✔
1384
                        t = AP.preStart;
465✔
1385
                        while ( FG.cTable[*t] <= 1 ) t++;
2,274✔
1386
                        cp = *t; *t = 0;
465✔
1387
                        if ( ( parlevel == 0 )
465✔
1388
                                 && ( StrICmp(AP.preStart,(UBYTE *)"call") == 0 ) ) {
426✔
1389
                                AP.AllowDelay = 1;
114✔
1390
                                oldstream = AC.CurrentStream;
114✔
1391
                        }
1392
                        *t = cp;
465✔
1393
                        parlevel++;
465✔
1394
                }
1395
                else if ( quotelevel == 0 && bralevel == 0 && c == ')' ) {
35,704,063✔
1396
                        parlevel--;
465✔
1397
                }
1398
                else if ( quotelevel == 0 && parlevel == 0 && c == '{' ) {
35,703,598✔
1399
                        t = AP.preStart;
45✔
1400
                        while ( FG.cTable[*t] <= 1 ) t++;
111✔
1401
                        cp = *t; *t = 0;
45✔
1402
                        if ( ( bralevel == 0 )
45✔
1403
                                && ( ( StrICmp(AP.preStart,(UBYTE *)"call") == 0 )
45✔
1404
                                || ( StrICmp(AP.preStart,(UBYTE *)"do") == 0 ) ) ) {
45✔
1405
                                AP.AllowDelay = 1;
33✔
1406
                                oldstream = AC.CurrentStream;
33✔
1407
                        }
1408
                        *t = cp;
45✔
1409
                        bralevel++;
45✔
1410
                }
1411
                else if ( quotelevel == 0 && parlevel == 0 && c == '}' ) {
35,703,553✔
1412
                        bralevel--;
45✔
1413
                        if ( bralevel < 0 ) {
45✔
1414
                                if ( mode != 5 ) {
×
1415
                                        MesPrint("@Unmatched brackets");
×
1416
                                        oldmode = mode;
×
1417
                                        return(-1);
×
1418
                                }
1419
                                bralevel = 0;
1420
                        }
1421
                }
1422
                if ( s >= (AP.preStop-1) ) {
42,368,157✔
1423
                        UBYTE **ppp;
×
1424
                        position = s - AP.preStart;
×
1425
                        if ( AP.preFill ) fillpos = AP.preFill - AP.preStart;
×
1426
                        ppp = &(AP.preStart); /* to avoid a compiler warning */
×
1427
                        if ( DoubleLList((VOID ***)ppp,&AP.pSize,sizeof(UBYTE),
×
1428
                        "instruction buffer") ) { *s = 0; oldmode = mode; return(-1); }
×
1429
                        AP.preStop = AP.preStart + AP.pSize-3;
×
1430
                        s = AP.preStart + position;
×
1431
                        if ( AP.preFill ) AP.preFill = fillpos + AP.preStart;
×
1432
                }
1433
                *s++ = c;
42,368,157✔
1434
        }
1435
        *s = 0;
4,465,072✔
1436
        oldmode = mode;
4,465,072✔
1437
        if ( mode == 0 ) {
4,465,072✔
1438
                if ( ExpandTripleDots(1) < 0 ) return(-1);
4,463,878✔
1439
        }
1440
        return(0);
1441
}
1442

1443
/*
1444
                 #] LoadInstruction : 
1445
                 #[ LoadStatement :
1446

1447
                Puts the current string together in the input buffer.
1448
                Does things like placing comma's where needed and expand ...
1449
                We force a comma after the keyword. Before 8-sep-2009 the program might
1450
                not put a comma if a + or - followed. And then the compiler ate
1451
                the + or - and we needed repair code in the routines that used the
1452
                + or - (Print, modulus, multiply and (a)bracket). This worked but
1453
                the problem was with statements like  Dimension -4; which then would
1454
                be processed as Dimension 4; (JV)
1455
*/
1456

1457
int LoadStatement(int type)
29,303✔
1458
{
1459
        UBYTE *s, c, cp;
29,303✔
1460
        int retval = 0, stringlevel = 0, newstatement = 0;
29,303✔
1461
        if ( type == NEWSTATEMENT ) { AP.eat = 1; newstatement = 1;
29,303✔
1462
                s = AC.iBuffer+AP.PreAssignStack[AP.PreAssignLevel]; }
11,018✔
1463
        else { s = AC.iPointer; *s = 0; c = ' '; goto blank; }
18,285✔
1464
        *s = 0;
11,018✔
1465
        for(;;) {
4,990,916✔
1466
                c = GetChar(0);
4,990,916✔
1467
                if ( c == ENDOFINPUT ) { retval = -1; break; }
4,990,916✔
1468
                if ( stringlevel == 0 ) {
4,990,916✔
1469
                        if ( c == LINEFEED ) {
4,969,790✔
1470
                                if ( AP.eat < 0 ) { s--; AP.eat = 0; }
18,288✔
1471
                                retval = 0; break;
1472
                        }
1473
                        if ( c == ';' ) {
4,951,502✔
1474
                                if ( AP.eat < 0 ) { s--; AP.eat = 0; }
11,015✔
1475
                                while ( ( c = GetChar(0) ) == ' ' || c == '\t' ) {}
11,069✔
1476
                                if ( c != LINEFEED ) UngetChar(c);
11,015✔
1477
                                retval = 1;
1478
                                break;
1479
                        }
1480
                }
1481
                if ( c == '\\' ) {
4,961,613✔
1482
                        cp = GetChar(0);
×
1483
                        if ( cp == LINEFEED ) continue;
×
1484
                        *s++ = c;
×
1485
                        c = cp;
×
1486
                }
1487
                if ( c == '"' ) {
4,961,613✔
1488
                        if ( stringlevel == 0 ) stringlevel = 1;
2,574✔
1489
                        else stringlevel = 0;
1,287✔
1490
                        AP.eat = 0;
2,574✔
1491
                }
1492
                else if ( stringlevel == 0 ) {
4,959,039✔
1493
                        if ( c == '\t' ) c = ' ';
4,939,200✔
1494
                        if ( c == ' ' ) {
4,939,194✔
1495
blank:                        if ( newstatement < 0 ) newstatement = 0;
64,879✔
1496
                                if ( AP.eat && ( newstatement == 0 ) ) continue;
64,879✔
1497
                                c = ',';
28,533✔
1498
                                AP.eat = -2;
28,533✔
1499
                                if ( newstatement > 0 ) newstatement = -1;
28,533✔
1500
                        }
1501
                        else if ( chartype[c] <= 3 ) {
4,892,606✔
1502
                                AP.eat = 0;
3,215,638✔
1503
                                if ( newstatement < 0 ) newstatement = 0;
3,215,638✔
1504
                        }
1505
                        else if ( c == ',' ) {
1,676,968✔
1506
                                if ( newstatement > 0 ) {
62,932✔
1507
                                        newstatement = -1;
1,305✔
1508
                                        AP.eat = -2;
1,305✔
1509
                                }
1510
/*                                else if ( AP.eat == -2 ) { s--; } */
1511
                                else if ( AP.eat == -2 ) { AP.eat = 1; continue; }
61,627✔
1512
                                else { goto doall; }
61,624✔
1513
                        }
1514
                        else {
1515
doall:;                        if ( AP.eat < 0 ) {
1,675,660✔
1516
                                        if ( newstatement == 0 ) s--;
19,361✔
1517
                                        else { newstatement = 0; }
1518
                                }
1519
                                else if ( newstatement == 1 ) newstatement = 0;
1,656,299✔
1520
                                AP.eat = 1;
1,675,660✔
1521
                                if ( c == '*' && s > AC.iBuffer+AP.PreAssignStack[AP.PreAssignLevel] && s[-1] == '*' ) {
1,675,660✔
1522
                                        s[-1] = '^';
×
1523
                                        continue;
×
1524
                                }
1525
                        }
1526
                }
1527
                if ( s >= AC.iStop ) {
4,943,549✔
1528
                        if ( !AP.iBufError ) {
69✔
1529
                                LONG position = s - AC.iBuffer;
69✔
1530
                                LONG position2 = AC.iPointer - AC.iBuffer;
69✔
1531
                                UBYTE **ppp = &(AC.iBuffer); /* to avoid a compiler warning */
69✔
1532
                                if ( DoubleLList((VOID ***)ppp,&AC.iBufferSize
69✔
1533
                                ,sizeof(UBYTE),"statement buffer") ) {
1534
                                        *s = 0; retval = -1; AP.iBufError = 1;
×
1535
                                }
1536
                                AC.iPointer = AC.iBuffer + position2;
69✔
1537
                                AC.iStop = AC.iBuffer + AC.iBufferSize-2;
69✔
1538
                                s = AC.iBuffer + position;
69✔
1539
                        }
1540
                        if ( AP.iBufError ) {
69✔
1541
                                for(;;){
×
1542
                                        c = GetChar(0);
×
1543
                                        if ( c == ENDOFINPUT ) { retval = -1; break; }
×
1544
                                        if ( c == '"' ) {
×
1545
                                                if ( stringlevel > 0 ) stringlevel = 0;
×
1546
                                                else stringlevel = 1;
×
1547
                                        }
1548
                                        else if ( c == LINEFEED && !stringlevel ) { retval = -2; break; }
×
1549
                                        else if ( c == ';' && !stringlevel ) {
×
1550
                                                while ( ( c = GetChar(0) ) == ' ' || c == '\t' ) {}
×
1551
                                                if ( c != LINEFEED ) UngetChar(c);
×
1552
                                                retval = -1;
1553
                                                break;
1554
                                        }
1555
                                        else if ( c == '\\' ) c = GetChar(0);
×
1556
                                }
1557
                                break;
1558
                        }
1559
                }
1560
                *s++ = c;
4,943,549✔
1561
        }
1562
        AC.iPointer = s;
29,303✔
1563
        *s = 0;
29,303✔
1564
        if ( stringlevel > 0 ) {
29,303✔
1565
                MesPrint("@Unbalanced \". Runaway string");
×
1566
                retval = -1;
×
1567
        }
1568
        if ( retval == 1 ) {
29,303✔
1569
                if ( ExpandTripleDots(0) < 0 ) retval = -1;
11,015✔
1570
        }
1571
        return(retval);
29,303✔
1572
}
1573

1574
/*
1575
                 #] LoadStatement : 
1576
                 #[ ExpandTripleDots :
1577
*/
1578

1579
static inline int IsSignChar(UBYTE c)
141,504✔
1580
{
1581
        return c == '+' || c == '-';
141,504✔
1582
}
1583

1584
static inline int IsAlphanumericChar(UBYTE c)
600✔
1585
{
1586
        return FG.cTable[c] == 0 || FG.cTable[c] == 1;
600✔
1587
}
1588

1589
static inline int CanParseSignedNumber(const UBYTE *s)
1,191✔
1590
{
1591
        while ( IsSignChar(*s) ) s++;
1,239✔
1592
        return FG.cTable[*s] == 1;
1,191✔
1593
}
1594

1595
int ExpandTripleDots(int par)
4,474,893✔
1596
{
1597
        UBYTE *s, *s1, *s2, *n1, *n2, *t1, *t2, *startp, operator1, operator2, c, cc;
4,474,893✔
1598
        UBYTE *nBuffer, *strngs, *Buffer, *Stop;
4,474,893✔
1599
        LONG withquestion, x1, x2, y1, y2, number, inc, newsize, pow, fullsize;
4,474,893✔
1600
        int i, error = 0, i1 ,i2, ii, *nums = 0;
4,474,893✔
1601

1602
        if ( par == 0 ) {
4,474,893✔
1603
                Buffer = AC.iBuffer+AP.PreAssignStack[AP.PreAssignLevel]; Stop = AC.iStop;
11,015✔
1604
        }
1605
        else {
1606
                Buffer = AP.preStart; Stop = AP.preStop;
4,463,878✔
1607
        }
1608
        s = Buffer; while ( *s ) s++;
51,722,663✔
1609
        fullsize = s - Buffer;
4,474,893✔
1610
        if ( fullsize < 7 ) return(error);
4,474,893✔
1611

1612
        s = Buffer+2;
2,232,039✔
1613
        while ( *s ) {
34,115,616✔
1614
                if ( *s != '.' || ( s[-1] != ',' && FG.cTable[s[-1]] != 5 ) )
31,883,577✔
1615
                        { s++; continue; }
31,883,199✔
1616
                if ( s[-1] == '%' || s[-1] == '^' || s[1] != '.' || s[2] != '.' )
378✔
1617
                        { s++; continue; }
6✔
1618
                s1 = s - 2;
372✔
1619
                s += 3;
372✔
1620
                if ( *s != s[-4] && ( *s != '+' || s[-4] != '-' )
372✔
1621
                 && ( *s != '-' || s[-4] != '+' ) ) {
×
1622
                        MesPrint("&Improper operators for ...");
×
1623
                        error = -1;
×
1624
                } 
1625
                operator1 = s[-4];
372✔
1626
                operator2 = *s++;
372✔
1627
                if ( operator1 == ':' ) operator1 = '.';
372✔
1628
                if ( operator2 == ':' ) operator2 = '.';
372✔
1629
/*
1630
                We have now O1...O2 (O stands for operator)
1631
                Full syntax is
1632
                [str]#1[?]O1...O2[str]#2[?]   (Special case)
1633
                in which both strings are identical and if one ? then also the other.
1634
                <pattern1>O1...O2<pattern2>   (General case)
1635
                in which the difference in the patterns is just numerical.
1636
*/
1637
                s2 = s;                        /* the beginning of the second string */
372✔
1638
                if ( *s2 != '<' || *s1 != '>' ) {        /* Special case */
372✔
1639
                        startp = s1+1;
207✔
1640
                        withquestion = ( *s1 == '?' ); s1--;
207✔
1641
                        while ( FG.cTable[*s1] == 1 && s1 >= Buffer ) s1--;
210✔
1642
                        n1 = s1+1;                /* Beginning of first number */ 
207✔
1643
                        if ( FG.cTable[*n1] != 1 ) {
207✔
1644
                                MesPrint("&No first number in ... operator");
×
1645
                                error = -1;
×
1646
                        } 
1647
                        while ( FG.cTable[*s1] <= 1 && s1 >= Buffer ) s1--;
420✔
1648
                        s1++;
207✔
1649
/*
1650
                        We have now the first string from s1 to n1, number from n1
1651
*/
1652
                        t1 = s1; t2 = s2;
207✔
1653
                        while ( t1 < n1 && *t1 == *t2 ) { t1++; t2++; }
420✔
1654
                        n2 = t2;
207✔
1655
                        if ( FG.cTable[*t2] != 1 ) {
207✔
1656
                                MesPrint("&No second number in ... operator");
×
1657
                                error = -1;
×
1658
                        }
1659
                        x2 = 0;
207✔
1660
                        while ( FG.cTable[*t2] == 1 ) x2 = 10*x2 + *t2++ - '0';
534✔
1661
                        x1 = 0;
1662
                        while ( FG.cTable[*t1] == 1 ) x1 = 10*x1 + *t1++ - '0';
417✔
1663
                        if ( withquestion != ( *t2 == '?' ) ) {
207✔
1664
                                MesPrint("&Improper use of ? in ... operator");
×
1665
                                if ( *t2 == '?' ) t2++;
×
1666
                                error = -1;
1667
                        }
1668
                        else if ( withquestion ) t2++;
207✔
1669
                        if ( FG.cTable[*t2] <= 2 ) {
207✔
1670
                                MesPrint("&Illegal object after ... construction");
×
1671
                                error = -1;
×
1672
                        }
1673
                        c = *n1; *n1 = 0; s = t2;
207✔
1674
                        if ( error ) continue;
207✔
1675
/*
1676
                        At this point the syntax has been fulfilled. We have
1677
                        str in s1.
1678
                        x1,x2 are #1,#2
1679
                        operator1,operator2 are the two operators.
1680
                        s points at whatever comes after.
1681
                        Expansion will have to be computed. 
1682
*/
1683
                        if ( x2 < x1 ) { number = x1-x2; inc = -1; y1 = x2; y2 = x1; }
207✔
1684
                        else           { number = x2-x1; inc =  1; y1 = x1; y2 = x2; }
207✔
1685
                        newsize = (number+1)*(n1-s1)                    /* the strings   */
414✔
1686
                                 + number                                            /* the operators */
207✔
1687
                                 +(number+1)*(withquestion?1:0)        /* questionmarks */
207✔
1688
                                 +(number+1);                   /* last digits   */
1689
                        pow = 10;
207✔
1690
                        for ( i = 1; i < 10; i++, pow *= 10 ) {
327✔
1691
                                if ( y1 >= pow )      newsize += number+1;
327✔
1692
                                else if ( y2 >= pow ) newsize += y2-pow+1;
324✔
1693
                                else break;
1694
                        }
1695
                        while ( Buffer+(fullsize+newsize-(s-s1)) >= Stop ) {
261✔
1696
                                LONG strpos = s1-Buffer;
54✔
1697
                                LONG endstr = n1-Buffer;
54✔
1698
                                LONG startq = startp - Buffer;
54✔
1699
                                LONG position = s - Buffer;
54✔
1700
                                UBYTE **ppp;
54✔
1701
                                if ( par == 0 ) {
54✔
1702
                                        LONG position2 = AC.iPointer - AC.iBuffer;
54✔
1703
                                        ppp = &(AC.iBuffer); /* to avoid a compiler warning */
54✔
1704
                                        if ( DoubleLList((VOID ***)ppp,&AC.iBufferSize
54✔
1705
                                                ,sizeof(UBYTE),"statement buffer") ) {
1706
                                                        Terminate(-1);
×
1707
                                        }
1708
                                        AC.iPointer = AC.iBuffer + position2;
54✔
1709
                                        AC.iStop = AC.iBuffer + AC.iBufferSize-2;
54✔
1710
                                        Buffer = AC.iBuffer+AP.PreAssignStack[AP.PreAssignLevel]; Stop = AC.iStop;
54✔
1711
                                }
1712
                                else {
1713
                                        LONG fillpos = 0;
×
1714
                                        if ( AP.preFill ) fillpos = AP.preFill - AP.preStart;
×
1715
                                        ppp = &(AP.preStart); /* to avoid a compiler warning */
×
1716
                                        if ( DoubleLList((VOID ***)ppp,&AP.pSize,sizeof(UBYTE),
×
1717
                                                "instruction buffer") ) {
1718
                                                        Terminate(-1);
×
1719
                                        }
1720
                                        AP.preStop = AP.preStart + AP.pSize-3;
×
1721
                                        if ( AP.preFill ) AP.preFill = fillpos + AP.preStart;
×
1722
                                        Buffer = AP.preStart; Stop = AP.preStop;
1723
                                }
1724
                                s  = Buffer + position;
54✔
1725
                                n1 = Buffer + endstr;
54✔
1726
                                s1 = Buffer + strpos;
54✔
1727
                                startp = Buffer + startq;
54✔
1728
                        }
1729
/*
1730
                        We have space for the expansion in the buffer.
1731
                        There are two cases: new size >  old size
1732
                                             old size >= new size
1733
                        Note that whereever we move things, it will be at least startp.
1734
*/
1735
                        if ( newsize > (s-s1) ) {
207✔
1736
                                t2 = Buffer + fullsize;
192✔
1737
                                t1 = t2 + (newsize - (s-s1));
192✔
1738
                                *t1 = 0;
192✔
1739
                                while ( t2 > s ) { *--t1 = *--t2; }
546✔
1740
                        }
1741
                        else if ( newsize < (s-s1) ) {
15✔
1742
                                t1 = s1 + newsize; t2 = s; s = t1;
15✔
1743
                                while ( *t2 ) *t1++ = *t2++;
15✔
1744
                                *t1 = 0;
15✔
1745
                        }
1746
                        for ( x1 += inc, t1 = startp; number > 0; number--, x1 += inc ) {
65,169✔
1747
                                *t1++ = operator1;
64,962✔
1748
                                cc = operator1; operator1 = operator2; operator2 = cc;
64,962✔
1749
                                t2 = s1; while ( *t2 ) *t1++ = *t2++;
69,918✔
1750
                                x2 = x1; n2 = t1;
244,851✔
1751
                                do {
244,851✔
1752
                                        *t1++ = '0' + x2 % 10;
244,851✔
1753
                                        x2 /= 10;
244,851✔
1754
                                } while ( x2 );
244,851✔
1755
                                s2 = t1 - 1;
1756
                                while ( s2 > n2 ) { cc = *s2; *s2 = *n2; *n2++ = cc; s2--; }
182,676✔
1757
                                if ( withquestion ) *t1++ = '?';
64,962✔
1758
                        }
1759
                        fullsize += newsize - ( s - s1 );
207✔
1760
                        *n1 = c;
207✔
1761
                }
1762
                else {                /* General case. Find the patterns first */
1763
                        t1 = s1; s1--;
165✔
1764
                        while ( s1 > Buffer ) {
1,110✔
1765
                                if ( *s1 == '<' ) break;
1,110✔
1766
                                s1--;
945✔
1767
                        }
1768
                        t2 = s2;
1769
                        while ( *t2 ) {
1,512✔
1770
                                if ( *t2 == '>' ) break;
1,512✔
1771
                                t2++;
1,347✔
1772
                        }
1773
                        if ( *s1 != '<' || *t2 != '>' ) {
165✔
1774
                                MesPrint("&Illegal attempt to use ... operator");
×
1775
                                return(-1);
×
1776
                        }
1777
                        s1++; s2++;                /* Pointers to the patterns */
165✔
1778
                        nums = (int *)Malloc1((t1-s1)*2*(sizeof(int)+sizeof(UBYTE))
165✔
1779
                                                        ,"Expand ...");
1780
                        strngs = (UBYTE *)(nums + 2*(t1-s1));
165✔
1781
                        n1 = s1; n2 = s2; ii = -1; i = 0;
165✔
1782
                        s = strngs;                        
165✔
1783
                        while ( n1 < t1 || n2 < t2 ) {
1,056✔
1784
                                /* Check the next characters can be parsed as numbers including signs. */
1785
                                if ( CanParseSignedNumber(n1) && CanParseSignedNumber(n2) ) {
891✔
1786
                                        /*
1787
                                         * Don't allow the cases that one has the sign and the other doesn't,
1788
                                         * and the meaning changes without the sign. For example,
1789
                                         *   <f(1)>+...+<f(3)>       Allowed
1790
                                         *   <f(-2)>+...+<f(2)>      Allowed
1791
                                         *   <f(x-2)>+...+<f(x+2)>   Allowed
1792
                                         *   <f(x-2)>+...+<f(x2)>    Not allowed
1793
                                         */
1794
                                        int sign1 = IsSignChar(*n1);
300✔
1795
                                        int sign2 = IsSignChar(*n2);
300✔
1796
                                        int inword1 = s1 < n1 && IsAlphanumericChar(n1[-1]);
300✔
1797
                                        int inword2 = s2 < n2 && IsAlphanumericChar(n2[-1]);
300✔
1798
                                        if ( ( sign1 ^ sign2 ) && ( inword1 || inword2 ) ) break;  /* Not allowed. */
300✔
1799
                                        if ( sign1 || sign2 ) {
300✔
1800
                                                *s++ = '+';  /* Marker indicating we need the sign. */
24✔
1801
                                        }
1802
                                } else {
1803
                                        /* If they are not numbers, they should be same. */
1804
                                        if ( *n1 == *n2 ) { *s++ = *n1++; n2++; continue; }
591✔
1805
                                        else break;
1806
                                }
1807
                                ParseSignedNumber(x1,n1)
654✔
1808
                                ParseSignedNumber(x2,n2)
891✔
1809
                                if ( x1 == x2 ) {
300✔
1810
                                        if ( s != strngs && ( s[-1] == '+' || s[-1] == '-' ) ) {
45✔
1811
                                                /* We need the sign. */
1812
                                                s--;
6✔
1813
                                                if ( x1 >= 0 ) {
6✔
1814
                                                        *s++ = '+';
3✔
1815
                                                }
1816
                                        }
1817
                                        s = NumCopy(x1, s);
45✔
1818
                                }
1819
                                else {
1820
                                        nums[2*i] = x1; nums[2*i+1] = x2;
255✔
1821
                                        i++; *s++ = 0;
255✔
1822
                                }
1823
                        }
1824
                        if ( n1 < t1 || n2 < t2 ) {
165✔
1825
                                MesPrint("&Improper use of ... operator.");
×
1826
theend:                        M_free(nums,"Expand ...");
×
1827
                                return(-1);
×
1828
                        }
1829
                        *s = 0;
165✔
1830
                        if ( i == 0 ) ii = 0;
165✔
1831
                        else {
1832
                                ii = nums[0] - nums[1];
165✔
1833
                                if ( ii < 0 ) ii = -ii;
165✔
1834
                                for ( x1 = 1; x1 < i; x1++ ) {
255✔
1835
                                        x2 = nums[2*x1]-nums[2*x1+1];
90✔
1836
                                        if ( x2 < 0 ) x2 = -x2;
90✔
1837
                                        if ( x2 != ii ) {
90✔
1838
                                                MesPrint("&Improper synchronization of numbers in ... operator");
×
1839
                                                goto theend;
×
1840
                                        }
1841
                                }
1842
                        }
1843
                        ii++;
165✔
1844
/*
1845
                        We have now proper syntax.
1846
                        There are i+1 strings in strngs and i pairs of numbers
1847
                        in nums. Each time a start value and a finish value.
1848
                        We have ii steps. If ii <= 2, it will fit in the existing
1849
                        allocation. But this is hardly useful.
1850
                        We make a new allocation and copy from the old.
1851
                        Compute space.
1852
*/
1853
                        x2 = s - strngs - i;  /* -1 for end-of-string and +1 for the operator*/
165✔
1854
                        for ( i1 = 0; i1 < i; i1++ ) {
420✔
1855
                                i2 = nums[2*i1];
255✔
1856
                                x1 = nums[2*i1+1];
255✔
1857
                                if ( i2 < 0 ) i2 = -i2;
255✔
1858
                                if ( x1 < 0 ) x1 = -x1;
255✔
1859
                                if ( x1 > i2 ) i2 = x1;
255✔
1860
                                x1 = 2;
1861
                                while ( i2 > 0 ) { i2 /= 10; x1++; }
792✔
1862
                                x2 += x1;
255✔
1863
                        }
1864
                        x2 *= ii;        /* Space for the expanded string (a bit more) */
165✔
1865
                        x2 += fullsize;
165✔
1866
                        x2 += 5;                /* This will definitely hold everything */
165✔
1867
                        x2 += sizeof(UBYTE *);
165✔
1868
                        x2 = x2 - (x2 & (sizeof(UBYTE *)-1));
165✔
1869

1870
                        nBuffer = (UBYTE *)Malloc1(x2,"input buffer");
165✔
1871
                        n1 = nBuffer; s = Buffer; s1--;
165✔
1872
                        while ( s < s1 ) *n1++ = *s++;
239,232✔
1873
/*
1874
                        Solution of the special case that no comma was generated
1875
                        due to the presence of < to start the pattern.
1876
                        We get a comma when the word before ends in an alphanumeric
1877
                        character, a _ or a ] and the word inside starts with an
1878
                        alphanumeric character, a [ (or an _ (for future considerations))
1879
*/
1880
                        if ( ( ( n1 > nBuffer ) && ( ( FG.cTable[n1[-1]] <= 1 )
165✔
1881
                        || ( n1[-1] == '_' ) || ( n1[-1] == ']' ) ) ) &&
165✔
1882
                        ( ( FG.cTable[strngs[0]] <= 1 ) || ( strngs[0] == '[' )
×
1883
                         || ( strngs[0] == '_' ) ) ) *n1++ = ',';
×
1884

1885
                        for ( i1 = 0; i1 < ii; i1++ ) {
136,926✔
1886
                                s = strngs; while ( *s ) *n1++ = *s++;
411,417✔
1887
                                for ( i2 = 0; i2 < i; i2++ ) {
276,726✔
1888
                                        if ( n1 > nBuffer && IsSignChar(n1[-1]) ) {
139,965✔
1889
                                                /* We need the sign of counters. */
1890
                                                n1--;
2,076✔
1891
                                                if ( nums[2*i2] >= 0 ) {
2,076✔
1892
                                                        *n1++ = '+';
1,965✔
1893
                                                }
1894
                                        }
1895
                                        n1 = NumCopy((WORD)(nums[2*i2]),n1);
139,965✔
1896
                                        if ( nums[2*i2] > nums[2*i2+1] ) nums[2*i2]--;
139,965✔
1897
                                        else nums[2*i2]++;
139,887✔
1898
                                        s++; while ( *s ) *n1++ = *s++;
280,905✔
1899
                                }
1900
                                if ( ( i1 & 1 ) == 0 ) *n1++ = operator1;
136,761✔
1901
                                else *n1++ = operator2;
68,352✔
1902
                        }
1903
                        n1--;        /* drop the trailing operator */
165✔
1904
                        s = t2 + 1; n2 = n1;
165✔
1905
/*
1906
                        Similar extra comma
1907
*/
1908
                        if ( ( ( ( FG.cTable[n1[-1]] <= 1 )
165✔
1909
                        || ( n1[-1] == '_' ) || ( n1[-1] == ']' ) ) ) &&
84✔
1910
                        ( ( FG.cTable[s[0]] <= 1 ) || ( s[0] == '[' )
87✔
1911
                         || ( s[0] == '_' ) ) ) *n1++ = ',';
87✔
1912

1913
                        while ( *s ) *n1++ = *s++;
20,163✔
1914
                        *n1 = 0;
165✔
1915
                        if ( par == 0 ) {
165✔
1916
                                LONG nnn1 = n1-nBuffer;
165✔
1917
                                LONG nnn2 = n2-nBuffer;
165✔
1918
                                LONG nnn3;
165✔
1919
                                while ( AC.iBuffer+AP.PreAssignStack[AP.PreAssignLevel] + x2 >= AC.iStop ) {
255✔
1920
                                        LONG position = s-Buffer;
90✔
1921
                                        LONG position2 = AC.iPointer - AC.iBuffer;
90✔
1922
                                        UBYTE **ppp;
90✔
1923
                                        ppp = &(AC.iBuffer); /* to avoid a compiler warning */
90✔
1924
                                        if ( DoubleLList((VOID ***)ppp,&AC.iBufferSize
90✔
1925
                                                ,sizeof(UBYTE),"statement buffer") ) {
1926
                                                        Terminate(-1);
×
1927
                                        }
1928
                                        AC.iPointer = AC.iBuffer + position2;
90✔
1929
                                        AC.iStop = AC.iBuffer + AC.iBufferSize-2;
90✔
1930
                                        Buffer = AC.iBuffer+AP.PreAssignStack[AP.PreAssignLevel]; Stop = AC.iStop;
90✔
1931
                                        s  = Buffer + position;
90✔
1932
                                }
1933
/*
1934
                                This can be improved. We only have to start from the first term.
1935
*/
1936
                                for ( nnn3 = 0; nnn3 < nnn1; nnn3++ ) Buffer[nnn3] = nBuffer[nnn3];
1,427,430✔
1937
                                Buffer[nnn3] = 0;
165✔
1938
                                n1 = Buffer + nnn1;
165✔
1939
                                n2 = Buffer + nnn2;
165✔
1940
                                M_free(nBuffer,"input buffer");
165✔
1941
                                M_free(nums,"Expand ...");
165✔
1942
                        }
1943
                        else { /* Comes here only inside a real preprocessor instruction */
1944
                                AP.preStop = nBuffer + x2 - 2;
×
1945
                                AP.pSize = x2;
×
1946
                                M_free(AP.preStart,"input buffer");
×
1947
                                M_free(nums,"Expand ...");
×
1948
                                AP.preStart = nBuffer;
×
1949
                                Buffer = AP.preStart; Stop = AP.preStop;
×
1950
                        }
1951
                        fullsize = n1 - Buffer;
165✔
1952
                        s = n2;
165✔
1953
                }
1954
        }
1955
        return(error);
1956
}
1957

1958
/*
1959
                 #] ExpandTripleDots : 
1960
                 #[ FindKeyWord :
1961
*/
1962

1963
KEYWORD *FindKeyWord(UBYTE *theword, KEYWORD *table, int size)
4,464,254✔
1964
{
1965
        int low,med,hi;
4,464,254✔
1966
        UBYTE *s1, *s2;
4,464,254✔
1967
        low = 0;
4,464,254✔
1968
        hi = size-1;
4,464,254✔
1969
        while ( hi >= low ) {
26,779,469✔
1970
                med = (hi+low)/2;
26,779,469✔
1971
                s1 = (UBYTE *)(table[med].name);
26,779,469✔
1972
                s2 = theword;
26,779,469✔
1973
                while ( *s1 && tolower(*s1) == tolower(*s2) ) { s1++; s2++; }
78,100,843✔
1974
                if ( *s1 == 0 &&
26,779,469✔
1975
/*[30apr2004 mt]:*/
1976
/* The bug!:
1977
                                FG.cTable[*s2] != 1 && FG.cTable[*s2] != 2
1978
*/
1979
                                FG.cTable[*s2] != 0 && FG.cTable[*s2] != 1
4,464,296✔
1980
/*                ( *s2 == ' ' || *s2 == '\t' || *s2 == 0 || *s2 == ',' || *s2 == '(' ) */
1981
                         )
1982
                        return(table+med);
1983
                if ( tolower(*s2) > tolower(*s1) ) low = med+1;
22,315,215✔
1984
                else hi = med - 1;
11,169,584✔
1985
        }
1986
        return(0);
1987
}
1988

1989
/*
1990
                 #] FindKeyWord : 
1991
                 #[ FindInKeyWord :
1992
*/
1993

1994
KEYWORD *FindInKeyWord(UBYTE *theword, KEYWORD *table, int size)
×
1995
{
1996
        int i;
×
1997
        UBYTE *s1, *s2;
×
1998
        for ( i = 0; i < size; i++ ) {
×
1999
                s1 = (UBYTE *)(table[i].name);
×
2000
                s2 = theword;
×
2001
                while ( *s1 && tolower(*s1) == tolower(*s2) ) { s1++; s2++; }
×
2002
                if ( *s2 == 0 || *s2 == ' ' || *s2 == ',' || *s2 == '\t' )
×
2003
                        return(table+i);
2004
        }
2005
        return(0);
2006
}
2007

2008
/*
2009
                 #] FindInKeyWord : 
2010
                 #[ TheDefine :
2011
*/
2012

2013
/**
2014
 *  Preprocessor assignment. Possible arguments and values are treated and the
2015
 *  new preprocessor variable is put into the name administration.
2016
 *
2017
 *  @param   s      Pointer to the character string following the preprocessor
2018
 *                  command.
2019
 *  @param   mode   Bitmask. 0-bit clear: always create a new name entry, 0-bit
2020
 *                  set: try to redefine an existing name, 1-bit set: ignore
2021
 *                  preprocessor if/switch status.
2022
 *  @return         zero: no errors, negative number: errors.
2023
 */
2024
int TheDefine(UBYTE *s, int mode)
2,220,547✔
2025
{
2026
        UBYTE *name, *value, *valpoin, *args = 0, c;
2,220,547✔
2027
        if ( ( mode & 2 ) == 0 ) {
2,220,547✔
2028
                if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
2,220,547✔
2029
                if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
2,220,547✔
2030
        }
2031
        else { mode &= ~2; }
×
2032
        name = s;
2,220,544✔
2033
        if ( chartype[*s] != 0 ) goto illname;
2,220,544✔
2034
        s++;
2,220,544✔
2035
        while ( chartype[*s] <= 1 ) s++;
2,220,759✔
2036
        value = s;
4,439,927✔
2037
        while ( *s == ' ' || *s == '\t' ) s++;
4,439,927✔
2038
        c = *s; *value = 0;
2,220,544✔
2039
        if ( c == 0 ) {
2,220,544✔
2040
                if ( PutPreVar(name,(UBYTE *)"1",0,mode) < 0 ) return(-1);
1,152✔
2041
                return(0);
1,152✔
2042
        }
2043
        if ( c == '(' ) {        /* arguments. scan for correctness */
2,219,392✔
2044
                s++; args = s;
9✔
2045
                for (;;) {
15✔
2046
                        if ( chartype[*s] != 0 ) goto illarg;
15✔
2047
                        s++;
15✔
2048
                        while ( chartype[*s] <= 1 ) s++;
15✔
2049
                        while ( *s == ' ' || *s == '\t' ) s++;
15✔
2050
                        if ( *s == ')' ) break;
15✔
2051
                        if ( *s != ',' ) goto illargs;
6✔
2052
                        s++;
6✔
2053
                        while ( *s == ' ' || *s == '\t' ) s++;
6✔
2054
                }
2055
                *s++ = 0;
9✔
2056
                while ( *s == ' ' || *s == '\t' ) s++;
18✔
2057
                c = *s;
2058
        }
2059
        if ( c == '"' ) {
2,219,392✔
2060
                s++; valpoin = value = s;
2,219,392✔
2061
                while ( *s != '"' ) {
4,439,104✔
2062
                        if ( *s == '\\' ) {
2,219,712✔
2063
                                if ( s[1] == 'n' ) { *valpoin++ = LINEFEED; s += 2; }
×
2064
                                else if ( s[1] == '"' ) { *valpoin++ = '"'; s += 2; }
×
2065
                                else if ( s[1] == 0 ) goto illval;
×
2066
                                else { *valpoin++ = *s++; *valpoin++ = *s++; }
×
2067
                        }
2068
                        else *valpoin++ = *s++;
2,219,712✔
2069
                }
2070
                *valpoin = 0;
2,219,392✔
2071
                if ( PutPreVar(name,value,args,mode) < 0 ) return(-1);
2,219,392✔
2072
        }
2073
        else {
2074
                MesPrint("@Illegal string for preprocessor variable %s. Forgotten double quotes (\") ?",name);
×
2075
                return(-1);
×
2076
        }
2077
        return(0);
2078
illname:;
×
2079
        MesPrint("@Illegally formed name of preprocessor variable");
×
2080
        return(-1);
×
2081
illarg:;
×
2082
        MesPrint("@Illegally formed name of argument of preprocessor definition");
×
2083
        return(-1);
×
2084
illargs:;
×
2085
        MesPrint("@Illegally formed arguments of preprocessor definition");
×
2086
        return(-1);
×
2087
illval:;
×
2088
        MesPrint("@Illegal valpoin for preprocessor variable %s",name);
×
2089
        return(-1);
×
2090
}
2091

2092
/*
2093
                 #] TheDefine : 
2094
                 #[ DoCommentChar :
2095
*/
2096

2097
int DoCommentChar(UBYTE *s)
×
2098
{
2099
        UBYTE c;
×
2100
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
2101
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
2102
        while ( *s == ' ' || *s == '\t' ) s++;
×
2103
        if ( *s == 0 || *s == '\n' ) {
×
2104
                MesPrint("@No valid comment character specified");
×
2105
                return(-1);
×
2106
        }
2107
        c = *s++;
×
2108
        while ( *s == ' ' || *s == '\t' ) s++;
×
2109
        if ( *s != 0 && *s != '\n' ) {
×
2110
                MesPrint("@Comment character should be a single valid character");
×
2111
                return(-1);
×
2112
        }
2113
        AP.ComChar = c;
×
2114
        return(0);
×
2115
}
2116

2117
/*
2118
                 #] DoCommentChar : 
2119
                 #[ DoPreAssign :
2120

2121
                Routine assigns a 'value' to a $variable.
2122
                Syntax: #assign
2123
                        next line(s) a statement of the type
2124
                        $name = expression;
2125
                Note: at the moment of the assign there cannot be an 'open' statement.
2126
*/
2127

2128
int DoPreAssign(UBYTE *s)
327✔
2129
{
2130
        int error = 0;
327✔
2131
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) {
327✔
2132
                return(0);
2133
        }
2134
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) {
327✔
2135
                return(0);
2136
        }
2137
        if ( *s ) {
327✔
2138
                MesPrint("@Illegal characters in %#assign instruction");
×
2139
                error = 1;
×
2140
        }
2141
        PUSHPREASSIGNLEVEL;
327✔
2142
        AP.PreAssignFlag = 1;
327✔
2143
/*
2144
        if ( AP.PreContinuation ) {
2145
                MesPrint("@Assign instructions cannot occur inside statements");
2146
                MesPrint("@Missing ; ?");
2147
                AP.PreContinuation = 0;
2148
                error = 1;
2149
        }
2150
*/
2151
        return(error);
327✔
2152
}
2153

2154
/*
2155
                 #] DoPreAssign : 
2156
                 #[ DoDefine :
2157
*/
2158

2159
int DoDefine(UBYTE *s)
1,267✔
2160
{
2161
        return(TheDefine(s,0));
1,267✔
2162
}
2163

2164
/*
2165
                 #] DoDefine : 
2166
                 #[ DoRedefine :
2167
*/
2168

2169
int DoRedefine(UBYTE *s)
2,219,280✔
2170
{
2171
        return(TheDefine(s,1));
2,219,280✔
2172
}
2173

2174
/*
2175
                 #] DoRedefine : 
2176
                 #[ ClearMacro :
2177

2178
                Undefines the arguments of a macro after its use.
2179
*/
2180

2181
int ClearMacro(UBYTE *name)
148,044✔
2182
{
2183
        int i;
148,044✔
2184
        PREVAR *p;
148,044✔
2185
        UBYTE *s;
148,044✔
2186
        for ( i = NumPre-1, p = &(PreVar[NumPre-1]); i >= 0; i--, p-- ) {
876,729✔
2187
                if ( StrCmp(name,p->name) == 0 ) break;
876,477✔
2188
        }
2189
        if ( i < 0 ) return(-1);
148,044✔
2190
        if ( p->nargs <= 0 ) return(0);
147,792✔
2191
        s = p->argnames;
1,158✔
2192
        for ( i = 0; i < p->nargs; i++ ) {
2,322✔
2193
                TheUndefine(s);
1,164✔
2194
                while ( *s ) s++;
2,328✔
2195
                s++;
1,164✔
2196
        }
2197
        return(0);
2198
}
2199

2200
/*
2201
                 #] ClearMacro : 
2202
                 #[ TheUndefine :
2203

2204
                There is a complication here. If there are redefine statements
2205
                they will be pointing at the wrong variable if their number is
2206
                greater than the number of the variable we pop.
2207
*/
2208

2209
int TheUndefine(UBYTE *name)
1,362✔
2210
{
2211
        int i, inum, error = 0;
1,362✔
2212
        PREVAR *p;
1,362✔
2213
        for ( i = NumPre-1, p = &(PreVar[NumPre-1]); i >= 0; i--, p-- ) {
2,520✔
2214
                if ( StrCmp(name,p->name) == 0 ) {
2,520✔
2215
                        M_free(p->name,"undefining PreVar");
1,362✔
2216
                        NumPre--;
1,362✔
2217
                        inum = i;
1,362✔
2218
                        while ( i < NumPre ) {
2,520✔
2219
                                p->name  = p[1].name;
1,158✔
2220
                                p->value = p[1].value;
1,158✔
2221
                                p++; i++;
1,158✔
2222
                        }
2223
                        p->name = 0; p->value = 0;
1,362✔
2224
                        {
2225
                                CBUF *CC = cbuf + AC.cbufnum;
1,362✔
2226
                                int j, k;
1,362✔
2227
                                for ( j = 1; j <= CC->numlhs; j++ ) {
9,531✔
2228
                                        if ( CC->lhs[j][0] == TYPEREDEFPRE ) {
8,169✔
2229
                                                if ( CC->lhs[j][2] > inum ) CC->lhs[j][2]--;
×
2230
                                                else if ( CC->lhs[j][2] == inum ) {
×
2231
                                                        for ( k = inum - 1; k >= 0; k-- )
×
2232
                                                                if ( StrCmp(name, PreVar[k].name) == 0 ) break;
×
2233
                                                        if ( k >= 0 ) CC->lhs[j][2] = k;
×
2234
                                                        else {
2235
                                                                MesPrint("@Conflict between undefining a preprocessor variable and a redefine statement");
×
2236
                                                                error = 1;
×
2237
                                                        }
2238
                                                }
2239
                                        }
2240
                                }
2241
#ifdef PARALLELCODE
2242
                                for ( j = 0; j < AC.numpfirstnum; j++ ) {
908✔
2243
                                        if ( AC.pfirstnum[j] > inum ) AC.pfirstnum[j]--;
2244
                                        else if ( AC.pfirstnum[j] == inum ) {
2245
                                                for ( k = inum - 1; k >= 0; k-- )
2246
                                                        if ( StrCmp(name, PreVar[k].name) == 0 ) break;
2247
                                                if ( k >= 0 ) AC.pfirstnum[j] = k;
2248
                                        }
2249
                                }
2250
#endif
2251
                        }
2252
                        break;
2253
                }
2254
        }
2255
        return(error);
1,362✔
2256
}
2257

2258
/*
2259
                 #] TheUndefine : 
2260
                 #[ DoUndefine :
2261
*/
2262

2263
int DoUndefine(UBYTE *s)
198✔
2264
{
2265
        UBYTE *name, *t;
198✔
2266
        int error = 0, retval;
198✔
2267
/*
2268
        int i;
2269
        PREVAR *p;
2270
*/
2271
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
198✔
2272
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
198✔
2273
        name = s;
198✔
2274
        if ( chartype[*s] != 0 ) goto illname;
198✔
2275
        s++;
198✔
2276
        while ( chartype[*s] <= 1 ) s++;
204✔
2277
        t = s;
198✔
2278
        if ( *s && *s != ' ' && *s != '\t' ) goto illname;
198✔
2279
        while ( *s == ' ' || *s == '\t' ) s++;
198✔
2280
        if ( *s ) {
198✔
2281
                MesPrint("@Undefine should just have a variable name");
×
2282
                error = -1;
×
2283
        }
2284
        *t = 0;
198✔
2285
        if ( ( retval = TheUndefine(name) ) != 0 ) {
198✔
2286
                if ( error == 0 ) return(retval);
×
2287
                if ( error > 0 ) error = retval;
×
2288
        }
2289
/*
2290
        for ( i = NumPre-1, p = &(PreVar[NumPre-1]); i >= 0; i--, p-- ) {
2291
                if ( StrCmp(name,p->name) == 0 ) {
2292
                        M_free(p->name,"undefining PreVar");
2293
                        NumPre--;
2294
                        while ( i < NumPre ) {
2295
                                p->name  = p[1].name;
2296
                                p->value = p[1].value;
2297
                                p++; i++;
2298
                        }
2299
                        p->name = 0; p->value = 0;
2300
                        break;
2301
                }
2302
        }
2303
*/
2304
        return(error);
2305
illname:;
×
2306
        MesPrint("@Illegally formed name of preprocessor variable");
×
2307
        return(-1);
×
2308
}
2309

2310
/*
2311
                 #] DoUndefine : 
2312
                 #[ DoInclude :
2313
*/
2314

2315
int DoInclude(UBYTE *s) { return(Include(s,FILESTREAM)); }
9✔
2316

2317
/*
2318
                 #] DoInclude : 
2319
                 #[ DoReverseInclude :
2320
*/
2321

2322
int DoReverseInclude(UBYTE *s) { return(Include(s,REVERSEFILESTREAM)); }
×
2323

2324
/*
2325
                 #] DoReverseInclude : 
2326
                 #[ Include :
2327
*/
2328

2329
int Include(UBYTE *s, int type)
9✔
2330
{
2331
        UBYTE *name = s, *fold, *t, c, c1 = 0, c2 = 0, c3 = 0;
9✔
2332
        int str1offset, withnolist = AC.NoShowInput;
9✔
2333
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
9✔
2334
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
9✔
2335
    if ( *s == '-' || *s == '+' ) {
9✔
2336
                if ( *s == '-' ) withnolist = 1;
×
2337
                else             withnolist = 0;
×
2338
                s++;
×
2339
                while ( *s == ' ' || *s == '\t' ) s++;
×
2340
                name = s;
2341
        }
2342
        if ( *s == '"' ) {
9✔
2343
                while ( *s && *s != '"' ) {
×
2344
                        if ( *s == '\\' ) s++;
×
2345
                        s++;
×
2346
                }
2347
                t = s++;
×
2348
        }
2349
        else {
2350
                while ( *s && *s != ' ' && *s != '\t' ) {
75✔
2351
                        if ( *s == '\\' ) s++;
66✔
2352
                        s++;
66✔
2353
                }
2354
                t = s;
9✔
2355
        }
2356
        while ( *s == ' ' || *s == '\t' ) s++;
9✔
2357
        if ( *s == '#' ) {
9✔
2358
                *t = 0;
×
2359
                s++;
×
2360
                while ( *s == ' ' || *s == '\t' ) s++;
×
2361
                fold = s;
×
2362
                if ( *s == 0 ) {
×
2363
                        MesPrint("@Empty fold name");
×
2364
                        return(-1);
×
2365
                }
2366
continue_fold:
×
2367
                while ( *s && *s != ' ' && *s != '\t' ) {
×
2368
                        if ( *s == '\\' ) s++;
×
2369
                        s++;
×
2370
                }
2371
                t = s;
×
2372
                while ( *s == ' ' || *s == '\t' ) s++;
×
2373
                if ( *s ) {
×
2374
                        /*
2375
                         * A non-whitespace character is found. Continue parsing the fold.
2376
                         */
2377
                        goto continue_fold;
×
2378
                }
2379
        }
2380
        else if ( *s == 0 ) {
9✔
2381
                fold = 0;
2382
        }
2383
        else {
2384
                MesPrint("@Improper syntax for file name");
×
2385
                return(-1);
×
2386
        }
2387
        *t = 0;
9✔
2388
        if ( fold ) {
9✔
2389
                fold = strDup1(fold,"foldname");
×
2390
        }
2391
/*
2392
        We have the name of the file in 'name' and the fold in 'fold' (or NULL)
2393
*/
2394
        if ( OpenStream(name,type,0,PRENOACTION) == 0 ) {
9✔
2395
                if ( fold ) { M_free(fold,"foldname"); fold = 0; }
×
2396
                return(-1);
×
2397
        }
2398
        if ( fold ) {
9✔
2399
                LONG position = -1;
×
2400
                int foldopen = 0;
×
2401
                LONG linenum = 0, prevline = 0;
×
2402
                name = strDup1(name,"name of include file");
×
2403
                AC.CurrentStream->FoldName = strDup1(fold,"name of fold");
×
2404
                AC.NoShowInput++;
×
2405
                for(;;) {
×
2406
                        c = GetFromStream(AC.CurrentStream);
×
2407
                        if ( c == ENDOFSTREAM ) {
×
2408
                                AC.CurrentStream = CloseStream(AC.CurrentStream);
×
2409
                                goto nofold;
×
2410
                        }
2411
                        if ( c == AP.ComChar ) {
×
2412
                                str1offset = AC.CurrentStream-AC.Streams;
×
2413
                                LoadInstruction(1);
×
2414
                                if ( AC.CurrentStream != str1offset+AC.Streams ) {
×
2415
                                        c = ENDOFSTREAM;
2416
                                }
2417
                                else {
2418
                                        t = AP.preStart;
×
2419
                                        if ( t[2] == '#' && ( ( t[3] == '[' && !foldopen )
×
2420
                                        || ( t[3] == ']' && foldopen ) ) ) {
×
2421
                                                t += 4;
×
2422
                                                while ( *t == ' ' || *t == '\t' ) t++;
×
2423
                                                s = AC.CurrentStream->FoldName;
×
2424
                                                while ( *s == *t ) { s++; t++; }
×
2425
                                                if ( *s == 0 && ( *t == ' ' || *t == '\t'
×
2426
                                                || *t == ':' ) ) {
2427
                                                        while ( *t == ' ' || *t == '\t' ) t++;
×
2428
                                                        if ( *t == ':' ) {
×
2429
                                                                if ( foldopen == 0 ) {
×
2430
                                                                        foldopen = 1;
×
2431
                                                                        position = GetStreamPosition(AC.CurrentStream);
×
2432
                                                                        linenum = AC.CurrentStream->linenumber;
×
2433
                                                                        prevline = AC.CurrentStream->prevline;
×
2434
                                                                        c3 = AC.CurrentStream->isnextchar;
×
2435
                                                                        c1 = AC.CurrentStream->nextchar[0];
×
2436
                                                                        c2 = AC.CurrentStream->nextchar[1];
×
2437
                                                                }
2438
                                                                else {
2439
                                                                        foldopen = 0;
×
2440
                                                                        PositionStream(AC.CurrentStream,position);
×
2441
                                                                        AC.CurrentStream->linenumber = linenum;
×
2442
                                                                        AC.CurrentStream->prevline = prevline;
×
2443
                                                                        AC.CurrentStream->eqnum = 1;
×
2444
                                                                        AC.NoShowInput--;
×
2445
                                                                        AC.CurrentStream->isnextchar = c3;
×
2446
                                                                        AC.CurrentStream->nextchar[0] = c1;
×
2447
                                                                        AC.CurrentStream->nextchar[1] = c2;
×
2448
                                                                        break;
×
2449
                                                                }
2450
                                                        }
2451
                                                }
2452
                                        }
2453
                                }
2454
                        }
2455
                        else {
2456
                                while ( c != LINEFEED && c != ENDOFSTREAM ) {
×
2457
                                        c = GetFromStream(AC.CurrentStream);
×
2458
                                        if ( c == ENDOFSTREAM ) {
×
2459
                                                AC.CurrentStream = CloseStream(AC.CurrentStream);
×
2460
                                                break;
×
2461
                                        }
2462
                                }
2463
                        }
2464
                        if ( c == ENDOFSTREAM ) {
×
2465
nofold:
×
2466
                                MesPrint("@Cannot find fold %s in file %s",fold,name);
×
2467
                                UngetChar(c);
×
2468
                                AC.NoShowInput--;
×
2469
                                M_free(name,"name of include file");
×
2470
                                Terminate(-1);
×
2471
                        }
2472
                }
2473
                M_free(name,"name of include file");
×
2474
        }
2475
        AC.NoShowInput = withnolist;
9✔
2476
        if ( fold ) { M_free(fold,"foldname"); fold = 0; }
9✔
2477
        return(0);
2478
}
2479

2480
/*
2481
                 #] Include : 
2482
                 #[ DoPreExchange :
2483

2484
                Exchanges the names of expressions or the contents of dollars
2485
                Syntax:
2486
                        #exchange expr1,expr2
2487
                        #exchange $var1,$var2
2488
*/
2489

2490
int DoPreExchange(UBYTE *s)
×
2491
{
2492
        int error = 0;
×
2493
        UBYTE *s1, *s2;
×
2494
        WORD num1, num2;
×
2495
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
2496
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
2497
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
×
2498
        if ( *s == '$' ) {
×
2499
                s++; s1 = s; while ( FG.cTable[*s] <= 1 ) s++;
×
2500
                if ( *s != ',' && *s != ' ' && *s != '\t' ) goto syntax;
×
2501
                *s++ = 0;
×
2502
                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
2503
                if ( *s != '$' ) goto syntax;
×
2504
                s++; s2 = s; while ( FG.cTable[*s] <= 1 ) s++;
×
2505
                if ( *s != 0 && *s != ';' ) goto syntax;
×
2506
                *s = 0;
×
2507
                if ( ( num1 = GetDollar(s1) ) <= 0 ) {
×
2508
                        MesPrint("@$%s has not been defined (yet)",s1);
×
2509
                        error = 1;
×
2510
                }
2511
                if ( ( num2 = GetDollar(s2) ) <= 0 ) {
×
2512
                        MesPrint("@$%s has not been defined (yet)",s2);
×
2513
                        error = 1;
×
2514
                }
2515
                if ( error == 0 ) {
×
2516
                        ExchangeDollars((int)num1,(int)num2);
×
2517
                }
2518
        }
2519
        else {
2520
                s1 = s; s = SkipAName(s);
×
2521
                if ( *s != ',' && *s != ' ' && *s != '\t' ) goto syntax;
×
2522
                *s++ = 0;
×
2523
                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
2524
                if ( FG.cTable[*s] != 0 && *s != '[' ) goto syntax;
×
2525
                s2 = s; s = SkipAName(s);
×
2526
                if ( *s != 0 && *s != ';' ) goto syntax;
×
2527
                *s = 0;
×
2528
            if ( GetName(AC.exprnames,s1,&num1,NOAUTO) != CEXPRESSION ) {
×
2529
                        MesPrint("@%s is not an expression",s1);
×
2530
                        error = 1;
×
2531
                }
2532
            if ( GetName(AC.exprnames,s2,&num2,NOAUTO) != CEXPRESSION ) {
×
2533
                        MesPrint("@%s is not an expression",s2);
×
2534
                        error = 1;
×
2535
                }
2536
                if ( error == 0 ) {
×
2537
                        ExchangeExpressions((int)num1,(int)num2);
×
2538
                }
2539
        }
2540
        return(error);
2541
syntax:
×
2542
        MesPrint("@Proper syntax: %#exchange expr1,expr2 or %#exchange $var1,$var2");
×
2543
        return(1);
×
2544
}
2545

2546
/*
2547
                 #] DoPreExchange : 
2548
                 #[ DoCall :
2549
*/
2550

2551
int DoCall(UBYTE *s)
156✔
2552
{
2553
        UBYTE *t, *u, *v, *name, c, cp, *args1, *args2, *t1, *t2, *wild = 0;
156✔
2554
        int bratype = 0, wildargs = 0, inwildargs = 0, nwildargs = 0;
156✔
2555
        PROCEDURE *p;
156✔
2556
        int streamoffset;
156✔
2557
        int i, namesize, narg1, narg2, bralevel, numpre;
156✔
2558
        LONG i1, i2;
156✔
2559
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
156✔
2560
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
156✔
2561
/*
2562
        1:        Get the name of the procedure.
2563
        2:        Locate the procedure.
2564
*/
2565
        name = s; s = EndOfToken(s); c = *s; *s = 0;
156✔
2566
        for ( i = NumProcedures-1; i >= 0; i-- ) {
204✔
2567
                if ( StrCmp(Procedures[i].name,name) == 0 ) break;
189✔
2568
        }
2569
        p = (PROCEDURE *)FromList(&AP.ProcList);
156✔
2570
        if ( i < 0 ) {        /* Try to find a file */
156✔
2571
                namesize = 0;
2572
                t = name;
2573
                while ( *t ) { t++; namesize++; }
45✔
2574
                t = AP.procedureExtension;
15✔
2575
                while ( *t ) { t++; namesize++; }
60✔
2576
                t = p->name = (UBYTE *)Malloc1(namesize+2,"procedure");
15✔
2577
                u = name;
15✔
2578
                while ( *u ) *t++ = *u++;
45✔
2579
                *t++ = '.';
15✔
2580
                v = AP.procedureExtension;
15✔
2581
                while ( *v ) *t++ = *v++;
60✔
2582
                *t = 0;
15✔
2583
                p->loadmode = 0;        /* buffer should be freed at end */
15✔
2584
                p->p.buffer = LoadInputFile(p->name,PROCEDUREFILE);
15✔
2585
                if ( p->p.buffer == 0 ) return(-1);
15✔
2586
                t[-4] = 0;
15✔
2587
        }
2588
        else {
2589
                p->p.buffer = Procedures[i].p.buffer;
141✔
2590
                p->name = Procedures[i].name;
141✔
2591
                p->loadmode = 1;
141✔
2592
        }
2593
        t = p->p.buffer;
156✔
2594
        SKIPBLANKS(t)
156✔
2595
        if ( *t++ != '#' ) goto wrongfile;
156✔
2596
        SKIPBLANKS(t)
156✔
2597
        t += 9;
156✔
2598
        SKIPBLANKS(t)
312✔
2599
        u = EndOfToken(t);
156✔
2600
        cp = *u; *u = 0;
156✔
2601
        if ( StrCmp(t,name) != 0 ) goto wrongfile;
156✔
2602
        *u = cp;
156✔
2603
        *s = c;
156✔
2604
/*
2605
        The pointer p points to the contents of the procedure (in memory)
2606
        Now we have to match the arguments. u points to after the name
2607
        in the 'file', s to after the name in the call statement.
2608
*/
2609
        bralevel = narg1 = narg2 = 0; args2 = u;
156✔
2610
        SKIPBLANKS(u)
156✔
2611
        if ( *u == '(' ) {
156✔
2612
                u++; SKIPBLANKS(u)
123✔
2613
                args2 = u;
231✔
2614
                while ( *u != ')' ) {
231✔
2615
                        if ( *u == '?' ) { wildargs++; u++; nwildargs = narg2+1; }
108✔
2616
                        narg2++; u = EndOfToken(u); SKIPBLANKS(u)
108✔
2617
                        if ( *u == ',' ) { u++; SKIPBLANKS(u) }
108✔
2618
                        else if ( *u != ')' || ( wildargs > 1 ) ) {
78✔
2619
                                MesPrint("@Illegal argument field in procedure %s",p->name);
×
2620
                                return(-1);
×
2621
                        }
2622
                }
2623
        }
2624
        while ( *u != LINEFEED ) u++;
279✔
2625
        SKIPBLANKS(s)
156✔
2626
        args1 = s+1;
156✔
2627
        if ( *s == '(' ) bratype = 1;
156✔
2628
        do {
849✔
2629
                if ( *s == '{' && bratype == 0 ) bralevel++;
849✔
2630
                else if ( *s == '(' && bratype == 1 ) bralevel++;
849✔
2631
                else if ( *s == '}' && bratype == 0 ) {
735✔
2632
                        bralevel--;
×
2633
                        if ( bralevel == 0 ) {
×
2634
                                *s = 0; narg1++;
×
2635
                                if ( wildargs && narg1 == nwildargs ) wild = s;
×
2636
                        }
2637
                }
2638
                else if ( *s == ')' && bratype == 1 ) {
735✔
2639
                        bralevel--;
114✔
2640
                        if ( bralevel == 0 ) {
114✔
2641
                                *s = 0; narg1++;
114✔
2642
                                if ( wildargs && narg1 == nwildargs ) wild = s;
114✔
2643
                        }
2644
                }
2645
                /*[12dec2003 mt]:*/
2646
                /*else if ( *s == ',' || *s == '|' ) {*/
2647
                else if (set_in(*s,AC.separators)) {/*Function set_in see in
621✔
2648
                                                                                                                        file tools.c*/
2649
                /*:[12dec2003 mt]*/
2650
                        *s = 0; narg1++;
36✔
2651
                        if ( wildargs && narg1 == nwildargs ) wild = s;
36✔
2652
                }
2653
                else if ( *s == '\\' ) s++;
585✔
2654
                s++;
849✔
2655
        } while ( bralevel > 0 );
849✔
2656
        if ( wildargs && narg1 >= narg2-1 ) {
156✔
2657
                inwildargs = narg1-narg2+1;
3✔
2658
                if ( inwildargs == 0 ) nwildargs = 0;
3✔
2659
                else {
2660
                        while ( inwildargs > 1 ) {
9✔
2661
                                *wild = ',';
6✔
2662
                                while ( *wild ) wild++;
30✔
2663
                                inwildargs--;
6✔
2664
                        }
2665
                }
2666
        }
2667
        else if ( narg1 != narg2 && ( narg2 != 0 || narg1 != 1 || *args1 != 0 ) ) {
153✔
2668
                MesPrint("@Arguments of procedure %s are not matching",p->name);
×
2669
                return(-1);
×
2670
        }
2671
        numpre = -NumPre-1;        /* For the stream */
156✔
2672
        for ( i = 0; i < narg2; i++ ) {
264✔
2673
                t = args2;
108✔
2674
                if ( *t == '?' ) {
108✔
2675
                        args2++;
3✔
2676
                }
2677
                if ( *t == '?' && inwildargs == 0 ) {
108✔
2678
                        args2 = EndOfToken(args2); c = *args2; *args2 = 0;
×
2679
                        if ( PutPreVar(t,(UBYTE *)"",0,0) < 0 ) return(-1);
×
2680
                }
2681
                else {
2682
                        args2 = EndOfToken(args2); c = *args2; *args2 = 0;
108✔
2683
                        t1 = t2 = args1;
108✔
2684
                        while ( *t1 ) {
657✔
2685
                                if ( *t1 == '\\' ) t1++;
549✔
2686
                                if ( t1 != t2 ) *t2 = *t1;
549✔
2687
                                t2++; t1++;
549✔
2688
                        }
2689
                        *t2 = 0;
108✔
2690
                        if ( PutPreVar(t,args1,0,0) < 0 ) return(-1);
108✔
2691
                        args1 = t1+1;                  /* Next argument */
108✔
2692
                }
2693
                *args2 = c; SKIPBLANKS(args2)  /* skip to next name */
108✔
2694
                args2++; SKIPBLANKS(args2)
108✔
2695
        }
2696
        streamoffset = AC.CurrentStream - AC.Streams;
156✔
2697
        args1 = AC.CurrentStream->name;
156✔
2698
        AC.CurrentStream->name = p->name;
156✔
2699
        i1 = AC.CurrentStream->linenumber;
156✔
2700
        i2 = AC.CurrentStream->prevline;
156✔
2701
        AC.CurrentStream->prevline   =
156✔
2702
        AC.CurrentStream->linenumber = 2;
156✔
2703
        OpenStream(u+1,PREREADSTREAM3,numpre,PRENOACTION);
156✔
2704
        AC.Streams[streamoffset].name = args1;
156✔
2705
        AC.Streams[streamoffset].linenumber = i1;
156✔
2706
        AC.Streams[streamoffset].prevline   = i2;
156✔
2707
        AddToPreTypes(PRETYPEPROCEDURE);
156✔
2708
        return(0);
156✔
2709
wrongfile:;
×
2710
        if ( i < 0 ) MesPrint("@File %s is not a proper procedure",p->name);
×
2711
        else MesPrint("!!!Internal error with procedure names: %s",name);
×
2712
        return(-1);
2713
}
2714

2715
/*
2716
                 #] DoCall : 
2717
                 #[ DoDebug :
2718
*/
2719

2720
int DoDebug(UBYTE *s)
×
2721
{
2722
        int x;
×
2723
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
2724
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
2725
        NeedNumber(x,s,nonumber)
×
2726
        if ( x < 0 || x >(PREPROONLY
×
2727
                                        | DUMPTOCOMPILER
2728
                                        | DUMPOUTTERMS
2729
                                        | DUMPINTERMS
2730
                                        | DUMPTOSORT
2731
                                        | DUMPTOPARALLEL
2732
#ifdef WITHPTHREADS
2733
                                        | THREADSDEBUG
2734
#endif
2735
                         ) ) goto nonumber;
×
2736
        AP.PreDebug = 0;
×
2737
        if ( ( x & PREPROONLY     ) != 0 ) AP.PreDebug |= PREPROONLY;     /* 1  */
×
2738
        if ( ( x & DUMPTOCOMPILER ) != 0 ) AP.PreDebug |= DUMPTOCOMPILER; /* 2  */
×
2739
        if ( ( x & DUMPOUTTERMS   ) != 0 ) AP.PreDebug |= DUMPOUTTERMS;   /* 4  */
×
2740
        if ( ( x & DUMPINTERMS    ) != 0 ) AP.PreDebug |= DUMPINTERMS;    /* 8  */
×
2741
        if ( ( x & DUMPTOSORT     ) != 0 ) AP.PreDebug |= DUMPTOSORT;     /* 16 */
×
2742
        if ( ( x & DUMPTOPARALLEL ) != 0 ) AP.PreDebug |= DUMPTOPARALLEL; /* 32 */
×
2743
#ifdef WITHPTHREADS
2744
        if ( ( x & THREADSDEBUG   ) != 0 ) AP.PreDebug |= THREADSDEBUG;   /* 64 */
2745
#endif
2746
        return(0);
2747
nonumber:
×
2748
        MesPrint("@Illegal argument for debug instruction");
×
2749
        return(1);
×
2750
}
2751

2752
/*
2753
                 #] DoDebug : 
2754
                 #[ DoTerminate :
2755
*/
2756

2757
int DoTerminate(UBYTE *s)
3✔
2758
{
2759
        int x;
3✔
2760
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
3✔
2761
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
3✔
2762
        if ( *s ) {
×
2763
                NeedNumber(x,s,nonumber)
×
2764
                Terminate(x);
×
2765
        }
2766
        else {
2767
                Terminate(-1);
×
2768
        }
2769
        return(0);
2770
nonumber:
×
2771
        MesPrint("@Illegal argument for terminate instruction");
×
2772
        return(1);
×
2773
}
2774

2775
/*
2776
                 #] DoTerminate : 
2777
                 #[ DoContinueDo :
2778
*/
2779

2780
int DoContinueDo(UBYTE *s)
18✔
2781
{
2782
        DOLOOP *loop;
18✔
2783

2784
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
18✔
2785
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
18✔
2786

2787
        if ( NumDoLoops <= 0 ) {
6✔
2788
                MesPrint("@%#continuedo without %#do");
3✔
2789
                return(1);
3✔
2790
        }
2791

2792
        loop = &(DoLoops[NumDoLoops-1]);
3✔
2793
        AP.NumPreTypes = loop->NumPreTypes+1;
3✔
2794
        AP.PreIfLevel = loop->PreIfLevel;
3✔
2795
        AP.PreSwitchLevel = loop->PreSwitchLevel;
3✔
2796

2797
        return(DoEnddo(s));
3✔
2798
}
2799

2800
/*
2801
                 #] DoContinueDo :
2802
                 #[ DoDo :
2803

2804
                The do loop has three varieties:
2805
                #do i = num1,num2 [,num3]
2806
                #do i = {string1,string2,....,stringn}
2807
                        The | as separator is also allowed for backwards compatibility
2808
                #do i = expression      One by one all terms of the expression
2809
*/
2810

2811
int DoDo(UBYTE *s)
201✔
2812
{
2813
        GETIDENTITY
134✔
2814
        UBYTE *t, c, *u, *uu;
201✔
2815
        DOLOOP *loop;
201✔
2816
        WORD expnum;
201✔
2817
        LONG linenum  = AC.CurrentStream->linenumber;
201✔
2818
        int oldNoShowInput = AC.NoShowInput, i, oldpreassignflag;
201✔
2819

2820
        if ( ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH )
201✔
2821
        || ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) ) {
201✔
2822
                if ( PreSkip((UBYTE *)"do",(UBYTE *)"enddo",1) ) return(-1);
×
2823
                return(0);
×
2824
        }
2825

2826
/*
2827
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
2828
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
2829
*/
2830
        AddToPreTypes(PRETYPEDO);
201✔
2831
 
2832
        loop = (DOLOOP *)FromList(&AP.LoopList);
201✔
2833
        loop->firstdollar = loop->lastdollar = loop->incdollar = -1;
201✔
2834
        loop->NumPreTypes = AP.NumPreTypes-1;
201✔
2835
        loop->PreIfLevel = AP.PreIfLevel;
201✔
2836
        loop->PreSwitchLevel = AP.PreSwitchLevel;
201✔
2837
        AC.NoShowInput = 1;
201✔
2838
        if ( PreLoad(&(loop->p),(UBYTE *)"do",(UBYTE *)"enddo",1,"doloop") ) return(-1);
201✔
2839
        AC.NoShowInput = oldNoShowInput;
201✔
2840
        loop->NoShowInput = AC.NoShowInput;
201✔
2841
/*
2842
        Get now the name. We have to take great care when the name is terminated!
2843
*/
2844
        s = loop->p.buffer + (s - AP.preStart);
201✔
2845
        SKIPBLANKS(s)
402✔
2846
        loop->name = s;
201✔
2847
        if ( chartype[*s] != 0 ) goto illname;
201✔
2848
        s++;
201✔
2849
        while ( chartype[*s] <= 1 ) s++;
207✔
2850
        t = s;
294✔
2851
        while ( *s == ' ' || *s == '\t' ) s++;
294✔
2852
        if ( *s != '=' ) goto illdo;
201✔
2853
        s++;
201✔
2854
        while ( *s == ' ' || *s == '\t' ) s++;
294✔
2855
        *t = 0;
201✔
2856

2857
        if ( *s == '{' ) {
201✔
2858
                loop->type = LISTEDLOOP;
33✔
2859
                s++; loop->vars = s;
33✔
2860
                loop->lastnum = 0;
33✔
2861
                while ( *s != '}' && *s != 0 ) {
636✔
2862
                        if ( set_in(*s,AC.separators) ) { *s = 0; loop->lastnum++; }
603✔
2863
                        else if ( *s == '\\' ) s++;
495✔
2864
                        s++;
603✔
2865
                }
2866
                if ( *s == 0 ) goto illdo;
33✔
2867
                *s++ = 0;
33✔
2868
                loop->lastnum++;
33✔
2869
                loop->firstnum = 0;
33✔
2870
                loop->contents = s;
33✔
2871
        }
2872
        else if ( *s == '-' || *s == '+' || chartype[*s] == 1 || *s == '$' ) {
168✔
2873
                loop->type = NUMERICALLOOP;
168✔
2874
                t = s;
168✔
2875
                while ( *s && *s != ',' ) s++;
342✔
2876
                if ( *s == 0 ) goto illdo;
168✔
2877
                if ( *t == '$' ) {
168✔
2878
                        c = *s; *s = 0;
×
2879
                        if ( GetName(AC.dollarnames,t+1,&loop->firstdollar,NOAUTO) != CDOLLAR ) {
×
2880
                                MesPrint("@%s is undefined in first parameter in %#do instruction",t);
×
2881
                                return(-1);
×
2882
                        }
2883
                        loop->firstnum = DolToLong(BHEAD loop->firstdollar);
×
2884
                        if ( AN.ErrorInDollar ) {
×
2885
                                MesPrint("@%s does not evaluate into a valid loop parameter",t);
×
2886
                                return(-1);
×
2887
                        }
2888
                        *s++ = c;
×
2889
                }
2890
                else {
2891
                        *s = '}';
168✔
2892
                        if ( PreEval(t,&loop->firstnum) == 0 ) goto illdo;
168✔
2893
                        *s++ = ',';
168✔
2894
                }
2895
                t = s;
168✔
2896
                while ( *s && *s != ',' && *s != ';' && *s != LINEFEED ) s++;
393✔
2897
                c = *s;
168✔
2898
                if ( *t == '$' ) {
168✔
2899
                        *s = 0;
×
2900
                        if ( GetName(AC.dollarnames,t+1,&loop->lastdollar,NOAUTO) != CDOLLAR ) {
×
2901
                                MesPrint("@%s is undefined in second parameter in %#do instruction",t);
×
2902
                                return(-1);
×
2903
                        }
2904
                        loop->lastnum = DolToLong(BHEAD loop->lastdollar);
×
2905
                        if ( AN.ErrorInDollar ) {
×
2906
                                MesPrint("@%s does not evaluate into a valid loop parameter",t);
×
2907
                                return(-1);
×
2908
                        }
2909
                        *s++ = c;
×
2910
                }
2911
                else {
2912
                        *s = '}';
168✔
2913
                        if ( PreEval(t,&loop->lastnum) == 0 ) goto illdo;
168✔
2914
                        *s++ = c;
168✔
2915
                }
2916
                if ( c == ',' ) {
168✔
2917
                        t = s;
12✔
2918
                        while ( *s && *s != ';' && *s != LINEFEED ) s++;
12✔
2919
                        if ( *t == '$' ) {
6✔
2920
                                c = *s; *s = 0;
×
2921
                                if ( GetName(AC.dollarnames,t+1,&loop->incdollar,NOAUTO) != CDOLLAR ) {
×
2922
                                        MesPrint("@%s is undefined in third parameter in %#do instruction",t);
×
2923
                                        return(-1);
×
2924
                                }
2925
                                loop->incnum = DolToLong(BHEAD loop->incdollar);
×
2926
                                if ( AN.ErrorInDollar ) {
×
2927
                                        MesPrint("@%s does not evaluate into a valid loop parameter",t);
×
2928
                                        return(-1);
×
2929
                                }
2930
                                *s++ = c;
×
2931
                        }
2932
                        else {
2933
                                c = *s; *s = '}';
6✔
2934
                                if ( PreEval(t,&loop->incnum) == 0 ) goto illdo;
6✔
2935
                                *s++ = c;
6✔
2936
                        }
2937
                }
2938
                else loop->incnum = 1;
162✔
2939
                loop->contents = s;
168✔
2940
        }
2941
        else if ( ( chartype[*s] == 0 ) || ( *s == '[' ) ) {
×
2942
                int oldNumPotModdollars = NumPotModdollars;
×
2943
#ifdef WITHMPI
2944
                WORD oldRhsExprInModuleFlag = AC.RhsExprInModuleFlag;
2945
                AC.RhsExprInModuleFlag = 0;
2946
#endif
2947
                t = s;
×
2948
                if ( ( s = SkipAName(s) ) == 0 ) goto illdo;
×
2949
                c = *s; *s = 0;
×
2950
                if ( GetName(AC.exprnames,t,&expnum,NOAUTO) == CEXPRESSION ) {
×
2951
                        loop->type = ONEEXPRESSION;
×
2952
/*
2953
                        We should remember the expression by name for when it gets
2954
                        renumbered!!! If it gets deleted there will be a crash or at
2955
                        least the loop terminates.
2956
*/        
2957
                        loop->vars = t;
×
2958
                }
2959
                else goto illdo;
×
2960
                if ( c == ',' || c == '\t' || c == ';' ) { s++; }
×
2961
                else if ( c != 0 && c != '\n' ) goto illdo;
×
2962
                while ( *s == ',' || *s == '\t' || *s == ';' ) s++;
×
2963
                if ( *s != 0 && *s != '\n' ) goto illdo;
×
2964
                loop->firstnum = 0;
×
2965
                s++;
×
2966
                loop->contents = s;
×
2967
                loop->incnum = 0;
×
2968
/*
2969
                Next determine size of statement and allocate space
2970
*/
2971
                while ( *t ) t++;
×
2972
                i = t - loop->vars;
×
2973
                t = loop->name;
×
2974
                while ( *t ) { t++; i++; }
×
2975
                i += 4;
×
2976
                loop->dollarname = Malloc1((LONG)i,"do-loop instruction");
×
2977
/*
2978
                Construct the statement
2979
*/
2980
                u = loop->dollarname;
×
2981
                *u++ = '$'; t = loop->name; while ( *t ) *u++ = *t++;
×
2982
                *u++ = '_'; uu = u; *u++ = '='; t = loop->vars;
×
2983
                while ( *t ) *u++ = *t++;
×
2984
                *t = 0; *u = 0;
×
2985
/*
2986
                Compile and put in dollar variable.
2987
                Note that we remember the dollar by name and that this name ends in _
2988
*/
2989
                oldpreassignflag = AP.PreAssignFlag;
×
2990
                AP.PreAssignFlag = 2;
×
2991
        CompileStatement(loop->dollarname);
×
2992
                if ( CatchDollar(0) ) {
×
2993
                        MesPrint("@Cannot load expression in do loop");
×
2994
                        return(-1);
×
2995
                }
2996
                AP.PreAssignFlag = oldpreassignflag;
×
2997
                NumPotModdollars = oldNumPotModdollars;
×
2998
#ifdef WITHMPI
2999
                AC.RhsExprInModuleFlag = oldRhsExprInModuleFlag;
3000
#endif
3001
                *uu = 0;
×
3002
        }
3003
        else goto illdo; /* Syntax problems */
×
3004
        loop->errorsinloop = 0;
201✔
3005
/*        loop->startlinenumber = linenum+1; 5-oct-2000 One too much? */
3006
        loop->startlinenumber = linenum;
201✔
3007
        PutPreVar(loop->name,(UBYTE *)"0",0,0);                        
201✔
3008
        loop->firstloopcall = 1;
201✔
3009
        return(DoEnddo(s));
201✔
3010
illname:;
×
3011
        MesPrint("@Improper name for do loop variable");
×
3012
        return(-1);
×
3013
illdo:;
×
3014
        MesPrint("@Improper syntax in do loop instruction");
×
3015
        return(-1);
×
3016
}
3017

3018
/*
3019
                 #] DoDo : 
3020
                 #[ DoBreakDo :
3021

3022
                #breakdo [num]
3023
                jumps out of num #do-loops (if there are that many) (default is 1)
3024
*/
3025

3026
int DoBreakDo(UBYTE *s)
×
3027
{
3028
        DOLOOP *loop;
×
3029
        WORD levels;
×
3030

3031
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
3032
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
3033

3034
        if ( NumDoLoops <= 0 ) {
×
3035
                MesPrint("@%#breakdo without %#do");
×
3036
                return(1);
×
3037
        }
3038
/*
3039
        if ( AP.PreTypes[AP.NumPreTypes] != PRETYPEDO ) { MessPreNesting(4); return(-1); }
3040
*/
3041
        while ( *s && ( *s == ',' || *s == ' ' || *s == '\t' ) ) s++;
×
3042
        if ( *s == 0 ) {
×
3043
                levels = 1;
3044
        }
3045
        else if ( FG.cTable[*s] == 1 ) {
×
3046
                levels = 0;
3047
                while ( *s >= '0' && *s <= '9' ) { levels = 10*levels + *s++ - '0'; }
×
3048
                if ( *s != 0 ) goto improper;
×
3049
        }
3050
        else {
3051
improper:
×
3052
                MesPrint("@Improper syntax of %#breakdo instruction");
×
3053
                return(1);
×
3054
        }
3055
        if ( levels > NumDoLoops ) {
×
3056
                MesPrint("@Too many loop levels requested in %#breakdo instruction");
×
3057
                Terminate(-1);
×
3058
        }
3059
        while ( levels > 0 ) {
×
3060
                while ( AC.CurrentStream->type != PREREADSTREAM
×
3061
                  && AC.CurrentStream->type != PREREADSTREAM2
×
3062
                  && AC.CurrentStream->type != PREREADSTREAM3 ) {
×
3063
                        AC.CurrentStream = CloseStream(AC.CurrentStream);
×
3064
                }
3065
                while ( AP.PreTypes[AP.NumPreTypes] != PRETYPEDO
×
3066
                && AP.PreTypes[AP.NumPreTypes] != PRETYPEPROCEDURE ) AP.NumPreTypes--;
×
3067
                if ( AC.CurrentStream->type == PREREADSTREAM3
×
3068
                || AP.PreTypes[AP.NumPreTypes] == PRETYPEPROCEDURE ) {
×
3069
                        MesPrint("@Trying to jump out of a procedure with a %#breakdo instruction");
×
3070
                        Terminate(-1);
×
3071
                }
3072
                loop = &(DoLoops[NumDoLoops-1]);
×
3073
                AP.NumPreTypes = loop->NumPreTypes;
×
3074
                AP.PreIfLevel = loop->PreIfLevel;
×
3075
                AP.PreSwitchLevel = loop->PreSwitchLevel;
×
3076
/*
3077
                AP.NumPreTypes--;
3078
*/
3079
                NumDoLoops--;
×
3080
                DoUndefine(loop->name);
×
3081
                M_free(loop->p.buffer,"loop->p.buffer");
×
3082
                loop->firstloopcall = 0;
×
3083

3084
                AC.CurrentStream = CloseStream(AC.CurrentStream);
×
3085
                levels--;
×
3086
        }
3087
        return(0);
3088
}
3089

3090
/*
3091
                 #] DoBreakDo : 
3092
                 #[ DoElse :
3093
*/
3094

3095
int DoElse(UBYTE *s)
3✔
3096
{
3097
        if ( AP.PreTypes[AP.NumPreTypes] != PRETYPEIF ) {
3✔
3098
                if ( AP.PreIfLevel <= 0 ) MesPrint("@%#else without corresponding %#if");
×
3099
                else MessPreNesting(1);
×
3100
                return(-1);
×
3101
        }
3102
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
3✔
3103
        while ( *s == ' ' ) s++;
3✔
3104
        if ( tolower(*s) == 'i' && tolower(s[1]) == 'f' && s[2]
3✔
3105
                && FG.cTable[s[2]] > 1 && s[2] != '_' ) {
×
3106
                s += 2;
×
3107
                while ( *s == ' ' ) s++;
×
3108
                return(DoElseif(s));
×
3109
        }
3110
        if ( AP.PreIfLevel <= 0 ) {
3✔
3111
                MesPrint("@%#else without corresponding %#if");
×
3112
                return(-1);
×
3113
        }
3114
        switch ( AP.PreIfStack[AP.PreIfLevel] ) {
3✔
3115
                case EXECUTINGIF:
×
3116
                        AP.PreIfStack[AP.PreIfLevel] = LOOKINGFORENDIF;
×
3117
                        break;
×
3118
                case LOOKINGFORELSE:
3✔
3119
                        AP.PreIfStack[AP.PreIfLevel] = EXECUTINGIF;
3✔
3120
                        break;
3✔
3121
                case LOOKINGFORENDIF:
3122
                        break;
3123
        }
3124
        return(0);
3125
}
3126

3127
/*
3128
                 #] DoElse : 
3129
                 #[ DoElseif :
3130
*/
3131

3132
int DoElseif(UBYTE *s)
×
3133
{
3134
        int condition;
×
3135
        if ( AP.PreTypes[AP.NumPreTypes] != PRETYPEIF ) {
×
3136
                if ( AP.PreIfLevel <= 0 ) MesPrint("@%#elseif without corresponding %#if");
×
3137
                else MessPreNesting(2);
×
3138
                return(-1);
×
3139
        }
3140
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
3141
        if ( AP.PreIfLevel <= 0 ) {
×
3142
                MesPrint("@%#elseif without corresponding %#if");
×
3143
                return(-1);
×
3144
        }
3145
        switch ( AP.PreIfStack[AP.PreIfLevel] ) {
×
3146
                case EXECUTINGIF:
×
3147
                        AP.PreIfStack[AP.PreIfLevel] = LOOKINGFORENDIF;
×
3148
                        break;
×
3149
                case LOOKINGFORELSE:
×
3150
                        if ( ( condition = EvalPreIf(s) ) < 0 ) return(-1);
×
3151
                        AP.PreIfStack[AP.PreIfLevel] = condition;
×
3152
                        break;
×
3153
                case LOOKINGFORENDIF:
3154
                        break;
3155
        }
3156
        return(0);
3157
}
3158

3159
/*
3160
                 #] DoElseif : 
3161
                 #[ DoEnddo :
3162

3163
                At the first call there is no stream yet.
3164
                After that we have to close the stream and start a new one.
3165
*/
3166

3167
int DoEnddo(UBYTE *s)
2,238,872✔
3168
{
3169
        GETIDENTITY
1,154,801✔
3170
        DOLOOP *loop;
2,238,872✔
3171
        UBYTE *t, *tt, *value, numstr[16];
2,238,872✔
3172
        LONG xval;
2,238,872✔
3173
        int xsign, retval;
2,238,872✔
3174
        DUMMYUSE(s);
2,238,872✔
3175
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
2,238,872✔
3176
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
2,238,872✔
3177
/*
3178
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ||
3179
                AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) {
3180
                if ( AP.PreTypes[AP.NumPreTypes] == PRETYPEDO ) AP.NumPreTypes--;
3181
                else { MessPreNesting(3); return(-1); }
3182
                return(0);
3183
        }
3184
*/
3185
        if ( NumDoLoops <= 0 ) {
2,238,872✔
3186
                MesPrint("@%#enddo without %#do");
×
3187
                return(1);
×
3188
        }
3189
        if ( AP.PreTypes[AP.NumPreTypes] != PRETYPEDO ) { MessPreNesting(4); return(-1); }
2,238,872✔
3190
        loop = &(DoLoops[NumDoLoops-1]);
2,238,872✔
3191
        if ( !loop->firstloopcall ) AC.CurrentStream = CloseStream(AC.CurrentStream);
2,238,872✔
3192

3193
        if ( loop->errorsinloop ) {
2,238,872✔
3194
                MesPrint("++++Errors in Loop");
×
3195
                goto finish;
×
3196
        }
3197
        if ( loop->type == LISTEDLOOP ) {
2,238,872✔
3198
                if ( loop->firstnum >= loop->lastnum ) goto finish;
174✔
3199
                loop->firstnum++;
141✔
3200
                t = value = loop->vars;
141✔
3201
                while ( *value ) value++;
663✔
3202
                value++;
141✔
3203
                loop->vars = value;
141✔
3204
                value = tt = t;
141✔
3205
                while ( *value ) {
636✔
3206
                        if ( *value == '\\' ) value++;
495✔
3207
                        *tt++ = *value++;
495✔
3208
                } 
3209
                *tt = 0;
141✔
3210
                PutPreVar(loop->name,t,0,1);        /* We overwrite the definition */
141✔
3211
        }
3212
        else if ( loop->type == NUMERICALLOOP ) {
2,238,698✔
3213

3214
                if ( !loop->firstloopcall ) {
2,238,698✔
3215
/*
3216
                        Test whether the variable was changed inside the loop into
3217
                        a different numerical value. If so, adjust.
3218
*/
3219
                        t = GetPreVar(loop->name,WITHOUTERROR);
2,238,530✔
3220
                        if ( t ) {
2,238,530✔
3221
                                value = t;
3222
                                xsign = 1;
3223
                                while ( *value && ( *value == ' '
2,238,548✔
3224
                                                || *value == '-' || *value == '+' ) ) {
2,238,548✔
3225
                                        if ( *value == '-' ) xsign = -xsign;
18✔
3226
                                        value++;
18✔
3227
                                }
3228
                                t = value; xval = 0;
4,524,529✔
3229
                                while ( *value >= '0' && *value <= '9' ) xval = 10*xval + *value++ - '0';
4,524,529✔
3230
                                while ( *value && *value == ' ' ) value++;
2,238,530✔
3231
                                if ( *value == 0 ) {
2,238,530✔
3232
/*
3233
                                        Now we may substitute the loopvalue.
3234
*/
3235
                                        if ( xsign < 0 ) xval = -xval;
2,238,530✔
3236
                                        if ( loop->incdollar >= 0 ) {
2,238,530✔
3237
                                                loop->incnum = DolToLong(BHEAD loop->incdollar);
×
3238
                                                if ( AN.ErrorInDollar ) {
×
3239
                                                        MesPrint("@%s does not evaluate into a valid third loop parameter",DOLLARNAME(Dollars,loop->incdollar));
×
3240
                                                        return(-1);
×
3241
                                                }
3242
                                        }
3243
                                        loop->firstnum = xval + loop->incnum;
2,238,530✔
3244
                                }
3245
                        }
3246
                        if ( loop->lastdollar >= 0 ) {
2,238,530✔
3247
                                loop->lastnum = DolToLong(BHEAD loop->lastdollar);
×
3248
                                if ( AN.ErrorInDollar ) {
×
3249
                                        MesPrint("@%s does not evaluate into a valid second loop parameter",DOLLARNAME(Dollars,loop->lastdollar));
×
3250
                                        return(-1);
×
3251
                                }
3252
                        }
3253
                }
3254
                if ( ( loop->incnum > 0 && loop->firstnum > loop->lastnum )
2,238,698✔
3255
                || ( loop->incnum < 0 && loop->firstnum < loop->lastnum ) ) goto finish;
2,238,698✔
3256
                NumToStr(numstr,loop->firstnum);
2,238,533✔
3257
                t = numstr;
2,238,533✔
3258
                loop->firstnum += loop->incnum;
2,238,533✔
3259
                PutPreVar(loop->name,t,0,1);        /* We overwrite the definition */
2,238,533✔
3260
        }
3261
        else if ( loop->type == ONEEXPRESSION ) {
×
3262
/*
3263
                Find the dollar expression
3264
*/
3265
                WORD numdollar = GetDollar(loop->dollarname+1);
×
3266
                DOLLARS d = Dollars + numdollar;
×
3267
                WORD *w, *dw, v, *ww;
×
3268
                if ( (d->where) == 0 ) {
×
3269
                        d->type = DOLUNDEFINED;
×
3270
                        M_free(loop->dollarname,"do-loop instruction");
×
3271
                        goto finish;
×
3272
                }
3273
                w = d->where + loop->incnum;
×
3274
                if ( *w == 0 ) {
×
3275
                        M_free(d->where,"dollar");
×
3276
                        d->where = 0;
×
3277
                        d->type = DOLUNDEFINED;
×
3278
                        M_free(loop->dollarname,"do-loop instruction");
×
3279
                        goto finish;
×
3280
                }
3281
                loop->incnum += *w;
×
3282
/*
3283
                Now the term has to be converted to text.
3284
*/
3285
                ww = w + *w; v = *ww; *ww = 0;
×
3286
                dw = d->where; d->where = w;
×
3287
                t = WriteDollarToBuffer(numdollar,1);
×
3288
                d->where = dw; *ww = v;
×
3289
                PutPreVar(loop->name,t,0,1);        /* We overwrite the definition */
×
3290
                M_free(t,"dollar");
×
3291
        }
3292
        if ( loop->firstloopcall ) OpenStream(loop->contents,PREREADSTREAM2,0,PRENOACTION);
2,238,674✔
3293
        else OpenStream(loop->contents,PREREADSTREAM,0,PRENOACTION);
2,238,473✔
3294
        AC.CurrentStream->prevline   =
2,238,674✔
3295
        AC.CurrentStream->linenumber = loop->startlinenumber;
2,238,674✔
3296
        AC.CurrentStream->eqnum = 0;
2,238,674✔
3297
        loop->firstloopcall = 0;
2,238,674✔
3298
        return(0);
2,238,674✔
3299
finish:;
198✔
3300
        NumDoLoops--;
198✔
3301
        retval = DoUndefine(loop->name);
198✔
3302
        M_free(loop->p.buffer,"loop->p.buffer");
198✔
3303
        loop->firstloopcall = 0;
198✔
3304
        AP.NumPreTypes--;
198✔
3305
        return(retval);
198✔
3306
}
3307

3308
/*
3309
                 #] DoEnddo : 
3310
                 #[ DoEndif :
3311
*/
3312

3313
int DoEndif(UBYTE *s)
174✔
3314
{
3315
        DUMMYUSE(s);
174✔
3316
        if ( AP.PreTypes[AP.NumPreTypes] != PRETYPEIF ) {
174✔
3317
                if ( AP.PreIfLevel <= 0 ) MesPrint("@%#endif without corresponding %#if");
×
3318
                else MessPreNesting(5);
×
3319
                return(-1);
×
3320
        }
3321
        AP.NumPreTypes--;
174✔
3322
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
174✔
3323
        if ( AP.PreIfLevel <= 0 ) {
174✔
3324
                MesPrint("@%#endif without corresponding %#if");
×
3325
                return(-1);
×
3326
        }
3327
        AP.PreIfLevel--;
174✔
3328
        return(0);
174✔
3329
}
3330

3331
/*
3332
                 #] DoEndif : 
3333
                 #[ DoEndprocedure :
3334

3335
                Action is simple: close the current stream if it is still
3336
                the stream from which the statement came.
3337
                Then pop the current procedure and all its local derivatives.
3338
                if loadmode > 1 the procedure was defined locally.
3339
*/
3340

3341
int DoEndprocedure(UBYTE *s)
153✔
3342
{
3343
        DUMMYUSE(s);
153✔
3344
        if ( AP.PreTypes[AP.NumPreTypes] != PRETYPEPROCEDURE ) {
153✔
3345
                MessPreNesting(6);
×
3346
                return(-1);
×
3347
        }
3348
        AP.NumPreTypes--;
153✔
3349
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
153✔
3350
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
153✔
3351
        AC.CurrentStream = CloseStream(AC.CurrentStream);
153✔
3352
        do {
153✔
3353
                NumProcedures--;
153✔
3354
                if ( Procedures[NumProcedures].loadmode == 0 ) {
153✔
3355
                        M_free(Procedures[NumProcedures].p.buffer,"procedures buffer");
15✔
3356
                        M_free(Procedures[NumProcedures].name,"procedures name");
15✔
3357
                }
3358
        } while ( Procedures[NumProcedures].loadmode > 1 );
153✔
3359
        return(0);
3360
}
3361

3362
/*
3363
                 #] DoEndprocedure : 
3364
                 #[ DoIf :
3365
*/
3366

3367
int DoIf(UBYTE *s)
162✔
3368
{
3369
        int condition;
162✔
3370
        AddToPreTypes(PRETYPEIF);
162✔
3371
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
162✔
3372
        if ( AP.PreIfStack[AP.PreIfLevel] == EXECUTINGIF ) {
162✔
3373
                condition = EvalPreIf(s);
162✔
3374
                if ( condition < 0 ) return(-1);
159✔
3375
        }
3376
        else condition = LOOKINGFORENDIF;
3377
        if ( AP.PreIfLevel+1 >= AP.MaxPreIfLevel ) {
159✔
3378
                int **ppp = &AP.PreIfStack; /* To avoid a compiler warning */
×
3379
                if ( DoubleList((VOID ***)ppp,&AP.MaxPreIfLevel,sizeof(int),
×
3380
                        "PreIfLevels") ) return(-1);
3381
        }
3382
        AP.PreIfStack[++AP.PreIfLevel] = condition;
159✔
3383
        return(0);
159✔
3384
}
3385

3386
/*
3387
                 #] DoIf : 
3388
                 #[ DoIfdef :
3389
*/
3390

3391
int DoIfdef(UBYTE *s, int par)
18✔
3392
{
3393
        int condition;
18✔
3394
        AddToPreTypes(PRETYPEIF);
18✔
3395
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
18✔
3396
        if ( AP.PreIfStack[AP.PreIfLevel] == EXECUTINGIF ) {
18✔
3397
                while ( *s == ' ' || *s == '\t' ) s++;
18✔
3398
                if ( ( *s == 0 ) == ( par == 1 ) ) condition = LOOKINGFORELSE;
18✔
3399
                else                               condition = EXECUTINGIF;
18✔
3400
        }
3401
        else condition = LOOKINGFORENDIF;
3402
        if ( AP.PreIfLevel+1 >= AP.MaxPreIfLevel ) {
18✔
3403
                int **ppp = &AP.PreIfStack; /* to avoid a compiler warning */
×
3404
                if ( DoubleList((VOID ***)ppp,&AP.MaxPreIfLevel,sizeof(int),
×
3405
                        "PreIfLevels") ) return(-1);
3406
        }
3407
        AP.PreIfStack[++AP.PreIfLevel] = condition;
18✔
3408
        return(0);
18✔
3409
}
3410

3411
/*
3412
                 #] DoIfdef : 
3413
                 #[ DoIfydef :
3414
*/
3415

3416
int DoIfydef(UBYTE *s)
12✔
3417
{
3418
        return DoIfdef(s,1);
12✔
3419
}
3420

3421
/*
3422
                 #] DoIfydef : 
3423
                 #[ DoIfndef :
3424
*/
3425

3426
int DoIfndef(UBYTE *s)
6✔
3427
{
3428
        return DoIfdef(s,2);
6✔
3429
}
3430

3431
/*
3432
                 #] DoIfndef : 
3433
                 #[ DoInside :
3434

3435
        #inside $var1,...,$varn
3436
                statements without .sort
3437
        #endinside
3438

3439
        executes the statements on the contents of the $ variables as if they
3440
        are a module. The results are put back in the dollar variables.
3441
        To do this right we need a struct with
3442
                old compiler buffer
3443
                list of numbers of dollars
3444
                length of the list
3445
                length of the array containing the list
3446
        Because we need to compose statements, the statement buffer must be
3447
        empty. This means that we have to test for that. Same at the end. We
3448
        must have a completed statement.
3449
*/
3450

3451
int DoInside(UBYTE *s)
36✔
3452
{
3453
        GETIDENTITY
24✔
3454
        int numdol, error = 0;
36✔
3455
        WORD *nb, newsize, i;
36✔
3456
        UBYTE *name, c;
36✔
3457
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
36✔
3458
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
36✔
3459
        if ( AP.PreInsideLevel != 0 ) {
36✔
3460
                MesPrint("@Illegal nesting of %#inside/%#endinside instructions");
×
3461
                return(-1);
×
3462
        }
3463
/*
3464
        if ( AP.PreContinuation ) {
3465
                error = -1;
3466
                MesPrint("@%#inside cannot be inside a regular statement");
3467
        }
3468
*/
3469
        PUSHPREASSIGNLEVEL
36✔
3470
/*
3471
        Now the dollars to do
3472
*/
3473
        AP.inside.numdollars = 0;
36✔
3474
        for(;;) {
3475
                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
72✔
3476
                if ( *s == 0 ) break;
3477
                if ( *s != '$' ) {
3478
                        MesPrint("@%#inside instruction can have only $ variables for parameters");
×
3479
                        return(-1);
×
3480
                }
3481
                s++;
36✔
3482
                name = s;
36✔
3483
                while (chartype[*s] <= 1 ) s++;
138✔
3484
                c = *s; *s = 0;
36✔
3485
                if ( ( numdol = GetDollar(name) ) < 0 ) {
36✔
3486
                        MesPrint("@%#inside: $%s has not (yet) been defined",name);
×
3487
                        *s = c;
×
3488
                        error = -1;
×
3489
                }
3490
                else {
3491
                        *s = c;
36✔
3492
                        if ( AP.inside.numdollars >= AP.inside.size ) {
36✔
3493
                                if ( AP.inside.buffer == 0 ) newsize = 20;
6✔
3494
                                else                         newsize = 2*AP.inside.size;
×
3495
                                nb = (WORD *)Malloc1(newsize*sizeof(WORD),"insidebuffer");
6✔
3496
                                if ( AP.inside.buffer ) {
6✔
3497
                                        for ( i = 0; i < AP.inside.size; i++ ) nb[i] = AP.inside.buffer[i];
×
3498
                                        M_free(AP.inside.buffer,"insidebuffer");
×
3499
                                }
3500
                                AP.inside.buffer = nb;
6✔
3501
                                AP.inside.size = newsize;
6✔
3502
                        }
3503
                        AP.inside.buffer[AP.inside.numdollars++] = numdol;
36✔
3504
                }
3505
        }
3506
/*
3507
        We have to store the configuration of the compiler buffer, so that
3508
        we know where to start executing and how to reset the buffer.
3509
*/
3510
        AP.inside.oldcompiletype = AC.compiletype;
36✔
3511
        AP.inside.oldparallelflag = AC.mparallelflag;
36✔
3512
        AP.inside.oldnumpotmoddollars = NumPotModdollars;
36✔
3513
        AP.inside.oldcbuf = AC.cbufnum;
36✔
3514
        AP.inside.oldrbuf = AM.rbufnum;
36✔
3515
        AP.inside.oldcnumlhs = AR.Cnumlhs, 
36✔
3516
        AddToPreTypes(PRETYPEINSIDE);
36✔
3517
        AP.PreInsideLevel = 1;
36✔
3518
        AC.cbufnum = AP.inside.inscbuf;
36✔
3519
        AM.rbufnum = AP.inside.inscbuf;
36✔
3520
        clearcbuf(AC.cbufnum);
36✔
3521
        AC.compiletype = 0;
36✔
3522
        AC.mparallelflag = PARALLELFLAG;
36✔
3523
#ifdef WITHMPI
3524
        /*
3525
         * We use AC.RhsExprInModuleFlag, PotModdollars, and AC.pfirstnum
3526
         * in order to check (1) whether there are expression names in RHS,
3527
         * (2) which dollar variables can be modified, and (3) which
3528
         * preprocessor variables can be redefined, in #inside.
3529
         * We store the current values of them, and then reset them.
3530
         */
3531
        PF_StoreInsideInfo();
3532
        AC.RhsExprInModuleFlag = 0;
3533
        NumPotModdollars = 0;
3534
        AC.numpfirstnum = 0;
3535
#endif
3536
        return(error);
36✔
3537
}
3538

3539
/*
3540
                 #] DoInside : 
3541
                 #[ DoEndInside :
3542
*/
3543

3544
int DoEndInside(UBYTE *s)
36✔
3545
{
3546
        GETIDENTITY
24✔
3547
        WORD numdol, *oldworkpointer = AT.WorkPointer, *term, *t, j, i;
36✔
3548
        DOLLARS d, nd;
36✔
3549
        WORD oldbracketon = AR.BracketOn;
36✔
3550
        WORD *oldcompresspointer = AR.CompressPointer;
36✔
3551
        int oldmultithreaded = AS.MultiThreaded;
36✔
3552
        /* int oldmparallelflag = AC.mparallelflag; */
3553
        FILEHANDLE *f;
36✔
3554
#ifdef WITHMPI
3555
        int error = 0;
3556
#endif
3557
        DUMMYUSE(s);
36✔
3558
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
36✔
3559
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
36✔
3560
        if ( AP.PreTypes[AP.NumPreTypes] != PRETYPEINSIDE ) {
36✔
3561
                if ( AP.PreInsideLevel != 1 ) MesPrint("@%#endinside without corresponding %#inside");
×
3562
                else MessPreNesting(11);
×
3563
                return(-1);
×
3564
        }
3565
        AP.NumPreTypes--;
36✔
3566
        if ( AP.PreInsideLevel != 1 ) {
36✔
3567
                MesPrint("@%#endinside without corresponding %#inside");
×
3568
                return(-1);
×
3569
        }
3570
        if ( AP.PreContinuation ) {
36✔
3571
                MesPrint("@%#endinside: previous statement not terminated.");
×
3572
                Terminate(-1);
×
3573
        }
3574
        AC.compiletype = AP.inside.oldcompiletype;
36✔
3575
        AR.Cnumlhs = cbuf[AM.rbufnum].numlhs;
36✔
3576
#ifdef WITHMPI
3577
        /*
3578
         * If the #inside...#endinside contains expressions in RHS, only the master executes it
3579
         * and then broadcasts the result to the all slaves. If not, the all processes execute
3580
         * it and in this case no MPI interactions are needed.
3581
         */
3582
        if ( PF.me == MASTER || !AC.RhsExprInModuleFlag ) {
3583
#endif
3584
        AR.BracketOn = 0;
36✔
3585
        AS.MultiThreaded = 0;
36✔
3586
        /* AC.mparallelflag = PARALLELFLAG; */
3587
        if ( AR.CompressPointer == 0 ) AR.CompressPointer = AR.CompressBuffer;
36✔
3588
        f = AR.infile; AR.infile = AR.outfile; AR.outfile = f;
36✔
3589
/*
3590
        Now we have to execute the statements on the proper dollars.
3591
*/
3592
        for ( i = 0; i < AP.inside.numdollars; i++ ) {
72✔
3593
                numdol = AP.inside.buffer[i];
36✔
3594
                nd = d = Dollars + numdol;
36✔
3595
                if ( d->type != DOLZERO ) {
36✔
3596
                        if ( d->type != DOLTERMS ) nd = DolToTerms(BHEAD numdol);
36✔
3597
                        term = nd->where;
36✔
3598
                        NewSort(BHEAD0);
36✔
3599
                        NewSort(BHEAD0);
36✔
3600
                        AR.MaxDum = AM.IndDum;
36✔
3601
                        while ( *term ) {
102✔
3602
                                t = oldworkpointer; j = *term;
3603
                                NCOPY(t,term,j);
732✔
3604
                                AT.WorkPointer = t;
66✔
3605
                                AN.IndDum = AM.IndDum;
66✔
3606
                                AR.CurDum = ReNumber(BHEAD term);
66✔
3607
                                if ( Generator(BHEAD oldworkpointer,0) ) {
66✔
3608
                                        MesPrint("@Called from %#endinside");
×
3609
                                        MesPrint("@Evaluating variable $%s",DOLLARNAME(Dollars,numdol));
×
3610
                                        Terminate(-1);
×
3611
                                }
3612
                        }
3613
                        AT.WorkPointer = oldworkpointer;
36✔
3614
                        CleanDollarFactors(d);
36✔
3615
                        if ( d->where ) { M_free(d->where,"dollar contents"); d->where = 0; }
36✔
3616
                        EndSort(BHEAD (WORD *)((VOID *)(&(d->where))),2);
36✔
3617
                        LowerSortLevel();
36✔
3618
                        term = d->where; while ( *term ) term += *term;
102✔
3619
                        d->size = term - d->where;
36✔
3620
                        if ( nd != d ) M_free(nd,"Copy of dollar variable");
36✔
3621
                        if ( d->where[0] == 0 ) {
36✔
3622
                                M_free(d->where,"dollar contents"); d->where = 0;
×
3623
                                d->type = DOLZERO;
×
3624
                        }
3625
                }
3626
        }
3627
#ifdef WITHMPI
3628
        }
3629
        if ( AC.RhsExprInModuleFlag ) {
3630
                /*
3631
                 * The only master executed the statements in #inside.
3632
                 * We need to broadcast the result to the all slaves.
3633
                 */
3634
                for ( i = 0; i < AP.inside.numdollars; i++ ) {
3635
                        /*
3636
                         * Mark $-variables specified in the #inside instruction as modified
3637
                         * such that they will be broadcast.
3638
                         */
3639
                        AddPotModdollar(AP.inside.buffer[i]);
3640
                }
3641
                /* Now actual broadcast of modified variables. */
3642
                if ( NumPotModdollars > 0 ) {
3643
                        error = PF_BroadcastModifiedDollars();
3644
                        if ( error ) goto cleanup;
3645
                }
3646
                if ( AC.numpfirstnum > 0 ) {
3647
                        error = PF_BroadcastRedefinedPreVars();
3648
                        if ( error ) goto cleanup;
3649
                }
3650
        }
3651
cleanup:
3652
#endif
3653
        f = AR.infile; AR.infile = AR.outfile; AR.outfile = f;
36✔
3654
        AC.cbufnum = AP.inside.oldcbuf;
36✔
3655
        AM.rbufnum = AP.inside.oldrbuf;
36✔
3656
        AR.Cnumlhs = AP.inside.oldcnumlhs;
36✔
3657
        AR.BracketOn = oldbracketon;
36✔
3658
        AP.PreInsideLevel = 0;
36✔
3659
        AR.CompressPointer = oldcompresspointer;
36✔
3660
        AS.MultiThreaded = oldmultithreaded;
36✔
3661
        AC.mparallelflag = AP.inside.oldparallelflag;
36✔
3662
        NumPotModdollars = AP.inside.oldnumpotmoddollars;
36✔
3663
        POPPREASSIGNLEVEL
36✔
3664
#ifdef WITHMPI
3665
        PF_RestoreInsideInfo();
3666
        if ( error ) return error;
3667
#endif
3668
        return(0);
3669
}
3670

3671
/*
3672
                 #] DoEndInside : 
3673
                 #[ DoMessage :
3674
*/
3675

3676
int DoMessage(UBYTE *s)
1,464✔
3677
{
3678
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
1,464✔
3679
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
1,464✔
3680
        while ( *s == ' ' || *s == '\t' ) s++;
1,407✔
3681
        MesPrint("~~~%s",s);
1,407✔
3682
        return(0);
1,407✔
3683
}
3684

3685
/*
3686
                 #] DoMessage : 
3687
                 #[ DoPipe :
3688
*/
3689

3690
int DoPipe(UBYTE *s)
×
3691
{
3692
#ifndef WITHPIPE
3693
        DUMMYUSE(s);
3694
#endif
3695
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
3696
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
3697
#ifdef WITHPIPE
3698
        FLUSHCONSOLE;
×
3699
        while ( *s == ' ' || *s == '\t' ) s++;
×
3700
        if ( OpenStream(s,PIPESTREAM,0,PRENOACTION) == 0 ) return(-1);
×
3701
        return(0);
3702
#else
3703
        Error0("Pipes not implemented on this computer/system");
3704
        return(-1);
3705
#endif
3706
}
3707

3708
/*
3709
                 #] DoPipe : 
3710
                 #[ DoPrcExtension :
3711
*/
3712

3713
int DoPrcExtension(UBYTE *s)
×
3714
{
3715
        UBYTE *t, *u, c;
×
3716
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
3717
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
3718
        while ( *s == ' ' || *s == '\t' ) s++;
×
3719
        if ( *s == 0 || *s == '\n' ) {
×
3720
                MesPrint("@No valid procedure extension specified");
×
3721
                return(-1);
×
3722
        }
3723
        if ( FG.cTable[*s] != 0 ) {
×
3724
                MesPrint("@Procedure extension should be a string starting with an alphabetic character. No whitespace.");
×
3725
                return(-1);
×
3726
        }
3727
        t = s;
3728
        while ( *s && *s != '\n' && *s != ' ' && *s != '\t' ) s++;
×
3729
        u = s;
3730
        while ( *s == ' ' || *s == '\t' ) s++;
×
3731
        if ( *s != 0 && *s != '\n' ) {
×
3732
                MesPrint("@Too many parameters in ProcedureExtension instruction");
×
3733
                return(-1);
×
3734
        }
3735
        c = *u; *u = 0;
×
3736
        if ( AP.procedureExtension ) M_free(AP.procedureExtension,"ProcedureExtension");
×
3737
        AP.procedureExtension = strDup1(t,"ProcedureExtension");
×
3738
        *u = c;
×
3739
        return(0);
×
3740
}
3741

3742
/*
3743
                 #] DoPrcExtension : 
3744
                 #[ DoPreOut :
3745
*/
3746

3747
int DoPreOut(UBYTE *s)
3✔
3748
{
3749
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
3✔
3750
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
3✔
3751
        if ( tolower(*s) == 'o' ) {
3✔
3752
                if ( tolower(s[1]) == 'n' && s[2] == 0 ) {
3✔
3753
                        AP.PreOut = 1;
3✔
3754
                        return(0);
3✔
3755
                }
3756
                if ( tolower(s[1]) == 'f' && tolower(s[2]) == 'f' && s[3] == 0 ) {
×
3757
                        AP.PreOut = 0;
×
3758
                        return(0);
×
3759
                }
3760
        }
3761
        MesPrint("@Illegal option in PreOut instruction");
×
3762
        return(-1);
×
3763
}
3764

3765
/*
3766
                 #] DoPreOut : 
3767
                 #[ DoPrePrintTimes :
3768
*/
3769

3770
int DoPrePrintTimes(UBYTE *s)
×
3771
{
3772
        DUMMYUSE(s);
×
3773
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
3774
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
3775
        PrintRunningTime();
×
3776
        return(0);
×
3777
}
3778

3779
/*
3780
                 #] DoPrePrintTimes : 
3781
                #[ DoPreSortReallocate :
3782
*/
3783

3784
int DoPreSortReallocate(UBYTE *s)
3✔
3785
{
3786
        DUMMYUSE(s);
3✔
3787
        if ( AC.SortReallocateFlag == 0 ) {
3✔
3788
                /* Currently off, so set to 2. Then the reallocation code knows the flag was
3789
                   set here, since "On sortreallocate;" sets it to 1. */
3790
                AC.SortReallocateFlag = 2;
3✔
3791
        }
3792
        /* If the flag is already on, do nothing. */
3793
        return(0);
3✔
3794
}
3795

3796
/*
3797
                #] DoPreSortReallocate :
3798
                 #[ DoPreAppend :
3799

3800
                Syntax:
3801
                #append <filename>
3802
*/
3803

3804
int DoPreAppend(UBYTE *s)
×
3805
{
3806
        UBYTE *name, *to;
×
3807

3808
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
3809
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
3810
        if ( AP.preError ) return(0);
×
3811
        while ( *s == ' ' || *s == '\t' ) s++;
×
3812
/*
3813
        Determine where to write
3814
*/
3815
        if ( *s == '<' ) {
×
3816
                s++;
×
3817
                name = to = s;
×
3818
                while ( *s && *s != '>' ) {
×
3819
                        if ( *s == '\\' ) s++;
×
3820
                        *to++ = *s++;
×
3821
                }
3822
                if ( *s == 0 ) {
×
3823
                        MesPrint("@Improper termination of filename");
×
3824
                        return(-1);
×
3825
                }
3826
                s++;
×
3827
                *to = 0;
×
3828
                if ( *name ) { GetAppendChannel((char *)name); }
×
3829
                else goto improper;
×
3830
        }
3831
        else {
3832
improper:
×
3833
                MesPrint("@Proper syntax is: %#append <filename>");
×
3834
                return(-1);
×
3835
        }
3836
        return(0);
×
3837
}
3838

3839
/*
3840
                 #] DoPreAppend : 
3841
                 #[ DoPreCreate :
3842

3843
                Syntax:
3844
                #create <filename>
3845
*/
3846

3847
int DoPreCreate(UBYTE *s)
×
3848
{
3849
        UBYTE *name, *to;
×
3850

3851
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
3852
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
3853
        if ( AP.preError ) return(0);
×
3854
        while ( *s == ' ' || *s == '\t' ) s++;
×
3855
/*
3856
        Determine where to write
3857
*/
3858
        if ( *s == '<' ) {
×
3859
                s++;
×
3860
                name = to = s;
×
3861
                while ( *s && *s != '>' ) {
×
3862
                        if ( *s == '\\' ) s++;
×
3863
                        *to++ = *s++;
×
3864
                }
3865
                if ( *s == 0 ) {
×
3866
                        MesPrint("@Improper termination of filename");
×
3867
                        return(-1);
×
3868
                }
3869
                s++;
×
3870
                *to = 0;
×
3871
                if ( *name ) { GetChannel((char *)name,0); }
×
3872
                else goto improper;
×
3873
        }
3874
        else {
3875
improper:
×
3876
                MesPrint("@Proper syntax is: %#create <filename>");
×
3877
                return(-1);
×
3878
        }
3879
        return(0);
×
3880
}
3881

3882
/*
3883
                 #] DoPreCreate : 
3884
                 #[ DoPreRemove :
3885
*/
3886

3887
int DoPreRemove(UBYTE *s)
×
3888
{
3889
        UBYTE *name, *to;
×
3890
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
3891
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
3892
        if ( AP.preError ) return(0);
×
3893
        while ( *s == ' ' || *s == '\t' ) s++;
×
3894
        if ( *s == '<' ) { s++; }
×
3895
        else {
3896
                MesPrint("@Proper syntax is: %#remove <filename>");
×
3897
                return(-1);
×
3898
        }
3899
        name = to = s;
×
3900
        while ( *s && *s != '>' ) {
×
3901
                if ( *s == '\\' ) s++;
×
3902
                *to++ = *s++;
×
3903
        }
3904
        if ( *s == 0 ) {
×
3905
                MesPrint("@Improper filename");
×
3906
                return(-1);
×
3907
        }
3908
        s++;
×
3909
        *to = 0;
×
3910
        CloseChannel((char *)name);
×
3911
        remove((char *)name);
×
3912
        return(0);
×
3913
}
3914

3915
/*
3916
                 #] DoPreRemove : 
3917
                 #[ DoPreClose :
3918
*/
3919

3920
int DoPreClose(UBYTE *s)
×
3921
{
3922
        UBYTE *name, *to;
×
3923
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
3924
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
3925
        if ( AP.preError ) return(0);
×
3926
        while ( *s == ' ' || *s == '\t' ) s++;
×
3927
        if ( *s == '<' ) { s++; }
×
3928
        else {
3929
                MesPrint("@Proper syntax is: %#close <filename>");
×
3930
                return(-1);
×
3931
        }
3932
        name = to = s;
×
3933
        while ( *s && *s != '>' ) {
×
3934
                if ( *s == '\\' ) s++;
×
3935
                *to++ = *s++;
×
3936
        }
3937
        if ( *s == 0 ) {
×
3938
                MesPrint("@Improper filename");
×
3939
                return(-1);
×
3940
        }
3941
        s++;
×
3942
        *to = 0;
×
3943
        return(CloseChannel((char *)name));
×
3944
}
3945

3946
/*
3947
                 #] DoPreClose : 
3948
                 #[ DoPreWrite :
3949

3950
                Syntax:
3951
                #write [<filename>] "formatstring" [,objects]
3952
                The format string can contain the following special objects/codes
3953
                \n  newline
3954
                \t  tab
3955
                \!        if last entry in string: no linefeed at end
3956
                \b        put \ in output
3957
                %$  $-variable (to be found among the objects)
3958
                %e  expression (name to be found among the objects)
3959
                %E  expression without ; (name to be found among the objects)
3960
                %s        string (to be found among the objects) (with or without "")
3961
                %S        subterms (see PrintSubtermList)
3962
*/
3963

3964
int DoPreWrite(UBYTE *s)
201✔
3965
{
3966
        HANDLERS h;
201✔
3967

3968
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
201✔
3969
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
201✔
3970
        if ( AP.preError ) return(0);
201✔
3971

3972
#ifdef WITHMPI
3973
        if ( PF.me != MASTER ) return 0;
3974
#endif
3975

3976
        h.oldsilent    = AM.silent;
201✔
3977
        h.newlogonly   = h.oldlogonly = AM.FileOnlyFlag;
201✔
3978
        h.newhandle    = h.oldhandle  = AC.LogHandle;
201✔
3979
        h.oldprinttype = AO.PrintType;
201✔
3980
   
3981
        while ( *s == ' ' || *s == '\t' ) s++;
201✔
3982
/*
3983
        Determine where to write
3984
*/
3985
        if( (s=defineChannel(s,&h))==0 ) return(-1);
201✔
3986

3987
        return(writeToChannel(WRITEOUT,s,&h));
201✔
3988
}
3989

3990
/*
3991
                 #] DoPreWrite : 
3992
                 #[ DoProcedure :
3993

3994
                We have to read this procedure into a buffer.
3995
                The only complications are:
3996
                1: we have to seek through the file to do this efficiently
3997
                   the file operations under VMS cannot do this properly
3998
                   (unless we use the proper ANSI structs?)
3999
                   This is the reason why we read whole input files under VMS.
4000
                2: what to do when the same name is used twice.
4001
                Note that we have to do the reading without substitution of
4002
                preprocessor variables.
4003
*/
4004

4005
int DoProcedure(UBYTE *s)
51✔
4006
{
4007
        UBYTE c;
51✔
4008
        PROCEDURE *p;
51✔
4009
        LONG i;
51✔
4010
        if ( ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH )
51✔
4011
        || ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) ) {
51✔
4012
                if ( PreSkip((UBYTE *)"procedure",(UBYTE *)"endprocedure",1) ) return(-1);
×
4013
                return(0);
×
4014
        }
4015
        p = (PROCEDURE *)FromList(&AP.ProcList);
51✔
4016
        if ( PreLoad(&(p->p),(UBYTE *)"procedure",(UBYTE *)"endprocedure"
51✔
4017
                ,1,(char *)"procedure") ) return(-1);
4018

4019
        p->loadmode = 2;
51✔
4020
        s = p->p.buffer + 10;
51✔
4021
        while ( *s == ' ' || *s == LINEFEED ) s++;
102✔
4022
        if ( chartype[*s] ) {
51✔
4023
                MesPrint("@Illegal name for procedure");
×
4024
                return(-1);
×
4025
        }
4026
        p->name = s++;
51✔
4027
        while ( chartype[*s] == 0 || chartype[*s] == 1 ) s++;
609✔
4028
        c = *s; *s = 0;
51✔
4029
        p->name = strDup1(p->name,"procedure");
51✔
4030
        *s = c;
51✔
4031
/*
4032
        Check for double names
4033
*/
4034
        for ( i = NumProcedures-2; i >= 0; i-- ) {
99✔
4035
                if ( StrCmp(Procedures[i].name,p->name) == 0 ) {
48✔
4036
                        Error1("Multiple occurrence of procedure name ",p->name);
×
4037
                }
4038
        }
4039
        return(0);
4040
}
4041

4042
/*
4043
                 #] DoProcedure : 
4044
                 #[ DoPreBreak :
4045
*/
4046

4047
int DoPreBreak(UBYTE *s)
×
4048
{
4049
        DUMMYUSE(s);
×
4050
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
4051
        if ( AP.PreTypes[AP.NumPreTypes] != PRETYPESWITCH ) {
×
4052
                if ( AP.PreSwitchLevel <= 0 )
×
4053
                         MesPrint("@Break without corresponding Switch");
×
4054
                else MessPreNesting(7);
×
4055
                return(-1);
×
4056
        }
4057
        if ( AP.PreSwitchLevel <= 0 ) {
×
4058
                MesPrint("@Break without corresponding Switch");
×
4059
                return(-1);
×
4060
        }
4061
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] == EXECUTINGPRESWITCH )
×
4062
                AP.PreSwitchModes[AP.PreSwitchLevel] = SEARCHINGPREENDSWITCH;
×
4063
        return(0);
4064
}
4065

4066
/*
4067
                 #] DoPreBreak : 
4068
                 #[ DoPreCase :
4069
*/
4070

4071
int DoPreCase(UBYTE *s)
×
4072
{
4073
        UBYTE *t;
×
4074
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
4075
        if ( AP.PreTypes[AP.NumPreTypes] != PRETYPESWITCH ) {
×
4076
                if ( AP.PreSwitchLevel <= 0 )
×
4077
                         MesPrint("@Case without corresponding Switch");
×
4078
                else MessPreNesting(8);
×
4079
                return(-1);
×
4080
        }
4081
        if ( AP.PreSwitchLevel <= 0 ) {
×
4082
                MesPrint("@Case without corresponding Switch");
×
4083
                return(-1);
×
4084
        }
4085
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != SEARCHINGPRECASE ) return(0);
×
4086

4087
        SKIPBLANKS(s)
×
4088
        t = s;
×
4089
        while ( *s ) { if ( *s == '\\' ) s++; s++; }
×
4090
        while ( s > t && ( s[-1] == ' ' || s[-1] == '\t' ) && s[-2] != '\\' ) {
×
4091
                if ( s[-2] == '\\' ) s--;
×
4092
                s--;
×
4093
        }
4094
        if ( *t == '"' && s > t+1 && s[-1] == '"' && s[-2] != '\\' ) {
×
4095
                t++; s--; *s = 0;
×
4096
        }
4097
        else *s = 0;
×
4098
        s = AP.PreSwitchStrings[AP.PreSwitchLevel];
×
4099
        while ( *t == *s && *t ) { s++; t++; }
×
4100
        if ( *t || *s ) return(0);        /* case did not match */
×
4101
        AP.PreSwitchModes[AP.PreSwitchLevel] = EXECUTINGPRESWITCH;
×
4102
        return(0);
×
4103
}
4104

4105
/*
4106
                 #] DoPreCase : 
4107
                 #[ DoPreDefault :
4108
*/
4109

4110
int DoPreDefault(UBYTE *s)
×
4111
{
4112
        DUMMYUSE(s);
×
4113
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
4114
        if ( AP.PreTypes[AP.NumPreTypes] != PRETYPESWITCH ) {
×
4115
                if ( AP.PreSwitchLevel <= 0 )
×
4116
                         MesPrint("@Default without corresponding Switch");
×
4117
                else MessPreNesting(9);
×
4118
                return(-1);
×
4119
        }
4120
        if ( AP.PreSwitchLevel <= 0 ) {
×
4121
                MesPrint("@Default without corresponding Switch");
×
4122
                return(-1);
×
4123
        }
4124
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != SEARCHINGPRECASE ) return(0);
×
4125
        AP.PreSwitchModes[AP.PreSwitchLevel] = EXECUTINGPRESWITCH;
×
4126
        return(0);
×
4127
}
4128

4129
/*
4130
                 #] DoPreDefault : 
4131
                 #[ DoPreEndSwitch :
4132
*/
4133

4134
int DoPreEndSwitch(UBYTE *s)
×
4135
{
4136
        DUMMYUSE(s);
×
4137
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
4138
        if ( AP.PreTypes[AP.NumPreTypes] != PRETYPESWITCH ) {
×
4139
                if ( AP.PreSwitchLevel <= 0 )
×
4140
                         MesPrint("@EndSwitch without corresponding Switch");
×
4141
                else MessPreNesting(10);
×
4142
                return(-1);
×
4143
        }
4144
        AP.NumPreTypes--;
×
4145
        if ( AP.PreSwitchLevel <= 0 ) {
×
4146
                MesPrint("@EndSwitch without corresponding Switch");
×
4147
                return(-1);
×
4148
        }
4149
        M_free(AP.PreSwitchStrings[AP.PreSwitchLevel--],"pre switch string");
×
4150
        return(0);
×
4151
}
4152

4153
/*
4154
                 #] DoPreEndSwitch : 
4155
                 #[ DoPreSwitch :
4156

4157
                There should be a string after this.
4158
                We have to store it somewhere.
4159
*/
4160

4161
int DoPreSwitch(UBYTE *s)
×
4162
{
4163
        UBYTE *t, *switchstring, **newstrings;
×
4164
        int newnum, i, *newmodes;
×
4165
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
4166
        SKIPBLANKS(s)
×
4167
        t = s;
×
4168
        while ( *s ) { if ( *s == '\\' ) s++; s++; }
×
4169
        while ( s > t && ( s[-1] == ' ' || s[-1] == '\t' ) && s[-2] != '\\' ) {
×
4170
                if ( s[-2] == '\\' ) s--;
×
4171
                s--;
×
4172
        }
4173
        if ( *t == '"' && s > t+1 && s[-1] == '"' && s[-2] != '\\' ) {
×
4174
                t++; s--; *s = 0;
×
4175
        }
4176
        else *s = 0;
×
4177
        switchstring = (UBYTE *)Malloc1((s-t)+1,"case string");
×
4178
        s = switchstring;
×
4179
        while ( *t ) {
×
4180
                if ( *t == '\\' ) t++;
×
4181
                *s++ = *t++;
×
4182
        }
4183
        *s = 0;
×
4184
        if ( AP.PreSwitchLevel >= AP.NumPreSwitchStrings ) {
×
4185
                newnum = 2*AP.NumPreSwitchStrings;
×
4186
                newstrings = (UBYTE **)Malloc1(sizeof(UBYTE *)*(newnum+1),"case strings");
×
4187
                newmodes   = (int *)Malloc1(sizeof(int)*(newnum+1),"case strings");
×
4188
                for ( i = 0; i < AP.NumPreSwitchStrings; i++ )
×
4189
                        newstrings[i] = AP.PreSwitchStrings[i];
×
4190
                M_free(AP.PreSwitchStrings,"AP.PreSwitchStrings");
×
4191
                for ( i = 0; i <= AP.NumPreSwitchStrings; i++ )
×
4192
                        newmodes[i] = AP.PreSwitchModes[i];
×
4193
                M_free(AP.PreSwitchModes,"AP.PreSwitchModes");
×
4194
                AP.PreSwitchStrings = newstrings;
×
4195
                AP.PreSwitchModes   = newmodes;
×
4196
                AP.NumPreSwitchStrings = newnum;
×
4197
        }
4198
        AP.PreSwitchStrings[++AP.PreSwitchLevel] = switchstring;
×
4199
        if ( ( AP.PreSwitchLevel > 1 )
×
4200
         && ( AP.PreSwitchModes[AP.PreSwitchLevel-1] != EXECUTINGPRESWITCH ) )
×
4201
                AP.PreSwitchModes[AP.PreSwitchLevel] = SEARCHINGPREENDSWITCH;
×
4202
        else
4203
                AP.PreSwitchModes[AP.PreSwitchLevel] = SEARCHINGPRECASE;
×
4204
        AddToPreTypes(PRETYPESWITCH);
×
4205
        return(0);
×
4206
}
4207

4208
/*
4209
                 #] DoPreSwitch : 
4210
                 #[ DoPreShow :
4211

4212
                Print the contents of the preprocessor variables
4213
*/
4214

4215
int DoPreShow(UBYTE *s)
×
4216
{
4217
        int i;
×
4218
        UBYTE *name, c;
×
4219
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
4220
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
4221
        while ( *s == ' ' || *s == '\t' ) s++;
×
4222
        if ( *s == 0 ) {
×
4223
                MesPrint("%#The preprocessor variables:");
×
4224
                for ( i = 0; i < NumPre; i++ ) {
×
4225
                        MesPrint("%d: %s = \"%s\"",i,PreVar[i].name,PreVar[i].value);
×
4226
                }
4227
        }
4228
        else {
4229
                while ( *s ) {
×
4230
                        name = s; while ( *s && *s != ' ' && *s != '\t' && *s != ',' ) s++;
×
4231
                        c = *s; *s = 0;
×
4232
                        for ( i = 0; i < NumPre; i++ ) {
×
4233
                                if ( StrCmp(PreVar[i].name,name) == 0 )
×
4234
                                        MesPrint("%d: %s = \"%s\"",i,PreVar[i].name,PreVar[i].value);
×
4235
                        }
4236
                        *s = c;
×
4237
                        while ( *s == ' ' || *s == '\t' ) s++;
×
4238
                }
4239
        }
4240
        return(0);
4241
}
4242

4243
/*
4244
                 #] DoPreShow : 
4245
                 #[ DoSystem :
4246
*/
4247

4248
/*
4249
 * A macro for translating the contents of `x' into a string after expanding.
4250
 */
4251
#define STRINGIFY(x)  STRINGIFY__(x)
4252
#define STRINGIFY__(x) #x
4253

4254
int DoSystem(UBYTE *s)
×
4255
{
4256
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
4257
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
4258
        if ( AP.preError ) return(0);
×
4259
#ifdef WITHSYSTEM
4260
        FLUSHCONSOLE;
×
4261
        while ( *s == ' ' || *s == '\t' ) s++;
×
4262
        if ( *s == '-' && s[1] == 'e' ) {
×
4263
                LONG err;
×
4264
                UBYTE str[24];
×
4265
                s += 2;
×
4266
                if ( *s != ' ' ) {
×
4267
                        MesPrint("@Syntax error in #system command.");
×
4268
                        return(-1);
×
4269
                }
4270
                while ( *s == ' ' || *s == '\t' ) s++;
×
4271
                err = system((char *)s);
×
4272
                NumToStr(str,err);
×
4273
                PutPreVar((UBYTE *)"SYSTEMERROR_",str,0,1);
×
4274
        }
4275
        else if ( system((char *)s) ) {
×
4276
                MesPrint("@System call returned with error condition");
×
4277
                Terminate(-1);
×
4278
        }
4279
        return(0);
4280
#else
4281
        Error0("External programs not implemented on this computer/system");
4282
        return(-1);
4283
#endif
4284
}
4285

4286
/*
4287
                 #] DoSystem : 
4288
                 #[ PreLoad :
4289

4290
                Loads a loop or procedure into a special buffer.
4291
                Note: The current instruction is already in the preStart buffer
4292
*/
4293

4294
int PreLoad(PRELOAD *p, UBYTE *start, UBYTE *stop, int mode, char *message)
252✔
4295
{
4296
        UBYTE *s, *t, *top, *newbuffer, c;
252✔
4297
        LONG i, ppsize, linenum = AC.CurrentStream->linenumber;
252✔
4298
        int size1, size2, level, com=0, last=1, strng = 0;
252✔
4299
        p->size = AP.pSize;
252✔
4300
        p->buffer = (UBYTE *)Malloc1(p->size+1,message);
252✔
4301
        top = p->buffer + p->size - 2;
252✔
4302
        t = p->buffer; *t++ = '#';
252✔
4303
        s = start; size1 = size2 = 0;
252✔
4304
        while ( *s ) { s++; size1++; }
1,113✔
4305
        s = stop; while ( *s ) { s++; size2++; }
1,869✔
4306
        s = AP.preStart; while ( *s ) *t++ = *s++; *t++ = LINEFEED;
4,227✔
4307
        level = 1;
252✔
4308
        i = 100;
252✔
4309
        for (;;) {
1,116,453✔
4310
                c = GetInput();
1,116,453✔
4311
                if ( c == ENDOFINPUT ) {
1,116,453✔
4312
                        MesPrint("@Missing %#%s, Should match line %l",stop,linenum);
×
4313
                        return(-1);
×
4314
                }
4315
                if ( c == AP.ComChar && last == 1 ) com = 1;
1,116,453✔
4316
                if ( c == LINEFEED ) { last = 1; com = 0; }
1,116,453✔
4317
                else last = 0;
1,114,683✔
4318

4319
                if ( ( c == '"' ) && ( com == 0 ) ) { strng ^= 1; }
1,116,453✔
4320

4321
                if ( ( c == '#' ) && ( com == 0 ) ) i = 0;
1,116,453✔
4322
                else i++;
1,115,808✔
4323

4324
                if ( t >= top ) {
1,116,453✔
4325
                        ppsize = t - p->buffer;
153✔
4326
                        p->size *= 2;
153✔
4327
                        newbuffer = (UBYTE *)Malloc1(p->size,message);
153✔
4328
                        t = newbuffer; s = p->buffer;
153✔
4329
                        while ( --ppsize >= 0 ) *t++ = *s++;
1,621,095✔
4330
                        M_free(p->buffer,"loading do loop");
153✔
4331
                        p->buffer = newbuffer;
153✔
4332
                        top = p->buffer + p->size - 2;
153✔
4333
                }
4334
                *t++ = c;
1,116,453✔
4335
                if ( strng == 0 ) {
1,116,453✔
4336
                  if ( ( i == size2 ) && ( com == 0 ) ) {
1,114,881✔
4337
                        *t = 0;
579✔
4338
                        if ( StrICmp(t-size2,(UBYTE *)(stop)) == 0 ) {
579✔
4339
                                while ( ( c = GetInput() ) != LINEFEED && c != ENDOFINPUT ) {}
267✔
4340
                                level--;
267✔
4341
                                if ( level <= 0 ) break;
267✔
4342
                                if ( c == ENDOFINPUT ) Error1("Missing #",stop);
15✔
4343
                                *t++ = LINEFEED; *t = 0; last = 1;
15✔
4344
                        }
4345
                  }
4346
                  if ( ( i == size1 ) && mode && ( com == 0 ) ) {
1,114,629✔
4347
                        *t = 0;
594✔
4348
                        if ( StrICmp(t-size1,(UBYTE *)(start)) == 0 ) {
594✔
4349
/*
4350
                                while ( ( c = GetInput() ) != LINEFEED && c != ENDOFINPUT ) {}
4351
                                if ( c == ENDOFINPUT ) Error1("Missing #",stop);
4352
*/
4353
                                level++;
15✔
4354
                        }
4355
                  }
4356
                  if ( i == 1 && t[-2] == LINEFEED ) {
1,114,629✔
4357
                        if ( c == '-' )      AC.NoShowInput = 1;
×
4358
                        else if ( c == '+' ) AC.NoShowInput = 0;
×
4359
                  }
4360
                }
4361
        }
4362
        *t++ = LINEFEED;
252✔
4363
        *t = 0;
252✔
4364
        return(0);
252✔
4365
}
4366

4367
/*
4368
                 #] PreLoad : 
4369
                 #[ PreSkip :
4370

4371
                Skips a loop or procedure.
4372
                Note: The current instruction is already in the preStart buffer
4373
*/
4374

4375
#define SKIPBUFSIZE 20
4376

4377
int PreSkip(UBYTE *start, UBYTE *stop, int mode)
×
4378
{
4379
        UBYTE *s, *t, buffer[SKIPBUFSIZE+2], c;
×
4380
        LONG i, linenum = AC.CurrentStream->linenumber;
×
4381
        int size1, size2, level, com=0, last=1;
×
4382

4383
        t = buffer; *t++ = '#';
×
4384
        s = start; size1 = size2 = 0;
×
4385
        while ( *s ) { s++; size1++; }
×
4386
        s = stop; while ( *s ) { s++; size2++; }
×
4387
        level = 1;
4388
        i = 0;
4389
        for (;;) {
×
4390
                c = GetInput();
×
4391
                if ( c == ENDOFINPUT ) {
×
4392
                        MesPrint("@Missing %#%s, Should match line %l",stop,linenum);
×
4393
                        return(-1);
×
4394
                }
4395
                if ( c == AP.ComChar && last == 1 ) com = 1;
×
4396
                if ( c == LINEFEED ) { last = 1; com = 0; i = 0; t = buffer; }
×
4397
                else last = 0;
×
4398
                if ( ( c == '#' ) && ( com == 0 ) ) { i = 0; t = buffer; }
×
4399
                else i++;
×
4400

4401
                if ( i < SKIPBUFSIZE ) *t++ = c;
×
4402
                if ( ( i == size2 ) && ( com == 0 ) ) {
×
4403
                        *t = 0;
×
4404
                        if ( StrICmp(t-size2,(UBYTE *)(stop)) == 0 ) {
×
4405
                                while ( ( c = GetInput() ) != LINEFEED && c != ENDOFINPUT ) {}
×
4406
                                level--;
×
4407
                                if ( level <= 0 ) {
×
4408
                                        pushbackchar = LINEFEED;
×
4409
                                        break;
×
4410
                                }
4411
                                if ( c == ENDOFINPUT ) Error1("Missing #",stop);
×
4412
                                i = 0; t = buffer;
4413
                        }
4414
                }
4415
                if ( ( i == size1 ) && mode && ( com == 0 ) ) {
×
4416
                        *t = 0;
×
4417
                        if ( StrICmp(t-size1,(UBYTE *)(start)) == 0 ) {
×
4418
                                while ( ( c = GetInput() ) != LINEFEED && c != ENDOFINPUT ) {}
×
4419
                                level++;
×
4420
                                i = 0; t = buffer;
×
4421
                        }
4422
                }
4423
        }
4424
        return(0);
×
4425
}
4426

4427
/*
4428
                 #] PreSkip : 
4429
                 #[ StartPrepro :
4430
*/
4431

4432
VOID StartPrepro(VOID)
886✔
4433
{
4434
        int **ppp;
886✔
4435
        AP.MaxPreIfLevel = 2;
886✔
4436
        ppp = &AP.PreIfStack;
886✔
4437
        if ( DoubleList((VOID ***)ppp,&AP.MaxPreIfLevel,sizeof(int),
886✔
4438
                        "PreIfLevels") ) Terminate(-1);
×
4439
        AP.PreIfLevel = 0; AP.PreIfStack[0] = EXECUTINGIF;
886✔
4440

4441
        AP.NumPreSwitchStrings = 10;
886✔
4442
        AP.PreSwitchStrings = (UBYTE **)Malloc1(sizeof(UBYTE *)*
886✔
4443
                                                                (AP.NumPreSwitchStrings+1),"case strings");
4444
        AP.PreSwitchModes   = (int *)Malloc1(sizeof(int)*
1,772✔
4445
                                                                (AP.NumPreSwitchStrings+1),"case strings");
886✔
4446
        AP.PreSwitchModes[0] = EXECUTINGPRESWITCH;
886✔
4447
        AP.PreSwitchLevel = 0;
886✔
4448
}
886✔
4449

4450
/*
4451
                 #] StartPrepro : 
4452
                 #[ EvalPreIf :
4453

4454
                Evaluates the condition in an if instruction.
4455
                The return value is EXECUTINGIF if the condition is true.
4456
                If it is false the returnvalue is LOOKINGFORELSE.
4457
                An error gives a return value of -1
4458
*/
4459

4460
int EvalPreIf(UBYTE *s)
162✔
4461
{
4462
        UBYTE *t, *u;
162✔
4463
        int val;
162✔
4464
        t = s;
162✔
4465
        while ( *t ) t++;
831✔
4466
        *t++ = ')';
162✔
4467
        *t = 0;
162✔
4468
        if ( ( u = PreIfEval(s,&val) ) == 0 ) return(-1);
162✔
4469
        if ( u < t ) {
159✔
4470
                MesPrint("@Unmatched parentheses in condition");
×
4471
                return(-1);
×
4472
        }
4473
        if ( val ) return(EXECUTINGIF);
159✔
4474
        else       return(LOOKINGFORELSE);
78✔
4475
}
4476

4477
/*
4478
                 #] EvalPreIf : 
4479
                 #[ PreIfEval :
4480

4481
                Used for recursions in the evaluation of a preprocessor if-condition.
4482
                It determines whether the contents of () is true or false
4483
                (or in error).
4484
                The return value is the address of the first character after the
4485
                closing parenthesis or null if there is an error.
4486
                In value we find true(1) or false(0)
4487
                We enter after the opening parenthesis.
4488
                There are levels:
4489
                        0: orlevel:  a || b
4490
                        1: andlevel: a && b
4491
                        2: eqlevel:  a == b or a != b or a = b
4492
                        3: cmplevel: a > b or a >= b or a < b or a <= b or a >~ b etc
4493
*/
4494

4495
UBYTE *PreIfEval(UBYTE *s, int *value)
180✔
4496
{
4497
        int orlevel = 0, andlevel = 0, eqlevel = 0, cmplevel = 0;
180✔
4498
        int type, val;
180✔
4499
        LONG val2;
180✔
4500
        int ortype, orval, cmptype, cmpval, eqtype, eqval, andtype, andval;
180✔
4501
        UBYTE *t, *eqt, *cmpt, c;
180✔
4502
        int eqop, cmpop;
180✔
4503
        ortype = orval = cmptype = cmpval = eqtype = eqval = andtype = andval = 0;
180✔
4504
        eqop = cmpop = 0;
180✔
4505
        eqt = cmpt = 0;
180✔
4506
        *value = 0;
180✔
4507
        while ( *s != ')' ) {
198✔
4508
                while ( *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r' ) s++;
216✔
4509
                t = s;
198✔
4510
                s = pParseObject(s,&type,&val2);
198✔
4511
                if ( s == 0 ) return(0);
192✔
4512
                val = val2;
192✔
4513
                c = *s;
192✔
4514
                *s++ = 0;    /* in case the object is a string without " */
192✔
4515
                while ( c == ' ' || c == '\t' || c == '\n' || c == '\r' ) {
207✔
4516
                        c = *s; *s++ = 0;
15✔
4517
                }
4518
                if ( *t == '"' ) t++;
192✔
4519
                switch(c) {
192✔
4520
                        case '|':
×
4521
                                if ( *s != '|' ) goto illoper;
×
4522
                                s++;
×
4523
                                /* fall through */
4524
                        case ')':
174✔
4525
                                if ( cmplevel ) {
174✔
4526
                                        if ( type == 0 || cmptype == 0 ) goto illobject;
×
4527
                                        val = PreCmp(type,val,t,cmptype,cmpval,cmpt,cmpop);
×
4528
                                        type = 0;
×
4529
                                        cmplevel = 0;
×
4530
                                }
4531
                                if ( eqlevel ) {
174✔
4532
                                        val = PreEq(type,val,t,eqtype,eqval,eqt,eqop);
18✔
4533
                                        type = 0;
18✔
4534
                                        eqlevel = 0;
18✔
4535
                                }
4536
                                if ( andlevel ) {
174✔
4537
                                        if ( andtype != 0 || type != 0 ) goto illobject;
×
4538
                                        val &= andval;
×
4539
                                        andlevel = 0;
×
4540
                                }
4541
                                if ( orlevel ) {
174✔
4542
                                        if ( ortype != 0 || type != 0 ) goto illobject;
×
4543
                                        val |= orval;
×
4544
                                }
4545
                                if ( c == ')' ) {
174✔
4546
                                        *value = val;
174✔
4547
                                        return(s);
174✔
4548
                                }
4549
                                orlevel = 1;
×
4550
                                orval = val;
×
4551
                                ortype = type;
×
4552
                                break;
×
4553
                        case '&':
×
4554
                                if ( *s != '&' ) goto illoper;
×
4555
                                s++;
×
4556
                                if ( cmplevel ) {
×
4557
                                        if ( type == 0 || cmptype == 0 ) goto illobject;
×
4558
                                        val = PreCmp(type,val,t,cmptype,cmpval,cmpt,cmpop);
×
4559
                                        type = 0;
×
4560
                                        cmplevel = 0;
×
4561
                                }
4562
                                if ( eqlevel ) {
×
4563
                                        val = PreEq(type,val,t,eqtype,eqval,eqt,eqop);
×
4564
                                        type = 0;
×
4565
                                        eqlevel = 0;
×
4566
                                }
4567
                                if ( andlevel ) {
×
4568
                                        if ( andtype != 0 || type != 0 ) goto illobject;
×
4569
                                        val &= andval;
×
4570
                                }
4571
                                andlevel = 1;
×
4572
                                andval = val;
×
4573
                                andtype = type;
×
4574
                                break;
×
4575
                        case '!':
18✔
4576
                        case '=':
4577
                                if ( eqlevel ) goto illorder;
18✔
4578
                                if ( cmplevel ) {
18✔
4579
                                        if ( type == 0 || cmptype == 0 ) goto illobject;
×
4580
                                        val = PreCmp(type,val,t,cmptype,cmpval,cmpt,cmpop);
×
4581
                                        type = 0;
×
4582
                                        cmplevel = 0;
×
4583
                                }
4584
                                if ( c == '!' && *s != '=' ) goto illoper;
18✔
4585
                                if ( *s == '=' ) s++;
18✔
4586
                                if ( c == '!' ) eqop = 1;
18✔
4587
                                else eqop = 0;
18✔
4588
                                eqlevel = 1; eqt = t; eqval = val; eqtype = type;
18✔
4589
                                break;
18✔
4590
                        case '>':
×
4591
                        case '<':
4592
                                if ( cmplevel ) goto illorder;
×
4593
                                if ( c == '<' ) cmpop = -1;
×
4594
                                else            cmpop = 1;
×
4595
                                cmplevel = 1; cmpt = t; cmpval = val; cmptype = type;
×
4596
                                if ( *s == '=' ) {
×
4597
                                        s++;
×
4598
                                        if ( *s == '~' ) { s++; cmpop *= 4; }
×
4599
                                        else cmpop *= 2;
×
4600
                                }
4601
                                else if ( *s == '~' ) { s++; cmpop *= 3; }
×
4602
                                break;
4603
                        default:
×
4604
                                goto illoper;
×
4605
                }
4606
        }
4607
        return(s);
4608
illorder:
×
4609
        MesPrint("@illegal order of operators");
×
4610
        return(0);
×
4611
illobject:
×
4612
        MesPrint("@illegal object for this operator");
×
4613
        return(0);
×
4614
illoper:
×
4615
        MesPrint("@illegal operator");
×
4616
        return(0);
×
4617
}
4618

4619
/*
4620
                 #] PreIfEval : 
4621
                 #[ PreCmp :
4622
*/
4623

4624
int PreCmp(int type, int val, UBYTE *t, int type2, int val2, UBYTE *t2, int cmpop)
×
4625
{
4626
        if ( type == 2 || type2 == 2 || cmpop < -2 || cmpop > 2 ) {
×
4627
                if ( cmpop < 0 && cmpop > -3 ) cmpop -= 2;
×
4628
                if ( cmpop > 0 && cmpop <  3 ) cmpop += 2;
×
4629
                     if ( cmpop ==  3 ) val = StrCmp(t2,t) >  0;
×
4630
                else if ( cmpop ==  4 ) val = StrCmp(t2,t) >= 0;
×
4631
                else if ( cmpop == -3 ) val = StrCmp(t2,t) <  0; 
×
4632
                else if ( cmpop == -4 ) val = StrCmp(t2,t) <= 0; 
×
4633
        }
4634
        else {
4635
                     if ( cmpop ==  1 ) val = ( val2 >  val );
×
4636
                else if ( cmpop ==  2 ) val = ( val2 >= val );
×
4637
                else if ( cmpop == -1 ) val = ( val2 <  val );
×
4638
                else if ( cmpop == -2 ) val = ( val2 <= val );
×
4639
        }
4640
        return(val);
×
4641
}
4642

4643
/*
4644
                 #] PreCmp : 
4645
                 #[ PreEq :
4646
*/
4647

4648
int PreEq(int type, int val, UBYTE *t, int type2, int val2, UBYTE *t2, int eqop)
18✔
4649
{
4650
        UBYTE str[20];
18✔
4651
        if ( type == 2 || type2 == 2 ) {
18✔
4652
                if ( type  != 2 ) { NumToStr(str,val ); t  = str; }
3✔
4653
                if ( type2 != 2 ) { NumToStr(str,val2); t2 = str; }
3✔
4654
                if ( eqop == 1 ) val = StrCmp(t,t2) != 0;
3✔
4655
                else             val = StrCmp(t,t2) == 0;
3✔
4656
        }
4657
        else {
4658
                if ( eqop ) val = val != val2;
15✔
4659
                else        val = val == val2;
15✔
4660
        }
4661
        return(val);
18✔
4662
}
4663

4664
/*
4665
                 #] PreEq : 
4666
                 #[ pParseObject :
4667

4668
                Parses a preprocessor object. We can have:
4669
                1: a number  (type = 1)
4670
                2: a string  (type = 2)
4671
                3: an expression between parentheses (type = 0)
4672
                4: a special function (type = 3)
4673
                If the object is not a number, an expression or a special operator
4674
                we try to interpret it as a string.
4675
*/
4676

4677
UBYTE *pParseObject(UBYTE *s, int *type, LONG *val2)
198✔
4678
{
4679
        UBYTE *t, c;
198✔
4680
        int sign, val = 0;
198✔
4681
        LONG x;
198✔
4682
        while ( *s == ' ' || *s == '\t' ) s++;
198✔
4683
        if ( *s == '(' ) {
198✔
4684
                s++;
18✔
4685
                while ( *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r' ) s++;
36✔
4686
                s = PreIfEval(s,&val);
18✔
4687
                *type = 0;
15✔
4688
                *val2 = val;
15✔
4689
                return(s);
15✔
4690
        }
4691
        else if ( *s == '$' && s[1] == '(' ) {
180✔
4692
                s += 2;
×
4693
                while ( *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r' ) s++;
×
4694
                s = PreIfDollarEval(s,&val);
×
4695
                *type = 0; *val2 = val;
×
4696
                return(s);
×
4697
        }
4698
        if ( *s == 0 ) {
180✔
4699
illend:
×
4700
                MesPrint("@illegal end of condition");
×
4701
                return(0);
×
4702
        }
4703
        if ( *s == '"' ) {
180✔
4704
                s++;
6✔
4705
                while ( *s && *s != '"' ) {
39✔
4706
                        if ( *s == '\\' ) s++;
33✔
4707
                        s++;
33✔
4708
                }
4709
                if ( *s == 0 ) goto illend;
6✔
4710
                else *s = 0;
6✔
4711
                *type = 2;
6✔
4712
                s++;
6✔
4713

4714
                while ( *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r' ) s++;
9✔
4715

4716
                return(s);
4717
        }
4718
        t = s; sign = 1; x = 0;
174✔
4719
        if ( chartype[*t] == 0 ) {        /* Special operators and strings without "" */
174✔
4720
                do { t++; } while ( chartype[*t] <= 1 );
198✔
4721
                if ( *t == '(' ) {
18✔
4722
                        WORD ttype;
18✔
4723
                        c = *t; *t = 0;
18✔
4724
                        if ( StrICmp(s,(UBYTE *)"termsin") == 0 ) {
18✔
4725
                                UBYTE *tt;
4726
                                WORD numdol, numexp;
4727
                                ttype = 0;
4728
together:
×
4729
                                *t++ = c;
×
4730
                                while ( *t == ' ' || *t == '\t' || *t == '\n' || *t == '\r' ) t++;
×
4731
                                if ( *t == '$' ) {
×
4732
                                        t++; tt = t; while (chartype[*tt] <= 1 ) tt++;
×
4733
                                        c = *tt; *tt = 0;
×
4734
                                        if ( ( numdol = GetDollar(t) ) > 0 ) {
×
4735
                                                *tt = c;
×
4736
                                                if ( ttype == 1 ) {
×
4737
                                                        x = SizeOfDollar(numdol);
×
4738
                                                }
4739
                                                else {
4740
                                                        x = TermsInDollar(numdol);
×
4741
                                                }
4742
                                        }
4743
                                        else {
4744
                                                MesPrint("@$%s has not (yet) been defined",t);
×
4745
                                                *tt = c;
×
4746
                                                Terminate(-1);
×
4747
                                        }
4748
                                }
4749
                                else {
4750
                                        tt = SkipAName(t);
×
4751
                                        c = *tt; *tt = 0;
×
4752
                                        if ( GetName(AC.exprnames,t,&numexp,NOAUTO) == NAMENOTFOUND ) {
×
4753
                                                MesPrint("@%s has not (yet) been defined",t);
×
4754
                                                *tt = c;
×
4755
                                                Terminate(-1);
×
4756
                                        }
4757
                                        else {
4758
                                                *tt = c;
×
4759
                                                if ( ttype == 1 ) {
×
4760
                                                        x = SizeOfExpression(numexp);
×
4761
                                                }
4762
                                                else {
4763
                                                        x = TermsInExpression(numexp);
×
4764
                                                }
4765
                                        }
4766
                                }
4767
                                while ( *tt == ' ' || *tt == '\t'
×
4768
                                                 || *tt == '\n' || *tt == '\r' ) tt++;
×
4769
                                if ( *tt != ')' ) {
×
4770
                                        MesPrint("@Improper use of terms($var) or terms(expr)");
×
4771
                                        Terminate(-1);
×
4772
                                }
4773
                                *type = 3;
×
4774
                                s = tt+1;
×
4775
                                *val2 = x;
×
4776
                                return(s);
×
4777
                        }
4778
                        else if ( StrICmp(s,(UBYTE *)"sizeof") == 0 ) {
18✔
4779
                                ttype = 1;
×
4780
                                goto together;
×
4781
                        }
4782
                        else if ( StrICmp(s,(UBYTE *)"exists") == 0 ) {
18✔
4783
                                UBYTE *tt;
×
4784
                                WORD numdol, numexp;
×
4785
                                *t++ = c;
×
4786
                                while ( *t == ' ' || *t == '\t' || *t == '\n' || *t == '\r' ) t++;
×
4787
                                if ( *t == '$' ) {
4788
                                        t++; tt = t; while (chartype[*tt] <= 1 ) tt++;
×
4789
                                        c = *tt; *tt = 0;
×
4790
                                        if ( ( numdol = GetDollar(t) ) >= 0 ) { x = 1; }
×
4791
                                        else                                  { x = 0; }
×
4792
                                        *tt = c;
×
4793
                                }
4794
                                else if ( *t == '"' ) {        /* see whether a file exists */
4795
/*                                        UBYTE *name, *oldname; */
4796
                                        t++; tt = t;
×
4797
                                        for (;;) {
×
4798
                                                if ( *tt == '\\' ) tt++;
×
4799
                                                else if ( *tt == '"' ) break;
×
4800
                                                tt++;
×
4801
                                        }
4802
                                        c = *tt; *tt = 0;
×
4803
/*
4804
                                        Try to open the file. If possible, return 1.
4805
                                        Afterwards close it.
4806
                                        We do have to run through the FORMPATH. Hence we use LocateFile.
4807
                                        This routine may change the name to the full name.
4808

4809
                                        oldname = name = strDup1(t,"name in exists");
4810
                                        x = LocateFile(&name,-1);
4811
*/
4812
                                        x = OpenFile((char *)t);
×
4813
                                        if ( x >= 0 ) {
×
4814
                                                CloseFile(x);
×
4815
                                                x = 1;
×
4816
/*
4817
                                                if ( name != oldname ) M_free(name,"name from LocateFile");
4818
*/
4819
                                        }
4820
                                        else x = 0;
4821
/*
4822
                                        M_free(oldname,"name in exists");
4823
*/
4824
                                        *tt++ = c;
×
4825
                                }
4826
                                else {
4827
                                        tt = SkipAName(t);
×
4828
                                        c = *tt; *tt = 0;
×
4829
                                        if ( GetName(AC.exprnames,t,&numexp,NOAUTO) == NAMENOTFOUND ) { x = 0; }
×
4830
                                        else { x = 1; }
×
4831
                                        *tt = c;
×
4832
                                } 
4833
                                while ( *tt == ' ' || *tt == '\t'
×
4834
                                                 || *tt == '\n' || *tt == '\r' ) tt++;
×
4835
                                if ( *tt != ')' ) {
×
4836
                                        MesPrint("@Improper use of exists($var) or exists(expr)");
×
4837
                                        Terminate(-1);
×
4838
                                }
4839
                                *type = 3;
×
4840
                                s = tt+1;
×
4841
                                *val2 = x;
×
4842
                                return(s);
×
4843
                        }
4844
                        else if ( StrICmp(s,(UBYTE *)"isnumerical") == 0 ) {
18✔
4845
                                GETIDENTITY
12✔
4846
                                UBYTE *tt;
18✔
4847
                                WORD numdol, numexp;
18✔
4848
                                *t++ = c;
18✔
4849
                                while ( *t == ' ' || *t == '\t' || *t == '\n' || *t == '\r' ) t++;
18✔
4850
                                if ( *t == '$' ) {
18✔
4851
                                        t++; tt = t; while (chartype[*tt] <= 1 ) tt++;
×
4852
                                        c = *tt; *tt = 0;
×
4853
                                        if ( ( numdol = GetDollar(t) ) < 0 ) {
×
4854
                                                MesPrint("@$ variable in isnumerical(%s) does not exist",t);
×
4855
                                                Terminate(-1);
×
4856
                                        }
4857
                                        x = DolToLong(BHEAD numdol);
×
4858
                                        if ( AN.ErrorInDollar ) {
×
4859
                                                DOLLARS d = Dollars + numdol;
×
4860
                                                x = 0;
×
4861
                                                if ( d->type == DOLNUMBER || d->type == DOLTERMS ) {
×
4862
                                                        if ( d->where[0] == 0 ) x = 1;
×
4863
                                                        else if ( d->where[d->where[0]] == 0 ) {
×
4864
                                                                if ( ABS(d->where[d->where[0]-1]) == d->where[0]-1 )
×
4865
                                                                        x = 1;
×
4866
                                                        }
4867
                                                }
4868
                                        }
4869
                                        else x = 1;
4870
                                        *tt = c;
×
4871
                                }
4872
                                else {
4873
                                        tt = SkipAName(t);
18✔
4874
                                        c = *tt; *tt = 0;
18✔
4875
                                        if ( GetName(AC.exprnames,t,&numexp,NOAUTO) == NAMENOTFOUND ) {
18✔
4876
                                                MesPrint("@expression in isnumerical(%s) does not exist",t);
×
4877
                                                Terminate(-1);
×
4878
                                        }
4879
                                        x = TermsInExpression(numexp);
18✔
4880
                                        if ( x != 1 ) x = 0;
18✔
4881
                                        else {
4882
                                                WORD *term = AT.WorkPointer;
18✔
4883
                                                if ( GetFirstTerm(term,numexp,1) < 0 ) {
18✔
4884
                                                        MesPrint("@error reading expression in isnumerical(%s)",t);
×
4885
                                                        Terminate(-1);
×
4886
                                                }
4887
                                                if ( *term == ABS(term[*term-1])+1 ) x = 1;
15✔
4888
                                                else                                 x = 0;
×
4889
                                        }
4890
                                        *tt = c;
15✔
4891
                                } 
4892
                                while ( *tt == ' ' || *tt == '\t'
15✔
4893
                                                 || *tt == '\n' || *tt == '\r' ) tt++;
15✔
4894
                                if ( *tt != ')' ) {
15✔
4895
                                        MesPrint("@Improper use of isnumerical($var) or numerical(expr)");
×
4896
                                        Terminate(-1);
×
4897
                                }
4898
                                *type = 3;
15✔
4899
                                s = tt+1;
15✔
4900
                                *val2 = x;
15✔
4901
                                return(s);
15✔
4902
                        }
4903
                        else if ( StrICmp(s,(UBYTE *)("maxpowerof")) == 0 ) {
×
4904
                                UBYTE *tt;
×
4905
                                WORD numsym;
×
4906
                                int stype;
×
4907
                                *t++ = c;
×
4908
                                while ( *t == ' ' || *t == '\t' || *t == '\n' || *t == '\r' ) t++;
×
4909
                                tt = SkipAName(t);
×
4910
                                c = *tt; *tt = 0;
×
4911
                                if ( ( stype = GetName(AC.varnames,t,&numsym,NOAUTO) ) == NAMENOTFOUND ) {
×
4912
                                        MesPrint("@%s has not (yet) been defined",t);
×
4913
                                        *tt = c;
×
4914
                                        Terminate(-1);
×
4915
                                }
4916
                                else if ( stype != CSYMBOL ) {
×
4917
                                        MesPrint("@%s should be a symbol",t);
×
4918
                                        *tt = c;
×
4919
                                        Terminate(-1);
×
4920
                                }
4921
                                else {
4922
                                        *tt = c;
×
4923
                                        x = symbols[numsym].maxpower;
×
4924
                                }
4925
                                while ( *tt == ' ' || *tt == '\t'
×
4926
                                                 || *tt == '\n' || *tt == '\r' ) tt++;
×
4927
                                if ( *tt != ')' ) {
×
4928
                                        MesPrint("@Improper use of maxpowerof(symbol)");
×
4929
                                        Terminate(-1);
×
4930
                                }
4931
                                *type = 3;
×
4932
                                s = tt+1;
×
4933
                                *val2 = x;
×
4934
                                return(s);
×
4935
                        }
4936
                        else if ( StrICmp(s,(UBYTE *)("minpowerof")) == 0 ) {
×
4937
                                UBYTE *tt;
×
4938
                                WORD numsym;
×
4939
                                int stype;
×
4940
                                *t++ = c;
×
4941
                                while ( *t == ' ' || *t == '\t' || *t == '\n' || *t == '\r' ) t++;
×
4942
                                tt = SkipAName(t);
×
4943
                                c = *tt; *tt = 0;
×
4944
                                if ( ( stype = GetName(AC.varnames,t,&numsym,NOAUTO) ) == NAMENOTFOUND ) {
×
4945
                                        MesPrint("@%s has not (yet) been defined",t);
×
4946
                                        *tt = c;
×
4947
                                        Terminate(-1);
×
4948
                                }
4949
                                else if ( stype != CSYMBOL ) {
×
4950
                                        MesPrint("@%s should be a symbol",t);
×
4951
                                        *tt = c;
×
4952
                                        Terminate(-1);
×
4953
                                }
4954
                                else {
4955
                                        *tt = c;
×
4956
                                        x = symbols[numsym].minpower;
×
4957
                                }
4958
                                while ( *tt == ' ' || *tt == '\t'
×
4959
                                                 || *tt == '\n' || *tt == '\r' ) tt++;
×
4960
                                if ( *tt != ')' ) {
×
4961
                                        MesPrint("@Improper use of minpowerof(symbol)");
×
4962
                                        Terminate(-1);
×
4963
                                }
4964
                                *type = 3;
×
4965
                                s = tt+1;
×
4966
                                *val2 = x;
×
4967
                                return(s);
×
4968
                        }
4969
                        else if ( StrICmp(s,(UBYTE *)"isfactorized") == 0 ) {
×
4970
                                UBYTE *tt;
×
4971
                                WORD numdol, numexp;
×
4972
                                *t++ = c;
×
4973
                                while ( *t == ' ' || *t == '\t' || *t == '\n' || *t == '\r' ) t++;
×
4974
                                if ( *t == '$' ) {
×
4975
                                        t++; tt = t; while (chartype[*tt] <= 1 ) tt++;
×
4976
                                        c = *tt; *tt = 0;
×
4977
                                        if ( ( numdol = GetDollar(t) ) > 0 ) {
×
4978
                                                if ( Dollars[numdol].factors != 0 ) x = 1;
×
4979
                                                else x = 0;
×
4980
                                        }
4981
                                        else {
4982
                                                MesPrint("@ %s should be the name of an expression or a $ variable",t-1);
×
4983
                                                Terminate(-1);
×
4984
                                        }
4985
                                        *tt = c;
×
4986
                                }
4987
                                else {
4988
                                        tt = SkipAName(t);
×
4989
                                        c = *tt; *tt = 0;
×
4990
                                        if ( GetName(AC.exprnames,t,&numexp,NOAUTO) == NAMENOTFOUND ) {
×
4991
                                                MesPrint("@ %s should be the name of an expression or a $ variable",t);
×
4992
                                                Terminate(-1);
×
4993
                                        }
4994
                                        else {
4995
                                                if ( ( Expressions[numexp].vflags & ISFACTORIZED ) != 0 ) x = 1;
×
4996
                                                else x = 0;
×
4997
                                        }
4998
                                        *tt = c;
×
4999
                                } 
5000
                                while ( *tt == ' ' || *tt == '\t'
×
5001
                                                 || *tt == '\n' || *tt == '\r' ) tt++;
×
5002
                                if ( *tt != ')' ) {
×
5003
                                        MesPrint("@Improper use of isfactorized($var) or isfactorized(expr)");
×
5004
                                        Terminate(-1);
×
5005
                                }
5006
                                *type = 3;
×
5007
                                s = tt+1;
×
5008
                                *val2 = x;
×
5009
                                return(s);
×
5010
                        }
5011
                        else if ( StrICmp(s,(UBYTE *)"isdefined") == 0 ) {
×
5012
                                UBYTE *tt;
×
5013
                                *t++ = c;
×
5014
                                while ( *t == ' ' || *t == '\t' || *t == '\n' || *t == '\r' ) t++;
×
5015
                                tt = SkipAName(t);
×
5016
                                c = *tt; *tt = 0;
×
5017
                                if ( GetPreVar(t,WITHOUTERROR) != 0 ) x = 1;
×
5018
                                else x = 0;
×
5019
                                *tt = c;
×
5020
                                while ( *tt == ' ' || *tt == '\t'
×
5021
                                                 || *tt == '\n' || *tt == '\r' ) tt++;
×
5022
                                if ( *tt != ')' ) {
×
5023
                                        MesPrint("@Improper use of isdefined(var)");
×
5024
                                        Terminate(-1);
×
5025
                                }
5026
                                *type = 3;
×
5027
                                s = tt+1;
×
5028
                                *val2 = x;
×
5029
                                return(s);
×
5030
                        }
5031
                        else if ( StrICmp(s,(UBYTE *)"flag") == 0 ) {
×
5032
                                UBYTE *tt;
×
5033
                                WORD x = 0, numexp;
×
5034
                                {
5035
                                *t++ = c;
×
5036
                                while ( *t == ' ' || *t == '\t' ) t++;
×
5037
                                if ( FG.cTable[*t] != 1 ) goto flagerror;
×
5038
                                while ( FG.cTable[*t] == 1 ) x = 10*x + (*t++ - '0');
×
5039
                                if ( x < 1 || x > BITSINWORD ) {
×
5040
                                        MesPrint("@Illegal number %d for flag in flag condition",x);
×
5041
                                        goto flagerror;
×
5042
                                }
5043
                                while ( *t == ' ' || *t == '\t' ) t++;
×
5044
                                if ( *t != ',' ) goto flagerror;
×
5045
                                t++;
×
5046
                                while ( *t == ' ' || *t == '\t' ) t++;
×
5047
                                tt = SkipAName(t);
×
5048
                                c = *tt; *tt = 0;
×
5049
                                if ( GetName(AC.exprnames,t,&numexp,NOAUTO) == NAMENOTFOUND ) {
×
5050
                                        MesPrint("@ %s should be the name of an expression",t);
×
5051
                                        goto flagerror;
×
5052
                                }
5053
                                *tt = c;
×
5054
                                while ( *t == ' ' || *t == '\t' ) t++;
×
5055
                                if ( *tt != ')' ) {
×
5056
flagerror:
×
5057
                                        MesPrint("@Improper use of flag(num,expr)");
×
5058
                                        Terminate(-1);
×
5059
                                        return(0);
×
5060
                                }
5061
                                if ( ( Expressions[numexp].uflags & ( 1 << (x-1) ) ) != 0 )
×
5062
                                        *val2 = 1;
×
5063
                                else *val2 = 0;
×
5064
                                *type = 3;
×
5065
                                s = tt+1;
×
5066
                                return(s);
×
5067
                                }
5068
                        }
5069
                        else *t = c;
×
5070
                }
5071
                else if ( *t == '=' || *t == '<' || *t == '>' || *t == '!'
5072
                || *t == ')' || *t == ' ' || *t == '\t' || *t == 0 || *t == '\n' ) {
5073
                        *val2 = 0;
×
5074
                        *type = 2;
×
5075
                        return(t);
×
5076
                }
5077
                else {
5078
                        MesPrint("@Illegal use of string in preprocessor condition: %s",s);
×
5079
                        Terminate(-1);
×
5080
                }
5081
        }
5082
        while ( *t == '-' || *t == '+' || *t == ' ' || *t == '\t' ) {
156✔
5083
                if ( *t == '-' ) sign = -sign;
×
5084
                t++;
×
5085
        }
5086
        while ( chartype[*t] == 1 ) { x = 10*x + *t++ - '0'; }
312✔
5087
        while ( *t == ' ' || *t == '\t' ) t++;
171✔
5088
        if ( chartype[*t] == 8 || *t == ')' || *t == '=' || *t == 0 ) {
156✔
5089
                *val2 = sign > 0 ? x: -x;
156✔
5090
                *type = 1;
156✔
5091
                return(t);
156✔
5092
        }
5093
        while ( chartype[*t] != 8 && *t != ')' && *t != '=' && *t ) t++;
×
5094
        while ( ( t > s ) && ( t[-1] == ' ' || t[-1] == '\t' ) ) t--;
×
5095
        *type = 2;
×
5096
        *val2 = val;
×
5097
        return(t);
×
5098
}
5099

5100
/*
5101
                 #] pParseObject : 
5102
                 #[ PreCalc :
5103
 
5104
                To be called when a { is encountered.
5105
                Action: read first till matching }. This is to be stored.
5106
                Next we look whether this is a set or whether it can be
5107
                evaluated. If it is a set we consider it as a new stream.
5108
                The stream will have to be deallocated when read completely.
5109
                If it is to be evaluated we do that and put the result in
5110
                a stream.
5111
*/
5112

5113
UBYTE *PreCalc(VOID)
4,092✔
5114
{
5115
        UBYTE *buff, *s = 0, *t, *newb, c;
4,092✔
5116
        int size, i, n, parlevel = 0, bralevel = 0;
4,092✔
5117
        LONG answer;
4,092✔
5118
        ULONG uanswer;
4,092✔
5119
        size = n = 0;
4,092✔
5120
        buff = 0; c = '{';
4,092✔
5121
        for (;;) {
25,062✔
5122
                if ( n >= size ) {
25,062✔
5123
                        if ( size == 0 ) size = 72;
4,092✔
5124
                        else size *= 2;
×
5125
                        if ( ( newb = (UBYTE *)Malloc1(size+2,"{}") ) == 0 ) return(0);
4,092✔
5126
                        s = newb;
4,092✔
5127
                        if ( buff ) {
4,092✔
5128
                                i = n;
5129
                                t = buff;
5130
                                NCOPYB(s,t,i);
×
5131
                                M_free(buff,"pre calc buffer");
×
5132
                        }
5133
                        else s = newb;
5134
                        buff = newb;
5135
                }
5136
                *s++ = c; n++;
25,062✔
5137
                c = GetChar(0);
25,062✔
5138
                if ( c == 0 ) {
25,062✔
5139
                        Error0("Unmatched {}");
×
5140
                        M_free(buff,"precalc buffer");
×
5141
                        return(0);
×
5142
                }
5143
                else if ( c == '{' ) { bralevel++; }
25,062✔
5144
                else if ( c == '}' ) {
25,062✔
5145
                        if ( --bralevel < 0 ) { *s++ = c; *s = 0; break; }
3,060✔
5146
                }
5147
                else if ( c == '(' ) { parlevel++; }
22,002✔
5148
                else if ( c == ')' ) {
21,978✔
5149
                        if ( --parlevel < 0 ) { *s++ = c; *s = 0; goto setstring; }
24✔
5150
                }
5151
                else if ( chartype[c] != 1 && chartype[c] != 5
21,954✔
5152
                && chartype[c] != 6 && c != '!' && c != '&'
1,038✔
5153
                && c != '|' && c != '\\' ) { *s++ = c; *s = 0; goto setstring; }
1,035✔
5154
        }
5155
        if ( parlevel > 0 ) goto setstring;
3,060✔
5156
/*
5157
        Try now to evaluate the string.
5158
        If it works, copy the resulting value back into buff as a string.
5159
*/
5160
        answer = 0;
3,060✔
5161
        if ( PreEval(buff+1,&answer) == 0 ) goto setstring;
3,060✔
5162
        t = buff + size;
3,051✔
5163
        s = buff;
3,051✔
5164
        if ( answer < 0 ) { *s++ = '-'; }
3,051✔
5165
        uanswer = LongAbs(answer);
3,051✔
5166
        n = 0;
5167
        do {
9,294✔
5168
                *--t = ( uanswer % 10 ) + '0';
9,294✔
5169
                uanswer /= 10;
9,294✔
5170
                n++;
9,294✔
5171
        } while ( uanswer > 0 );
9,294✔
5172
        NCOPYB(s,t,n);
12,345✔
5173
        *s = 0;
3,051✔
5174
setstring:;
4,092✔
5175
/*
5176
        Open a stream that contains the current string.
5177
        Mark it to be removed after termination.
5178
*/
5179
        if ( OpenStream(buff,PRECALCSTREAM,0,PRENOACTION) == 0 ) return(0);
4,092✔
5180
        return(buff);
5181
}
5182

5183
/*
5184
                 #] PreCalc : 
5185
                 #[ PreEval :
5186

5187
                Operations are:
5188
                +, -, *, /, %, &, |, ^, !,  ^% (postfix 2log), ^/ (postfix sqrt)
5189
*/
5190

5191
UBYTE *PreEval(UBYTE *s, LONG *x)
3,426✔
5192
{
5193
        LONG y, z, a;
3,426✔
5194
        int tobemultiplied, tobeadded = 1, expsign, i;
3,426✔
5195
        UBYTE *t;
3,426✔
5196
        *x = 0; a = 1;
3,426✔
5197
        while ( *s == ' ' || *s == '\t' ) s++;
3,426✔
5198
        for(;;){
6,444✔
5199
                if ( *s == '+' || *s == '-' ) {
6,444✔
5200
                        if ( *s == '-' ) tobeadded = -1;
3,033✔
5201
                        else tobeadded = 1;
3,006✔
5202
                        s++;
3,033✔
5203
                        while ( *s == '-' || *s == '+' || *s == ' ' || *s == '\t' ) {
3,033✔
5204
                                if ( *s == '-' ) tobeadded = -tobeadded;
×
5205
                                s++;
×
5206
                        }
5207
                }
5208
                tobemultiplied = 0;
6,444✔
5209
                for(;;){
36✔
5210
                        while ( *s == ' ' || *s == '\t' ) s++;
6,480✔
5211
                        if ( *s <= '9' && *s >= '0' ) {
6,480✔
5212
                                ULONG uy;
5213
                                ParseNumber(uy,s)
24,570✔
5214
                                y = uy;  /* may cause an implementation-defined behaviour */
6,465✔
5215
                        }
5216
                        else if ( *s == '(' || *s == '{' ) {
15✔
5217
                                if ( ( t = PreEval(s+1,&y) ) == 0 ) return(0);
6✔
5218
                                s = t;
5219
                        }
5220
                        else return(0);
5221
                        while ( *s == ' ' || *s == '\t' ) s++;
6,471✔
5222
                        expsign = 1;
5223
                        while ( *s == '^' || *s == '!' ) {
6,495✔
5224
                                s++;
24✔
5225
                                if ( s[-1] == '!' ) {   /* factorial of course */
24✔
5226
                                        while ( *s == ' ' || *s == '\t' ) s++;
×
5227
                                        if ( y < 0 ) {
×
5228
                                                MesPrint("@Negative value in preprocessor factorial: %l",y);
×
5229
                                                return(0);
×
5230
                                        }
5231
                                        else if ( y == 0 ) y = 1;
×
5232
                                        else if ( y > 1 ) {
×
5233
                                                z = y-1;
×
5234
                                                while ( z > 0 ) { y = y*z; z--; }
×
5235
                                        }
5236
                                        continue;
×
5237
                                }
5238
                                else if ( *s == '%' ) {        /* ^% is postfix 2log */
24✔
5239
                                        s++;
×
5240
                                        while ( *s == ' ' || *s == '\t' ) s++;
×
5241
                                        z = y;
×
5242
                                        if ( z <= 0 ) {
×
5243
                                                MesPrint("@Illegal value in preprocessor logarithm: %l",z);
×
5244
                                                return(0);
×
5245
                                        }
5246
                                        y = 0; z >>= 1;
×
5247
                                        while ( z ) { y++; z >>= 1; }
×
5248
                                        continue;
×
5249
                                }
5250
                                else if ( *s == '/' ) { /* ^/ is postfix sqrt */
24✔
5251
                                        LONG yy, zz;
×
5252
                                        s++;
×
5253
                                        while ( *s == ' ' || *s == '\t' ) s++;
×
5254
                                        z = y;
×
5255
                                        if ( z <= 0 ) {
×
5256
                                                MesPrint("@Illegal value in preprocessor square root: %l",z);
×
5257
                                                return(0);
×
5258
                                        }
5259
                                        if ( z > 8 ) {                /* Very crude integer square root */
×
5260
                                                zz = z;
×
5261
                                                yy = 0; zz >>= 1;
×
5262
                                                while ( zz ) { yy++; zz >>= 1; }
×
5263
                                                zz = z >> (yy/2); i = 10; y = 0;
×
5264
                                                do { 
×
5265
                                                        yy = zz/2 + z/(2*zz); i--;
×
5266
                                                        if ( y == yy ) break;
×
5267
                                                        y = zz; zz = yy;
×
5268
                                                } while ( y != yy && i > 0 );
×
5269
                                                while ( y*y < z ) y++;
×
5270
                                                while ( y*y > z ) y--;
×
5271
                                        }
5272
                                        else if ( z >= 4 ) y = 2;
×
5273
                                        else if ( z == 0 ) y = 0;
×
5274
                                        else y = 1;
×
5275
                                        continue;
×
5276
                                }
5277
                                while ( *s == ' ' || *s == '\t' ) s++;
24✔
5278
                                while ( *s == '-' || *s == '+' || *s == ' ' || *s == '\t' ) {
24✔
5279
                                        if ( *s == '-' ) expsign = -expsign;
×
5280
                                }
5281
                                if ( *s <= '9' && *s >= '0' ) {
5282
                                        ParseNumber(z,s)
15✔
5283
                                }
5284
                                else if ( *s == '(' || *s == '{' ) {
5285
                                        if ( ( t = PreEval(s+1,&z) ) == 0 ) return(0);
18✔
5286
                                        s = t;
5287
                                }
5288
                                else return(0);
5289
                                while ( *s == ' ' || *s == '\t' ) s++;
24✔
5290
                                y = iexp(y,(int)z);
24✔
5291
                        }
5292
                        if ( tobemultiplied == 0 ) {
6,471✔
5293
                                if ( expsign < 0 ) a = 1/y;
6,435✔
5294
                                else a = y;
6,435✔
5295
                        }
5296
                        else {
5297
                                if ( tobemultiplied > 2 && expsign != 1 ) {
36✔
5298
                                        MesPrint("&Incorrect use of ^ with & or |. Use brackets!");
×
5299
                                        Terminate(-1);
×
5300
                                }
5301
                                tobemultiplied *= expsign;
36✔
5302
                                if ( tobemultiplied == 1 ) a *= y;
36✔
5303
                                else if ( tobemultiplied == 3 ) a &= y;
3✔
5304
                                else if ( tobemultiplied == 4 ) a |= y;
3✔
5305
                                else {
5306
                                        if ( y == 0 || tobemultiplied == -2 ) {
3✔
5307
                                                MesPrint("@Division by zero in preprocessor calculator");
×
5308
                                                Terminate(-1);
×
5309
                                        }
5310
                                        if ( tobemultiplied == 2 ) a %= y;
3✔
5311
                                        else a /= y;
3✔
5312
                                }
5313
                        }
5314
                        if ( *s == '%' ) tobemultiplied = 2;
6,471✔
5315
                        else if ( *s == '*' ) tobemultiplied = 1;
5316
                        else if ( *s == '/' ) tobemultiplied = -1;
5317
                        else if ( *s == '&' ) tobemultiplied = 3;
5318
                        else if ( *s == '|' ) tobemultiplied = 4;
5319
                        else {
5320
                                ULONG ux, ua;
6,435✔
5321
                                ux = *x;
6,435✔
5322
                                ua = a;
6,435✔
5323
                                if ( tobeadded >= 0 ) ux += ua;
6,435✔
5324
                                else ux -= ua;
27✔
5325
                                *x = ULongToLong(ux);
6,435✔
5326
                                if ( *s == ')' || *s == '}' ) return(s+1);
6,435✔
5327
                                else if ( *s == '-' || *s == '+' ) { tobeadded = 1; break; }
3,018✔
5328
                                else return(0);
5329
                        }
5330
                        s++;
36✔
5331
                }
5332
        }
5333
/*        return(0); */
5334
}
5335

5336
/*
5337
                 #] PreEval : 
5338
                 #[ AddToPreTypes :
5339
*/
5340

5341
void AddToPreTypes(int type)
573✔
5342
{
5343
        if ( AP.NumPreTypes >= AP.MaxPreTypes ) {
573✔
5344
                int i, *newlist = (int *)Malloc1(sizeof(int)*(2*AP.MaxPreTypes+1)
×
5345
                                                ,"preprocessor type lists");
5346
                for ( i = 0; i <= AP.MaxPreTypes; i++ ) newlist[i] = AP.PreTypes[i];
×
5347
                M_free(AP.PreTypes,"preprocessor type lists");
×
5348
                AP.PreTypes = newlist;
×
5349
                AP.MaxPreTypes = 2*AP.MaxPreTypes;
×
5350
        }
5351
        AP.PreTypes[++AP.NumPreTypes] = type;
573✔
5352
}
573✔
5353

5354
/*
5355
                 #] AddToPreTypes : 
5356
                 #[ MessPreNesting :
5357
*/
5358

5359
void MessPreNesting(int par)
×
5360
{
5361
        MesPrint("@(%d)Illegal nesting of %#if, %#do, %#procedure and/or %#switch",par);
×
5362
}
×
5363

5364
/*
5365
                 #] MessPreNesting : 
5366
                 #[ DoPreAddSeparator :
5367

5368
                Preprocessor directives "addseparator" and "rmseparator" add/remove 
5369
                separator characters used to separate function arguments. 
5370
                Example:
5371

5372
                        #define QQ "a|g|a"
5373
                        #addseparator %
5374
                        *Comma must be quoted!:
5375
                        #rmseparator ","
5376
                        #rmseparator |
5377
                        #call H(a,a%`QQ')
5378

5379
                Characters ' ', '\t' and '"' are ignored!
5380
*/
5381

5382
int DoPreAddSeparator(UBYTE *s)
×
5383
{
5384
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
5385
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
5386
        for(;*s != '\0';s++){
×
5387
                while ( *s == ' ' || *s == '\t' || *s == '"') s++;
×
5388
                /* Todo: 
5389
                if ( set_in(*s,invalidseparators) ) {
5390
                        MesPrint("@Invalid separator specified");
5391
                        return(-1);
5392
                }
5393
                */
5394
                set_set(*s,AC.separators);
×
5395
        }
5396
        return(0);
5397
}
5398

5399
/*
5400
                 #] DoPreAddSeparator : 
5401
                 #[ DoPreRmSeparator :
5402

5403
                See commentary with DoPreAddSeparator
5404

5405
                Characters ' ', '\t' and '"' are ignored!
5406
*/
5407
int DoPreRmSeparator(UBYTE *s)
×
5408
{
5409
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
5410
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
5411
        for(;*s != '\0';s++){
×
5412
                while ( *s == ' ' || *s == '\t' || *s == '"') s++;
×
5413
                set_del(*s,AC.separators);
×
5414
        }
5415
        return(0);
5416
}
5417

5418
/*
5419
                 #] DoPreRmSeparator : 
5420
                 #[ DoExternal:
5421

5422
                #external ["prevar"] command
5423
*/
5424
int DoExternal(UBYTE *s)
×
5425
{ 
5426
#ifdef WITHEXTERNALCHANNEL
5427
        UBYTE *prevar=0;
×
5428
        int externalD= 0;
×
5429
#else
5430
        DUMMYUSE(s);
5431
#endif
5432
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
5433
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
5434
        if ( AP.preError ) return(0);
×
5435

5436
#ifdef WITHEXTERNALCHANNEL
5437
        while ( *s == ' ' || *s == '\t' ) s++;
×
5438
        if(*s == '"'){/*prevar to store the descriptor is defined*/
×
5439
                prevar=++s;
×
5440

5441
                if ( chartype[*s] == 0 )for(;*s != '"'; s++)switch(chartype[*s]){
×
5442
                        case 10:/*'\0' fits here*/
×
5443
                                MesPrint("@Can't finde closing \"");
×
5444
                                Terminate(-1);
×
5445
                        case 0:case 1: continue;
×
5446
                        default:
5447
                                break;
5448
                }
5449
                if(*s != '"'){
×
5450
                                MesPrint("@Illegal name of preprocessor variable to store external channel");
×
5451
                                return(-1);
×
5452
      }
5453
      *s='\0';
×
5454
                for(s++; *s == ' ' || *s == '\t'; s++);
×
5455
        }
5456

5457
        if(*s == '\0'){
×
5458
                MesPrint("@Illegal external command");
×
5459
                return(-1);
×
5460
        }
5461
        /*here s is a command*/
5462
   /*See the file extcmd.c*/
5463
        /*[08may2006 mt]:*/
5464
        externalD=openExternalChannel(
×
5465
                                s,
5466
                                 AX.daemonize,
5467
                                AX.shellname,
5468
                                AX.stderrname);
5469
        /*:[08may2006 mt]*/
5470
        if(externalD<1){/*error?*/
×
5471
                /*Not quite correct - terminate the program on error:*/
5472
                Error1("Can't start external program",s);
×
5473
                return(-1);
×
5474
        }
5475
   /*Now external command runs.*/
5476
   
5477
   if(prevar){/*Store the external channel descriptor in the provided variable:*/
×
5478
                UBYTE buf[21];/* 64/Log_2[10] = 19.3, so this is enough forever...*/
×
5479
                NumToStr(buf,externalD);
×
5480
                if ( PutPreVar(prevar,buf,0,1) < 0 ) return(-1);
×
5481
        }
5482

5483
        AX.currentExternalChannel=externalD;
×
5484
        /*[08may2006 mt]:*/
5485
        if(AX.currentPrompt!=0){/*Change default terminator*/
×
5486
                if(setTerminatorForExternalChannel(  (char *)AX.currentPrompt)){
×
5487
                        MesPrint("@Prompt is too long");
×
5488
                        return(-1);
×
5489
                }
5490
        }
5491
        setKillModeForExternalChannel(AX.killSignal,AX.killWholeGroup);
×
5492
        /*:[08may2006 mt]*/
5493
        return(0);
×
5494
#else /*ifdef WITHEXTERNALCHANNEL*/
5495
        Error0("External channel: not implemented on this computer/system");
5496
        return(-1);
5497
#endif /*ifdef WITHEXTERNALCHANNEL ... else*/
5498
}
5499

5500
/*
5501
                 #] DoExternal: 
5502
                 #[ DoPrompt:
5503
                        #prompt string
5504
*/
5505

5506
int DoPrompt(UBYTE *s)
×
5507
{
5508
#ifndef WITHEXTERNALCHANNEL
5509
        DUMMYUSE(s);
5510
#endif
5511
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
5512
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
5513

5514
#ifdef WITHEXTERNALCHANNEL
5515
        while ( *s == ' ' || *s == '\t' ) s++;
×
5516
        if ( AX.currentPrompt )
×
5517
                        M_free(AX.currentPrompt,"external channel prompt");
×
5518
        if ( *s == '\0' )
×
5519
                AX.currentPrompt = (UBYTE *)strDup1((UBYTE *)"","external channel prompt");
×
5520
        else
5521
                AX.currentPrompt = strDup1(s,"external channel prompt");
×
5522
        if(  setTerminatorForExternalChannel( (char *)AX.currentPrompt) > 0  ){
×
5523
                MesPrint("@Prompt is too long");
×
5524
                return(-1);
×
5525
        }
5526
        /*else: if 0, ok; if -1, there is no current channel-ok, just prompt is stored.*/
5527
        return(0);
5528
#else /*ifdef WITHEXTERNALCHANNEL*/
5529
        Error0("External channel: not implemented on this computer/system");
5530
        return(-1);
5531
#endif /*ifdef WITHEXTERNALCHANNEL ... else*/
5532
}
5533
/*
5534
                 #] DoPrompt: 
5535
                 #[ DoSetExternal:
5536
                        #setexternal n
5537
*/
5538

5539
int DoSetExternal(UBYTE *s)
×
5540
{
5541
#ifdef WITHEXTERNALCHANNEL
5542
        int n=0;
×
5543
#else
5544
        DUMMYUSE(s);
5545
#endif
5546
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
5547
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
5548
        if ( AP.preError ) return(0);
×
5549

5550
#ifdef WITHEXTERNALCHANNEL
5551
        while ( *s == ' ' || *s == '\t' ) s++;
×
5552
        while ( chartype[*s] == 1 ) { n = 10*n + *s++ - '0'; }
×
5553
        while ( *s == ' ' || *s == '\t' ) s++;
×
5554
        if(*s!='\0'){
×
5555
                MesPrint("@setexternal: number expected");
×
5556
                return(-1);
×
5557
        }
5558
        if(selectExternalChannel(n)<0){
×
5559
                MesPrint("@setexternal: invalid number");
×
5560
                return(-1);
×
5561
        }
5562
        AX.currentExternalChannel=n;
×
5563
        return(0);
×
5564
#else /*ifdef WITHEXTERNALCHANNEL*/
5565
        Error0("External channel: not implemented on this computer/system");
5566
        return(-1);
5567
#endif /*ifdef WITHEXTERNALCHANNEL ... else*/
5568
}
5569
/*
5570
                 #] DoSetExternal: 
5571
                 #[ DoSetExternalAttr:
5572
*/
5573

5574
static FORM_INLINE UBYTE *pickupword(UBYTE *s)
×
5575
{
5576

5577
        for(;*s>' ';s++)switch(*s){
×
5578
                case '=':
5579
                case ',':
5580
                case ';':
5581
                        return(s);
5582
        }/*for(;*s>' ';s++)switch(*s)*/
5583
        return(s);
5584
}
5585
/*Returns 0 if the first string (case insensitively) equal to
5586
  the beginning of the second string (of length n):
5587
*/
5588
static inline int strINCmp(UBYTE *a, UBYTE *b, int n)
×
5589
{
5590
        for(;n>0;n--)if(tolower(*a++)!=tolower(*b++))
×
5591
                return(1);
5592
        return(*a != '\0');
×
5593
}
5594

5595
#define KILL "kill"
5596
#define KILLALL "killall"
5597
#define DAEMON "daemon"
5598
#define SHELL "shell"
5599
#define STDERR "stderr"
5600

5601
#define TRUE_EXPR "true"
5602
#define FALSE_EXPR "false"
5603
#define NOSHELL "noshell"
5604
#define TERMINAL "terminal"
5605

5606
/*
5607
        Expects comma-separated list of pairs name=value
5608
*/
5609
int DoSetExternalAttr(UBYTE *s)
×
5610
{
5611
#ifdef WITHEXTERNALCHANNEL
5612
        int lnam,lval;
×
5613
        UBYTE *nam,*val;
×
5614
#else
5615
        DUMMYUSE(s);
5616
#endif
5617
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
5618
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
5619
        if ( AP.preError ) return(0);
×
5620

5621
#ifdef WITHEXTERNALCHANNEL
5622
        do{
5623
                /*Read the name:*/
5624
                while ( *s == ' ' || *s == '\t' ) s++;
×
5625
                s=pickupword(nam=s);
×
5626
                lnam=s-nam;
×
5627
                while ( *s == ' ' || *s == '\t' ) s++;
×
5628
                if(*s++!='='){
×
5629
                        MesPrint("@External channel:'=' expected instead of %s",s-1);
×
5630
                        return(-1);
×
5631
                }
5632
                /*Read the value:*/
5633
                while ( *s == ' ' || *s == '\t' ) s++;
×
5634
                val=s;
×
5635

5636
                for(;;){
×
5637
                        UBYTE *m;
×
5638
                        s=pickupword(s);
×
5639
                        m=s;
×
5640
                        while ( *s == ' ' || *s == '\t' ) s++;
×
5641
         if( (*s == ',')||(*s == '\n')||(*s == ';')||(*s == '\0') ){
5642
                                s=m;
×
5643
                                break;
×
5644
                        }
5645
                }/*for(;;)*/
5646

5647
                lval=s-val;
×
5648
                while ( *s == ' ' || *s == '\t' ) s++;
×
5649

5650
                if(strINCmp((UBYTE *)SHELL,nam,lnam)==0){
×
5651
                        if(AX.shellname!=NULL)
×
5652
                                M_free(AX.shellname,"external channel shellname");
×
5653
                        if(strINCmp((UBYTE *)NOSHELL,val,lval)==0)
×
5654
                                AX.shellname=NULL;
×
5655
                        else{
5656
                                UBYTE *ch,*b;
×
5657
                                b=ch=AX.shellname=Malloc1(lval+1,"external channel shellname");
×
5658
                                while(ch-b<lval)
×
5659
                                        *ch++=*val++;
×
5660
                                *ch='\0';
×
5661
                        }
5662
                }else if(strINCmp((UBYTE *)DAEMON,nam,lnam)==0){
×
5663
                        if(strINCmp((UBYTE *)TRUE_EXPR,val,lval)==0)
×
5664
                                AX.daemonize = 1;
×
5665
                        else if(strINCmp((UBYTE *)FALSE_EXPR,val,lval)==0)
×
5666
                                AX.daemonize = 0;
×
5667
                        else{
5668
                                MesPrint("@External channel:true or false expected for %s",DAEMON);
×
5669
                                return(-1);
×
5670
                        }
5671
                }else        if(strINCmp((UBYTE *)KILLALL,nam,lnam)==0){
×
5672
                        if(strINCmp((UBYTE *)TRUE_EXPR,val,lval)==0)
×
5673
                                AX.killWholeGroup = 1;
×
5674
                        else if(strINCmp((UBYTE *)FALSE_EXPR,val,lval)==0)
×
5675
                                AX.killWholeGroup = 0;
×
5676
                        else{
5677
                                MesPrint("@External channel: true or false expected for %s",KILLALL);
×
5678
                                return(-1);
×
5679
                        }
5680
                }else        if(strINCmp((UBYTE *)KILL,nam,lnam)==0){
×
5681
                        int i,n=0;
5682
                        for(i=0;i<lval;i++) {
×
5683
                                if( *val>='0' && *val<= '9' )
×
5684
                                        n = 10*n + *val++  - '0';
×
5685
                                else{
5686
                                        MesPrint("@External channel: number expected for %s",KILL);
×
5687
                                        return(-1);
×
5688
                                }
5689
                        }
5690
                        AX.killSignal=n;
×
5691
                }else        if(strINCmp((UBYTE *)STDERR,nam,lnam)==0){
×
5692
                        if( AX.stderrname != NULL ) {
×
5693
                                M_free(AX.stderrname,"external channel stderrname");
×
5694
                        }
5695
                        if(strINCmp((UBYTE *)TERMINAL,val,lval)==0)
×
5696
                                AX.stderrname = NULL;
×
5697
                        else{
5698
                                UBYTE *ch,*b;
×
5699
                                b=ch=AX.stderrname=Malloc1(lval+1,"external channel stderrname");
×
5700
                                while(ch-b<lval)
×
5701
                                        *ch++=*val++;
×
5702
                                *ch='\0';
×
5703
                        }
5704
                }else{
5705
                        nam[lnam+1]='\0';
×
5706
                        MesPrint("@External channel: unrecognized attribute",nam);
×
5707
                        return(-1);
×
5708
                }
5709
        }while(*s++ == ',');
×
5710
        if(  (*(s-1)>' ')&&(*(s-1)!=';')  ){
×
5711
                MesPrint("@External channel: syntax error: %s",s-1);
×
5712
                return(-1);
×
5713
        }
5714
   return(0);
5715
#else /*ifdef WITHEXTERNALCHANNEL*/
5716
        Error0("External channel: not implemented on this computer/system");
5717
        return(-1);
5718
#endif /*ifdef WITHEXTERNALCHANNEL ... else*/
5719
}
5720
/*
5721
                 #] DoSetExternalAttr: 
5722
                 #[ DoRmExternal:
5723
                        #rmexternal [n] (if 0, close all)
5724
*/
5725

5726
int DoRmExternal(UBYTE *s)
×
5727
{
5728
#ifdef WITHEXTERNALCHANNEL
5729
        int n = -1;
×
5730
#else
5731
        DUMMYUSE(s);
5732
#endif
5733
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
5734
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
5735
        if ( AP.preError ) return(0);
×
5736

5737
#ifdef WITHEXTERNALCHANNEL
5738
        while ( *s == ' ' || *s == '\t' ) s++;
×
5739
        if( chartype[*s] == 1 ){
×
5740
                for(n=0; chartype[*s] == 1 ; s++) { n = 10*n + *s - '0'; }
×
5741
                while ( *s == ' ' || *s == '\t' ) s++;
×
5742
        }
5743
        if(*s!='\0'){
×
5744
                MesPrint("@rmexternal: invalid number");
×
5745
                return(-1);
×
5746
        }
5747
        switch(n){
×
5748
                case 0:/*Close all opened channels*/
×
5749
                        closeAllExternalChannels();
×
5750
                        AX.currentExternalChannel=0;
×
5751
                        /*Do not clean AX.currentPrompt!*/
5752
                        return(0);
×
5753
                case -1:/*number is not specified - try current*/
×
5754
                        n=AX.currentExternalChannel;
×
5755
                        /* fall through */
5756
                default:
×
5757
                        closeExternalChannel(n);/*No reaction for possible error*/
×
5758
        }
5759
        if (n == AX.currentExternalChannel)/*cleaned up by closeExternalChannel()*/
×
5760
                AX.currentExternalChannel=0;
×
5761
        return(0);
5762
#else /*ifdef WITHEXTERNALCHANNEL*/
5763
        Error0("External channel: not implemented on this computer/system");
5764
        return(-1);
5765
#endif /*ifdef WITHEXTERNALCHANNEL ... else*/
5766

5767
}
5768
/*
5769
                 #] DoRmExternal: 
5770
                 #[ DoFromExternal :
5771
                                #fromexternal 
5772
                                        is used to read the text from the running external
5773
                                        program, the syntax is similar to the #include
5774
                                        directive.
5775
                                #fromexternal "varname"
5776
                                        is used to read the text from the running external
5777
                                        program into the preprocessor variable varname.
5778
                                        directive.
5779
                                #fromexternal "varname" maxlength
5780
                                        is used to read the text from the running external
5781
                                        program into the preprocessor variable varname.
5782
                                        directive. Only first maxlength characters are 
5783
                                        stored.
5784

5785
                                        FORM continues to read the running external
5786
                                        program output until the external program outputs a
5787
                                        prompt.
5788

5789
*/
5790

5791
int DoFromExternal(UBYTE *s)
×
5792
{
5793
#ifdef WITHEXTERNALCHANNEL
5794
        UBYTE *prevar=0; 
×
5795
        int lbuf=-1;
×
5796
        int withNoList=AC.NoShowInput;
×
5797
        int oldpreassignflag;
×
5798
#else
5799
        DUMMYUSE(s);
5800
#endif
5801
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
5802
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
5803
        if ( AP.preError ) return(0);
×
5804
#ifdef WITHEXTERNALCHANNEL
5805
        
5806
        FLUSHCONSOLE;
×
5807

5808
        while ( *s == ' ' || *s == '\t' ) s++;
×
5809
        /*[17may2006 mt]:*/
5810
        if ( *s == '-' || *s == '+' ) {
×
5811
                if ( *s == '-' )
×
5812
                        withNoList = 1;
5813
                else
5814
                        withNoList = 0;
×
5815
                s++;
×
5816
                while ( *s == ' ' || *s == '\t' ) s++;
×
5817
        }/*if ( *s == '-' || *s == '+' )*/
5818
        /*:[17may2006 mt]*/
5819
        /*[02feb2006 mt]:*/
5820
        if(*s == '"'){/*prevar to store the output is defined*/
×
5821
                prevar=++s;
×
5822

5823
                if ( *s=='$' || chartype[*s] == 0 )for(;*s != '"'; s++)switch(chartype[*s]){
×
5824
                        case 10:/*'\0' fits here*/
×
5825
                                MesPrint("@Can't finde closing \"");
×
5826
                                Terminate(-1);
×
5827
                        case 0:case 1: continue;
×
5828
                        default:
5829
                                break;
5830
                }
5831
                if(*s != '"'){
×
5832
                                MesPrint("@Illegal name to store output of external channel");
×
5833
                                return(-1);
×
5834
      }
5835
      *s='\0';
×
5836
                for(s++; *s == ' ' || *s == '\t'; s++);
×
5837
        }/*if(*s == '"')*/
5838

5839
        if(*s != '\0'){
×
5840
                if( chartype[*s] == 1 ){
×
5841
                        for(lbuf=0; chartype[*s] == 1 ; s++) { lbuf = 10*lbuf + *s - '0'; }
×
5842
                        while ( *s == ' ' || *s == '\t' ) s++;
×
5843
                }
5844
                if( (*s!='\0')||(lbuf<0) ){
×
5845
                        MesPrint("@Illegal buffer length in fromexternal");
×
5846
                        return(-1);
×
5847
                }
5848
        }/*if(*s != '\0')*/
5849
        /*:[02feb20006 mt]*/
5850
        if(getCurrentExternalChannel()!=AX.currentExternalChannel)
×
5851
                /*[08may20006 mt]:*/
5852
                /*selectExternalChannel(AX.currentExternalChannel);*/
5853
                if(selectExternalChannel(AX.currentExternalChannel)){
×
5854
                        MesPrint("@No current external channel");
×
5855
                        return(-1);
×
5856
                }
5857
                /*:[08may20006 mt]*/
5858

5859
        /*[02feb2006 mt]:*/
5860
        if(prevar!=0){/*The result must be stored into preprovar*/
×
5861
      UBYTE *buf;
×
5862
                int cc = 0;
×
5863
                if(lbuf == -1){/*Unlimited buffer, everything must be stored*/
×
5864
                        int i;
×
5865
                        buf=Malloc1( (lbuf=255)+1,"Fromexternal");
×
5866
                        /*[18may20006 mt]:*/
5867
                        /*for(i=0;(cc=getcFromExtChannel())!=EOF;i++){*/
5868
                        /* May 2006: now getcFromExtChannelOk returns EOF while 
5869
                                getcFromExtChannelFailure returns -2 (see comments in 
5870
                                exctcmd.c):*/
5871
                        for(i=0;(cc=getcFromExtChannel())>0;i++){
×
5872
                        /*:[18may20006 mt]*/
5873
                                if(i==lbuf){
×
5874
                                        int j;
×
5875
                                        UBYTE *tmp=Malloc1( (lbuf*=2)+1,"Fromexternal");
×
5876
                                        for(j=0;j<i;j++)tmp[j]=buf[j];
×
5877
                                        M_free(buf,"Fromexternal");
×
5878
                                        buf=tmp;
×
5879
                                }
5880
                                buf[i]=(UBYTE)(cc);
×
5881
                        }/*for(i=0;(cc=getcFromExtChannel())>0;i++)*/
5882
                        /*[18may20006 mt]:*/
5883
         if(cc == -2){
×
5884
                                MesPrint("@No current external channel");
×
5885
                                return(-1);
×
5886
                        }
5887
                        lbuf=i;
×
5888
                        /*:[18may20006 mt]*/
5889
                        buf[i]='\0';
×
5890
                }else{/*Fixed buffer, only lbuf chars must be stored*/
5891
                        int i;
×
5892
                        buf=Malloc1(lbuf+1,"Fromexternal");
×
5893
                        for(i=0; i<lbuf;i++){
×
5894
                        /*[18may20006 mt]:*/
5895
                                /*if( (cc=getcFromExtChannel())==EOF )*/
5896
                                /* May 2006: now getcFromExtChannelOk returns EOF while 
5897
                                        getcFromExtChannelFailure returns -2 (see comments in 
5898
                                        exctcmd.c):*/
5899
                                if( (cc=getcFromExtChannel())<1 )
×
5900
                        /*:[18may20006 mt]*/
5901
                                        break;
5902
                                buf[i]=(UBYTE)(cc);
×
5903
                        }
5904
                        buf[i]='\0';
×
5905
                        /*[18may20006 mt]:*/
5906
                        /*if(cc!=EOF)
5907
                                while(getcFromExtChannel()!=EOF);*//*Eat the rest*/
5908
                        /* May 2006: now getcFromExtChannelOk returns EOF while 
5909
                                getcFromExtChannelFailure returns -2 (see comments in 
5910
                                exctcmd.c):*/
5911
                        if(cc>0)
×
5912
                                while(getcFromExtChannel()>0);/*Eat the rest*/
×
5913
                        else if(cc == -2){
×
5914
                                MesPrint("@No current external channel");
×
5915
                                return(-1);
×
5916
                        }
5917
                        /*:[18may20006 mt]*/
5918
                }
5919
                /*[18may20006 mt]:*/
5920
                if(*prevar == '$'){/*Put the answer to the dollar variable*/
×
5921
                        int oldNumPotModdollars = NumPotModdollars;
×
5922
#ifdef WITHMPI
5923
                        WORD oldRhsExprInModuleFlag = AC.RhsExprInModuleFlag;
5924
                        AC.RhsExprInModuleFlag = 0;
5925
#endif
5926
                        /*Here lbuf is the actual length of buf!*/
5927
                        /*"prevar=buf'\0'":*/
5928
                        UBYTE *pbuf=Malloc1(StrLen(prevar)+1+lbuf+1,"Fromexternal to dollar");
×
5929
                        UBYTE *c=pbuf;
×
5930
                        UBYTE *b=prevar;
×
5931
                        while(*b!='\0'){*c++ = *b++;}
×
5932
                        *c++='=';
×
5933
                        b=buf;
×
5934
                        while(  (*c++=*b++)!='\0'  );
×
5935
                        oldpreassignflag = AP.PreAssignFlag;
×
5936
                        AP.PreAssignFlag = 1;
×
5937
                        if ( ( cc = CompileStatement(pbuf) ) || ( cc = CatchDollar(0) ) ) {
×
5938
                                Error1("External channel: can't asign output to dollar variable ",prevar);
×
5939
                        }
5940
                        AP.PreAssignFlag = oldpreassignflag;
×
5941
                        NumPotModdollars = oldNumPotModdollars;
×
5942
#ifdef WITHMPI
5943
                        AC.RhsExprInModuleFlag = oldRhsExprInModuleFlag;
5944
#endif
5945
                        M_free(pbuf,"Fromexternal to dollar");
×
5946
                }else{
5947
                        cc = PutPreVar(prevar, buf, 0, 1) < 0;
×
5948
                }
5949
                /*:[18may20006 mt]*/
5950
                M_free(buf,"Fromexternal");
×
5951
                if ( cc ) return(-1);
×
5952
                return(0);
×
5953
        }
5954
        /*:[02feb2006 mt]*/
5955
        if ( OpenStream(s,EXTERNALCHANNELSTREAM,0,PRENOACTION) == 0 ) return(-1);
×
5956
        /*[17may2006 mt]:*/
5957
        AC.NoShowInput = withNoList;
×
5958
        /*:[17may2006 mt]*/
5959
        return(0);
×
5960
#else
5961
        Error0("External channel: not implemented on this computer/system");
5962
        return(-1);
5963
#endif
5964
}
5965

5966
/*
5967
                 #] DoFromExternal : 
5968
                 #[ DoToExternal :
5969
                        #toexetrnal
5970
*/
5971

5972
#ifdef WITHEXTERNALCHANNEL
5973

5974
/*A wrapper to writeBufToExtChannel, see the file extcmd.c:*/
5975
LONG WriteToExternalChannel(int handle, UBYTE *buffer, LONG size)
×
5976
{
5977
        /*ATT! handle is not used! Actual output is performed to
5978
                 the current external channel, see extcmd.c!*/
5979
        DUMMYUSE(handle);
×
5980
        if(writeBufToExtChannel((char*)buffer,size))
×
5981
                return(-1);
×
5982
        return(size);
5983
}
5984
#endif /*ifdef WITHEXTERNALCHANNEL*/
5985

5986
int DoToExternal(UBYTE *s)
×
5987
{
5988
#ifdef WITHEXTERNALCHANNEL
5989
   HANDLERS h;
×
5990
   LONG        (*OldWrite)(int handle, UBYTE *buffer, LONG size) = WriteFile;
×
5991
        int ret=-1;
×
5992
#else
5993
        DUMMYUSE(s);
5994
#endif
5995
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
5996
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
5997
        if ( AP.preError ) return(0);
×
5998
#ifdef WITHEXTERNALCHANNEL
5999

6000
        h.oldsilent=AM.silent;
×
6001
        h.newlogonly = h.oldlogonly = AM.FileOnlyFlag;
×
6002
        h.newhandle = h.oldhandle = AC.LogHandle;
×
6003
        h.oldprinttype = AO.PrintType;
×
6004

6005
        WriteFile=&WriteToExternalChannel;
×
6006

6007
        while ( *s == ' ' || *s == '\t' ) s++;
×
6008

6009
        if(AX.currentExternalChannel==0){
×
6010
                MesPrint("@No current external channel");
×
6011
                goto DoToExternalReady;
×
6012
        }
6013

6014
        if(getCurrentExternalChannel()!=AX.currentExternalChannel)
×
6015
                selectExternalChannel(AX.currentExternalChannel);
×
6016

6017
        ret=writeToChannel(EXTERNALCHANNELOUT,s,&h);
×
6018
        DoToExternalReady:
×
6019
                WriteFile=OldWrite;
×
6020
                return(ret);
×
6021
#else /*ifdef WITHEXTERNALCHANNEL*/
6022
        Error0("External channel: not implemented on this computer/system");
6023
        return(-1);
6024
#endif /*ifdef WITHEXTERNALCHANNEL ... else*/
6025

6026
}
6027

6028
/*
6029
                 #] DoToExternal : 
6030
                 #[ defineChannel :
6031
*/
6032
 
6033
UBYTE *defineChannel(UBYTE *s, HANDLERS *h)
201✔
6034
{
6035
        UBYTE *name,*to;
201✔
6036

6037
        if ( *s != '<' )
201✔
6038
                return(s);
6039

6040
        s++;
102✔
6041
        name = to = s;
102✔
6042
        while ( *s && *s != '>' ) {
555✔
6043
                if ( *s == '\\' ) s++;
453✔
6044
                *to++ = *s++;
453✔
6045
        }
6046
        if ( *s == 0 ) {
102✔
6047
                MesPrint("@Improper termination of filename");
×
6048
                return(0);
×
6049
        }
6050
        s++;
102✔
6051
        *to = 0;
102✔
6052
        if ( *name ) {
102✔
6053
                h->newhandle = GetChannel((char *)name,0);
87✔
6054
                h->newlogonly = 1;
87✔
6055
        }
6056
        else if ( AC.LogHandle >= 0 ) {
15✔
6057
                h->newhandle = AC.LogHandle;
×
6058
                h->newlogonly = 1;
×
6059
        }
6060
        return(s);        
6061
}
6062

6063
/*
6064
                 #] defineChannel : 
6065
                 #[ writeToChannel :
6066
*/
6067
 
6068
int writeToChannel(int wtype, UBYTE *s, HANDLERS *h)
201✔
6069
{
6070
        UBYTE *to, *fstring, *ss, *sss, *s1, c, c1;
201✔
6071
        WORD  num, number, nfac;
201✔
6072
        WORD oldOptimizationLevel;
201✔
6073
        UBYTE Out[MAXLINELENGTH+14], *stopper;
201✔
6074
        int nosemi, i;
201✔
6075
        int plus = 0;
201✔
6076

6077
/*
6078
        Now determine the format string
6079
*/
6080
        while ( *s == ',' || *s == ' ' ) s++;
303✔
6081
        if ( *s != '"' ) {
201✔
6082
                MesPrint("@No format string present");
×
6083
                return(-1);
×
6084
        }
6085
        s++; fstring = to = s;
201✔
6086
        while ( *s ) {
3,072✔
6087
                if ( *s == '\\' ) {
3,072✔
6088
                        s++;
9✔
6089
                        if ( *s == '\\' ) {
9✔
6090
                                *to++ = *s++;
6✔
6091
                                if ( *s == '\\' ) *to++ = *s++;
6✔
6092
                        }
6093
                        else if ( *s == '"' ) *to++ = *s++;
3✔
6094
                        else { *to++ = '\\'; *to++ = *s++; }
3✔
6095
                }
6096
                else if ( *s == '"' ) break;
3,063✔
6097
                else *to++ = *s++;
2,862✔
6098
        }
6099
        if ( *s != '"' ) {
201✔
6100
                MesPrint("@No closing \" in format string");
×
6101
                return(-1);
×
6102
        }
6103
        *to = 0; s++;
201✔
6104
        if ( AC.LineLength > 20 && AC.LineLength <= MAXLINELENGTH ) stopper = Out + AC.LineLength;
201✔
6105
        else stopper = Out + MAXLINELENGTH;
6106
        to = Out;
201✔
6107
/*
6108
        s points now at the list of objects (if any)
6109
        we can start executing the format string.
6110
*/
6111
        AM.silent = 0;
201✔
6112
        AC.LogHandle = h->newhandle;
201✔
6113
        AM.FileOnlyFlag = h->newlogonly;
201✔
6114
        if ( h->newhandle >= 0 ) {
201✔
6115
                AO.PrintType |= PRINTLFILE;
87✔
6116
        }
6117
        while ( *fstring ) {
2,958✔
6118
                if ( to >= stopper ) {
2,757✔
6119
                        if ( AC.OutputMode == FORTRANMODE && AC.IsFortran90 == ISFORTRAN90 ) {
×
6120
                                *to++ = '&';
×
6121
                        }
6122
                        num = to - Out;
×
6123
                        WriteString(wtype,Out,num);
×
6124
                        to = Out;
×
6125
                        if ( AC.OutputMode == FORTRANMODE
×
6126
                         || AC.OutputMode == PFORTRANMODE ) {
×
6127
                                number = 7;
×
6128
                                for ( i = 0; i < number; i++ ) *to++ = ' ';
×
6129
                                to[-2] = '&';
×
6130
                        }
6131
                }
6132
                if ( *fstring == '\\' ) {
2,757✔
6133
                        fstring++;
9✔
6134
                        if ( *fstring == 'n' ) {
9✔
6135
                                num = to - Out;
9✔
6136
                                WriteString(wtype,Out,num);
9✔
6137
                                to = Out;
9✔
6138
                                fstring++;
9✔
6139
                        }
6140
                        else if ( *fstring == 't' ) { *to++ = '\t'; fstring++; }
×
6141
                        else if ( *fstring == 'b' ) { *to++ = '\\'; fstring++; }
×
6142
                        else *to++ = *fstring++;
×
6143
                }
6144
                else if ( *fstring == '%' ) {
2,748✔
6145
                        plus = 0;
6146
retry:
144✔
6147
                        fstring++;
144✔
6148
                        if ( *fstring == 'd' ) {
144✔
6149
                                int sign,dig;
6150
                                number = -1;
×
6151
donumber:
×
6152
                                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
6153
                                sign = 1;
6154
                                while ( *s == '+' || *s == '-' ) {
×
6155
                                        if ( *s == '-' ) sign = -sign;
×
6156
                                        s++;
×
6157
                                }
6158
                                dig = 0; ss = s; if ( sign < 0 ) { ss--; *ss = '-'; dig++; }
×
6159
                                while ( *s >= '0' && *s <= '9' ) { s++; dig++; }
×
6160
                                if ( number < 0 ) {
×
6161
                                        while ( ss < s ) {
×
6162
                                                if ( to >= stopper ) {
×
6163
                                                        num = to - Out;
×
6164
                                                        WriteString(wtype,Out,num);
×
6165
                                                        to = Out;
×
6166
                                                }
6167
                                                if ( *ss == '\\' ) ss++;
×
6168
                                                *to++ = *ss++;
×
6169
                                        }
6170
                                }
6171
                                else {
6172
                                        if ( number < dig ) { dig = number; ss = s - dig; }
×
6173
                                        while ( number > dig ) {
×
6174
                                                if ( to >= stopper ) {
×
6175
                                                        num = to - Out;
×
6176
                                                        WriteString(wtype,Out,num);
×
6177
                                                        to = Out;
×
6178
                                                }
6179
                                                *to++ = ' '; number--;
×
6180
                                        }
6181
                                        while ( ss < s ) {
×
6182
                                                if ( to >= stopper ) {
×
6183
                                                        num = to - Out;
×
6184
                                                        WriteString(wtype,Out,num);
×
6185
                                                        to = Out;
×
6186
                                                }
6187
                                                if ( *ss == '\\' ) ss++;
×
6188
                                                *to++ = *ss++;
×
6189
                                        }
6190
                                }
6191
                                fstring++;
×
6192
                        }
6193
                        else if ( *fstring == '$' ) {
6194
                                UBYTE *dolalloc;
48✔
6195
                                number = AO.OutSkip;
48✔
6196
dodollar:
48✔
6197
                                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
132✔
6198
                                if ( AC.OutputMode == FORTRANMODE
48✔
6199
                                 || AC.OutputMode == PFORTRANMODE ) {
48✔
6200
                                        number = 7;
×
6201
                                }
6202
                                if ( *s != '$' ) {
48✔
6203
nodollar:                        MesPrint("@$-variable expected in #write instruction");
×
6204
                                        AM.FileOnlyFlag = h->oldlogonly;
×
6205
                                        AC.LogHandle = h->oldhandle;
×
6206
                                        AO.PrintType = h->oldprinttype;
×
6207
                                        AM.silent = h->oldsilent;
×
6208
                                        return(-1);
×
6209
                                }
6210
                                s++; ss = s;
48✔
6211
                                while ( chartype[*s] <= 1 ) s++;
105✔
6212
                                if ( s == ss ) goto nodollar;
48✔
6213
                                c = *s; *s = 0;
48✔
6214
                                num = GetDollar(ss);
48✔
6215
                                if ( num < 0 ) {
48✔
6216
                                        MesPrint("@#write instruction: $%s has not been defined",ss);
×
6217
                                        AM.FileOnlyFlag = h->oldlogonly;
×
6218
                                        AC.LogHandle = h->oldhandle;
×
6219
                                        AO.PrintType = h->oldprinttype;
×
6220
                                        AM.silent = h->oldsilent;
×
6221
                                        return(-1);
×
6222
                                }
6223
                                *s = c;
48✔
6224
                                if ( *s == '[' ) {
48✔
6225
                                        if ( Dollars[num].nfactors <= 0 ) {
36✔
6226
                                                *s = 0;
×
6227
                                                MesPrint("@#write instruction: $%s has not been factorized",ss);
×
6228
                                                AM.FileOnlyFlag = h->oldlogonly;
×
6229
                                                AC.LogHandle = h->oldhandle;
×
6230
                                                AO.PrintType = h->oldprinttype;
×
6231
                                                AM.silent = h->oldsilent;
×
6232
                                                return(-1);
×
6233
                                        }
6234
/*
6235
                                        Now get the number between the []
6236
*/
6237
                                        nfac = GetDollarNumber(&s,Dollars+num);
36✔
6238

6239
                                        if ( Dollars[num].nfactors == 1 && nfac == 1 ) goto writewhole;
36✔
6240

6241
                                        if ( ( dolalloc = WriteDollarFactorToBuffer(num,nfac,0) ) == 0 ) {
36✔
6242
                                                AM.FileOnlyFlag = h->oldlogonly;
×
6243
                                                AC.LogHandle = h->oldhandle;
×
6244
                                                AO.PrintType = h->oldprinttype;
×
6245
                                                AM.silent = h->oldsilent;
×
6246
                                                return(-1);
×
6247
                                        }
6248
                                        goto writealloc;
36✔
6249
                                }
6250
                                else if ( *s && *s != ' ' && *s != ',' && *s != '\t' ) {
12✔
6251
                                        MesPrint("@#write instruction: illegal characters after $-variable");
×
6252
                                        AM.FileOnlyFlag = h->oldlogonly;
×
6253
                                        AC.LogHandle = h->oldhandle;
×
6254
                                        AO.PrintType = h->oldprinttype;
×
6255
                                        AM.silent = h->oldsilent;
×
6256
                                        return(-1);
×
6257
                                }
6258
                                else {
6259
writewhole:
12✔
6260
                                  if ( ( dolalloc = WriteDollarToBuffer(num,0) ) == 0 ) {
12✔
6261
                                        AM.FileOnlyFlag = h->oldlogonly;
×
6262
                                        AC.LogHandle = h->oldhandle;
×
6263
                                        AO.PrintType = h->oldprinttype;
×
6264
                                        AM.silent = h->oldsilent;
×
6265
                                        return(-1);
×
6266
                                  }
6267
                                  else {
6268
writealloc:
12✔
6269
                                        ss = dolalloc;
48✔
6270
                                        while ( *ss ) {
306✔
6271
                                                if ( to >= stopper ) {
258✔
6272
                                                        if ( AC.OutputMode == FORTRANMODE && AC.IsFortran90 == ISFORTRAN90 ) {
×
6273
                                                                *to++ = '&';
×
6274
                                                        }
6275
                                                        num = to - Out;
×
6276
                                                        WriteString(wtype,Out,num);
×
6277
                                                        to = Out;
×
6278
                                                        for ( i = 0; i < number; i++ ) *to++ = ' ';
×
6279
                                                        if ( AC.OutputMode == FORTRANMODE
×
6280
                                                         || AC.OutputMode == PFORTRANMODE ) to[-2] = '&';
×
6281
                                                }
6282
                                                if ( chartype[*ss] > 3 ) { *to++ = *ss++; }
258✔
6283
                                                else {
6284
                                                        sss = ss; while ( chartype[*ss] <= 3 ) ss++;
303✔
6285
                                                        if ( ( to + (ss-sss) ) >= stopper ) {
138✔
6286
                                                                if ( (ss-sss) >= (stopper-Out) ) {
×
6287
                                                                        if ( ( to - stopper ) < 10 ) {
×
6288
                                                                                if ( AC.OutputMode == FORTRANMODE && AC.IsFortran90 == ISFORTRAN90 ) {
×
6289
                                                                                        *to++ = '&';
×
6290
                                                                                }
6291
                                                                                num = to - Out;
×
6292
                                                                                WriteString(wtype,Out,num);
×
6293
                                                                                to = Out;
×
6294
                                                                                for ( i = 0; i < number; i++ ) *to++ = ' ';
×
6295
                                                                                if ( AC.OutputMode == FORTRANMODE
×
6296
                                                                                 || AC.OutputMode == PFORTRANMODE ) to[-2] = '&';
×
6297
                                                                        }
6298
                                                                        while ( (ss-sss) >= (stopper-Out) ) {
×
6299
                                                                                while ( to < stopper-1 ) {
×
6300
                                                                                        *to++ = *sss++;
×
6301
                                                                                }
6302
                                                                                if ( AC.OutputMode == FORTRANMODE && AC.IsFortran90 == ISFORTRAN90 ) {
×
6303
                                                                                        *to++ = '&';
×
6304
                                                                                }
6305
                                                                                else {
6306
                                                                                        *to++ = '\\';
×
6307
                                                                                }
6308
                                                                                num = to - Out;
×
6309
                                                                                WriteString(wtype,Out,num);
×
6310
                                                                                to = Out;
×
6311
                                                                                if ( AC.OutputMode == FORTRANMODE
×
6312
                                                                                 || AC.OutputMode == PFORTRANMODE ) {
×
6313
                                                                                        for ( i = 0; i < number; i++ ) *to++ = ' ';
×
6314
                                                                                        to[-2] = '&';
×
6315
                                                                                }
6316
                                                                        }
6317
                                                                }
6318
                                                                else {
6319
                                                                        if ( AC.OutputMode == FORTRANMODE && AC.IsFortran90 == ISFORTRAN90 ) {
×
6320
                                                                                *to++ = '&';
×
6321
                                                                        }
6322
                                                                        num = to - Out;
×
6323
                                                                        WriteString(wtype,Out,num);
×
6324
                                                                        to = Out;
×
6325
                                                                        for ( i = 0; i < number; i++ ) *to++ = ' ';
×
6326
                                                                        if ( AC.OutputMode == FORTRANMODE
×
6327
                                                                         || AC.OutputMode == PFORTRANMODE ) to[-2] = '&';
×
6328
                                                                }
6329
                                                        }
6330
                                                        while ( sss < ss ) *to++ = *sss++;
303✔
6331
                                                }
6332
                                        }
6333
                                  }
6334
                                  M_free(dolalloc,"written dollar");
48✔
6335
                                  fstring++;
48✔
6336
                                }
6337
                        }
6338
                        else if ( *fstring == 's' ) {
6339
                                fstring++;
3✔
6340
                                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
6✔
6341
                                if ( *s == '"' ) {
3✔
6342
                                        s++; ss = s;
3✔
6343
                                        while ( *s ) {
27✔
6344
                                                if ( *s == '\\' ) s++;
27✔
6345
                                                else if ( *s == '"' ) break;
27✔
6346
                                                s++;
24✔
6347
                                        }
6348
                                        if ( *s == 0 ) {
3✔
6349
                                                MesPrint("@#write instruction: Missing \" in string");
×
6350
                                                AM.FileOnlyFlag = h->oldlogonly;
×
6351
                                                AC.LogHandle = h->oldhandle;
×
6352
                                                AO.PrintType = h->oldprinttype;
×
6353
                                                AM.silent = h->oldsilent;
×
6354
                                                return(-1);
×
6355
                                        }
6356
                                        while ( ss < s ) {
27✔
6357
                                                if ( to >= stopper ) {
24✔
6358
                                                        num = to - Out;
×
6359
                                                        WriteString(wtype,Out,num);
×
6360
                                                        to = Out;
×
6361
                                                }
6362
                                                if ( *ss == '\\' ) ss++;
24✔
6363
                                                *to++ = *ss++;
24✔
6364
                                        }
6365
                                        s++;
3✔
6366
                                }
6367
                                else {
6368
                                        sss = ss = s;
×
6369
                                        while ( *s && *s != ',' ) {
×
6370
                                                if ( *s == '\\' ) { s++; sss = s+1; }
×
6371
                                                s++;
×
6372
                                        }
6373
                                        while ( s > sss+1 && ( s[-1] == ' ' || s[-1] == '\t' ) ) s--;
×
6374
                                        while ( ss < s ) {
×
6375
                                                if ( to >= stopper ) {
×
6376
                                                        num = to - Out;
×
6377
                                                        WriteString(wtype,Out,num);
×
6378
                                                        to = Out;
×
6379
                                                }
6380
                                                if ( *ss == '\\' ) ss++;
×
6381
                                                *to++ = *ss++;
×
6382
                                        }
6383
                                }
6384
                        }
6385
                        else if ( *fstring == 'X' ) {
6386
                                fstring++;
3✔
6387
                                if ( cbuf[AM.sbufnum].numrhs > 0 ) {
3✔
6388
/*
6389
                                        This should be only to the value of AM.oldnumextrasymbols
6390
*/
6391
                                        UBYTE *s = GetPreVar(AM.oldnumextrasymbols,0);
3✔
6392
                                        WORD x = 0;
3✔
6393
                                        while ( *s >= '0' && *s <= '9' ) x = 10*x + *s++ - '0';
6✔
6394
                                        if ( x > 0 )
3✔
6395
                                                PrintSubtermList(1,x);
3✔
6396
                                        else
6397
                                                PrintSubtermList(1,cbuf[AM.sbufnum].numrhs);
×
6398
                                }
6399
                        }
6400
                        else if ( *fstring == 'O' ) {
6401
                                number = AO.OutSkip;
6✔
6402
dooptim:
6✔
6403
                                fstring++;
6✔
6404
/*
6405
                                First test whether there is an optimization buffer
6406
*/
6407
                                if ( AO.OptimizeResult.code == NULL && AO.OptimizationLevel != 0 ) {
6✔
6408
                                        MesPrint("@In #write instruction: no optimization results available!");
×
6409
                                        return(-1);
×
6410
                                }
6411
                                num = to - Out;
6✔
6412
                                WriteString(wtype,Out,num);
6✔
6413
                                to = Out;
6✔
6414
                                if ( AO.OptimizationLevel != 0 ) {
6✔
6415
                                        WORD oldoutskip = AO.OutSkip;
6✔
6416
                                        AO.OutSkip = number;
6✔
6417
                                        optimize_print_code(0);
6✔
6418
                                        AO.OutSkip = oldoutskip;
6✔
6419
                                }
6420
                        }
6421
                        else if ( *fstring == 'e' || *fstring == 'E' ) {
6422
                                if ( *fstring == 'E'
48✔
6423
                                        || AC.OutputMode == FORTRANMODE
15✔
6424
                                        || AC.OutputMode == PFORTRANMODE ) nosemi = 1;
6✔
6425
                                else nosemi = 0;
6✔
6426
                                fstring++;
48✔
6427
                                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
129✔
6428
                                if ( chartype[*s] != 0 && *s != '[' ) {
48✔
6429
noexpr:                                MesPrint("@expression name expected in #write instruction");
×
6430
                                        AM.FileOnlyFlag = h->oldlogonly;
×
6431
                                        AC.LogHandle = h->oldhandle;
×
6432
                                        AO.PrintType = h->oldprinttype;
×
6433
                                        AM.silent = h->oldsilent;
×
6434
                                        return(-1);
×
6435
                                }
6436
                                ss = s;
48✔
6437
                                if ( ( s = SkipAName(ss) ) == 0 || s[-1] == '_' ) goto noexpr;
48✔
6438
                                s1 = s; c = c1 = *s1;
48✔
6439
                                if ( c1 == '(' ) {
48✔
6440
                                        SKIPBRA3(s)
12✔
6441
                                        if ( *s == ')' ) {
3✔
6442
                                                AO.CurBufWrt = s1+1;
3✔
6443
                                                c = *s; *s = 0;
3✔
6444
                                        }
6445
                                        else {
6446
                                                MesPrint("@Illegal () specifier in expression name in #write");
×
6447
                                                AM.FileOnlyFlag = h->oldlogonly;
×
6448
                                                AC.LogHandle = h->oldhandle;
×
6449
                                                AO.PrintType = h->oldprinttype;
×
6450
                                                AM.silent = h->oldsilent;
×
6451
                                                return(-1);
×
6452
                                        }
6453
                                }
6454
                                else AO.CurBufWrt = (UBYTE *)underscore;
45✔
6455
                                *s1 = 0;
48✔
6456
                                num = to - Out;
48✔
6457
                                if ( num > 0 ) WriteUnfinString(wtype,Out,num);
48✔
6458
                                to = Out;
48✔
6459
                                oldOptimizationLevel = AO.OptimizationLevel;
48✔
6460
                                AO.OptimizationLevel = 0;
48✔
6461
                                if ( WriteOne(ss,(int)num,nosemi,plus) < 0 ) {
48✔
6462
                                        AM.FileOnlyFlag = h->oldlogonly;
×
6463
                                        AC.LogHandle = h->oldhandle;
×
6464
                                        AO.PrintType = h->oldprinttype;
×
6465
                                        AM.silent = h->oldsilent;
×
6466
                                        return(-1);
×
6467
                                }
6468
                                AO.OptimizationLevel = oldOptimizationLevel;
48✔
6469
                                *s1 = c1;
48✔
6470
                                if ( s > s1 ) *s++ = c;
48✔
6471
                        }
6472
/*
6473
                        File content
6474
*/
6475
                        else if ( ( *fstring == 'f' ) || ( *fstring == 'F' ) ) {
6476
                                LONG n;
6477
                                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
6478
                                ss = s;
×
6479
                                while ( *s && *s != ',' ) {
×
6480
                                        if ( *s == '\\' ) s++;
×
6481
                                        s++;
×
6482
                                }
6483
                                c = *s; *s = 0;
×
6484
                                s1 = LoadInputFile(ss,HEADERFILE);
×
6485
                                *s = c;
×
6486
/*
6487
                                There should have been a way to pass the file size.
6488
                                Also there should be conversions for \r\n etc.
6489
*/
6490
                                if ( s1 ) {
×
6491
                                        ss = s1; while ( *ss ) ss++;
×
6492
                                        n = ss-s1;
×
6493
                                        WriteString(wtype,s1,n);
×
6494
                                        M_free(s1,"copy file");
×
6495
                                }
6496
                                else if ( *fstring == 'F' ) {
×
6497
                                        *s = 0;
×
6498
                                        MesPrint("@Error in #write: could not open file %s",ss);
×
6499
                                        *s = c;
×
6500
                                        goto ReturnWithError;
×
6501
                                }
6502
                                fstring++;
×
6503
                        }
6504
                        else if ( *fstring == '%' ) {
6505
                                *to++ = *fstring++;
×
6506
                        }
6507
                        else if ( FG.cTable[*fstring] == 1 ) {  /* %#S */
36✔
6508
                                number = 0;
6509
                                while ( FG.cTable[*fstring] == 1 ) {
×
6510
                                        number = 10*number + *fstring++ - '0';
×
6511
                                }
6512
                                if ( *fstring == 'O' ) goto dooptim;
×
6513
                                else if ( *fstring == 'd' ) goto donumber;
×
6514
                                else if ( *fstring == '$' ) goto dodollar;
×
6515
                                else if ( *fstring == 't' ) {        /* `tab' position */
6516
                                        if ( number < (WORD)(stopper-Out) ) {
×
6517
                                                while ( (WORD)(to-Out) < number ) *to++ = ' ';
×
6518
                                        }
6519
                                        fstring++;
×
6520
                                }
6521
                                else if ( *fstring == 'X' || *fstring == 'x' ) {
6522
                                        if ( number > 0 && number <= cbuf[AM.sbufnum].numrhs ) {
×
6523
                                                UBYTE buffer[80], *out, *old1, *old2, *old3;
×
6524
                                                WORD *term, first;
×
6525
                                                if ( *fstring == 'X' ) {
×
6526
                                                        out = StrCopy((UBYTE *)AC.extrasym,buffer);
×
6527
                                                        if ( AC.extrasymbols == 0 ) {
×
6528
                                                                out = NumCopy(number,out);
×
6529
                                                                out = StrCopy((UBYTE *)"_",out);
×
6530
                                                        }
6531
                                                        else if ( AC.extrasymbols == 1 ) {
×
6532
                                                                if ( AC.OutputMode == CMODE ) {
×
6533
                                                                        out = StrCopy((UBYTE *)"[",out);
×
6534
                                                                        out = NumCopy(number,out);
×
6535
                                                                        out = StrCopy((UBYTE *)"]",out);
×
6536
                                                                }
6537
                                                                else {
6538
                                                                        out = StrCopy((UBYTE *)"(",out);
×
6539
                                                                        out = NumCopy(number,out);
×
6540
                                                                        out = StrCopy((UBYTE *)")",out);
×
6541
                                                                }
6542
                                                        }
6543
                                                        out = StrCopy((UBYTE *)"=",out);
×
6544
                                                        ss = buffer;
×
6545
                                                        while ( ss < out ) {
×
6546
                                                                if ( to >= stopper ) {
×
6547
                                                                        num = to - Out;
×
6548
                                                                        WriteString(wtype,Out,num);
×
6549
                                                                        to = Out;
×
6550
                                                                }
6551
                                                                *to++ = *ss++;
×
6552
                                                        }
6553
                                                }
6554
                                                term = cbuf[AM.sbufnum].rhs[number];
×
6555
                                                first = 1;
×
6556
                                                if ( *term == 0 ) {
×
6557
                                                        *to++ = '0';
×
6558
                                                }
6559
                                                else {
6560
                                                        old1 = AO.OutFill;
×
6561
                                                        old2 = AO.OutputLine;
×
6562
                                                        old3 = AO.OutStop;
×
6563
                                                        AO.OutFill = to;
×
6564
                                                        AO.OutputLine = Out;
×
6565
                                                        AO.OutStop = Out + AC.LineLength;
×
6566
                                                        while ( *term ) {
×
6567
                                                                if ( WriteInnerTerm(term,first) ) Terminate(-1);
×
6568
                                                                term += *term;
×
6569
                                                                first = 0;
×
6570
                                                        }
6571
                                                        to = Out + (AO.OutFill-AO.OutputLine);
×
6572
                                                        AO.OutFill = old1;
×
6573
                                                        AO.OutputLine = old2;
×
6574
                                                        AO.OutStop = old3;
×
6575
                                                }
6576
                                        }
6577
                                        fstring++;
×
6578
                                }
6579
                                else {
6580
                                        goto IllegControlSequence;
×
6581
                                }
6582
                        }
6583
                        else if ( *fstring == '+' ) {
36✔
6584
                                plus = 1; goto retry;
×
6585
                        }
6586
                        else if ( *fstring == 0 ) {
36✔
6587
                                *to++ = 0;
36✔
6588
                        }
6589
                        else {
6590
IllegControlSequence:
×
6591
                                MesPrint("@Illegal control sequence in format string in #write instruction");
×
6592
ReturnWithError:
×
6593
                                AM.FileOnlyFlag = h->oldlogonly;
×
6594
                                AC.LogHandle = h->oldhandle;
×
6595
                                AO.PrintType = h->oldprinttype;
×
6596
                                AM.silent = h->oldsilent;
×
6597
                                return(-1);
×
6598
                        }
6599
                }
6600
                else {
6601
                        *to++ = *fstring++;
2,604✔
6602
                }
6603
        }
6604
/*
6605
        Now flush the output
6606
*/
6607
        num = to - Out;
201✔
6608
        /*[15apr2004 mt]:*/
6609
        if(wtype==EXTERNALCHANNELOUT){
201✔
6610
                if(num!=0)
×
6611
                        WriteUnfinString(wtype,Out,num);
×
6612
        }else
6613
        /*:[15apr2004 mt]*/
6614
        WriteString(wtype,Out,num);
201✔
6615
/*
6616
        and restore original parameters
6617
*/
6618
        AM.FileOnlyFlag = h->oldlogonly;
201✔
6619
        AC.LogHandle = h->oldhandle;
201✔
6620
        AO.PrintType = h->oldprinttype;
201✔
6621
        AM.silent = h->oldsilent;
201✔
6622
        return(0);
201✔
6623
}
6624

6625
/*
6626
                 #] writeToChannel : 
6627
                 #[ DoFactDollar :
6628

6629
                Executes the #factdollar $var
6630
                      instruction
6631
*/
6632

6633
int DoFactDollar(UBYTE *s)
27✔
6634
{
6635
        GETIDENTITY
18✔
6636
        WORD numdollar, *oldworkpointer;
27✔
6637

6638
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
27✔
6639
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
27✔
6640
        while ( *s == ' ' || *s == '\t' ) s++;
27✔
6641
        if ( *s == '$' ) {
27✔
6642
                if ( GetName(AC.dollarnames,s+1,&numdollar,NOAUTO) != CDOLLAR ) {
27✔
6643
                        MesPrint("@%s is undefined",s);
×
6644
                        return(-1);
×
6645
                }
6646
                s = SkipAName(s+1);
27✔
6647
                if ( *s != 0 ) {
27✔
6648
                        MesPrint("@#FactDollar should have a single $variable for its argument");
×
6649
                        return(-1);
×
6650
                }
6651
                NewSort(BHEAD0);
27✔
6652
                oldworkpointer = AT.WorkPointer;
27✔
6653
                if ( DollarFactorize(BHEAD numdollar) ) return(-1);
27✔
6654
                AT.WorkPointer = oldworkpointer;
27✔
6655
                LowerSortLevel();
27✔
6656
                return(0);
27✔
6657
        }
6658
        else if ( ParenthesesTest(s) ) return(-1);
×
6659
        else {
6660
                MesPrint("@#FactDollar should have a single $variable for its argument");
×
6661
                return -1;
×
6662
        }
6663
}
6664

6665
/*
6666
                 #] DoFactDollar : 
6667
                 #[ GetDollarNumber :
6668
*/
6669

6670
WORD GetDollarNumber(UBYTE **inp, DOLLARS d)
36✔
6671
{
6672
        UBYTE *s = *inp, c, *name;
36✔
6673
        WORD number, nfac, *w;
36✔
6674
        DOLLARS dd;
36✔
6675
        s++;
36✔
6676
        if ( *s == '$' ) {
36✔
6677
                s++; name = s;
×
6678
                while ( FG.cTable[*s] < 2 ) s++;
×
6679
                c = *s; *s = 0;
×
6680
                if ( GetName(AC.dollarnames,name,&number,NOAUTO) == NAMENOTFOUND ) {
×
6681
                        MesPrint("@dollar in #write should have been defined previously");
×
6682
                        Terminate(-1);
×
6683
                }
6684
                *s = c;
×
6685
                dd = Dollars + number;
×
6686
                if ( c == '[' ) {
×
6687
                        *inp = s;
×
6688
                        nfac = GetDollarNumber(inp,dd);
×
6689
                        s = *inp;
×
6690
                        if ( *s != ']' ) {
×
6691
                                MesPrint("@Illegal factor for dollar variable");
×
6692
                                Terminate(-1);
×
6693
                        }
6694
                        *inp = s+1;
×
6695
                        if ( nfac == 0 ) {
×
6696
                                if ( dd->nfactors > d->nfactors ) {
×
6697
TooBig:
×
6698
                                        MesPrint("@Factor number for dollar variable too large");
×
6699
                                        Terminate(-1);
×
6700
                                }
6701
                                return(dd->nfactors);
×
6702
                        }
6703
                        w = dd->factors[nfac-1].where;
×
6704
                        if ( w == 0 ) {
×
6705
                                if ( dd->factors[nfac-1].value > d->nfactors ||
×
6706
                                     dd->factors[nfac-1].value < 0 ) goto TooBig;
×
6707
                                return(dd->factors[nfac-1].value);
6708
                        }
6709
                        if ( *w == 4 && w[4] == 0 && w[3] == 3 && w[2] == 1
×
6710
                          && w[1] <= d->nfactors ) return(w[1]);
×
6711
                        if ( w[*w] == 0 && w[*w-1] == *w-1 ) goto TooBig;
×
6712
IllNum:
×
6713
                        MesPrint("@Illegal factor number for dollar variable");
×
6714
                        Terminate(-1);
×
6715
                }
6716
                else {        /* The dollar should be a number */
6717
                        if ( dd->type == DOLZERO ) {
×
6718
                                return(0);
6719
                        }
6720
                        else if ( dd->type == DOLTERMS || dd->type == DOLNUMBER ) {
×
6721
                                w = dd->where;
×
6722
                                if ( *w == 4 && w[4] == 0 && w[3] == 3 && w[2] == 1
×
6723
                                  && w[1] <= d->nfactors ) return(w[1]);
×
6724
                                if ( w[*w] == 0 && w[*w-1] == *w-1 ) goto TooBig;
×
6725
                                goto IllNum;
×
6726
                        }
6727
                        else goto IllNum;
×
6728
                }
6729
        }
6730
        else if ( FG.cTable[*s] == 1 ) {
36✔
6731
                WORD x = *s++ - '0';
36✔
6732
                while ( FG.cTable[*s] == 1 ) {
36✔
6733
                        x = 10*x + *s++ - '0';
×
6734
                        if ( x > d->nfactors ) {
×
6735
                                MesPrint("@Factor number %d for dollar variable too large",x);
×
6736
                                Terminate(-1);
×
6737
                        }
6738
                }
6739
                if ( *s != ']' ) {
36✔
6740
                        MesPrint("@Illegal factor number for dollar variable");
×
6741
                        Terminate(-1);
×
6742
                }
6743
                s++; *inp = s;
36✔
6744
                return(x);
36✔
6745
        }
6746
        else {
6747
                MesPrint("@Illegal factor indicator for dollar variable");
×
6748
                Terminate(-1);
×
6749
        }
6750
        return(-1);
6751
}
6752

6753
/*
6754
                 #] GetDollarNumber : 
6755
                 #[ DoSetRandom :
6756

6757
                Executes the #SetRandom number
6758
*/
6759

6760
int DoSetRandom(UBYTE *s)
×
6761
{
6762
        ULONG x;
×
6763
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
6764
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
6765
        while ( *s == ' ' || *s == '\t' ) s++;
×
6766
        x = 0;
6767
        while ( FG.cTable[*s] == 1 ) {
×
6768
                x = 10*x + (*s++-'0');
×
6769
        }
6770
        while ( *s == ' ' || *s == '\t' ) s++;
×
6771
        if ( *s  == 0 ) {
×
6772
#ifdef WITHPTHREADS
6773
#ifdef WITHSORTBOTS
6774
                int id, totnum = MaX(2*AM.totalnumberofthreads-3,AM.totalnumberofthreads);
6775
#else
6776
                int id, totnum = AM.totalnumberofthreads;
6777
#endif
6778
                for ( id = 0; id < totnum; id++ ) {
6779
                        AB[id]->R.wranfseed = x;
6780
                        if ( AB[id]->R.wranfia ) M_free(AB[id]->R.wranfia,"wranf");
6781
                        AB[id]->R.wranfia = 0;
6782
                }
6783
#else
6784
                AR.wranfseed = x;
6785
                if ( AR.wranfia ) M_free(AR.wranfia,"wranf");
6786
                AR.wranfia = 0;
6787
#endif
6788
                return(0);
6789
        }
6790
        else {
6791
                MesPrint("@proper syntax is #SetRandom number");
×
6792
                return(-1);
×
6793
        }
6794
}
6795

6796
/*
6797
                 #] DoSetRandom : 
6798
                 #[ DoOptimize :
6799

6800
                Executes the #Optimize(expr) instruction.
6801
*/
6802

6803
int DoOptimize(UBYTE *s)
18✔
6804
{
6805
        GETIDENTITY
12✔
6806
        UBYTE *exprname;
18✔
6807
        WORD numexpr;
18✔
6808
        int error = 0, i;
18✔
6809
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
18✔
6810
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
18✔
6811
        DUMMYUSE(*s)
18✔
6812
        exprname = s; s = SkipAName(s);
18✔
6813
        if ( *s != 0 && *s != ';' ) {
18✔
6814
                MesPrint("@proper syntax is #Optimize,expression");
×
6815
                return(-1);
×
6816
        }
6817
        *s = 0;
18✔
6818
    if ( GetName(AC.exprnames,exprname,&numexpr,NOAUTO) != CEXPRESSION ) {
18✔
6819
                MesPrint("@%s is not an expression",exprname);
×
6820
                error = 1;
×
6821
        }
6822
        else if ( AP.preError == 0 ) {
18✔
6823
                EXPRESSIONS e = Expressions + numexpr;
18✔
6824
                POSITION position;
18✔
6825
                int firstterm;
18✔
6826
                WORD *term = AT.WorkPointer;
18✔
6827
                ClearOptimize();
18✔
6828
                if ( AO.OptimizationLevel == 0 ) return(0);
18✔
6829
                switch ( e->status ) {
18✔
6830
                        case LOCALEXPRESSION:
6831
                        case GLOBALEXPRESSION:
6832
                                break;
6833
                        default:
×
6834
                                MesPrint("@Expression %s is not an active unhidden local or global expression.",exprname);
×
6835
                                Terminate(-1);
×
6836
                                break;
×
6837
                }
6838
#ifdef WITHMPI
6839
                if ( PF.me == MASTER )
6840
#endif
6841
                RevertScratch();
18✔
6842
                for ( i = NumExpressions-1; i >= 0; i-- ) {
39✔
6843
                        AS.OldOnFile[i] = Expressions[i].onfile;
21✔
6844
                        AS.OldNumFactors[i] = Expressions[i].numfactors;
21✔
6845
                        AS.Oldvflags[i] = Expressions[i].vflags;
21✔
6846
                        Expressions[i].vflags &= ~(ISUNMODIFIED|ISZERO);
21✔
6847
                }
6848
                for ( i = 0; i < NumExpressions; i++ ) {
39✔
6849
                        if ( i == numexpr ) {
21✔
6850
                                PutPreVar(AM.oldnumextrasymbols,
18✔
6851
                                                GetPreVar((UBYTE *)"EXTRASYMBOLS_",0),0,1);
6852
                                Optimize(numexpr, 0);
18✔
6853
                                AO.OptimizeResult.nameofexpr = strDup1(exprname,"optimize expression name");
18✔
6854
                                continue;
18✔
6855
                        }
6856
#ifdef WITHMPI
6857
                        if ( PF.me == MASTER ) {
6858
#endif
6859
                        e = Expressions + i;
3✔
6860
                        switch ( e->status ) {
3✔
6861
                                case LOCALEXPRESSION:
6862
                                case SKIPLEXPRESSION:
6863
                                case DROPLEXPRESSION:
6864
                                case DROPPEDEXPRESSION:
6865
                                case GLOBALEXPRESSION:
6866
                                case SKIPGEXPRESSION:
6867
                                case DROPGEXPRESSION:
6868
                                case HIDELEXPRESSION:
6869
                                case HIDEGEXPRESSION:
6870
                                case DROPHLEXPRESSION:
6871
                                case DROPHGEXPRESSION:
6872
                                case INTOHIDELEXPRESSION:
6873
                                case INTOHIDEGEXPRESSION:
6874
                                        break;
3✔
6875
                                default:
×
6876
                                        continue;
×
6877
                        }
6878
                        AR.GetFile = 0;
3✔
6879
                        SetScratch(AR.infile,&(e->onfile));
3✔
6880
                        if ( GetTerm(BHEAD term) <= 0 ) {
3✔
6881
                                MesPrint("@Expression %d has problems reading from scratchfile",i);
×
6882
                                Terminate(-1);
×
6883
                        }
6884
                        term[3] = i;
3✔
6885
                        AR.DeferFlag = 0;
3✔
6886
                        SeekScratch(AR.outfile,&position);
3✔
6887
                        e->onfile = position;
3✔
6888
                        *AM.S0->sBuffer = 0; firstterm = -1;
3✔
6889
                        do {
27✔
6890
                                WORD *oldipointer = AR.CompressPointer;
27✔
6891
                                WORD *comprtop = AR.ComprTop;
27✔
6892
                                AR.ComprTop = AM.S0->sTop;
27✔
6893
                                AR.CompressPointer = AM.S0->sBuffer;
27✔
6894
                                if ( firstterm > 0 ) {
27✔
6895
                                        if ( PutOut(BHEAD term,&position,AR.outfile,1) < 0 ) goto DoSerr;
21✔
6896
                                }
6897
                                else if ( firstterm < 0 ) {
6✔
6898
                                        if ( PutOut(BHEAD term,&position,AR.outfile,0) < 0 ) goto DoSerr;
3✔
6899
                                        firstterm++;
3✔
6900
                                }
6901
                                else {
6902
                                        if ( PutOut(BHEAD term,&position,AR.outfile,-1) < 0 ) goto DoSerr;
3✔
6903
                                        firstterm++;
3✔
6904
                                }
6905
                                AR.CompressPointer = oldipointer;
27✔
6906
                                AR.ComprTop = comprtop;
27✔
6907
                        } while ( GetTerm(BHEAD term) );
27✔
6908
                        if ( FlushOut(&position,AR.outfile,1) ) {
3✔
6909
DoSerr:
×
6910
                                MesPrint("@Expression %d has problems writing to scratchfile",i);
×
6911
                                Terminate(-1);
×
6912
                        }
6913
#ifdef WITHMPI
6914
                        }
6915
#endif
6916
                }
6917
/*
6918
                Now some administration and we are done
6919
*/
6920
                UpdateMaxSize();
18✔
6921
        }
6922
        else {
6923
                ClearOptimize();
×
6924
        }
6925
        return(error);
6926
        
6927
}
6928

6929
/*
6930
                 #] DoOptimize : 
6931
                 #[ DoClearOptimize :
6932

6933
                Clears all relevant buffers of the output optimization
6934
*/
6935

6936
int DoClearOptimize(UBYTE *s)
3✔
6937
{
6938
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
3✔
6939
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
3✔
6940
        DUMMYUSE(*s);
3✔
6941
        return(ClearOptimize());
3✔
6942
}
6943

6944
/*
6945
                 #] DoClearOptimize : 
6946
                 #[ DoSkipExtraSymbols :
6947

6948
                Adds the intermediate variables of the previous optimization
6949
                to the list of extra symbols, provided it has not yet been erased
6950
                by a #clearoptimize
6951
                To remove them again one needs to use the 'delete extrasymbols;'
6952
                or the 'delete extrasymbols>num;' statement in which num is the
6953
                old number of extra symbols.
6954
*/
6955

6956
int DoSkipExtraSymbols(UBYTE *s)
×
6957
{
6958
        CBUF *C = cbuf + AM.sbufnum;
×
6959
        WORD tt = 0, j = 0, oldval = AO.OptimizeResult.minvar;
×
6960
        if ( AO.OptimizeResult.code == NULL ) return(0);
×
6961
        if ( AO.OptimizationLevel == 0 ) return(0);
×
6962
        while ( *s == ',' ) s++;
×
6963
        if ( *s == 0 ) {
×
6964
                AO.OptimizeResult.minvar = AO.OptimizeResult.maxvar+1;
×
6965
        }
6966
        else {
6967
                while ( *s <= '9' && *s >= '0' ) j = 10*j + *s++ - '0';
×
6968
                if ( *s ) {
×
6969
                        MesPrint("@Illegal use of #SkipExtraSymbols instruction");
×
6970
                        Terminate(-1);
×
6971
                }
6972
                AO.OptimizeResult.minvar += j;
×
6973
                if ( AO.OptimizeResult.minvar > AO.OptimizeResult.maxvar )
×
6974
                        AO.OptimizeResult.minvar = AO.OptimizeResult.maxvar+1;
×
6975
        }
6976
        j = AO.OptimizeResult.minvar - oldval;
×
6977
        while ( j > 0 ) {
×
6978
                AddRHS(AM.sbufnum,1);
×
6979
                AddNtoC(AM.sbufnum,1,&tt,16);
×
6980
                AddToCB(C,0)
×
6981
                InsTree(AM.sbufnum,C->numrhs);
×
6982
                j--;
×
6983
        }
6984
        return(0);
6985
}
6986

6987
/*
6988
                 #] DoSkipExtraSymbols : 
6989
                 #[ DoPreReset :
6990

6991
                Does a reset of variables.
6992
                Currently only the timer (stopwatch) of `timer_'
6993
*/
6994

6995
int DoPreReset(UBYTE *s)
×
6996
{
6997
        UBYTE *ss, c;
×
6998
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
6999
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
7000
        while ( *s == ' ' || *s == '\t' ) s++;
×
7001
        if ( *s == 0 ) {
×
7002
                MesPrint("@proper syntax is #Reset variable");
×
7003
                return(-1);
×
7004
        }
7005
        ss = s;
7006
        while ( FG.cTable[*s] == 0 ) s++;
×
7007
        c = *s; *s = 0;
×
7008
        if ( ( StrICmp(ss,(UBYTE *)"timer") == 0 )
×
7009
          || ( StrICmp(ss,(UBYTE *)"stopwatch") == 0 ) ) {
×
7010
                *s = c;
×
7011
                AP.StopWatchZero = GetRunningTime();
×
7012
                return(0);
×
7013
        }
7014
        else {
7015
                *s = c;
×
7016
                MesPrint("@proper syntax is #Reset variable");
×
7017
                return(-1);
×
7018
        }
7019
}
7020

7021
/*
7022
                 #] DoPreReset : 
7023
                 #[ DoPreAppendPath :
7024
*/
7025

7026
static int DoAddPath(UBYTE *s, int bPrepend)
9✔
7027
{
7028
        /* NOTE: this doesn't support some file systems, e.g., 0x5c with CP932. */
7029

7030
        UBYTE *path, *path_end, *current_dir, *current_dir_end, *NewPath, *t;
9✔
7031
        int bRelative, n;
9✔
7032

7033
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
9✔
7034
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
9✔
7035

7036
        /* Parse the path in the input. */
7037
        while ( *s == ' ' || *s == '\t' ) s++;  /* skip spaces */
9✔
7038
        if ( *s == '"' ) {  /* the path is given by "..." */
9✔
7039
                path = ++s;
×
7040
                while ( *s && *s != '"' ) {
×
7041
                        if ( SEPARATOR != '\\' && *s == '\\' ) {  /* escape character, e.g., "\\\"" */
×
7042
                                if ( !s[1] ) goto ImproperPath;
×
7043
                                s++;
×
7044
                        }
7045
                        s++;
×
7046
                }
7047
                if ( *s != '"' ) goto ImproperPath;
×
7048
                path_end = s++;
×
7049
        }
7050
        else {
7051
                path = s;
36✔
7052
                while ( *s && *s != ' ' && *s != '\t' ) {
36✔
7053
                        if ( SEPARATOR != '\\' && *s == '\\' ) {  /* escape character, e.g., "\\ " */
27✔
7054
                                if ( !s[1] ) goto ImproperPath;
×
7055
                                s++;
×
7056
                        }
7057
                        s++;
27✔
7058
                }
7059
                path_end = s;
7060
        }
7061
        if ( path == path_end ) goto ImproperPath;  /* empty path */
9✔
7062
        while ( *s == ' ' || *s == '\t' ) s++;  /* skip spaces */
9✔
7063
        if ( *s ) goto ImproperPath;  /* extra tokens found */
9✔
7064

7065
        /* Check if the path is an absolute path. */
7066
        bRelative = 1;
9✔
7067
        if ( path[0] == SEPARATOR ) {  /* starts with the directory separator */
9✔
7068
                bRelative = 0;
7069
        }
7070
#ifdef WINDOWS
7071
        else if ( chartype[path[0]] == 0 && path[1] == ':' ) {  /* starts with (drive letter): */
7072
                bRelative = 0;
7073
        }
7074
#endif
7075

7076
        /* Get the current file directory when a relative path is given. */
7077
        if ( bRelative ) {
9✔
7078
                if ( !AC.CurrentStream ) goto FileNameUnavailable;
9✔
7079
                if ( AC.CurrentStream->type != FILESTREAM && AC.CurrentStream->type != REVERSEFILESTREAM ) goto FileNameUnavailable;
9✔
7080
                if ( !AC.CurrentStream->name ) goto FileNameUnavailable;
9✔
7081
                s = current_dir = current_dir_end = AC.CurrentStream->name;
99✔
7082
                while ( *s ) {
99✔
7083
                        if ( SEPARATOR != '\\' && *s == '\\' && s[1] ) {  /* escape character, e.g., "\\\"" */
90✔
7084
                                s += 2;
×
7085
                                continue;
×
7086
                        }
7087
                        if ( *s == SEPARATOR ) {
90✔
7088
                                current_dir_end = s;
9✔
7089
                        }
7090
                        s++;
90✔
7091
                }
7092
        }
7093
        else {
7094
                current_dir = current_dir_end = NULL;
7095
        }
7096

7097
        /* Allocate a buffer for new AM.Path. */
7098
        n = path_end - path;
9✔
7099
        if ( AM.Path ) n += StrLen(AM.Path) + 1;
9✔
7100
        if ( current_dir != current_dir_end ) n+= current_dir_end - current_dir + 1;
9✔
7101
        s = NewPath = (UBYTE *)Malloc1(n + 1,"add path");
9✔
7102

7103
        /* Construct new FORM path. */
7104
        if ( bPrepend ) {
9✔
7105
                if ( current_dir != current_dir_end ) {
6✔
7106
                        t = current_dir;
7107
                        while ( t != current_dir_end ) *s++ = *t++;
24✔
7108
                        *s++ = SEPARATOR;
6✔
7109
                }
7110
                t = path;
7111
                while ( t != path_end ) *s++ = *t++;
24✔
7112
                if ( AM.Path ) *s++ = PATHSEPARATOR;
6✔
7113
        }
7114
        if ( AM.Path ) {
9✔
7115
                t = AM.Path;
7116
                while ( *t ) *s++ = *t++;
150✔
7117
        }
7118
        if ( !bPrepend ) {
9✔
7119
                if ( AM.Path ) *s++ = PATHSEPARATOR;
3✔
7120
                if ( current_dir != current_dir_end ) {
3✔
7121
                        t = current_dir;
7122
                        while ( t != current_dir_end ) *s++ = *t++;
12✔
7123
                        *s++ = SEPARATOR;
3✔
7124
                }
7125
                t = path;
7126
                while ( t != path_end ) *s++ = *t++;
12✔
7127
        }
7128
        *s = '\0';
9✔
7129

7130
        /* Update AM.Path. */
7131
        if ( AM.Path ) M_free(AM.Path,"add path");
9✔
7132
        AM.Path = NewPath;
9✔
7133

7134
        return(0);
9✔
7135

7136
ImproperPath:
×
7137
        MesPrint("@Improper syntax for %#%sPath", bPrepend ? "Prepend" : "Append");
×
7138
        return(-1);
×
7139

7140
FileNameUnavailable:
×
7141
        /* This may be improved in future. */
7142
        MesPrint("@Sorry, %#%sPath can't resolve the current file name from here", bPrepend ? "Prepend" : "Append");
×
7143
        return(-1);
×
7144
}
7145

7146
/**
7147
 * Appends the given path (absolute or relative to the current file directory)
7148
 * to the FORM path.
7149
 *
7150
 * Syntax:
7151
 *   #appendpath <path>
7152
 */
7153
int DoPreAppendPath(UBYTE *s)
3✔
7154
{
7155
        return DoAddPath(s, 0);
3✔
7156
}
7157

7158
/*
7159
                 #] DoPreAppendPath : 
7160
                 #[ DoPrePrependPath :
7161
*/
7162

7163
/**
7164
 * Prepends the given path (absolute or relative to the current file directory)
7165
 * to the FORM path.
7166
 *
7167
 * Syntax:
7168
 *   #prependpath <path>
7169
 */
7170
int DoPrePrependPath(UBYTE *s)
6✔
7171
{
7172
        return DoAddPath(s, 1);
6✔
7173
}
7174

7175
/*
7176
                 #] DoPrePrependPath : 
7177
                 #[ DoTimeOutAfter :
7178

7179
                Executes the #timeoutafter number
7180
*/
7181

7182
int DoTimeOutAfter(UBYTE *s)
9✔
7183
{
7184
#ifdef WITH_ALARM
7185
        ULONG x;
9✔
7186
#else
7187
        DUMMYUSE(s);
7188
#endif
7189
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
9✔
7190
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
9✔
7191
#ifdef WITH_ALARM
7192
        while ( *s == ' ' || *s == '\t' ) s++;
9✔
7193
        x = 0;
7194
        while ( FG.cTable[*s] == 1 ) {
27✔
7195
                x = 10*x + (*s++-'0');
18✔
7196
        }
7197
        while ( *s == ' ' || *s == '\t' ) s++;
9✔
7198
        if ( *s  == 0 ) {
9✔
7199
                alarm(x);
9✔
7200
                return(0);
9✔
7201
        }
7202
        else {
7203
                MesPrint("@proper syntax is #TimeoutAfter number");
×
7204
                return(-1);
×
7205
        }
7206
#else
7207
        Error0("#timeoutafter not implemented on this computer/system");
7208
        return(-1);
7209
#endif
7210
}
7211

7212
/*
7213
                 #] DoTimeOutAfter : 
7214
                 #[ DoNamespace :
7215

7216
                Syntax:
7217
                        #Namespace name
7218
                                .....
7219
                        #use variables
7220
                                .....
7221
                        #EndNamespace
7222
                Effect:
7223
                        All variables/expressions defined inside the range of the
7224
                        namespace get name_ prepended.
7225
                        This holds also for $-variables, names of procedures and 
7226
                        names of files.
7227
                Namespaces can be used in a nested way. cf this_is_deep_x
7228
                A leading _ takes the role of what is super:: in some other languages.
7229
                Remarks:
7230
                        Names of preprocessor variables are excluded!
7231
                        Names of built in objects are excluded! (like sum_, d_ etc.)
7232
*/
7233

7234
int DoNamespace(UBYTE *s)
×
7235
{
7236
        UBYTE *s1, *s2, c;
×
7237
        NAMESPACE *namespace;
×
7238
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
7239
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
7240
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
×
7241
        if ( FG.cTable[*s] != 0 ) {
×
7242
                MesPrint("@Illegal name in #namespace instruction: %s",s);
×
7243
                return(-1);
×
7244
        }
7245
        s1 = s;
7246
        while ( FG.cTable[*s1] <= 1 ) s1++;
×
7247
        s2 = s1;
7248
        while ( *s2 == ' ' || *s2 == ',' || *s2 == '\t' ) s2++;
×
7249
        if ( *s2 != 0 ) {
×
7250
                MesPrint("@A #namespace instruction can only have one name with only alphanumeric characters.");
×
7251
                return(-1);
×
7252
        }
7253
        c = *s1; *s1 = 0;
×
7254
/*
7255
        Now we have the name and the statement is legal.
7256
        We can proceed creating the namespace and its use tree.
7257
*/
7258
        namespace = (NAMESPACE *)Malloc1(sizeof(NAMESPACE),"namespace");
×
7259
        namespace->name = strDup1(s,"namespace_name");
×
7260
        namespace->usenames = MakeNameTree();
×
7261
        if ( AP.firstnamespace == 0 ) {
×
7262
                namespace->previous = 0;
×
7263
                namespace->next = 0;
×
7264
                AP.firstnamespace = namespace;
×
7265
                AP.lastnamespace = namespace;
×
7266
        }
7267
        else {
7268
                AP.lastnamespace->next = namespace;
×
7269
                namespace->next = 0;
×
7270
                namespace->previous = AP.lastnamespace;
×
7271
                AP.lastnamespace = namespace;
×
7272
        }
7273
        *s1 = c;
×
7274
        return(0);
×
7275
}
7276

7277
/*
7278
                 #] DoNamespace : 
7279
                 #[ DoEndNamespace :
7280
*/
7281

7282
int DoEndNamespace(UBYTE *s)
×
7283
{
7284
        NAMESPACE *namespace;
×
7285
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
7286
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
7287
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
×
7288
        if ( *s != 0 ) {
×
7289
                MesPrint("@Illegal #endnamespace instruction");
×
7290
                return(-1);
×
7291
        }
7292
        namespace = AP.lastnamespace;
×
7293
        AP.lastnamespace = namespace->previous;
×
7294
        M_free(namespace->name,"namespace_name");
×
7295
        FreeNameTree(namespace->usenames);
×
7296
        M_free(namespace,"namespace");
×
7297
        return(0);
×
7298
}
7299

7300
/*
7301
                 #] DoEndNamespace : 
7302
                 #[ SkipName :
7303
*/
7304

7305
UBYTE *SkipName(UBYTE *s)
15✔
7306
{
7307
        UBYTE *t = s, *s1, c;
15✔
7308
        int num = 0, block = 0;
15✔
7309
        if ( *s == '[' ) {
15✔
7310
straight:
×
7311
                SKIPBRA1(s)
×
7312
                if ( *s == 0 ) {
×
7313
                        MesPrint("&Illegal name: '%s'",t);
×
7314
                        return(0);
×
7315
                }
7316
                s++; s1 = s;
×
7317
                while ( FG.cTable[*s] <= 1 || *s == '_' ) s++;
×
7318
                if ( s1 != s ) goto witherror;
×
7319
        }
7320
        else if ( *s == '$' ) {
15✔
7321
                s++;
×
7322
                while ( *s == '_' ) { s++; num++; }
×
7323
                block = 1;
7324
                while ( FG.cTable[*s] <= 1 || *s == '_' ) {
×
7325
                        if ( FG.cTable[*s] != 0 && block == 1 ) {
×
7326
blocked:
×
7327
                                MesPrint("&Illegally formed name: %s",t);
×
7328
                                return(0);
×
7329
                        }
7330
                        if ( *s == '_' ) { num++; block = 1; }
×
7331
                        else block = 0;
7332
                        s++;
×
7333
                }
7334
                if ( s[-1] == '_' && num > 1 ) goto built;
×
7335
        }
7336
        else if ( FG.cTable[*s] == 0 ) {
15✔
7337
regular:
15✔
7338
                while ( FG.cTable[*s] <= 1 || *s == '_' ) {
54✔
7339
                        if ( FG.cTable[*s] != 0 && block == 1 ) goto blocked;
39✔
7340
                        if ( *s == '_' ) { block = 1; num++; }
39✔
7341
                        else block = 0;
7342
                        s++;
39✔
7343
                }
7344
                if ( *s == '[' ) goto straight;
15✔
7345
                if ( s[-1] == '_' && num > 1 ) {
15✔
7346
built:
×
7347
                        c = *s; *s = 0;
×
7348
                        MesPrint("&Built in objects cannot be part of namespaces: %s",t);
×
7349
                        *s = c;
×
7350
                        return(0);
×
7351
                }
7352
        }
7353
        else if ( *s == '_' ) {
×
7354
                while ( *s == '_' ) { s++; num++; }
×
7355
                if ( FG.cTable[*s] == 0 ) { block = 0; goto regular; }
×
7356
                goto witherror;
×
7357
        }
7358
        else if ( *s == '@' ) {
×
7359
                s++; block = 1;
×
7360
                if ( *s == '_' || FG.cTable[*s] == 1 ) {
×
7361
                        MesPrint("@Illegally formed name: %s",s-1);
×
7362
                }
7363
                goto regular;
×
7364
        }
7365
        else if ( *s == '#' ) {        /* name of a procedure */
×
7366
                s++;
×
7367
                while ( *s == '_' ) { s++; num++; }
×
7368
                block = 1;
7369
                while ( FG.cTable[*s] <= 1 || *s == '_' ) {
×
7370
                        if ( FG.cTable[*s] != 0 && block == 1 ) goto blocked;
×
7371
                        if ( *s == '_' ) { num++; block = 1; }
×
7372
                        else block = 0;
7373
                        s++;
×
7374
                }
7375
                if ( s[-1] == '_' ) {
×
7376
witherror:
×
7377
                        c = *s; *s = 0;
×
7378
                        MesPrint("&Illegally formed name: %s",t);
×
7379
                        *s = c;
×
7380
                        return(0);
×
7381
                }
7382
        }
7383
        else if ( *s == '<' ) {        /* name of a file. Can be anything (more or less) */
×
7384
                s++;
×
7385
                while ( *s && *s != '>' ) s++;
×
7386
                if ( *s != '>' ) goto witherror;
×
7387
                s++;
×
7388
        }
7389
        return(s);
7390
}
7391

7392
/*
7393
                 #] SkipName : 
7394
                 #[ ConstructName :
7395

7396
                Routine gets a 'raw' name and modifies it if the namespace
7397
                settings ask for it. It puts the new name in a buffer that
7398
                may be expanded if the names become rather long.
7399
                Note that eventually that name needs to be copied, because
7400
                we do not allocate new buffers for each name.
7401

7402
                type tells what kind of name we look for
7403
*/
7404

7405
UBYTE *ConstructName(UBYTE *s,UBYTE type)
3✔
7406
{
7407
        int len;
3✔
7408
        UBYTE *t, *u;
3✔
7409
        WORD number;
3✔
7410
        NAMESPACE *namespace;
3✔
7411
        if ( AP.lastnamespace == 0 ) return(s);
3✔
7412
        if ( *s == '@' ) return(s+1);
×
7413
        if ( GetName(AP.lastnamespace->usenames,s,&number,NOAUTO) !=
×
7414
                        NAMENOTFOUND ) return(s);
7415
/*
7416
        Now the real stuff
7417
        First we have to compute the size of the new name.
7418
*/
7419
        len = StrLen(s) + 1;
×
7420
        namespace = AP.firstnamespace;
×
7421
        while ( namespace ) {
×
7422
                len += StrLen(namespace->name)+1;
×
7423
                namespace = namespace->previous;
×
7424
        }
7425
        if ( len > AP.fullnamesize ) {
×
7426
                while ( len > AP.fullnamesize ) AP.fullnamesize *= 2;
×
7427
                M_free(AP.fullname,"AP.fullname");
×
7428
                AP.fullname = (UBYTE *)Malloc1(AP.fullnamesize*sizeof(UBYTE *),"AP.fullname");
×
7429
        }
7430
        namespace = AP.firstnamespace;
×
7431
        t = AP.fullname;
×
7432
        switch ( type ) {
×
7433
                case ' ':
7434
                case 0:
7435
                        while ( namespace ) {
×
7436
                                u = namespace->name;
×
7437
                                while ( *u ) *t++ = *u++;
×
7438
                                *t++ = '_';
×
7439
                                namespace = namespace->previous;
×
7440
                        }
7441
                        while ( *s ) *t++ = *s++;
×
7442
                        *t = 0;
×
7443
                        break;
×
7444
                case '$':
×
7445
                case '#':
7446
                        *t++ = type;
×
7447
                        while ( namespace ) {
×
7448
                                u = namespace->name;
×
7449
                                while ( *u ) *t++ = *u++;
×
7450
                                *t++ = '_';
×
7451
                                namespace = namespace->previous;
×
7452
                        }
7453
                        if ( type == '$' ) s++;
×
7454
                        while ( *s ) *t++ = *s++;
×
7455
                        *t = 0;
×
7456
                        break;
×
7457
                case '<':
7458
                        while ( namespace ) {
×
7459
                                u = namespace->name;
×
7460
                                while ( *u ) *t++ = *u++;
×
7461
                                *t++ = '_';
×
7462
                                namespace = namespace->previous;
×
7463
                        }
7464
                        s++;
×
7465
                        while ( *s ) *t++ = *s++;
×
7466
                        t--;  /* strip the '>' */
×
7467
                        *t = 0;
×
7468
                        break;
×
7469
                default:
×
7470
                        MesPrint("&Unrecognized datatype in ConstructName");
×
7471
                        *t = 0;
×
7472
                        break;
×
7473
        }
7474
        return(AP.fullname);
×
7475
}
7476

7477
/*
7478
                 #] ConstructName : 
7479
                 #[ DoUse :
7480

7481
                Routine makes (inside the confines of the current namespace)
7482
                a list of variables that are excluded from the namespace.
7483
                Once the namespace is ended, the list is removed.
7484
                The list can include names of variables, dollars and procedures.
7485
                Preprocessor variables are excluded from the namespace. Their
7486
                inclusion would be too complicated for the input streams.
7487
                Note that the preprocessor variables that are arguments in a #do
7488
                or in a procedure are on a stack and should not cause problems.
7489
                Names of variables can be just that.
7490
                Names of $-variables are also straightforward.
7491
                Names of procedures should be preceeded by a # character.
7492
                Names of files (like in #include) should be enclosed by <>.
7493
                The names are stored in a balanced tree. Each namespace may have
7494
                its own tree. The toplevel (no namespace) does not allow a #use.
7495
*/
7496

7497
int DoUse(UBYTE *s)
×
7498
{
7499
        NAMESPACE *namespace;
×
7500
        UBYTE *t, c;
×
7501
        int number;
×
7502
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
7503
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
7504
        if ( AP.lastnamespace == 0 ) {
×
7505
                MesPrint("@It is not allowed to use #use outside the scope of a namespace.");
×
7506
                return(-1);
×
7507
        }
7508
        namespace = AP.lastnamespace;
7509
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
×
7510
        while ( *s ) {
×
7511
                t = s;
×
7512
                if ( ( s = SkipName(t) ) == 0 ) return(-1);
×
7513
                if ( s == t ) {
×
7514
                        MesPrint("@Unrecognized object in #use instruction: %s",t);
×
7515
                        return(-1);
×
7516
                }
7517
                c = *s; *s = 0;
×
7518
/*
7519
                In usenames we only need the names to know whether they are 'protected'.
7520
                We need to keep the $, # and <> to avoid potential double names.
7521
*/
7522
                AddName(namespace->usenames,t,0,0,&number);
×
7523
                *s = c;
×
7524
                while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
×
7525
        }
7526
        return(0);
7527
}
7528

7529
/*
7530
                 #] DoUse : 
7531
                 #[ UserFlags :
7532
 
7533
        Syntax:
7534
                #ClearFlag number(s),expression(s)
7535
                #ClearFlag number(s)
7536
                #ClearFlag expression(s)
7537
                #ClearFlag
7538
                #SetFlag number(s),expression(s)
7539
                #SetFlag number(s)
7540
                #SetFlag expression(s)
7541
                #SetFlag
7542
                par == 0: Clear, par == 1: Set.
7543
*/
7544

7545
int UserFlags(UBYTE *s,int par)
×
7546
{
7547
        int mask = 0, error = 0, i;
×
7548
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
7549
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
7550
        while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
7551
        if ( *s == 0 ) {        /* Treat all flags in all active expressions */
×
7552
allexpr:
×
7553
                for ( i = 0; i < NumExpressions; i++ ) {
×
7554
                        switch ( Expressions[i].status ) {
×
7555
                                case UNHIDELEXPRESSION:
×
7556
                                case UNHIDEGEXPRESSION:
7557
                                case INTOHIDELEXPRESSION:
7558
                                case INTOHIDEGEXPRESSION:
7559
                                case LOCALEXPRESSION:
7560
                                case GLOBALEXPRESSION:
7561
                                case SKIPLEXPRESSION:
7562
                                case SKIPGEXPRESSION:
7563
                                case HIDELEXPRESSION:
7564
                                case HIDEGEXPRESSION:
7565
                                        if ( par == 1 ) Expressions[i].uflags |= ~mask;
×
7566
                                        else            Expressions[i].uflags &= mask;
×
7567
                                        break;
7568
                                case DROPPEDEXPRESSION:
7569
                                case DROPLEXPRESSION:
7570
                                case DROPGEXPRESSION:
7571
                                case DROPHLEXPRESSION:
7572
                                case DROPHGEXPRESSION:
7573
                                case STOREDEXPRESSION:
7574
                                case HIDDENLEXPRESSION:
7575
                                case HIDDENGEXPRESSION:
7576
                                case SPECTATOREXPRESSION:
7577
                                default:
7578
                                        break;
7579
                        }
7580
                }
7581
        }
7582
        else if ( FG.cTable[*s] == 1 ) {
×
7583
                mask = (int)WORDMASK;
7584
                while ( FG.cTable[*s] == 1 ) {
×
7585
                        int x = 0;
7586
                        while ( FG.cTable[*s] == 1 ) { x = 10*x + (*s++-'0'); }
×
7587
                        if ( x < 1 || x > BITSINWORD ) {
×
7588
                                MesPrint("@Illegal number %d for flag in #...Flag instruction",x);
×
7589
                                return(1);
×
7590
                        }
7591
                        mask ^= (1<<(x-1));
×
7592
                        while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
7593
                }
7594
                if ( *s == 0 ) goto allexpr;
×
7595
        }
7596
        else {        /* Clear all flags in all expressions that are specified */
7597
                mask = (int)WORDMASK;
×
7598
        }
7599
        while ( *s ) { /* now read the expressions */
×
7600
                UBYTE *s1, c;
×
7601
                WORD num1;
×
7602
                if ( FG.cTable[*s] != 0 && *s != '[' ) goto syntax;
×
7603
                s1 = s; s = SkipAName(s);
×
7604
                c = *s; *s = 0;
×
7605
            if ( GetName(AC.exprnames,s1,&num1,NOAUTO) != CEXPRESSION ) {
×
7606
                        MesPrint("@%s is not an active expression",s1);
×
7607
                        error = 1;
×
7608
                        return(error);
×
7609
                }
7610
                switch ( Expressions[num1].status ) {
×
7611
                        case UNHIDELEXPRESSION:
×
7612
                        case UNHIDEGEXPRESSION:
7613
                        case INTOHIDELEXPRESSION:
7614
                        case INTOHIDEGEXPRESSION:
7615
                        case LOCALEXPRESSION:
7616
                        case GLOBALEXPRESSION:
7617
                        case SKIPLEXPRESSION:
7618
                        case SKIPGEXPRESSION:
7619
                        case HIDELEXPRESSION:
7620
                        case HIDEGEXPRESSION:
7621
                                if ( par == 1 ) Expressions[num1].uflags |= ~mask;
×
7622
                                else            Expressions[num1].uflags &= mask;
×
7623
                                break;
7624
                        case DROPPEDEXPRESSION:
×
7625
                        case DROPLEXPRESSION:
7626
                        case DROPGEXPRESSION:
7627
                        case DROPHLEXPRESSION:
7628
                        case DROPHGEXPRESSION:
7629
                        case STOREDEXPRESSION:
7630
                        case HIDDENLEXPRESSION:
7631
                        case HIDDENGEXPRESSION:
7632
                        case SPECTATOREXPRESSION:
7633
                        default:
7634
                                MesPrint("@%s is not an active expression",s1);
×
7635
                                error = 1;
×
7636
                                break;
×
7637
                }
7638
                *s = c;
×
7639
                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
7640
        }
7641
        return(error);
7642
syntax:
×
7643
        MesPrint("@Illegal name in #...Flag instruction.");
×
7644
        return(1);
×
7645
}
7646

7647
/*
7648
                 #] UserFlags : 
7649
                 #[ DoClearUserFlag :
7650
*/
7651

7652
int DoClearUserFlag(UBYTE *s)
×
7653
{
7654
        return(UserFlags(s,0));
×
7655
}
7656

7657
/*
7658
                 #] DoClearUserFlag : 
7659
                 #[ DoSetUserFlag :
7660
*/
7661

7662
int DoSetUserFlag(UBYTE *s)
×
7663
{
7664
        return(UserFlags(s,1));
×
7665
}
7666

7667
/*
7668
                 #] DoSetUserFlag : 
7669
                 #[ DoStartFloat :
7670

7671
                If there is a number follwing, it will be the new default precision.
7672
                If float has been started before, the old one will be removed first.
7673
                If there are two numbers, the second one is the maximum weight for
7674
                MZV's.
7675
*/
7676
#ifdef WITHFLOAT
7677

7678
int DoStartFloat(UBYTE *s)
×
7679
{
7680
        GETIDENTITY
7681
        int error = 0;
×
7682
        LONG x;
×
7683
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
7684
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
7685
        if ( AR.PolyFun != 0 ) {
×
7686
                MesPrint("@Simultaneous use of Poly(Rat)Fun and float_ is not allowed.");
×
7687
                error = 1;
×
7688
        }
7689
        if ( AC.ncmod != 0 ) {
×
7690
                MesPrint("@Simultaneous use of floating point and modulus arithmetic makes no sense.");
×
7691
                error = 1;
×
7692
        }
7693
        while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
7694
        if ( *s >= '0' && *s <= '9' ) {
×
7695
                x = 0;
7696
                do {
×
7697
                        x = 10*x + (*s++-'0');
×
7698
                } while ( *s >= '0' && *s <= '9' );
×
7699
                AC.tDefaultPrecision = x;
×
7700
                while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
7701
                if ( *s >= '0' && *s <= '9' ) {
×
7702
                        x = 0;
7703
                        do {
×
7704
                                x = 10*x + (*s++ - '0');
×
7705
                        } while ( *s >= '0' && *s <= '9' );
×
7706
                        AC.tMaxWeight = x;
×
7707
                        while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
7708
                }
7709
                else {
7710
                        AC.tMaxWeight = 0;
×
7711
                }
7712
                if ( *s ) goto IllPar;
×
7713
        }
7714
        else if ( *s != 0 ) {
×
7715
IllPar:
×
7716
                MesPrint("@Illegal parameter in %#StartFloat instruction: %s ",s);
×
7717
                error = 1;
×
7718
        }
7719
        if ( error == 0 ) {
×
7720
                if ( AC.tDefaultPrecision && ( AC.tDefaultPrecision != AC.DefaultPrecision
×
7721
                || AT.aux_ == 0 ) ) {
×
7722
                        AC.DefaultPrecision = AC.tDefaultPrecision;
×
7723
                        AC.tDefaultPrecision = 0;
×
7724
                }
7725
                if ( AC.tMaxWeight && ( AC.tMaxWeight != AC.MaxWeight
×
7726
                || AT.aux_ == 0 ) ) {
×
7727
                        AC.MaxWeight = AC.tMaxWeight;
×
7728
                        AC.tMaxWeight = 0;
×
7729
                }
7730
                SetupMPFTables();
×
7731
                if ( AC.MaxWeight > 0 ) SetupMZVTables();
×
7732
                SetfFloatPrecision(AC.DefaultPrecision);
×
7733
        }
7734
        else {
7735
                AC.tDefaultPrecision = 0;
×
7736
                AC.tMaxWeight = 0;
×
7737
        }
7738
        return(error);
7739
}
7740

7741
#endif
7742
/*
7743
                 #] DoStartFloat : 
7744
                 #[ DoEndFloat :
7745
*/
7746
#ifdef WITHFLOAT
7747

7748
int DoEndFloat(UBYTE *s)
×
7749
{
7750
        int error = 0;
×
7751
        if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
×
7752
        if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
×
7753
        while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
×
7754
        if ( *s != 0 ) {
×
7755
                MesPrint("@Illegal parameter in %#EndFloat instruction: %s ",s);
×
7756
                error = 1;
×
7757
        }
7758
        if ( error == 0 ) {
×
7759
                ClearfFloat();
×
7760
                ClearMZVTables();
×
7761
        }
7762
        return(error);
7763
}
7764

7765
#endif
7766
/*
7767
                 #] DoEndFloat : 
7768
         # ] PreProcessor :
7769
*/
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

© 2026 Coveralls, Inc