• 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

53.85
/sources/tools.c
1
/** @file tools.c
2
 * 
3
 *  Low level routines for many types of task.
4
 *        There are routines for manipulating the input system (streams and files)
5
 *        routines for string manipulation, the memory allocation interface,
6
 *        and the clock. The last is the most sensitive to ports.
7
 *        In the past nearly every port to another OS or computer gave trouble.
8
 *        Nowadays it is slightly better but the poor POSIX compliance of LINUX
9
 *        again gave problems for the multithreaded version.
10
 */
11
/* #[ License : */
12
/*
13
 *   Copyright (C) 1984-2023 J.A.M. Vermaseren
14
 *   When using this file you are requested to refer to the publication
15
 *   J.A.M.Vermaseren "New features of FORM" math-ph/0010025
16
 *   This is considered a matter of courtesy as the development was paid
17
 *   for by FOM the Dutch physics granting agency and we would like to
18
 *   be able to track its scientific use to convince FOM of its value
19
 *   for the community.
20
 *
21
 *   This file is part of FORM.
22
 *
23
 *   FORM is free software: you can redistribute it and/or modify it under the
24
 *   terms of the GNU General Public License as published by the Free Software
25
 *   Foundation, either version 3 of the License, or (at your option) any later
26
 *   version.
27
 *
28
 *   FORM is distributed in the hope that it will be useful, but WITHOUT ANY
29
 *   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30
 *   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
31
 *   details.
32
 *
33
 *   You should have received a copy of the GNU General Public License along
34
 *   with FORM.  If not, see <http://www.gnu.org/licenses/>.
35
 */
36
/* #] License : */ 
37
/*
38
          #[ Includes :
39
        Note: TERMMALLOCDEBUG tests part of the TermMalloc and NumberMalloc
40
              system. To work properly it needs MEMORYMACROS in declare.h
41
              not to be defined to make sure that all calls will be diverted
42
              to the routines here.
43
#define TERMMALLOCDEBUG
44
#define FILLVALUE 126
45
#define MALLOCDEBUGOUTPUT
46
#define MALLOCDEBUG 1
47
*/
48
#ifndef FILLVALUE
49
        #define FILLVALUE 0
50
#endif
51

52
/*
53
    The enhanced malloc debugger, see comments in the beginning of the
54
    file mallocprotect.h
55
    MALLOCPROTECT == -1  -- protect left side, used block is left-aligned.
56
    MALLOCPROTECT == 0  -- protect both sides, used block is left-aligned;
57
    MALLOCPROTECT == 1  -- protect both sides, used block is right-aligned;
58
    ATTENTION! The macro MALLOCPROTECT must be defined
59
    BEFORE #include mallocprotect.h
60
#define MALLOCPROTECT 1
61
*/
62

63
#include "form3.h"
64
 
65
FILES **filelist;
66
int numinfilelist = 0;
67
int filelistsize = 0;
68
#ifdef MALLOCDEBUG
69
#define BANNER (4*sizeof(LONG))
70
void *malloclist[60000];
71
LONG mallocsizes[60000];
72
char *mallocstrings[60000];
73
int nummalloclist = 0;
74
#endif
75

76
#ifdef GPP
77
extern "C" getdtablesize();
78
#endif
79

80
#ifdef WITHSTATS
81
LONG numwrites = 0;
82
LONG numreads = 0;
83
LONG numseeks = 0;
84
LONG nummallocs = 0;
85
LONG numfrees = 0;
86
#endif
87
 
88
#ifdef MALLOCPROTECT
89
#ifdef TRAPSIGNALS
90
#error "MALLOCPROTECT":  undefine "TRAPSIGNALS" in unix.h first!
91
#endif
92
#include "mallocprotect.h"
93

94
#ifdef M_alloc
95
#undef M_alloc
96
#endif
97
    
98
#define M_alloc mprotectMalloc
99
    
100
#endif
101
 
102
#ifdef TERMMALLOCDEBUG
103
WORD **DebugHeap1, **DebugHeap2;
104
#endif
105

106
/*
107
          #] Includes : 
108
          #[ Streams :
109
                 #[ LoadInputFile :
110
*/
111

112
UBYTE *LoadInputFile(UBYTE *filename, int type)
901✔
113
{
114
        int handle;
901✔
115
        LONG filesize;
901✔
116
        UBYTE *buffer, *name = filename;
901✔
117
        POSITION scrpos;
901✔
118
        handle = LocateFile(&name,type);
901✔
119
        if ( handle < 0 ) return(0);
901✔
120
        PUTZERO(scrpos);
15✔
121
        SeekFile(handle,&scrpos,SEEK_END);
15✔
122
        TELLFILE(handle,&scrpos);
15✔
123
        filesize = BASEPOSITION(scrpos);
15✔
124
        PUTZERO(scrpos);
15✔
125
        SeekFile(handle,&scrpos,SEEK_SET);
15✔
126
        buffer = (UBYTE *)Malloc1(filesize+2,"LoadInputFile");
15✔
127
        if ( ReadFile(handle,buffer,filesize) != filesize ) {
15✔
128
                Error1("Read error for file ",name);
×
129
                M_free(buffer,"LoadInputFile");
×
130
                if ( name != filename ) M_free(name,"FromLoadInputFile");
×
131
                CloseFile(handle);
×
132
                return(0);
×
133
        }
134
        CloseFile(handle);
15✔
135
        if ( type == PROCEDUREFILE || type == SETUPFILE ) {
15✔
136
                buffer[filesize] = '\n';
15✔
137
                buffer[filesize+1] = 0;
15✔
138
        }
139
        else {
140
                buffer[filesize] = 0;
×
141
        }
142
        if ( name != filename ) M_free(name,"FromLoadInputFile");
15✔
143
        return(buffer);
144
}
145

146
/*
147
                 #] LoadInputFile : 
148
                 #[ ReadFromStream :
149
*/
150

151
UBYTE ReadFromStream(STREAM *stream)
73,688,434✔
152
{
153
        UBYTE c;
73,688,434✔
154
        POSITION scrpos;
73,688,434✔
155
#ifdef WITHPIPE
156
        if ( stream->type == PIPESTREAM ) {
73,688,434✔
157
#ifndef WITHMPI
158
                FILE *f;
×
159
                int cc;
×
160
                RWLOCKR(AM.handlelock);
×
161
                f = (FILE *)(filelist[stream->handle]);
×
162
                UNRWLOCK(AM.handlelock);
×
163
                cc = getc(f);
×
164
                if ( cc == EOF ) return(ENDOFSTREAM);
×
165
                c = (UBYTE)cc;
×
166
#else
167
                if ( stream->pointer >= stream->top ) {
168
                        /* The master reads the pipe and broadcasts it to the slaves. */
169
                        LONG len;
170
                        if ( PF.me == MASTER ) {
171
                                FILE *f;
172
                                UBYTE *p, *end;
173
                                RWLOCKR(AM.handlelock);
174
                                f = (FILE *)filelist[stream->handle];
175
                                UNRWLOCK(AM.handlelock);
176
                                p = stream->buffer;
177
                                end = stream->buffer + stream->buffersize;
178
                                while ( p < end ) {
179
                                        int cc = getc(f);
180
                                        if ( cc == EOF ) {
181
                                                break;
182
                                        }
183
                                        *p++ = (UBYTE)cc;
184
                                }
185
                                len = p - stream->buffer;
186
                                PF_BroadcastNumber(len);
187
                        }
188
                        else {
189
                                len = PF_BroadcastNumber(0);
190
                        }
191
                        if ( len > 0 ) {
192
                                PF_Bcast(stream->buffer, len);
193
                        }
194
                        stream->pointer = stream->buffer;
195
                        stream->inbuffer = len;
196
                        stream->top = stream->buffer + stream->inbuffer;
197
                        if ( stream->pointer == stream->top ) return ENDOFSTREAM;
198
                }
199
                c = (UBYTE)*stream->pointer++;
200
#endif
201
                if ( stream->eqnum == 1 ) { stream->eqnum = 0; stream->linenumber++; }
×
202
                if ( c == LINEFEED ) stream->eqnum = 1;
×
203
                return(c);
×
204
        }
205
#endif
206
/*[14apr2004 mt]:*/
207
#ifdef WITHEXTERNALCHANNEL
208
        if ( stream->type == EXTERNALCHANNELSTREAM ) {
73,688,434✔
209
                int cc;
×
210
                cc = getcFromExtChannel();
×
211
                /*[18may20006 mt]:*/
212
                /*if ( cc == EOF ) return(ENDOFSTREAM);*/
213
                if ( cc < 0 ){
×
214
                        if( cc == EOF )
×
215
                         return(ENDOFSTREAM);
216
                        else{
217
                                Error0("No current external channel");
×
218
                                Terminate(-1);
×
219
                        }
220
                }/*if ( cc < 0 )*/
221
                /*:[18may20006 mt]*/
222
                c = (UBYTE)cc;
×
223
                if ( stream->eqnum == 1 ) { stream->eqnum = 0; stream->linenumber++; }
×
224
                if ( c == LINEFEED ) stream->eqnum = 1;
×
225
                return(c);
×
226
        }
227
#endif /*ifdef WITHEXTERNALCHANNEL*/
228
/*:[14apr2004 mt]*/
229
        if ( stream->type == INPUTSTREAM ) {
73,688,434✔
230
                if ( stream->pointer < stream->top ) {
×
231
                        c = *stream->pointer++;
×
232
                }
233
                else {
234
                        if ( ReadFile(stream->handle,&c,1) != 1 ) {
×
235
                                return(ENDOFSTREAM);
236
                        }
237
                        if ( stream->fileposition == 0 ) {
×
238
                                if ( !stream->buffer ) {
×
239
                                        stream->buffersize = 32;
×
240
                                        stream->buffer = (UBYTE *)Malloc1(stream->buffersize,"input stream buffer");
×
241
                                        stream->pointer = stream->top = stream->buffer;
×
242
                                }
243
                                else {
244
                                        if ( stream->top - stream->buffer >= stream->buffersize ) {
×
245
                                                LONG oldsize = stream->buffersize;
×
246
                                                DoubleBuffer((void**)&stream->buffer,(void**)&stream->top,sizeof(UBYTE),"double input stream buffer");
×
247
                                                stream->buffersize = stream->top - stream->buffer;
×
248
                                                stream->pointer = stream->top = stream->buffer + oldsize;
×
249
                                        }
250
                                }
251
                                *stream->pointer = c;
×
252
                                stream->pointer = ++stream->top;
×
253
                                stream->inbuffer++;
×
254
                        }
255
                }
256
                if ( stream->eqnum == 1 ) { stream->eqnum = 0; stream->linenumber++; }
×
257
                if ( c == LINEFEED ) stream->eqnum = 1;
×
258
                return(c);
×
259
        }
260
        if ( stream->pointer >= stream->top ) {
73,688,434✔
261
                if ( stream->type != FILESTREAM ) return(ENDOFSTREAM);
2,393,334✔
262
                if ( stream->fileposition != stream->bufferposition+stream->inbuffer ) {
2,005✔
263
                        stream->fileposition = stream->bufferposition+stream->inbuffer;
×
264
                        SETBASEPOSITION(scrpos,stream->fileposition);
×
265
                        SeekFile(stream->handle,&scrpos,SEEK_SET);
×
266
                }
267
                stream->bufferposition = stream->fileposition;
2,005✔
268
                stream->inbuffer = ReadFile(stream->handle,
2,005✔
269
                                stream->buffer,stream->buffersize);
270
                if ( stream->inbuffer <= 0 ) return(ENDOFSTREAM);
2,005✔
271
                stream->top = stream->buffer + stream->inbuffer;
1,119✔
272
                stream->pointer = stream->buffer;
1,119✔
273
                stream->fileposition = stream->bufferposition + stream->inbuffer;
1,119✔
274
        }
275
        if ( stream->eqnum == 1 ) { stream->eqnum = 0; stream->linenumber++; }
71,296,219✔
276
        c = *(stream->pointer)++;
71,296,219✔
277
        if ( c == LINEFEED ) stream->eqnum = 1;
71,296,219✔
278
        return(c);
279
}
280

281
/*
282
                 #] ReadFromStream : 
283
                 #[ GetFromStream :
284
*/
285

286
UBYTE GetFromStream(STREAM *stream)
71,448,723✔
287
{
288
        UBYTE c1, c2;
71,448,723✔
289
        if ( stream->isnextchar > 0 ) {
71,448,723✔
290
                return(stream->nextchar[--stream->isnextchar]);
2,257,675✔
291
        }
292
        c1 = ReadFromStream(stream);
69,191,048✔
293
        if ( c1 == LINEFEED || c1 == CARRIAGERETURN ) {
69,191,047✔
294
                c2 = ReadFromStream(stream);
4,497,386✔
295
                if ( c2 == c1 || ( c2 != LINEFEED && c2 != CARRIAGERETURN ) ) {
4,497,386✔
296
                        stream->isnextchar = 1;
4,497,386✔
297
                        stream->nextchar[0] = c2;
4,497,386✔
298
                }
299
                return(LINEFEED);
4,497,386✔
300
        }
301
        else return(c1);
302
}
303

304
/*
305
                 #] GetFromStream : 
306
                 #[ LookInStream :
307
*/
308

309
UBYTE LookInStream(STREAM *stream)
×
310
{
311
        UBYTE c = GetFromStream(stream);
×
312
        UngetFromStream(stream,c);
×
313
        return(c);
×
314
}
315

316
/*
317
                 #] LookInStream : 
318
                 #[ OpenStream :
319
*/
320

321
STREAM *OpenStream(UBYTE *name, int type, int prevarmode, int raiselow)
2,392,248✔
322
{
323
        STREAM *stream;
2,392,248✔
324
        UBYTE *rhsofvariable, *s, *newname, c;
2,392,248✔
325
        POSITION scrpos;
2,392,248✔
326
        int handle, num;
2,392,248✔
327
        LONG filesize;
2,392,248✔
328
        switch ( type ) {
2,392,248✔
329
                case REVERSEFILESTREAM:
895✔
330
                case FILESTREAM:
331
/*
332
                        Notice that FILESTREAM is only used for text files:
333
                        The #include files and the main input file (.frm)
334
                        Hence we do not worry about files longer than 2 Gbytes.
335
*/
336
                        newname = name;
895✔
337
                        handle = LocateFile(&newname,-1);
895✔
338
                        if ( handle < 0 ) return(0);
895✔
339
                        PUTZERO(scrpos);
895✔
340
                        SeekFile(handle,&scrpos,SEEK_END);
895✔
341
                        TELLFILE(handle,&scrpos);
895✔
342
                        filesize = BASEPOSITION(scrpos);
895✔
343
                        PUTZERO(scrpos);
895✔
344
                        SeekFile(handle,&scrpos,SEEK_SET);
895✔
345
                        if ( filesize > AM.MaxStreamSize && type == FILESTREAM )
895✔
346
                                        filesize = AM.MaxStreamSize;
27✔
347
                        stream = CreateStream((UBYTE *)"filestream");
895✔
348
/*
349
                        The extra +1 in the Malloc1 is potentially needed in ReverseStatements!
350
*/
351
                        stream->buffer = (UBYTE *)Malloc1(filesize+1,"name of input stream");
895✔
352
                        stream->inbuffer = ReadFile(handle,stream->buffer,filesize);
895✔
353
                        if ( type == REVERSEFILESTREAM ) {
895✔
354
                                if ( ReverseStatements(stream) ) {
×
355
                                        M_free(stream->buffer,"name of input stream");
×
356
                                        return(0);
×
357
                                }
358
                        }
359
                        stream->top = stream->buffer + stream->inbuffer;
895✔
360
                        stream->pointer = stream->buffer;
895✔
361
                        stream->handle = handle;
895✔
362
                        stream->buffersize = filesize;
895✔
363
                        stream->fileposition = stream->inbuffer;
895✔
364
                        if ( newname != name ) stream->name = newname;
895✔
365
                        else if ( name ) stream->name = strDup1(name,"name of input stream");
889✔
366
                        else
367
                                stream->name = 0;
×
368
                        stream->prevline = stream->linenumber = 1;
895✔
369
                        stream->eqnum = 0;
895✔
370
                        break;
895✔
371
                case PREVARSTREAM:
148,044✔
372
                        if ( ( rhsofvariable = GetPreVar(name,WITHERROR) ) == 0 ) return(0);
148,044✔
373
                        stream = CreateStream((UBYTE *)"var-stream");
148,044✔
374
                        stream->buffer = stream->pointer = s = rhsofvariable;
148,044✔
375
                        while ( *s ) s++;
442,104✔
376
                        stream->top = s;
148,044✔
377
                        stream->inbuffer = s - stream->buffer;
148,044✔
378
                        stream->name = AC.CurrentStream->name;
148,044✔
379
                        stream->linenumber = AC.CurrentStream->linenumber;
148,044✔
380
                        stream->prevline = AC.CurrentStream->prevline;
148,044✔
381
                        stream->eqnum = AC.CurrentStream->eqnum;
148,044✔
382
                        stream->pname = strDup1(name,"stream->pname");
148,044✔
383
                        stream->olddelay = AP.AllowDelay;
148,044✔
384
                        s = stream->pname; while ( *s ) s++;
303,957✔
385
                        while ( s[-1] == '+' || s[-1] == '-' ) s--;
148,044✔
386
                        *s = 0;
148,044✔
387
                        UnsetAllowDelay();
148,044✔
388
                        break;
148,044✔
389
                case DOLLARSTREAM:
387✔
390
                        if ( ( num = GetDollar(name) ) < 0 ) {
387✔
391
                                WORD numfac = 0;
609✔
392
/*
393
                                Here we have to test first whether we have $x[1], $x[0]
394
                                or just an undefined $x.
395
*/
396
                                s = name; while ( *s && *s != '[' ) s++;
609✔
397
                                if ( *s == 0 ) return(0);
216✔
398
                                c = *s; *s = 0;
216✔
399
                                if ( ( num = GetDollar(name) ) < 0 ) return(0);
216✔
400
                                *s = c;
216✔
401
                                s++;
216✔
402
                                if ( *s == 0 || FG.cTable[*s] != 1 || *s == ']' ) {
216✔
403
                                        MesPrint("@Illegal factor number for dollar variable");
×
404
                                        return(0);
×
405
                                }
406
                                while ( *s && FG.cTable[*s] == 1 ) {
579✔
407
                                        numfac = 10*numfac+*s++-'0';
363✔
408
                                }
409
                                if ( *s != ']' || s[1] != 0 ) {
216✔
410
                                        MesPrint("@Illegal factor number for $ variable");
×
411
                                        return(0);
×
412
                                }
413
                                stream = CreateStream((UBYTE *)"dollar-stream");
216✔
414
                                stream->buffer = stream->pointer = s = WriteDollarFactorToBuffer(num,numfac,1);
216✔
415
                        }
416
                        else {
417
                                stream = CreateStream((UBYTE *)"dollar-stream");
171✔
418
                                stream->buffer = stream->pointer = s = WriteDollarToBuffer(num,1);
171✔
419
                        }
420
                        while ( *s ) s++;
3,225✔
421
                        stream->top = s;
387✔
422
                        stream->inbuffer = s - stream->buffer;
387✔
423
                        stream->name = AC.CurrentStream->name;
387✔
424
                        stream->linenumber = AC.CurrentStream->linenumber;
387✔
425
                        stream->prevline= AC.CurrentStream->prevline;
387✔
426
                        stream->eqnum = AC.CurrentStream->eqnum;
387✔
427
                        stream->pname = strDup1(name,"stream->pname");
387✔
428
                        s = stream->pname; while ( *s ) s++;
1,881✔
429
                        while ( s[-1] == '+' || s[-1] == '-' ) s--;
387✔
430
                        *s = 0;
387✔
431
                        /* We 'stole' the buffer. Later we can free it. */
432
                        AO.DollarOutSizeBuffer = 0;
387✔
433
                        AO.DollarOutBuffer = 0;
387✔
434
                        AO.DollarInOutBuffer = 0;
387✔
435
                        break;
387✔
436
                case PREREADSTREAM:
2,242,922✔
437
                case PREREADSTREAM2:
438
                case PREREADSTREAM3:
439
                case PRECALCSTREAM:
440
                        stream = CreateStream((UBYTE *)"calculator");
2,242,922✔
441
                        stream->buffer = stream->pointer = s = name;
2,242,922✔
442
                        while ( *s ) s++;
71,869,902✔
443
                        stream->top = s;
2,242,922✔
444
                        stream->inbuffer = s - stream->buffer;
2,242,922✔
445
                        stream->name = AC.CurrentStream->name;
2,242,922✔
446
                        stream->linenumber = AC.CurrentStream->linenumber;
2,242,922✔
447
                        stream->prevline = AC.CurrentStream->prevline;
2,242,922✔
448
                        stream->eqnum = 0;
2,242,922✔
449
                        break;
2,242,922✔
450
#ifdef WITHPIPE
451
                case PIPESTREAM:
×
452
                        stream = CreateStream((UBYTE *)"pipe");
×
453
#ifndef WITHMPI
454
                        {
455
                                FILE *f;
×
456
                                if ( ( f = popen((char *)name,"r") ) == 0 ) {
×
457
                                        Error0("@Cannot create pipe");
×
458
                                }
459
                                stream->handle = CreateHandle();
×
460
                                RWLOCKW(AM.handlelock);
×
461
                                filelist[stream->handle] = (FILES *)f;
×
462
                                UNRWLOCK(AM.handlelock);
×
463
                        }
464
                        stream->buffer = stream->top = 0;
×
465
                        stream->inbuffer = 0;
×
466
#else
467
                        {
468
                                /* Only the master opens the pipe. */
469
                                FILE *f;
470
                                if ( PF.me == MASTER ) {
471
                                        f = popen((char *)name, "r");
472
                                        PF_BroadcastNumber(f == 0);
473
                                        if ( f == 0 ) Error0("@Cannot create pipe");
474
                                }
475
                                else {
476
                                        if ( PF_BroadcastNumber(0) ) Error0("@Cannot create pipe");
477
                                        f = (FILE *)123;  /* dummy */
478
                                }
479
                                stream->handle = CreateHandle();
480
                                RWLOCKW(AM.handlelock);
481
                                filelist[stream->handle] = (FILES *)f;
482
                                UNRWLOCK(AM.handlelock);
483
                        }
484
                        /* stream->buffer as a send/receive buffer. */
485
                        stream->buffersize = AM.MaxStreamSize;
486
                        stream->buffer = (UBYTE *)Malloc1(stream->buffersize, "pipe buffer");
487
                        stream->inbuffer = 0;
488
                        stream->top = stream->buffer;
489
                        stream->pointer = stream->buffer;
490
#endif
491
                        stream->name = strDup1((UBYTE *)"pipe","pipe");
×
492
                        stream->prevline = stream->linenumber = 1;
×
493
                        stream->eqnum = 0;
×
494
                        break;
×
495
#endif
496
/*[14apr2004 mt]:*/
497
#ifdef WITHEXTERNALCHANNEL
498
                case EXTERNALCHANNELSTREAM:
×
499
                        {/*Block*/
500
                                int n, *tmpn;
×
501
                                if( (n=getCurrentExternalChannel()) == 0 )
×
502
                                        Error0("@No current external channel");
×
503
                                stream = CreateStream((UBYTE *)"externalchannel");
×
504
                                stream->handle = CreateHandle();
×
505
                                tmpn = (int *)Malloc1(sizeof(int),"external channel handle");
×
506
                                *tmpn = n;
×
507
                                RWLOCKW(AM.handlelock);
×
508
                                filelist[stream->handle] = (FILES *)tmpn;
×
509
                                UNRWLOCK(AM.handlelock);
×
510
                        }/*Block*/
511
                        stream->buffer = stream->top = 0;
×
512
                        stream->inbuffer = 0;
×
513
                        stream->name = strDup1((UBYTE *)"externalchannel","externalchannel");
×
514
                        stream->prevline = stream->linenumber = 1;
×
515
                        stream->eqnum = 0;
×
516
                        break;
×
517
#endif /*ifdef WITHEXTERNALCHANNEL*/
518
/*:[14apr2004 mt]*/
519
                case INPUTSTREAM:
×
520
                        /*
521
                         * Assume that "name" stores a file descriptor (UNIX) or a FILE
522
                         * pointer (Windows). We don't close it automatically on closing
523
                         * the INPUTSTREAM stream (e.g., for stdin).
524
                         */
525
                        stream = CreateStream((UBYTE *)"input stream");
×
526
                        stream->handle = CreateHandle();
×
527
                        {
528
                                FILES *f = (FILES *)Malloc1(sizeof(int),"input stream handle");
×
529
                                /* NOTE: in both cases name=0 indicates stdin. */
530
#ifdef UNIX
531
                                f->descriptor = (int)(ssize_t)name;
×
532
#else
533
                                f = name ? (FILES *)name : stdin;
534
#endif
535
                                RWLOCKW(AM.handlelock);
×
536
                                filelist[stream->handle] = f;
×
537
                                UNRWLOCK(AM.handlelock);
×
538
                        }
539
                        stream->buffer = stream->pointer = stream->top = 0;
×
540
                        stream->inbuffer = 0;
×
541
                        stream->name = strDup1((UBYTE *)(name ? "INPUT" : "STDIN"),"input stream name");
×
542
                        stream->prevline = stream->linenumber = 1;
×
543
                        stream->eqnum = 0;
×
544
                        /*
545
                         * fileposition == -1: default
546
                         * fileposition ==  0: cache the input
547
                         * See also: ReadFromStream, TryFileSetups
548
                         */
549
                        stream->fileposition = -1;
×
550
                        break;
×
551
                default:
552
                        return(0);
553
        }
554
        stream->bufferposition = 0;
2,392,248✔
555
        stream->isnextchar = 0;
2,392,248✔
556
        stream->type = type;
2,392,248✔
557
        stream->previousNoShowInput = AC.NoShowInput;
2,392,248✔
558
        stream->afterwards = raiselow;
2,392,248✔
559
        if ( AC.CurrentStream ) stream->previous = AC.CurrentStream - AC.Streams;
2,392,248✔
560
        else stream->previous = -1;
886✔
561
        stream->FoldName = 0;
2,392,248✔
562
        if ( prevarmode == 0 ) stream->prevars = -1;
2,392,248✔
563
        else if ( prevarmode > 0 ) stream->prevars = NumPre;
156✔
564
        else if ( prevarmode < 0 ) stream->prevars = -prevarmode-1;
156✔
565
        AC.CurrentStream = stream;
2,392,248✔
566
        if ( type == PREREADSTREAM || type == PREREADSTREAM3 || type == PRECALCSTREAM
2,392,248✔
567
                || type == DOLLARSTREAM ) AC.NoShowInput = 1;
2,243,108✔
568
        return(stream);
569
}
570

571
/*
572
                 #] OpenStream : 
573
                 #[ LocateFile :
574
*/
575

576
int LocateFile(UBYTE **name, int type)
1,796✔
577
{
578
        int handle, namesize, i;
1,796✔
579
        UBYTE *s, *to, *u1, *u2, *newname, *indir;        
1,796✔
580
        handle = OpenFile((char *)(*name));
1,796✔
581
        if ( handle >= 0 ) return(handle);
1,796✔
582
        if ( type == SETUPFILE && AM.SetupFile ) {
907✔
583
                handle = OpenFile((char *)(AM.SetupFile));
×
584
                if ( handle >= 0 ) return(handle);
×
585
                MesPrint("Could not open setup file %s",(char *)(AM.SetupFile));
×
586
        }
587
        namesize = 4; s = *name;
907✔
588
        while ( *s ) { s++; namesize++; }
8,121✔
589
        if ( type == SETUPFILE ) indir = AM.SetupDir;
907✔
590
        else indir = AM.IncDir;
21✔
591
        if ( indir ) {
907✔
592

593
                s = indir; i = 0;
594
                while ( *s ) { s++; i++; }
45✔
595
                newname = (UBYTE *)Malloc1(namesize+i,"LocateFile");
21✔
596
                s = indir; to = newname;
21✔
597
                while ( *s ) *to++ = *s++;
45✔
598
                if ( to > newname && to[-1] != SEPARATOR ) *to++ = SEPARATOR;
21✔
599
                s = *name;
21✔
600
                while ( *s ) *to++ = *s++;
147✔
601
                *to = 0;
21✔
602
                handle = OpenFile((char *)newname);
21✔
603
                if ( handle >= 0 ) {
21✔
604
                        *name = newname;
3✔
605
                        return(handle);
3✔
606
                }
607
                M_free(newname,"LocateFile, incdir/file");
18✔
608
        }
609
        if ( type == SETUPFILE ) {
904✔
610
                handle = OpenFile(setupfilename);
886✔
611
                if ( handle >= 0 ) return(handle);
886✔
612
                s = (UBYTE *)getenv("FORMSETUP");
886✔
613
                if ( s ) {
886✔
614
                        handle = OpenFile((char *)s);
×
615
                        if ( handle >= 0 ) return(handle);
×
616
                        MesPrint("Could not open setup file %s",s);
×
617
                }
618
        }
619
        if ( type != SETUPFILE && AM.Path ) {
18✔
620
                u1 = AM.Path;
621
                while ( *u1 ) {
21✔
622
                        u2 = u1; i = 0;
623
#ifdef WINDOWS
624
                        while ( *u1 && *u1 != ';' ) {
625
                                u1++; i++;
626
                        }
627
#else
628
                        while ( *u1 && *u1 != ':' ) {
120✔
629
                                if ( *u1 == '\\' ) u1++;
99✔
630
                                u1++; i++;
99✔
631
                        }
632
#endif
633
                        newname = (UBYTE *)Malloc1(namesize+i,"LocateFile");
21✔
634
                        s = u2; to = newname;
21✔
635
                        while ( s < u1 ) {
120✔
636
#ifndef WINDOWS
637
                                if ( *s == '\\' ) s++;
99✔
638
#endif
639
                                *to++ = *s++;
99✔
640
                        }
641
                        if ( to > newname && to[-1] != SEPARATOR ) *to++ = SEPARATOR;
21✔
642
                        s = *name;
21✔
643
                        while ( *s ) *to++ = *s++;
147✔
644
                        *to = 0;
21✔
645
                        handle = OpenFile((char *)newname);
21✔
646
                        if ( handle >= 0 ) {
21✔
647
                                *name = newname;
18✔
648
                                return(handle);
18✔
649
                        }
650
                        M_free(newname,"LocateFile Path/file");
3✔
651
                        if ( *u1 ) u1++;
3✔
652
                }
653
        }
654
        if ( type != SETUPFILE && type >= -1 ) Error1("LocateFile: Cannot find file",*name);
886✔
655
        return(-1);
656
}
657

658
/*
659
                 #] LocateFile : 
660
                 #[ CloseStream :
661
*/
662

663
STREAM *CloseStream(STREAM *stream)
2,391,356✔
664
{
665
        int newstr = stream->previous, sgn;
2,391,356✔
666
        UBYTE *t, numbuf[24];
2,391,356✔
667
        LONG x;
2,391,356✔
668
        if ( stream->FoldName ) {
2,391,356✔
669
                M_free(stream->FoldName,"stream->FoldName");
×
670
                stream->FoldName = 0;
×
671
        }
672
        if ( stream->type == FILESTREAM || stream->type == REVERSEFILESTREAM ) {
2,391,356✔
673
                CloseFile(stream->handle);
9✔
674
                if ( stream->buffer != 0 ) M_free(stream->buffer,"name of input stream");
9✔
675
                stream->buffer = 0;
9✔
676
        }
677
#ifdef WITHPIPE
678
        else if ( stream->type == PIPESTREAM ) {
679
                RWLOCKW(AM.handlelock);
×
680
#ifdef WITHMPI
681
                if ( PF.me == MASTER )
682
#endif
683
                pclose((FILE *)(filelist[stream->handle]));
×
684
                filelist[stream->handle] = 0;
×
685
                numinfilelist--;
×
686
                UNRWLOCK(AM.handlelock);
×
687
#ifdef WITHMPI
688
                if ( stream->buffer != 0 ) {
689
                        M_free(stream->buffer, "pipe buffer");
690
                        stream->buffer = 0;
691
                }
692
#endif
693
        }
694
#endif
695
/*[14apr2004 mt]:*/
696
#ifdef WITHEXTERNALCHANNEL
697
        else if ( stream->type == EXTERNALCHANNELSTREAM ) {
698
                int *tmpn;
×
699
                RWLOCKW(AM.handlelock);
×
700
                tmpn = (int *)(filelist[stream->handle]);
×
701
                filelist[stream->handle] = 0;
×
702
                numinfilelist--;
×
703
                UNRWLOCK(AM.handlelock);
×
704
                M_free(tmpn,"external channel handle");
×
705
        }
706
#endif /*ifdef WITHEXTERNALCHANNEL*/
707
/*:[14apr2004 mt]*/
708
        else if ( stream->type == INPUTSTREAM ) {
709
                FILES *f;
×
710
                RWLOCKW(AM.handlelock);
×
711
                f = filelist[stream->handle];
×
712
                filelist[stream->handle] = 0;
×
713
                numinfilelist--;
×
714
                UNRWLOCK(AM.handlelock);
×
715
                M_free(f,"input stream handle");
×
716
        }
717
        else if ( stream->type == PREVARSTREAM && (
148,044✔
718
        stream->afterwards == PRERAISEAFTER || stream->afterwards == PRELOWERAFTER ) ) {
148,044✔
719
                t = stream->buffer; x = 0; sgn = 1;
×
720
                while ( *t == '-' || *t == '+' ) {
×
721
                        if ( *t == '-' ) sgn = -sgn;
×
722
                        t++;
×
723
                }
724
                if ( FG.cTable[*t] == 1 ) {
×
725
                        while ( *t && FG.cTable[*t] == 1 ) x = 10*x + *t++ - '0';
×
726
                        if ( *t == 0 ) {
×
727
                                if ( stream->afterwards == PRERAISEAFTER ) x = sgn*x + 1;
×
728
                                else x = sgn*x - 1;
×
729
                                NumToStr(numbuf,x);
×
730
                                PutPreVar(stream->pname,numbuf,0,1);
×
731
                        }
732
                }
733
        }
734
        else if ( stream->type == DOLLARSTREAM && (
2,391,347✔
735
        stream->afterwards == PRERAISEAFTER || stream->afterwards == PRELOWERAFTER ) ) {
387✔
736
                if ( stream->afterwards == PRERAISEAFTER ) x = 1;
×
737
                else x = -1;
×
738
                DollarRaiseLow(stream->pname,x);
×
739
        }
740
        else if ( stream->type == PRECALCSTREAM || stream->type == DOLLARSTREAM ) {
2,391,347✔
741
                if ( stream->buffer ) M_free(stream->buffer,"stream->buffer");
4,479✔
742
                stream->buffer = 0;
4,479✔
743
        }
744
        if ( stream->name && stream->type != PREVARSTREAM
2,391,356✔
745
        && stream->type != PREREADSTREAM && stream->type != PREREADSTREAM2 && stream->type != PREREADSTREAM3
746
        && stream->type != PRECALCSTREAM && stream->type != DOLLARSTREAM ) {
747
                M_free(stream->name,"stream->name");
9✔
748
        }
749
        stream->name = 0;
2,391,356✔
750
/*        if ( stream->type != FILESTREAM )  */
751
        AC.NoShowInput = stream->previousNoShowInput;
2,391,356✔
752
        stream->buffer = 0;                /* To make sure we will not reuse it */
2,391,356✔
753
        stream->pointer = 0;
2,391,356✔
754
/*
755
        Look whether we have to pop preprocessor variables.
756
*/
757
        if ( stream->prevars >= 0 ) {
2,391,356✔
758
                while ( NumPre > stream->prevars ) {
261✔
759
                        NumPre--;
108✔
760
                        M_free(PreVar[NumPre].name,"PreVar[NumPre].name");
108✔
761
                        PreVar[NumPre].name = PreVar[NumPre].value = 0;
108✔
762
                }
763
        }
764
        if ( stream->type == PREVARSTREAM ) {
2,391,356✔
765
                AP.AllowDelay = stream->olddelay;
148,044✔
766
                ClearMacro(stream->pname);
148,044✔
767
                M_free(stream->pname,"stream->pname");
148,044✔
768
        }
769
        else if ( stream->type == DOLLARSTREAM ) {
2,243,312✔
770
                M_free(stream->pname,"stream->pname");
387✔
771
        }
772
        AC.NumStreams--;
2,391,356✔
773
        if ( newstr >= 0 ) return(AC.Streams + newstr);
2,391,356✔
774
        else return(0);
775
}
776

777
/*
778
                 #] CloseStream : 
779
                 #[ CreateStream :
780
*/
781

782
STREAM *CreateStream(UBYTE *where)
2,392,248✔
783
{
784
        STREAM *newstreams;
2,392,248✔
785
        int numnewstreams,i;
2,392,248✔
786
        int offset;
2,392,248✔
787
        if ( AC.NumStreams >= AC.MaxNumStreams ) {
2,392,248✔
788
                if ( AC.MaxNumStreams == 0 ) numnewstreams = 10;
886✔
789
                else                        numnewstreams = 2*AC.MaxNumStreams;
×
790
                newstreams = (STREAM *)Malloc1(sizeof(STREAM)*(numnewstreams+1),"CreateStream");
886✔
791
                if ( AC.MaxNumStreams > 0 ) {
886✔
792
                        offset = AC.CurrentStream - AC.Streams;
×
793
                        for ( i = 0; i < AC.MaxNumStreams; i++ ) {
×
794
                                newstreams[i] = AC.Streams[i];
×
795
                        }
796
                        AC.CurrentStream = newstreams + offset;
×
797
                }
798
                else newstreams[0].previous = -1;
886✔
799
                AC.MaxNumStreams = numnewstreams;
886✔
800
                if ( AC.Streams ) M_free(AC.Streams,(char *)where);
886✔
801
                AC.Streams = newstreams;
886✔
802
        }
803
        newstreams = AC.Streams+AC.NumStreams++;
2,392,248✔
804
        newstreams->name = 0;
2,392,248✔
805
        return(newstreams);
2,392,248✔
806
}
807

808
/*
809
                 #] CreateStream : 
810
                 #[ GetStreamPosition :
811
*/
812

813
LONG GetStreamPosition(STREAM *stream)
886✔
814
{
815
        return(stream->bufferposition + ((LONG)stream->pointer-(LONG)stream->buffer));
886✔
816
}
817

818
/*
819
                 #] GetStreamPosition : 
820
                 #[ PositionStream :
821
*/
822

823
VOID PositionStream(STREAM *stream, LONG position)
886✔
824
{
825
        POSITION scrpos;
886✔
826
        if ( position >= stream->bufferposition
886✔
827
        && position < stream->bufferposition + stream->inbuffer ) {
886✔
828
                stream->pointer = stream->buffer + (position-stream->bufferposition);
886✔
829
        }
830
        else if ( stream->type == FILESTREAM ) {
×
831
                SETBASEPOSITION(scrpos,position);
×
832
                SeekFile(stream->handle,&scrpos,SEEK_SET);
×
833
                stream->inbuffer = ReadFile(stream->handle,stream->buffer,stream->buffersize);
×
834
                stream->pointer = stream->buffer;
×
835
                stream->top = stream->buffer + stream->inbuffer;
×
836
                stream->bufferposition = position;
×
837
                stream->fileposition = position + stream->inbuffer;
×
838
                stream->isnextchar = 0;
×
839
        }
840
        else {
841
                Error0("Illegal position for stream");
×
842
                Terminate(-1);
×
843
        } 
844
}
886✔
845

846
/*
847
                 #] PositionStream : 
848
                 #[ ReverseStatements :
849

850
                Reverses the order of the statements in the buffer.
851
                We allocate an extra buffer and copy a bit to and from.
852
                Note that there are some nasties that cannot be resolved.
853
*/
854

855
int ReverseStatements(STREAM *stream)
×
856
{
857
        UBYTE *spare = (UBYTE *)Malloc1((stream->inbuffer+1)*sizeof(UBYTE),"Reverse copy");
×
858
        UBYTE *top = stream->buffer + stream->inbuffer, *in, *s, *ss, *out;
×
859
        out = spare+stream->inbuffer+1;
×
860
        in = stream->buffer;
×
861
        while ( in < top ) {
×
862
                s = in;
×
863
                if ( *s == AP.ComChar ) {
×
864
toeol:;
×
865
                        for(;;) {
×
866
                                if ( s == top ) { *--out = '\n'; break; }
×
867
                                if ( *s == '\\' ) {
×
868
                                        s++;
×
869
                                        if ( s >= top ) { /* This is an error! */
×
870
irrend:                                        MesPrint("@Irregular end of reverse include file.");
×
871
                                                return(1);
×
872
                                        }
873
                                }
874
                                else if ( *s == '\n' ) {
×
875
                                        s++; ss = s;
×
876
                                        while ( ss > in ) *--out = *--ss;
×
877
                                        in = s;
×
878
                                        if ( out[0] == AP.ComChar && ss+6 < s && out[3] == '#' ) {
×
879
/*
880
                                                For folds we have to exchange begin and end
881
*/
882
                                                if ( out[4] == '[' ) out[4] = ']';
×
883
                                                else if ( out[4] == ']' ) out[4] = '[';
×
884
                                        }
885
                                        break;
886
                                }
887
                                s++;
×
888
                        }
889
                        continue;
×
890
                }
891
                while ( s < top && ( *s == ' ' || *s == '\t' ) ) s++;
×
892
                if ( *s == '#' ) {        /* preprocessor instruction */
×
893
                        goto toeol;                /* read to end of line */
×
894
                }
895
                if ( *s == '.' ) {        /* end-of-module instruction */
×
896
                        goto toeol;                /* read to end of line */
×
897
                }
898
/*
899
                Here we have a regular statement. In principle we scan to ; and its \n
900
                but there are special cases.
901
                1: ; inside a string (in print "......;";)
902
                2: multiple statements on one line.
903
                3: ; + commentary after some blanks.
904
                4: `var' can cause problems.....
905
*/
906
                while ( s < top ) {
×
907
                        if ( *s == ';' ) {
×
908
                                s++;
×
909
                                while ( s < top && ( *s == ' ' || *s == '\t' ) ) s++;
×
910
                                while ( s < top && *s == '\n' ) s++;
×
911
                                if ( s >= top && s[-1] != '\n' ) *s++ = '\n';
×
912
                                ss = s;
×
913
                                while ( ss > in ) *--out = *--ss;
×
914
                                in = s;
915
                                break;
916
                        }
917
                        else if ( *s == '"' ) {
×
918
                                s++;
×
919
                                while ( s < top ) {
×
920
                                        if ( *s == '"' ) break;
×
921
                                        if ( *s == '\\' ) { s++; }
×
922
                                        s++;
×
923
                                }
924
                                if ( s >= top ) goto irrend;
×
925
                        }
926
                        else if ( *s == '\\' ) {
×
927
                                s++;
×
928
                                if ( s >= top ) goto irrend;
×
929
                        }
930
                        s++;
×
931
                }
932
                if ( in < top ) { /* Like blank lines at the end */
×
933
                        if ( s >= top && s[-1] != '\n' ) *s++ = '\n';
×
934
                        ss = s;
×
935
                        while ( ss > in ) *--out = *--ss;
×
936
                        in = s;
937
                }
938
        }
939
        if ( out == spare ) stream->inbuffer++;
×
940
        if ( out > spare+1 ) {
×
941
                MesPrint("@Internal error in #reverseinclude instruction.");
×
942
                return(1);
×
943
        }
944
        memcpy((void *)(stream->buffer),(void *)out,(size_t)(stream->inbuffer*sizeof(UBYTE)));
×
945
        M_free(spare,"Reverse copy");
×
946
        return(0);
×
947
}
948

949
/*
950
                 #] ReverseStatements : 
951
          #] Streams : 
952
          #[ Files :
953
                 #[ StartFiles :
954
*/
955

956
VOID StartFiles(VOID)
886✔
957
{
958
        int i = CreateHandle();
886✔
959
        filelist[i] = Ustdout;
886✔
960
        AM.StdOut = i;
886✔
961
        AC.StoreHandle = -1;
886✔
962
        AC.LogHandle = -1;
886✔
963
#ifndef WITHPTHREADS
964
        AR.Fscr[0].handle = -1;
296✔
965
        AR.Fscr[1].handle = -1;
296✔
966
        AR.Fscr[2].handle = -1;
296✔
967
        AR.FoStage4[0].handle = -1;
296✔
968
        AR.FoStage4[1].handle = -1;
296✔
969
        AR.infile = &(AR.Fscr[0]);
296✔
970
        AR.outfile = &(AR.Fscr[1]);
296✔
971
        AR.hidefile = &(AR.Fscr[2]);
296✔
972
        AR.StoreData.Handle = -1;
296✔
973
#endif
974
        AC.Streams = 0;
886✔
975
        AC.MaxNumStreams = 0;
886✔
976
}
886✔
977

978
/*
979
                 #] StartFiles : 
980
                 #[ OpenFile :
981
*/
982

983
int OpenFile(char *name)
3,610✔
984
{
985
        FILES *f;
3,610✔
986
        int i;
3,610✔
987

988
        if ( ( f = Uopen(name,"rb") ) == 0 ) return(-1);
3,610✔
989
/*        Usetbuf(f,0); */
990
        i = CreateHandle();
910✔
991
        RWLOCKW(AM.handlelock);
910✔
992
        filelist[i] = f;
910✔
993
        UNRWLOCK(AM.handlelock);
910✔
994
        return(i);
910✔
995
}
996

997
/*
998
                 #] OpenFile : 
999
                 #[ OpenAddFile :
1000
*/
1001

1002
int OpenAddFile(char *name)
×
1003
{
1004
        FILES *f;
×
1005
        int i;
×
1006
        POSITION scrpos;
×
1007
        if ( ( f = Uopen(name,"a+b") ) == 0 ) return(-1);
×
1008
/*        Usetbuf(f,0); */
1009
        i = CreateHandle();
×
1010
        RWLOCKW(AM.handlelock);
×
1011
        filelist[i] = f;
×
1012
        UNRWLOCK(AM.handlelock);
×
1013
        TELLFILE(i,&scrpos);
×
1014
        SeekFile(i,&scrpos,SEEK_SET);
×
1015
        return(i);
×
1016
}
1017

1018
/*
1019
                 #] OpenAddFile : 
1020
                 #[ ReOpenFile :
1021
*/
1022

1023
int ReOpenFile(char *name)
×
1024
{
1025
        FILES *f;
×
1026
        int i;
×
1027
        POSITION scrpos;
×
1028
        if ( ( f = Uopen(name,"r+b") ) == 0 ) return(-1);
×
1029
        i = CreateHandle();
×
1030
        RWLOCKW(AM.handlelock);
×
1031
        filelist[i] = f;
×
1032
        UNRWLOCK(AM.handlelock);
×
1033
        TELLFILE(i,&scrpos);
×
1034
        SeekFile(i,&scrpos,SEEK_SET);
×
1035
        return(i);
×
1036
}
1037

1038
/*
1039
                 #] ReOpenFile : 
1040
                 #[ CreateFile :
1041
*/
1042

1043
int CreateFile(char *name)
1,863✔
1044
{
1045
        FILES *f;
1,863✔
1046
        int i;
1,863✔
1047
        if ( ( f = Uopen(name,"w+b") ) == 0 ) return(-1);
1,863✔
1048
        i = CreateHandle();
1,860✔
1049
        RWLOCKW(AM.handlelock);
1,860✔
1050
        filelist[i] = f;
1,860✔
1051
        UNRWLOCK(AM.handlelock);
1,860✔
1052
        return(i);
1,860✔
1053
}
1054

1055
/*
1056
                 #] CreateFile : 
1057
                 #[ CreateLogFile :
1058
*/
1059

1060
int CreateLogFile(char *name)
×
1061
{
1062
        FILES *f;
×
1063
        int i;
×
1064
        if ( ( f = Uopen(name,"w+b") ) == 0 ) return(-1);
×
1065
        Usetbuf(f,0);
×
1066
        i = CreateHandle();
×
1067
        RWLOCKW(AM.handlelock);
×
1068
        filelist[i] = f;
×
1069
        UNRWLOCK(AM.handlelock);
×
1070
        return(i);
×
1071
}
1072

1073
/*
1074
                 #] CreateLogFile : 
1075
                 #[ CloseFile :
1076
*/
1077

1078
VOID CloseFile(int handle)
2,798✔
1079
{
1080
        if ( handle >= 0 ) {
2,798✔
1081
                FILES *f;        /* we need this variable to be thread-safe */
1,866✔
1082
                RWLOCKW(AM.handlelock);
1,866✔
1083
                f = filelist[handle];
1,866✔
1084
                filelist[handle] = 0;
1,866✔
1085
                numinfilelist--;
1,866✔
1086
                UNRWLOCK(AM.handlelock);
1,866✔
1087
                Uclose(f);
1,866✔
1088
        }
1089
}
2,798✔
1090

1091
/*
1092
                 #] CloseFile : 
1093
                 #[ CopyFile :
1094
*/
1095

1096
/** Copies a file with name *source to a file named *dest.
1097
 *  The involved files must not be open.
1098
 *  Returns non-zero if an error occurred.
1099
 *        Uses if possible the combined large and small sorting buffers as cache.
1100
 */
1101
int CopyFile(char *source, char *dest)
×
1102
{
1103
        #define COPYFILEBUFSIZE 40960L
1104
        FILE *in, *out;
×
1105
        size_t countin, countout, sumcount;
×
1106
        char *buffer = NULL;
×
1107

1108
        sumcount = (AM.S0->LargeSize+AM.S0->SmallEsize)*sizeof(WORD);
×
1109
        if ( sumcount <= COPYFILEBUFSIZE ) {
×
1110
                sumcount = COPYFILEBUFSIZE;
×
1111
                buffer = (char*)Malloc1(sumcount, "file copy buffer");
×
1112
        }
1113
        else {
1114
                buffer = (char *)(AM.S0->lBuffer);
×
1115
        }
1116
        
1117
        in = fopen(source, "rb");
×
1118
        if ( in == NULL ) {
×
1119
                perror("CopyFile: ");
×
1120
                return(1);
×
1121
        }
1122
        out = fopen(dest, "wb");
×
1123
        if ( out == NULL ) {
×
1124
                perror("CopyFile: ");
×
1125
                return(2);
×
1126
        }
1127

1128
        while ( !feof(in) ) {
×
1129
                countin = fread(buffer, 1, sumcount, in);
×
1130
                if ( countin != sumcount ) {
×
1131
                        if ( ferror(in) ) {
×
1132
                                perror("CopyFile: ");
×
1133
                                return(3);
×
1134
                        }
1135
                }
1136
                countout = fwrite(buffer, 1, countin, out);
×
1137
                if ( countin != countout ) {
×
1138
                        perror("CopyFile: ");
×
1139
                        return(4);
×
1140
                }
1141
        }
1142

1143
        fclose(in);
×
1144
        fclose(out);
×
1145
        if ( sumcount <= COPYFILEBUFSIZE ) {
×
1146
                M_free(buffer, "file copy buffer");
×
1147
        }
1148
        return(0);
1149
}
1150

1151
/*
1152
                 #] CopyFile : 
1153
                 #[ CreateHandle :
1154

1155
                We need a lock here.
1156
                Problem: the same lock is needed inside Malloc1 and M_free which
1157
                is used in DoubleList when we use MALLOCDEBUG
1158

1159
                Conclusion: MALLOCDEBUG will have to be a bit unsafe
1160
*/
1161

1162
int CreateHandle(VOID)
3,656✔
1163
{
1164
        int i, j;
3,656✔
1165
#ifndef MALLOCDEBUG
1166
        RWLOCKW(AM.handlelock);
3,656✔
1167
#endif
1168
        if ( filelistsize == 0 ) {
3,656✔
1169
        filelistsize = 10;
886✔
1170
        filelist = (FILES **)Malloc1(sizeof(FILES *)*filelistsize,"file handle");
886✔
1171
        for ( j = 0; j < filelistsize; j++ ) filelist[j] = 0;
9,746✔
1172
        numinfilelist = 1;
886✔
1173
        i = 0;
886✔
1174
        }
1175
        else if ( numinfilelist >= filelistsize ) {
2,770✔
1176
        VOID **fl = (VOID **)filelist;
1✔
1177
        i = filelistsize;
1✔
1178
        if ( DoubleList((VOID ***)(&fl),&filelistsize,(int)sizeof(FILES *),
1✔
1179
                        "list of open files") != 0 ) Terminate(-1);
×
1180
                filelist = (FILES **)fl;
1✔
1181
                for ( j = i; j < filelistsize; j++ ) filelist[j] = 0;
11✔
1182
                numinfilelist = i + 1;
1✔
1183
        }
1184
        else {
1185
        i = filelistsize;
8,453✔
1186
        for ( j = 0; j < filelistsize; j++ ) {
8,453✔
1187
            if ( filelist[j] == 0 ) { i = j; break; }
8,453✔
1188
        }
1189
                numinfilelist++;
2,769✔
1190
        }
1191
        filelist[i] = (FILES *)(filelist); /* Just for now to not get into problems */
3,656✔
1192
/*
1193
        The next code is not needed when we use open.
1194
        It may be needed when we use fopen.
1195
        fopen is used in minos.c without this central administration.
1196
*/
1197
        if ( numinfilelist > MAX_OPEN_FILES ) {
3,656✔
1198
#ifndef MALLOCDEBUG
1199
                UNRWLOCK(AM.handlelock);
×
1200
#endif
1201
                MesPrint("More than %d open files",MAX_OPEN_FILES);
×
1202
                Error0("System limit. This limit is not due to FORM!");
×
1203
        }
1204
        else {
1205
#ifndef MALLOCDEBUG
1206
                UNRWLOCK(AM.handlelock);
3,656✔
1207
#endif
1208
        }
1209
        return(i);
3,656✔
1210
}
1211

1212
/*
1213
                 #] CreateHandle : 
1214
                 #[ ReadFile :
1215
*/
1216

1217
LONG ReadFile(int handle, UBYTE *buffer, LONG size)
34,777✔
1218
{
1219
        LONG inbuf = 0, r;
34,777✔
1220
        FILES *f;
34,777✔
1221
        char *b;
34,777✔
1222
        b = (char *)buffer;
34,777✔
1223
        for(;;) {        /* Gotta do difficult because of VMS! */
48,049✔
1224
                RWLOCKR(AM.handlelock);
41,413✔
1225
                f = filelist[handle];
41,413✔
1226
                UNRWLOCK(AM.handlelock);
41,413✔
1227
#ifdef WITHSTATS
1228
                numreads++;
1229
#endif
1230
                r = Uread(b,1,size,f);
41,413✔
1231
                if ( r < 0 ) return(r);
41,413✔
1232
                if ( r == 0 ) return(inbuf);
41,413✔
1233
                inbuf += r;
33,882✔
1234
                if ( r == size ) return(inbuf);
33,882✔
1235
                if ( r > size ) return(-1);
6,636✔
1236
                size -= r;
6,636✔
1237
                b += r;
6,636✔
1238
        }
1239
}
1240

1241
/*
1242
                 #] ReadFile : 
1243
                 #[ ReadPosFile :
1244

1245
                Gets words from a file(handle).
1246
                First tries to get the information from the buffers.
1247
                Reads a file at a position. Updates the position.
1248
                Places a lock in the case of multithreading.
1249
                Exists for multiple reading from the same file.
1250
                size is the number of WORDs to read!!!!
1251

1252
                We may need some strategy in the caching. This routine is used from
1253
                GetOneTerm only. The problem is when it reads brackets and the
1254
                brackets are read backwards. This is very uneconomical because
1255
                each time it may read a large buffer.
1256
                On the other hand, reading piece by piece in GetOneTerm takes
1257
                much overhead as well.
1258
                Two strategies come to mind:
1259
                1: keep things as they are but limit the size of the buffers.
1260
                2: have the position of 'pos' at about 1/3 of the buffer.
1261
                   this is of course guess work.
1262
                Currently we have implemented the first method by creating the
1263
                setup parameter threadscratchsize with the default value 100K.
1264
                In the test program much bigger values gave a slower program.
1265
*/
1266

1267
LONG ReadPosFile(PHEAD FILEHANDLE *fi, UBYTE *buffer, LONG size, POSITION *pos)
9,114,303✔
1268
{
1269
        GETBIDENTITY
1270
        LONG i, retval = 0;
9,114,303✔
1271
        WORD *b = (WORD *)buffer, *t;
9,114,303✔
1272

1273
        if ( fi->handle < 0 ) {
9,114,303✔
1274
                fi->POfill = (WORD *)((UBYTE *)(fi->PObuffer) + BASEPOSITION(*pos));
×
1275
                t = fi->POfill;
×
1276
                while ( size > 0 && fi->POfill < fi->POfull ) { *b++ = *t++; size--; }
×
1277
        }
1278
        else {
1279
                if ( ISLESSPOS(*pos,fi->POposition) || ISGEPOSINC(*pos,fi->POposition,
9,114,303✔
1280
                        ((UBYTE *)(fi->POfull)-(UBYTE *)(fi->PObuffer))) ) {
1281
/*
1282
                        The start is not inside the buffer. Fill the buffer.
1283
*/
1284

1285
                        fi->POposition = *pos;
15,567✔
1286
                        LOCK(AS.inputslock);
15,567✔
1287
                        SeekFile(fi->handle,pos,SEEK_SET);
15,567✔
1288
                        retval = ReadFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize);
15,567✔
1289
                        UNLOCK(AS.inputslock);
15,567✔
1290
                        fi->POfull = fi->PObuffer+retval/sizeof(WORD);
15,567✔
1291
                        fi->POfill = fi->PObuffer;
15,567✔
1292
                        if ( fi != AR.hidefile ) AR.InInBuf = retval/sizeof(WORD);
15,567✔
1293
                        else                     AR.InHiBuf = retval/sizeof(WORD);
×
1294
                }
1295
                else {
1296
                        fi->POfill = (WORD *)((UBYTE *)(fi->PObuffer) + DIFBASE(*pos,fi->POposition));
9,098,736✔
1297
                }
1298
                if ( fi->POfill + size <= fi->POfull ) {
9,114,303✔
1299
                        t = fi->POfill;
1300
                        while ( size > 0 ) { *b++ = *t++; size--; }
28,195,288✔
1301
                }
1302
                else {
1303
                  for (;;) {
622✔
1304
                        i = fi->POfull - fi->POfill; t = fi->POfill;
622✔
1305
                        if ( i > size ) i = size;
622✔
1306
                        size -= i;
622✔
1307
                        while ( --i >= 0 ) *b++ = *t++;
2,191✔
1308
                        if ( size == 0 ) break;
622✔
1309
                        ADDPOS(fi->POposition,(UBYTE *)(fi->POfull)-(UBYTE *)(fi->PObuffer));
311✔
1310
                        LOCK(AS.inputslock);
311✔
1311
                        SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
311✔
1312
                        retval = ReadFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize);
311✔
1313
                        UNLOCK(AS.inputslock);
311✔
1314
                        fi->POfull = fi->PObuffer+retval/sizeof(WORD);
311✔
1315
                        fi->POfill = fi->PObuffer;
311✔
1316
                        if ( fi != AR.hidefile ) AR.InInBuf = retval/sizeof(WORD);
311✔
1317
                        else                     AR.InHiBuf = retval/sizeof(WORD);
×
1318
                        if ( retval == 0 ) { t = fi->POfill; break; }
311✔
1319
                  }
1320
                }
1321
        }
1322
        retval = (UBYTE *)b - buffer;
9,114,303✔
1323
        fi->POfill = t;
9,114,303✔
1324
        ADDPOS(*pos,retval);
9,114,303✔
1325
        return(retval);
9,114,303✔
1326
}
1327

1328
/*
1329
                 #] ReadPosFile : 
1330
                 #[ WriteFile :
1331
*/
1332

1333
LONG WriteFileToFile(int handle, UBYTE *buffer, LONG size)
53,309✔
1334
{
1335
        FILES *f;
53,309✔
1336
        LONG retval, totalwritten = 0, stilltowrite;
53,309✔
1337
        RWLOCKR(AM.handlelock);
53,309✔
1338
        f = filelist[handle];
53,309✔
1339
        UNRWLOCK(AM.handlelock);
53,309✔
1340
        while ( totalwritten < size ) {
106,594✔
1341
                stilltowrite = size - totalwritten;
53,285✔
1342
#ifdef WITHSTATS
1343
                numwrites++;
1344
#endif
1345
                retval = Uwrite((char *)buffer+totalwritten,1,stilltowrite,f);
53,285✔
1346
                if ( retval < 0 ) return(retval);
53,285✔
1347
                if ( retval == 0 ) return(totalwritten);
53,285✔
1348
                totalwritten += retval;
53,285✔
1349
        }
1350
/*
1351
if ( handle == AC.LogHandle || handle == ERROROUT ) FlushFile(handle);
1352
*/
1353
        return(totalwritten);
1354
}
1355
#ifndef WITHMPI
1356
/*[17nov2005]:*/
1357
WRITEFILE WriteFile = &WriteFileToFile;
1358
/*
1359
LONG (*WriteFile)(int handle, UBYTE *buffer, LONG size) = &WriteFileToFile;
1360
*/
1361
/*:[17nov2005]*/
1362
#else
1363
WRITEFILE WriteFile = &PF_WriteFileToFile;
1364
#endif
1365

1366
/*
1367
                 #] WriteFile : 
1368
                 #[ SeekFile :
1369
*/
1370

1371
VOID SeekFile(int handle, POSITION *offset, int origin)
35,462✔
1372
{
1373
        FILES *f;
35,462✔
1374
        RWLOCKR(AM.handlelock);
35,462✔
1375
        f = filelist[handle];
35,462✔
1376
        UNRWLOCK(AM.handlelock);
35,462✔
1377
#ifdef WITHSTATS
1378
        numseeks++;
1379
#endif
1380
        if ( origin == SEEK_SET ) {
35,462✔
1381
                Useek(f,BASEPOSITION(*offset),origin);
33,269✔
1382
                SETBASEPOSITION(*offset,(Utell(f)));
33,269✔
1383
                return;
33,269✔
1384
        }
1385
        else if ( origin == SEEK_END ) {
2,193✔
1386
                Useek(f,0,origin);
1,660✔
1387
        }
1388
        SETBASEPOSITION(*offset,(Utell(f)));
2,193✔
1389
}
1390

1391
/*
1392
                 #] SeekFile : 
1393
                 #[ TellFile :
1394
*/
1395

1396
LONG TellFile(int handle)
×
1397
{
1398
        POSITION pos;
×
1399
        TELLFILE(handle,&pos);
×
1400
#ifdef WITHSTATS
1401
        numseeks++;
1402
#endif
1403
        return(BASEPOSITION(pos));
×
1404
}
1405

1406
VOID TELLFILE(int handle, POSITION *position)
964✔
1407
{
1408
        FILES *f;
964✔
1409
        RWLOCKR(AM.handlelock);
964✔
1410
        f = filelist[handle];
964✔
1411
        UNRWLOCK(AM.handlelock);
964✔
1412
        SETBASEPOSITION(*position,(Utell(f)));
964✔
1413
}
964✔
1414

1415
/*
1416
                 #] TellFile : 
1417
                 #[ FlushFile :
1418
*/
1419

1420
void FlushFile(int handle)
27✔
1421
{
1422
        FILES *f;
27✔
1423
        RWLOCKR(AM.handlelock);
27✔
1424
        f = filelist[handle];
27✔
1425
        UNRWLOCK(AM.handlelock);
27✔
1426
        Uflush(f);
27✔
1427
}
27✔
1428

1429
/*
1430
                 #] FlushFile : 
1431
                 #[ GetPosFile :
1432
*/
1433

1434
int GetPosFile(int handle, fpos_t *pospointer)
×
1435
{
1436
        FILES *f;
×
1437
        RWLOCKR(AM.handlelock);
×
1438
        f = filelist[handle];
×
1439
        UNRWLOCK(AM.handlelock);
×
1440
        return(Ugetpos(f,pospointer));
×
1441
}
1442

1443
/*
1444
                 #] GetPosFile : 
1445
                 #[ SetPosFile :
1446
*/
1447

1448
int SetPosFile(int handle, fpos_t *pospointer)
×
1449
{
1450
        FILES *f;
×
1451
        RWLOCKR(AM.handlelock);
×
1452
        f = filelist[handle];
×
1453
        UNRWLOCK(AM.handlelock);
×
1454
        return(Usetpos(f,(fpos_t *)pospointer));
×
1455
}
1456

1457
/*
1458
                 #] SetPosFile : 
1459
                 #[ SynchFile :
1460

1461
                It may be that when we use many sort files at the same time there
1462
                is a big traffic jam in the cache. This routine is experimental,
1463
                just to see whether this improves the situation.
1464
                It could also be that the internal disk of the Quad opteron norma
1465
                is very slow.
1466
*/
1467

1468
VOID SynchFile(int handle)
×
1469
{
1470
        FILES *f;
×
1471
        if ( handle >= 0 ) {
×
1472
                RWLOCKR(AM.handlelock);
×
1473
                f = filelist[handle];
×
1474
                UNRWLOCK(AM.handlelock);
×
1475
                Usync(f);
×
1476
        }
1477
}
×
1478

1479
/*
1480
                 #] SynchFile : 
1481
                 #[ TruncateFile :
1482

1483
                It may be that when we use many sort files at the same time there
1484
                is a big traffic jam in the cache. This routine is experimental,
1485
                just to see whether this improves the situation.
1486
                It could also be that the internal disk of the Quad opteron norma
1487
                is very slow.
1488
*/
1489

1490
VOID TruncateFile(int handle)
×
1491
{
1492
        FILES *f;
×
1493
        if ( handle >= 0 ) {
×
1494
                RWLOCKR(AM.handlelock);
×
1495
                f = filelist[handle];
×
1496
                UNRWLOCK(AM.handlelock);
×
1497
                Utruncate(f);
×
1498
        }
1499
}
×
1500

1501
/*
1502
                 #] TruncateFile : 
1503
                 #[ GetChannel :
1504

1505
                Checks whether we have this file already. If so, we return its
1506
                handle. If not and mode == 0, we open the file first and add it
1507
                to the buffers.
1508
*/
1509

1510
int GetChannel(char *name,int mode)
87✔
1511
{
1512
        CHANNEL *ch;
87✔
1513
        int i;
87✔
1514
        FILES *f;
87✔
1515
        for ( i = 0; i < NumOutputChannels; i++ ) {
96✔
1516
                if ( channels[i].name == 0 ) continue;
78✔
1517
                if ( StrCmp((UBYTE *)name,(UBYTE *)(channels[i].name)) == 0 ) return(channels[i].handle);
78✔
1518
        }
1519
        if ( mode == 1 ) {
18✔
1520
                MesPrint("&File %s in print statement is not open",name);
×
1521
                MesPrint("   You should open it first with a #write or #append instruction");
×
1522
                return(-1);                
×
1523
        }
1524
        for ( i = 0; i < NumOutputChannels; i++ ) {
21✔
1525
                if ( channels[i].name == 0 ) break;
3✔
1526
        }
1527
        if ( i < NumOutputChannels ) { ch = &(channels[i]); }
18✔
1528
        else { ch = (CHANNEL *)FromList(&AC.ChannelList); }
18✔
1529
        ch->name = (char *)strDup1((UBYTE *)name,"name of channel");
18✔
1530
        ch->handle = CreateFile(name);
18✔
1531
        RWLOCKR(AM.handlelock);
18✔
1532
        f = filelist[ch->handle];
18✔
1533
        UNRWLOCK(AM.handlelock);
18✔
1534
        Usetbuf(f,0);         /* We turn the buffer off!!!!!!*/
18✔
1535
        return(ch->handle);
18✔
1536
}
1537

1538
/*
1539
                 #] GetChannel : 
1540
                 #[ GetAppendChannel :
1541

1542
                Checks whether we have this file already. If so, we return its
1543
                handle. If not, we open the file first and add it to the buffers.
1544
*/
1545

1546
int GetAppendChannel(char *name)
×
1547
{
1548
        CHANNEL *ch;
×
1549
        int i;
×
1550
        FILES *f;
×
1551
        for ( i = 0; i < NumOutputChannels; i++ ) {
×
1552
                if ( channels[i].name == 0 ) continue;
×
1553
                if ( StrCmp((UBYTE *)name,(UBYTE *)(channels[i].name)) == 0 ) return(channels[i].handle);
×
1554
        }
1555
        for ( i = 0; i < NumOutputChannels; i++ ) {
×
1556
                if ( channels[i].name == 0 ) break;
×
1557
        }
1558
        if ( i < NumOutputChannels ) { ch = &(channels[i]); }
×
1559
        else { ch = (CHANNEL *)FromList(&AC.ChannelList); }
×
1560
        ch->name = (char *)strDup1((UBYTE *)name,"name of channel");
×
1561
        ch->handle = OpenAddFile(name);
×
1562
        RWLOCKR(AM.handlelock);
×
1563
        f = filelist[ch->handle];
×
1564
        UNRWLOCK(AM.handlelock);
×
1565
        Usetbuf(f,0);         /* We turn the buffer off!!!!!!*/
×
1566
        return(ch->handle);
×
1567
}
1568

1569
/*
1570
                 #] GetAppendChannel : 
1571
                 #[ CloseChannel :
1572

1573
                Checks whether we have this file already. If so, we close it.
1574
*/
1575

1576
int CloseChannel(char *name)
×
1577
{
1578
        int i;
×
1579
        for ( i = 0; i < NumOutputChannels; i++ ) {
×
1580
                if ( channels[i].name == 0 ) continue;
×
1581
                if ( channels[i].name[0] == 0 ) continue;
×
1582
                if ( StrCmp((UBYTE *)name,(UBYTE *)(channels[i].name)) == 0 ) {
×
1583
                        CloseFile(channels[i].handle);
×
1584
                        M_free(channels[i].name,"CloseChannel");
×
1585
                        channels[i].name = 0;
×
1586
                        return(0);
×
1587
                }
1588
        }
1589
        return(0);
1590
}
1591

1592
/*
1593
                 #] CloseChannel : 
1594
                 #[ UpdateMaxSize :
1595

1596
                Updates the maximum size of the combined input/output/hide scratch
1597
                files, the sort files and the .str file.
1598
                The result becomes only visible with either
1599
                        ON totalsize;
1600
                        #: totalsize ON;
1601
                or the -T in the command tail.
1602

1603
                To be called, whenever a file is closed/removed or truncated to zero.
1604

1605
                We have no provisions yet for expressions that remain inside the
1606
                small or large buffer during the sort. The space they use there is
1607
                currently ignored.
1608
*/
1609

1610
void UpdateMaxSize(VOID)
9,811✔
1611
{
1612
        POSITION position, sumsize;
9,811✔
1613
        int i;
9,811✔
1614
        FILEHANDLE *scr;
9,811✔
1615
#ifdef WITHMPI
1616
        /* Currently, it works only on the master. The sort files on the slaves
1617
         * are ignored. (TU 11 Oct 2011) */
1618
        if ( PF.me != MASTER ) return;
1619
#endif
1620
        PUTZERO(sumsize);
9,811✔
1621
        if ( AM.PrintTotalSize ) {
9,811✔
1622
/*
1623
                First the three scratch files
1624
*/
1625
#ifdef WITHPTHREADS
1626
        scr = AB[0]->R.Fscr;
1627
#else
1628
        scr = AR.Fscr;
1629
#endif
1630
        for ( i = 0; i <=2; i++ ) {
×
1631
                if ( scr[i].handle < 0 ) {
×
1632
                        SETBASEPOSITION(position,(scr[i].POfull-scr[i].PObuffer)*sizeof(WORD));
×
1633
                }
1634
                else {
1635
                        position = scr[i].filesize;
×
1636
                }
1637
                ADD2POS(sumsize,position);
×
1638
        }
1639
/*
1640
                Now the sort file(s)
1641
*/
1642
#ifdef WITHPTHREADS
1643
        {
1644
                int j;
1645
                ALLPRIVATES *B;
1646
                for ( j = 0; j < AM.totalnumberofthreads; j++ ) {
1647
                        B = AB[j];
1648
                        if ( AT.SS && AT.SS->file.handle >= 0 ) {
1649
                                position = AT.SS->file.filesize;
1650
/*
1651
MLOCK(ErrorMessageLock);
1652
MesPrint("%d: %10p",j,&(AT.SS->file.filesize));
1653
MUNLOCK(ErrorMessageLock);
1654
*/
1655
                                ADD2POS(sumsize,position);
1656
                        }
1657
                        if ( AR.FoStage4[0].handle >= 0 ) {
1658
                                position = AR.FoStage4[0].filesize;
1659
                                ADD2POS(sumsize,position);
1660
                        }
1661
                }
1662
        }
1663
#else
1664
        if ( AT.SS && AT.SS->file.handle >= 0 ) {
1665
                position = AT.SS->file.filesize;
1666
                ADD2POS(sumsize,position);
1667
        }
1668
        if ( AR.FoStage4[0].handle >= 0 ) {
1669
                position = AR.FoStage4[0].filesize;
1670
                ADD2POS(sumsize,position);
1671
        }
1672
#endif
1673
/*
1674
                And of course the str file.
1675
*/
1676
        ADD2POS(sumsize,AC.StoreFileSize);
×
1677
/*
1678
                Finally the test whether it is bigger
1679
*/
1680
        if ( ISLESSPOS(AS.MaxExprSize,sumsize) ) {
×
1681
#ifdef WITHPTHREADS
1682
                LOCK(AS.MaxExprSizeLock);
1683
                if ( ISLESSPOS(AS.MaxExprSize,sumsize) ) AS.MaxExprSize = sumsize;
1684
                UNLOCK(AS.MaxExprSizeLock);
1685
#else
1686
                AS.MaxExprSize = sumsize;
1687
#endif
1688
        }
1689
        }
1690
        return;
9,811✔
1691
}
1692

1693
/*
1694
                 #] UpdateMaxSize : 
1695
          #] Files : 
1696
          #[ Strings :
1697
                 #[ StrCmp :
1698
*/
1699

1700
int StrCmp(UBYTE *s1, UBYTE *s2)
18,878,313✔
1701
{
1702
        while ( *s1 && *s1 == *s2 ) { s1++; s2++; }
31,504,352✔
1703
        return((int)*s1-(int)*s2);
18,878,313✔
1704
}
1705

1706
/*
1707
                 #] StrCmp : 
1708
                 #[ StrICmp :
1709
*/
1710

1711
int StrICmp(UBYTE *s1, UBYTE *s2)
19,268,563✔
1712
{
1713
        while ( *s1 && tolower(*s1) == tolower(*s2) ) { s1++; s2++; }
38,123,979✔
1714
        return((int)tolower(*s1)-(int)tolower(*s2));
19,268,563✔
1715
}
1716

1717
/*
1718
                 #] StrICmp : 
1719
                 #[ StrHICmp :
1720
*/
1721

1722
int StrHICmp(UBYTE *s1, UBYTE *s2)
24✔
1723
{
1724
        while ( *s1 && tolower(*s1) == *s2 ) { s1++; s2++; }
78✔
1725
        return((int)tolower(*s1)-(int)(*s2));
24✔
1726
}
1727

1728
/*
1729
                 #] StrHICmp : 
1730
                 #[ StrICont :
1731
*/
1732

1733
int StrICont(UBYTE *s1, UBYTE *s2)
17,223✔
1734
{
1735
        while ( *s1 && tolower(*s1) == tolower(*s2) ) { s1++; s2++; }
59,672✔
1736
        if ( *s1 == 0 ) return(0);
17,223✔
1737
        return((int)tolower(*s1)-(int)tolower(*s2));
8,182✔
1738
}
1739

1740
/*
1741
                 #] StrICont : 
1742
                 #[ CmpArray :
1743
*/
1744

1745
int CmpArray(WORD *t1, WORD *t2, WORD n)
×
1746
{
1747
        int i,x;
×
1748
        for ( i = 0; i < n; i++ ) {
×
1749
                if ( ( x = (int)(t1[i]-t2[i]) ) != 0 ) return(x);
×
1750
        }
1751
        return(0);
1752
}
1753

1754
/*
1755
                 #] CmpArray : 
1756
                 #[ ConWord :
1757
*/
1758

1759
int ConWord(UBYTE *s1, UBYTE *s2)
×
1760
{
1761
        while ( *s1 && ( tolower(*s1) == tolower(*s2) ) ) { s1++; s2++; }
×
1762
        if ( *s1 == 0 ) return(1);
×
1763
        return(0);
1764
}
1765

1766
/*
1767
                 #] ConWord : 
1768
                 #[ StrLen :
1769
*/
1770

1771
int StrLen(UBYTE *s)
132✔
1772
{
1773
        int i = 0;
132✔
1774
        while ( *s ) { s++; i++; }
1,167✔
1775
        return(i);
132✔
1776
}
1777

1778
/*
1779
                 #] StrLen : 
1780
                 #[ NumToStr :
1781
*/
1782

1783
VOID NumToStr(UBYTE *s, LONG x)
2,240,164✔
1784
{
1785
        UBYTE *t, str[24];
2,240,164✔
1786
        ULONG xx;
2,240,164✔
1787
        t = str;
2,240,164✔
1788
        if ( x < 0 ) { *s++ = '-'; xx = -x; }
2,240,164✔
1789
        else xx = x;
2,240,146✔
1790
        do {
2,287,696✔
1791
                *t++ = xx % 10 + '0';
2,287,696✔
1792
                xx /= 10;
2,287,696✔
1793
        } while ( xx );
2,287,696✔
1794
        while ( t > str ) *s++ = *--t;
4,527,860✔
1795
        *s = 0;
2,240,164✔
1796
}
2,240,164✔
1797

1798
/*
1799
                 #] NumToStr : 
1800
                 #[ WriteString :
1801

1802
                Writes a characterstring to the various outputs.
1803
                The action may depend on the flags involved.
1804
                The type of output is given by type, the string by str and the
1805
                number of characters in it by num
1806
*/
1807
VOID WriteString(int type, UBYTE *str, int num)
26,195✔
1808
{
1809
        int error = 0;
26,195✔
1810

1811
        if ( num > 0 && str[num-1] == 0 ) { num--; }
26,195✔
1812
        else if ( num <= 0 || str[num-1] != LINEFEED ) {
23,482✔
1813
                AddLineFeed(str,num);
14,769✔
1814
        }
1815
        /*[15apr2004 mt]:*/
1816
        if(type == EXTERNALCHANNELOUT){
26,195✔
1817
                if(WriteFile(0,str,num) != num) error = 1;
×
1818
        }else
1819
        /*:[15apr2004 mt]*/
1820
        if ( AM.silent == 0 || type == ERROROUT ) {
26,195✔
1821
                if ( type == INPUTOUT ) {
26,195✔
1822
                        if ( !AM.FileOnlyFlag && WriteFile(AM.StdOut,(UBYTE *)"    ",4) != 4 ) error = 1;
10,582✔
1823
                        if ( AC.LogHandle >= 0 && WriteFile(AC.LogHandle,(UBYTE *)"    ",4) != 4 ) error = 1;
10,582✔
1824
                }
1825
                if ( !AM.FileOnlyFlag && WriteFile(AM.StdOut,str,num) != num ) error = 1;
26,195✔
1826
                if ( AC.LogHandle >= 0 && WriteFile(AC.LogHandle,str,num) != num ) error = 1;
26,195✔
1827
        }
1828
        if ( error ) Terminate(-1);
26,195✔
1829
}
26,195✔
1830

1831
/*
1832
                 #] WriteString : 
1833
                 #[ WriteUnfinString :
1834

1835
                Writes a characterstring to the various outputs.
1836
                The action may depend on the flags involved.
1837
                The type of output is given by type, the string by str and the
1838
                number of characters in it by num
1839
*/
1840

1841
VOID WriteUnfinString(int type, UBYTE *str, int num)
42✔
1842
{
1843
        int error = 0;
42✔
1844

1845
        /*[15apr2004 mt]:*/
1846
        if(type == EXTERNALCHANNELOUT){
42✔
1847
                if(WriteFile(0,str,num) != num) error = 1;
×
1848
        }else
1849
        /*:[15apr2004 mt]*/
1850
        if ( AM.silent == 0 || type == ERROROUT ) {
42✔
1851
                if ( type == INPUTOUT ) {
42✔
1852
                        if ( !AM.FileOnlyFlag && WriteFile(AM.StdOut,(UBYTE *)"    ",4) != 4 ) error = 1;
×
1853
                        if ( AC.LogHandle >= 0 && WriteFile(AC.LogHandle,(UBYTE *)"    ",4) != 4 ) error = 1;
×
1854
                }
1855
                if ( !AM.FileOnlyFlag && WriteFile(AM.StdOut,str,num) != num ) error = 1;
42✔
1856
                if ( AC.LogHandle >= 0 && WriteFile(AC.LogHandle,str,num) != num ) error = 1;
42✔
1857
        }
1858
        if ( error ) Terminate(-1);
42✔
1859
}
42✔
1860

1861
/*
1862
                 #] WriteUnfinString : 
1863
                 #[ AddToString :
1864
*/
1865

1866
UBYTE *AddToString(UBYTE *outstring, UBYTE *extrastring, int par)
192✔
1867
{
1868
        UBYTE *s = extrastring, *t, *newstring;
192✔
1869
        int n, nn;
192✔
1870
        while ( *s ) { s++; }
654✔
1871
        n = s-extrastring;
192✔
1872
        if ( outstring == 0 ) {
192✔
1873
                s = extrastring;
36✔
1874
                t = outstring = (UBYTE *)Malloc1(n+1,"AddToString");
36✔
1875
                NCOPY(t,s,n)
159✔
1876
                *t++ = 0;
36✔
1877
                return(outstring);
36✔
1878
        }
1879
        else {
1880
                t = outstring;
1881
                while ( *t ) t++;
3,885✔
1882
                nn = t - outstring;
156✔
1883
                t = newstring = (UBYTE *)Malloc1(n+nn+2,"AddToString");
156✔
1884
                s = outstring;
156✔
1885
                NCOPY(t,s,nn)
3,885✔
1886
                if ( par == 1 ) *t++ = ',';
156✔
1887
                s = extrastring;
1888
                NCOPY(t,s,n)
495✔
1889
                *t = 0;
156✔
1890
                M_free(outstring,"AddToString");
156✔
1891
                return(newstring);
156✔
1892
        }
1893
}
1894

1895
/*
1896
                 #] AddToString : 
1897
                 #[ strDup1 :
1898

1899
                string duplication with message passing for Malloc1, allowing
1900
                this routine to give a more detailed error message if there
1901
                is not enough memory.
1902
*/
1903

1904
UBYTE *strDup1(UBYTE *instring, char *ifwrong)
155,807✔
1905
{
1906
        UBYTE *s = instring, *to;
155,807✔
1907
        while ( *s ) s++;
388,696✔
1908
        to = s = (UBYTE *)Malloc1((s-instring)+1,ifwrong);
155,807✔
1909
        while ( *instring ) *to++ = *instring++;
388,696✔
1910
        *to = 0;
155,807✔
1911
        return(s);
155,807✔
1912
}
1913

1914
/*
1915
                 #] strDup1 : 
1916
                 #[ EndOfToken :
1917
*/
1918

1919
UBYTE *EndOfToken(UBYTE *s)
4,617,416✔
1920
{
1921
        UBYTE c;
4,617,416✔
1922
        while ( ( c = (UBYTE)(FG.cTable[*s]) ) == 0 || c == 1 ) s++;
33,787,318✔
1923
        return(s);
4,617,416✔
1924
}
1925

1926
/*
1927
                 #] EndOfToken : 
1928
                 #[ ToToken :
1929
*/
1930

1931
UBYTE *ToToken(UBYTE *s)
60✔
1932
{
1933
        UBYTE c;
60✔
1934
        while ( *s && ( c = (UBYTE)(FG.cTable[*s]) ) != 0 && c != 1 ) s++;
69✔
1935
        return(s);
60✔
1936
}
1937

1938
/*
1939
                 #] ToToken : 
1940
                 #[ SkipField :
1941

1942
        Skips from s to the end of a declaration field.
1943
        par is the number of parentheses that still has to be closed.
1944
*/
1945
 
1946
UBYTE *SkipField(UBYTE *s, int level)
276✔
1947
{
1948
        while ( *s ) {
15,582✔
1949
                if ( *s == ',' && level == 0 ) return(s);
15,318✔
1950
                if ( *s == '(' ) level++;
15,306✔
1951
                else if ( *s == ')' ) { level--; if ( level < 0 ) level = 0; }
13,101✔
1952
                else if ( *s == '[' ) {
10,896✔
1953
                        SKIPBRA1(s)
9✔
1954
                }
1955
                else if ( *s == '{' ) {
10,893✔
1956
                        SKIPBRA2(s)
×
1957
                }
1958
                s++;
15,306✔
1959
        }
1960
        return(s);
1961
}
1962

1963
/*
1964
                 #] SkipField : 
1965
                 #[ ReadSnum :                        WORD ReadSnum(p)
1966

1967
                Reads a number that should fit in a word.
1968
                The number should be unsigned and a negative return value
1969
                indicates an irregularity.
1970

1971
*/
1972

1973
WORD ReadSnum(UBYTE **p)
×
1974
{
1975
        LONG x = 0;
×
1976
        UBYTE *s;
×
1977
        s = *p;
×
1978
        if ( FG.cTable[*s] == 1 ) {
×
1979
                do {
×
1980
                        x = ( x << 3 ) + ( x << 1 ) + ( *s++ - '0' );
×
1981
                        if ( x > MAXPOSITIVE ) return(-1);
×
1982
                } while ( FG.cTable[*s] == 1 );
×
1983
                *p = s;
×
1984
                return((WORD)x);
×
1985
        }
1986
        else return(-1);
1987
}
1988

1989
/*
1990
                 #] ReadSnum : 
1991
                 #[ NumCopy :
1992

1993
        Adds the decimal representation of a number to a string.
1994

1995
*/
1996

1997
UBYTE *NumCopy(WORD y, UBYTE *to)
171,964✔
1998
{
1999
        UBYTE *s;
171,964✔
2000
        WORD i = 0, j;
171,964✔
2001
        UWORD x;
171,964✔
2002
        if ( y < 0 ) {
171,964✔
2003
                *to++ = '-';
339✔
2004
        }
2005
        x = WordAbs(y);
171,964✔
2006
        s = to;
171,964✔
2007
        do { *s++ = (UBYTE)((x % 10)+'0'); i++; } while ( ( x /= 10 ) != 0 );
659,200✔
2008
        *s-- = '\0';
171,964✔
2009
        j = ( i - 1 ) >> 1;
171,964✔
2010
        while ( j >= 0 ) {
565,418✔
2011
                i = to[j]; to[j] = s[-j]; s[-j] = (UBYTE)i; j--;
393,454✔
2012
        }
2013
        return(s+1);
171,964✔
2014
}
2015

2016
/*
2017
                 #] NumCopy : 
2018
                 #[ LongCopy :
2019

2020
        Adds the decimal representation of a number to a string.
2021

2022
*/
2023

2024
char *LongCopy(LONG y, char *to)
3,995✔
2025
{
2026
        char *s;
3,995✔
2027
        WORD i = 0, j;
3,995✔
2028
        ULONG x;
3,995✔
2029
        if ( y < 0 ) {
3,995✔
2030
                *to++ = '-';
×
2031
        }
2032
        x = LongAbs(y);
3,995✔
2033
        s = to;
3,995✔
2034
        do { *s++ = (x % 10)+'0'; i++; } while ( ( x /= 10 ) != 0 );
6,821✔
2035
        *s-- = '\0';
3,995✔
2036
        j = ( i - 1 ) >> 1;
3,995✔
2037
        while ( j >= 0 ) {
8,948✔
2038
                i = to[j]; to[j] = s[-j]; s[-j] = (char)i; j--;
4,953✔
2039
        }
2040
        return(s+1);
3,995✔
2041
}
2042

2043
/*
2044
                 #] LongCopy : 
2045
                 #[ LongLongCopy :
2046

2047
        Adds the decimal representation of a number to a string.
2048
        Bugfix feb 2003. y was not pointer!
2049
*/
2050

2051
char *LongLongCopy(off_t *y, char *to)
×
2052
{
2053
        /*
2054
         * This code fails to print the maximum negative value on systems with two's
2055
         * complement. To fix this, we need the unsigned version of off_t with the
2056
         * same size, but unfortunately it is undefined. On the other hand, if a
2057
         * system is configured with a 64-bit off_t, in practice one never reaches
2058
         * 2^63 ~ 10^18 as of 2016. If one really reach such a big number, then it
2059
         * would be the time to move on a 128-bit off_t.
2060
         */
2061
        off_t x = *y;
×
2062
        char *s;
×
2063
        WORD i = 0, j;
×
2064
        if ( x < 0 ) { x = -x; *to++ = '-'; }
×
2065
        s = to;
×
2066
        do { *s++ = (x % 10)+'0'; i++; } while ( ( x /= 10 ) != 0 );
×
2067
        *s-- = '\0';
×
2068
        j = ( i - 1 ) >> 1;
×
2069
        while ( j >= 0 ) {
×
2070
                i = to[j]; to[j] = s[-j]; s[-j] = (char)i; j--;
×
2071
        }
2072
        return(s+1);
×
2073
}
2074

2075
/*
2076
                 #] LongLongCopy : 
2077
                 #[ MakeDate :
2078

2079
                Routine produces a string with the date and time of the run
2080
*/
2081

2082
#ifdef ANSI
2083
#else
2084
#ifdef mBSD
2085
#else
2086
static char notime[] = "";
2087
#endif
2088
#endif
2089

2090
UBYTE *MakeDate(VOID)
1,769✔
2091
{
2092
#ifdef ANSI
2093
        time_t tp;
1,769✔
2094
        time(&tp);
1,769✔
2095
        return((UBYTE *)ctime(&tp));
1,769✔
2096
#else
2097
#ifdef mBSD
2098
        time_t tp;
2099
        time(&tp);
2100
        return((UBYTE *)ctime(&tp));
2101
#else
2102
        return((UBYTE *)notime);
2103
#endif
2104
#endif
2105
}
2106

2107
/*
2108
                 #] MakeDate : 
2109
                 #[ set_in :
2110
         Returns 1 if ch is in set ; 0 if ch is not in set:
2111
*/
2112
int set_in(UBYTE ch, set_of_char set)
1,224✔
2113
{
2114
        set += ch/8;
1,224✔
2115
        switch (ch % 8){
1,224✔
2116
                case 0: return(set->bit_0);
117✔
2117
                case 1: return(set->bit_1);
183✔
2118
                case 2: return(set->bit_2);
126✔
2119
                case 3: return(set->bit_3);
129✔
2120
                case 4: return(set->bit_4);
354✔
2121
                case 5: return(set->bit_5);
132✔
2122
                case 6: return(set->bit_6);
90✔
2123
                case 7: return(set->bit_7);
93✔
2124
        }/*switch (ch % 8)*/
2125
        return(-1);
2126
}/*set_in*/
2127
/*
2128
                 #] set_in : 
2129
                 #[ set_set :
2130
                        sets ch into set; returns *set:
2131
*/
2132
one_byte set_set(UBYTE ch, set_of_char set)
1,772✔
2133
{
2134
        one_byte tmp=(one_byte)set;
1,772✔
2135
        set += ch/8;
1,772✔
2136
        switch (ch % 8){
1,772✔
2137
                case 0: set->bit_0=1;break;
×
2138
                case 1: set->bit_1=1;break;
×
2139
                case 2: set->bit_2=1;break;
×
2140
                case 3: set->bit_3=1;break;
×
2141
                case 4: set->bit_4=1;break;
1,772✔
2142
                case 5: set->bit_5=1;break;
×
2143
                case 6: set->bit_6=1;break;
×
2144
                case 7: set->bit_7=1;break;
×
2145
        }
2146
        return(tmp);
1,772✔
2147
}/*set_set*/
2148
/*
2149
                 #] set_set : 
2150
                 #[ set_del :
2151
                        deletes ch from set; returns *set:
2152
*/
2153
one_byte set_del(UBYTE ch, set_of_char set)
×
2154
{
2155
        one_byte tmp=(one_byte)set;
×
2156
        set += ch/8;
×
2157
        switch (ch % 8){
×
2158
                case 0: set->bit_0=0;break;
×
2159
                case 1: set->bit_1=0;break;
×
2160
                case 2: set->bit_2=0;break;
×
2161
                case 3: set->bit_3=0;break;
×
2162
                case 4: set->bit_4=0;break;
×
2163
                case 5: set->bit_5=0;break;
×
2164
                case 6: set->bit_6=0;break;
×
2165
                case 7: set->bit_7=0;break;
×
2166
        }
2167
        return(tmp);
×
2168
}/*set_del*/
2169
/*
2170
                 #] set_del : 
2171
                 #[ set_sub :
2172
                        returns *set = set1\set2. This function may be usd for initialising,
2173
                                set_sub(a,a,a) => now a is empty set :
2174
*/
2175
one_byte set_sub(set_of_char set, set_of_char set1, set_of_char set2)
886✔
2176
{
2177
        one_byte tmp=(one_byte)set;
886✔
2178
        int i=0,j=0;
886✔
2179
        while(j=0,i++<32)
29,238✔
2180
        while(j<9)
283,520✔
2181
                switch (j++){
255,168✔
2182
                        case 0: set->bit_0=(set1->bit_0&&(!set2->bit_0));break;
56,704✔
2183
                        case 1: set->bit_1=(set1->bit_1&&(!set2->bit_1));break;
56,704✔
2184
                        case 2: set->bit_2=(set1->bit_2&&(!set2->bit_2));break;
56,704✔
2185
                        case 3: set->bit_3=(set1->bit_3&&(!set2->bit_3));break;
56,704✔
2186
                        case 4: set->bit_4=(set1->bit_4&&(!set2->bit_4));break;
56,704✔
2187
                        case 5: set->bit_5=(set1->bit_5&&(!set2->bit_5));break;
56,704✔
2188
                        case 6: set->bit_6=(set1->bit_6&&(!set2->bit_6));break;
56,704✔
2189
                        case 7: set->bit_7=(set1->bit_7&&(!set2->bit_7));break;
56,704✔
2190
                        case 8: set++;set1++;set2++;
28,352✔
2191
     };
886✔
2192
        return(tmp);
886✔
2193
}/*set_sub*/
2194
/*
2195
                 #] set_sub : 
2196
          #] Strings : 
2197
          #[ Mixed :
2198
                 #[ iniTools :
2199
*/
2200

2201
VOID iniTools(VOID)
886✔
2202
{
2203
#ifdef MALLOCPROTECT
2204
        if ( mprotectInit() ) exit(0);
2205
#endif
2206
        return;
886✔
2207
}
2208

2209
/*
2210
                 #] iniTools : 
2211
                 #[ Malloc :
2212

2213
                Malloc routine with built in error checking.
2214
                This saves lots of messages.
2215
*/
2216
#ifdef MALLOCDEBUG
2217
char *dummymessage = "Malloc";
2218
INILOCK(MallocLock)
2219
#endif
2220
 
2221
VOID *Malloc(LONG size)
×
2222
{
2223
        VOID *mem;
×
2224
#ifdef MALLOCDEBUG
2225
        char *t, *u;
2226
        int i;
2227
        LOCK(MallocLock);
2228
/*        MLOCK(ErrorMessageLock); */
2229
        if ( size == 0 ) {
2230
                MesPrint("Asking for 0 bytes in Malloc");
2231
        }
2232
#endif
2233
        if ( ( size & 7 ) != 0 ) { size = size - ( size&7 ) + 8; }
×
2234
#ifdef MALLOCDEBUG
2235
        size += 2*BANNER;
2236
#endif
2237
        mem = (VOID *)M_alloc(size);
×
2238
        if ( mem == 0 ) {
×
2239
#ifndef MALLOCDEBUG
2240
                MLOCK(ErrorMessageLock);
×
2241
#endif
2242
                Error0("No memory!");
×
2243
#ifndef MALLOCDEBUG
2244
                MUNLOCK(ErrorMessageLock);
×
2245
#else
2246
/*                MUNLOCK(ErrorMessageLock); */
2247
#endif
2248
#ifdef MALLOCDEBUG
2249
                UNLOCK(MallocLock);
2250
#endif
2251
                Terminate(-1);
×
2252
        }
2253
#ifdef MALLOCDEBUG
2254
        mallocsizes[nummalloclist] = size;
2255
        mallocstrings[nummalloclist] = dummymessage;
2256
        malloclist[nummalloclist++] = mem;
2257
        if ( filelist ) MesPrint("Mem0 at 0x%x, %l bytes",mem,size);
2258
        {
2259
                int i = nummalloclist-1;
2260
                while ( --i >= 0 ) {
2261
                        if ( (char *)mem < (((char *)malloclist[i]) + mallocsizes[i])
2262
                        && (char *)(malloclist[i]) < ((char *)mem + size) ) {
2263
                                if ( filelist ) MesPrint("This memory overlaps with the block at 0x%x"
2264
                                        ,malloclist[i]);
2265
                        }
2266
                }
2267
        }
2268
        t = (char *)mem;
2269
        u = t + size;
2270
        for ( i = 0; i < (int)BANNER; i++ ) { *t++ = FILLVALUE; *--u = FILLVALUE; }
2271
        mem = (void *)t;
2272
        {
2273
                int j = nummalloclist-1, i;
2274
                while ( --j >= 0 ) {
2275
                        t = (char *)(malloclist[j]);
2276
                        u = t + mallocsizes[j];
2277
                        for ( i = 0; i < (int)BANNER; i++ ) {
2278
                                u--;
2279
                                if ( *t != FILLVALUE || *u != FILLVALUE ) {
2280
                                        MesPrint("Writing outside memory for %s",malloclist[i]);
2281
/*                                        MUNLOCK(ErrorMessageLock); */
2282
                                        UNLOCK(MallocLock);
2283
                                        Terminate(-1);
2284
                                }
2285
                                t--;
2286
                        }
2287
                }
2288
        }
2289
/*        MUNLOCK(ErrorMessageLock); */
2290
        UNLOCK(MallocLock);
2291
#endif
2292
        return(mem);
×
2293
}
2294

2295
/*
2296
                 #] Malloc : 
2297
                 #[ Malloc1 :
2298

2299
                Malloc with more detailed error message.
2300
                Gives the user some idea of what is happening.
2301
*/
2302

2303
VOID *Malloc1(LONG size, const char *messageifwrong)
489,190✔
2304
{
2305
        VOID *mem;
489,190✔
2306
#ifdef MALLOCDEBUG
2307
        char *t, *u;
2308
        int i;
2309
        LOCK(MallocLock);
2310
/*        MLOCK(ErrorMessageLock); */
2311
        if ( size == 0 ) {
2312
                MesPrint("%wAsking for 0 bytes in Malloc1");
2313
        }
2314
#endif
2315
#ifdef WITHSTATS
2316
        nummallocs++;
2317
#endif
2318
        if ( ( size & 7 ) != 0 ) { size = size - ( size&7 ) + 8; }
489,190✔
2319
#ifdef MALLOCDEBUG
2320
        size += 2*BANNER;
2321
#endif
2322
        mem = (VOID *)M_alloc(size);
489,190✔
2323
        if ( mem == 0 ) {
489,190✔
2324
#ifndef MALLOCDEBUG
2325
                MLOCK(ErrorMessageLock);
×
2326
#endif
2327
                Error1("No memory while allocating ",(UBYTE *)messageifwrong);
×
2328
#ifndef MALLOCDEBUG
2329
                MUNLOCK(ErrorMessageLock);
×
2330
#else
2331
/*                MUNLOCK(ErrorMessageLock); */
2332
#endif
2333
#ifdef MALLOCDEBUG
2334
                UNLOCK(MallocLock);
2335
#endif
2336
                Terminate(-1);
×
2337
        }
2338
#ifdef MALLOCDEBUG
2339
        mallocsizes[nummalloclist] = size;
2340
        mallocstrings[nummalloclist] = (char *)messageifwrong;
2341
        malloclist[nummalloclist++] = mem;
2342
        if ( AC.MemDebugFlag && filelist ) MesPrint("%wMem1 at 0x%x: %l bytes. %s",mem,size,messageifwrong);
2343
        {
2344
                int i = nummalloclist-1;
2345
                while ( --i >= 0 ) {
2346
                        if ( (char *)mem < (((char *)malloclist[i]) + mallocsizes[i])
2347
                        && (char *)(malloclist[i]) < ((char *)mem + size) ) {
2348
                                if ( filelist ) MesPrint("This memory overlaps with the block at 0x%x"
2349
                                        ,malloclist[i]);
2350
                        }
2351
                }
2352
        }
2353

2354
#ifdef MALLOCDEBUGOUTPUT
2355
        printf ("Malloc1: %s, allocated %li bytes at %.8lx\n",messageifwrong,size,(unsigned long)mem);
2356
        fflush (stdout);
2357
#endif
2358
        
2359
        t = (char *)mem;
2360
        u = t + size;
2361
        for ( i = 0; i < (int)BANNER; i++ ) { *t++ = FILLVALUE; *--u = FILLVALUE; }
2362
        mem = (void *)t;
2363
        M_check();
2364
/*        MUNLOCK(ErrorMessageLock); */
2365
        UNLOCK(MallocLock);
2366
#endif
2367
/* 
2368
        if ( size > 500000000L ) {
2369
                MLOCK(ErrorMessageLock);
2370
                MesPrint("Malloc1: %s, allocated %l bytes\n",messageifwrong,size);
2371
                MUNLOCK(ErrorMessageLock);
2372
        }
2373
*/
2374
        return(mem);
489,190✔
2375
}
2376

2377
/*
2378
                 #] Malloc1 : 
2379
                 #[ M_free :
2380
*/
2381

2382
void M_free(VOID *x, const char *where)
220,857✔
2383
{
2384
#ifdef MALLOCDEBUG
2385
        char *t = (char *)x;
2386
        int i, j, k;
2387
        LONG size = 0;
2388
        x = (void *)(((char *)x)-BANNER);
2389
/*        MLOCK(ErrorMessageLock); */
2390
        if ( AC.MemDebugFlag ) MesPrint("%wFreeing 0x%x: %s",x,where);
2391
        LOCK(MallocLock);
2392
        for ( i = nummalloclist-1; i >= 0; i-- ) {
2393
                if ( x == malloclist[i] ) {
2394
                        size = mallocsizes[i];
2395
                        for ( j = i+1; j < nummalloclist; j++ ) {
2396
                                malloclist[j-1] = malloclist[j];
2397
                                mallocsizes[j-1] = mallocsizes[j];
2398
                                mallocstrings[j-1] = mallocstrings[j];
2399
                        }
2400
                        nummalloclist--;
2401
                        break;
2402
                }
2403
        }
2404
        if ( i < 0 ) {
2405
                unsigned int xx = ((ULONG)x);
2406
                printf("Error returning non-allocated address: 0x%x from %s\n"
2407
                        ,xx,where);
2408
/*                MUNLOCK(ErrorMessageLock); */
2409
                UNLOCK(MallocLock);
2410
                exit(-1);
2411
        }
2412
        else {
2413
                for ( k = 0, j = 0; k < (int)BANNER; k++ ) {
2414
                        if ( *--t != FILLVALUE ) j++;
2415
                }
2416
                if ( j ) {
2417
                        LONG *tt = (LONG *)x;
2418
                        MesPrint("%w!!!!! Banner has been written in !!!!!: %x %x %x %x",
2419
                        tt[0],tt[1],tt[2],tt[3]);
2420
                }
2421
                t += size;
2422
                for ( k = 0, j = 0; k < (int)BANNER; k++ ) {
2423
                        if ( *--t != FILLVALUE ) j++;
2424
                }
2425
                if ( j ) {
2426
                        LONG *tt = (LONG *)x;
2427
                        MesPrint("%w!!!!! Tail has been written in !!!!!: %x %x %x %x",
2428
                        tt[0],tt[1],tt[2],tt[3]);
2429
                }
2430
                M_check();
2431
/*                MUNLOCK(ErrorMessageLock); */
2432
                UNLOCK(MallocLock);
2433
        }
2434
#else
2435
        DUMMYUSE(where);
220,857✔
2436
#endif
2437
#ifdef WITHSTATS
2438
        numfrees++;
2439
#endif
2440
        if ( x ) {
220,857✔
2441
#ifdef MALLOCDEBUGOUTPUT
2442
                printf ("M_free: %s, memory freed at %.8lx\n",where,(unsigned long)x);
2443
                fflush(stdout);
2444
#endif
2445
                
2446
#ifdef MALLOCPROTECT
2447
                mprotectFree((void *)x);
2448
#else
2449
                free(x);
220,857✔
2450
#endif
2451
        }
2452
}
220,857✔
2453

2454
/*
2455
                 #] M_free : 
2456
                 #[ M_check :
2457
*/
2458

2459
#ifdef MALLOCDEBUG
2460

2461
void M_check1() { MesPrint("Checking Malloc"); M_check(); }
2462

2463
void M_check()
2464
{
2465
        int i,j,k,error = 0;
2466
        char *t;
2467
        LONG *tt;
2468
        for ( i = 0; i < nummalloclist; i++ ) {
2469
                t = (char *)(malloclist[i]);
2470
                for ( k = 0, j = 0; k < (int)BANNER; k++ ) {
2471
                        if ( *t++ != FILLVALUE ) j++;
2472
                }
2473
                if ( j ) {
2474
                        tt = (LONG *)(malloclist[i]);
2475
                        MesPrint("%w!!!!! Banner %d (%s) has been written in !!!!!: %x %x %x %x",
2476
                        i,mallocstrings[i],tt[0],tt[1],tt[2],tt[3]);
2477
                        tt[0] = tt[1] = tt[2] = tt[3] = 0;
2478
                        error = 1;
2479
                }
2480
                t = (char *)(malloclist[i]) + mallocsizes[i];
2481
                for ( k = 0, j = 0; k < (int)BANNER; k++ ) {
2482
                        if ( *--t != FILLVALUE ) j++;
2483
                }
2484
                if ( j ) {
2485
                        tt = (LONG *)t;
2486
                        MesPrint("%w!!!!! Tail %d (%s) has been written in !!!!!: %x %x %x %x",
2487
                        i,mallocstrings[i],tt[0],tt[1],tt[2],tt[3]);
2488
                        tt[0] = tt[1] = tt[2] = tt[3] = 0;
2489
                        error = 1;
2490
                }
2491
                if ( ( mallocstrings[i][0] == ' ' ) || ( mallocstrings[i][0] == '#' ) ) {
2492
                        MesPrint("%w!!!!! Funny mallocstring");
2493
                        error = 1;
2494
                }
2495
        }
2496
        if ( error ) {
2497
                M_print();
2498
/*                MUNLOCK(ErrorMessageLock); */
2499
                UNLOCK(MallocLock);
2500
                Terminate(-1);
2501
        }
2502
}
2503

2504
void M_print()
2505
{
2506
        int i;
2507
        MesPrint("We have the following memory allocations left:");
2508
        for ( i = 0; i < nummalloclist; i++ ) {
2509
                MesPrint("0x%x: %l bytes. number %d: '%s'",malloclist[i],mallocsizes[i],i,mallocstrings[i]);
2510
        }
2511
}
2512

2513
#else
2514

2515
void M_check1(VOID) {}
×
2516
void M_print(VOID) {}
886✔
2517

2518
#endif
2519

2520
/*
2521
                 #] M_check : 
2522
                 #[ TermMalloc :
2523
*/
2524
/**
2525
 *        Provides memory for one term (or one small polynomial)
2526
 *        This means that the memory is limited to a buffer of size AM.MaxTer
2527
 *        plus a few extra words.
2528
 *        In parallel versions, each worker has its own memory pool.
2529
 *
2530
 *        The way we use the memory is by:
2531
 *        term = TermMalloc(BHEAD0);
2532
 *        and later we free it by
2533
 *        TermFree(BHEAD term);
2534
 *
2535
 *        Layout:
2536
 *                We have a list of available pointers to buffers:  AT.TermMemHeap
2537
 *                Its size is AT.TermMemMax
2538
 *                We take from the top (indicated by AT.TermMemTop).
2539
 *                When we run out of buffers we assign new ones (doubling the amount)
2540
 *                and we have to extend the AT.TermMemHeap array.
2541
 *        Important:
2542
 *                There is no checking that the returned memory is legal, ie is
2543
 *                memory that was handed out earlier.
2544
 */
2545

2546
#define TERMMEMSTARTNUM 16
2547
#define TERMEXTRAWORDS 10
2548

2549
VOID TermMallocAddMemory(PHEAD0)
1,644✔
2550
{
2551
        WORD *newbufs;
1,644✔
2552
        int i, extra;
1,644✔
2553
        if ( AT.TermMemMax == 0 ) extra = TERMMEMSTARTNUM;
1,644✔
2554
        else                      extra = AT.TermMemMax;
200✔
2555
        if ( AT.TermMemHeap ) M_free(AT.TermMemHeap,"TermMalloc");
1,644✔
2556
        newbufs = (WORD *)Malloc1(extra*(AM.MaxTer+TERMEXTRAWORDS*sizeof(WORD)),"TermMalloc");
1,644✔
2557
        AT.TermMemHeap = (WORD **)Malloc1((extra+AT.TermMemMax)*sizeof(WORD *),"TermMalloc");
1,644✔
2558
        for ( i = 0; i < extra; i++ ) {
30,780✔
2559
                AT.TermMemHeap[i] = newbufs + i*(AM.MaxTer/sizeof(WORD)+TERMEXTRAWORDS);
29,136✔
2560
        }
2561
#ifdef TERMMALLOCDEBUG
2562
        DebugHeap2 = (WORD **)Malloc1((extra+AT.TermMemMax)*sizeof(WORD *),"TermMalloc");
2563
        for ( i = 0; i < AT.TermMemMax; i++ ) { DebugHeap2[i] = DebugHeap1[i]; }
2564
        for ( i = 0; i < extra; i++ ) {
2565
                DebugHeap2[i+AT.TermMemMax] = newbufs + i*(AM.MaxTer/sizeof(WORD)+TERMEXTRAWORDS);
2566
        }
2567
        if ( DebugHeap1 ) M_free(DebugHeap1,"TermMalloc");
2568
        DebugHeap1 = DebugHeap2;
2569
#endif
2570
        AT.TermMemTop = extra;
1,644✔
2571
        AT.TermMemMax += extra;
1,644✔
2572
#ifdef TERMMALLOCDEBUG
2573
        MesPrint("AT.TermMemMax is now %l",AT.TermMemMax);
2574
#endif
2575
}
1,644✔
2576

2577
#ifndef MEMORYMACROS
2578

2579
WORD *TermMalloc2(PHEAD char *text)
2580
{
2581
        if ( AT.TermMemTop <= 0 ) TermMallocAddMemory(BHEAD0);
2582

2583
#ifdef TERMMALLOCDEBUG
2584
        MesPrint("TermMalloc: %s, %d",text,(AT.TermMemMax-AT.TermMemTop));
2585
#endif
2586

2587
#ifdef MALLOCDEBUGOUTPUT
2588
        MesPrint("TermMalloc: %s, %l/%l (%x)",text,AT.TermMemTop,AT.TermMemMax,AT.TermMemHeap[AT.TermMemTop-1]);
2589
#endif
2590

2591
        DUMMYUSE(text);
2592
        return(AT.TermMemHeap[--AT.TermMemTop]);
2593
}
2594
 
2595
VOID TermFree2(PHEAD WORD *TermMem, char *text)
2596
{
2597
#ifdef TERMMALLOCDEBUG
2598

2599
        int i;
2600

2601
        for ( i = 0; i < AT.TermMemMax; i++ ) {
2602
                if ( TermMem == DebugHeap1[i] ) break;
2603
        }
2604
        if ( i >= AT.TermMemMax ) {
2605
                MesPrint(" ERROR: TermFree called with an address not given by TermMalloc.");
2606
                Terminate(-1);
2607
        }
2608
#endif
2609
        DUMMYUSE(text);
2610
        AT.TermMemHeap[AT.TermMemTop++] = TermMem;
2611
        
2612
#ifdef TERMMALLOCDEBUG
2613
        MesPrint("TermFree: %s, %d",text,(AT.TermMemMax-AT.TermMemTop));
2614
#endif
2615
#ifdef MALLOCDEBUGOUTPUT
2616
        MesPrint("TermFree: %s, %l/%l (%x)",text,AT.TermMemTop,AT.TermMemMax,TermMem);
2617
#endif
2618
}
2619

2620
#endif
2621

2622
/*
2623
                 #] TermMalloc : 
2624
                 #[ NumberMalloc :
2625
*/
2626
/**
2627
 *        Provides memory for one Long number
2628
 *        This means that the memory is limited to a buffer of size AM.MaxTal
2629
 *        In parallel versions, each worker has its own memory pool.
2630
 *
2631
 *        The way we use the memory is by:
2632
 *        num = NumberMalloc(BHEAD0); Number = AT.NumberMemHeap[num];
2633
 *        and later we free it by
2634
 *        NumberFree(BHEAD num);
2635
 *
2636
 *        Layout:
2637
 *                We have a list of available pointers to buffers:  AT.NumberMemHeap
2638
 *                Its size is AT.NumberMemMax
2639
 *                We take from the top (indicated by AT.NumberMemTop).
2640
 *                When we run out of buffers we assign new ones (doubling the amount)
2641
 *                and we have to extend the AT.NumberMemHeap array.
2642
 *        Important:
2643
 *                There is no checking on the returned memory!!!!
2644
 */
2645

2646
#define NUMBERMEMSTARTNUM 16
2647
#define NUMBEREXTRAWORDS 10L
2648

2649
#ifdef TERMMALLOCDEBUG
2650
UWORD **DebugHeap3, **DebugHeap4;
2651
#endif
2652

2653
VOID NumberMallocAddMemory(PHEAD0)
933✔
2654
{
2655
        UWORD *newbufs;
933✔
2656
        WORD extra;
933✔
2657
        int i;
933✔
2658
        if ( AT.NumberMemMax == 0 ) extra = NUMBERMEMSTARTNUM;
933✔
2659
        else                        extra = AT.NumberMemMax;
95✔
2660
        if ( AT.NumberMemHeap ) M_free(AT.NumberMemHeap,"NumberMalloc");
933✔
2661
        newbufs = (UWORD *)Malloc1(extra*(AM.MaxTal+NUMBEREXTRAWORDS)*sizeof(UWORD),"NumberMalloc");
933✔
2662
        AT.NumberMemHeap = (UWORD **)Malloc1((extra+AT.NumberMemMax)*sizeof(UWORD *),"NumberMalloc");
933✔
2663
        for ( i = 0; i < extra; i++ ) {
40,757✔
2664
                AT.NumberMemHeap[i] = newbufs + i*(LONG)(AM.MaxTal+NUMBEREXTRAWORDS);
39,824✔
2665
        }
2666
#ifdef TERMMALLOCDEBUG
2667
        DebugHeap4 = (UWORD **)Malloc1((extra+AT.NumberMemMax)*sizeof(WORD *),"NumberMalloc");
2668
        for ( i = 0; i < AT.NumberMemMax; i++ ) { DebugHeap4[i] = DebugHeap3[i]; }
2669
        for ( i = 0; i < extra; i++ ) {
2670
                DebugHeap4[i+AT.NumberMemMax] = newbufs + i*(LONG)(AM.MaxTal+NUMBEREXTRAWORDS);
2671
        }
2672
        if ( DebugHeap3 ) M_free(DebugHeap3,"NumberMalloc");
2673
        DebugHeap3 = DebugHeap4;
2674
#endif
2675
        AT.NumberMemTop = extra;
933✔
2676
        AT.NumberMemMax += extra;
933✔
2677
/*
2678
MesPrint("AT.NumberMemMax is now %l",AT.NumberMemMax);
2679
*/
2680
}
933✔
2681

2682
#ifndef MEMORYMACROS
2683

2684
UWORD *NumberMalloc2(PHEAD char *text)
2685
{
2686
        if ( AT.NumberMemTop <= 0 ) NumberMallocAddMemory(BHEAD text);
2687

2688
#ifdef MALLOCDEBUGOUTPUT
2689
        if ( (AT.NumberMemMax-AT.NumberMemTop) > 10 )
2690
        MesPrint("NumberMalloc: %s, %l/%l (%x)",text,AT.NumberMemTop,AT.NumberMemMax,AT.NumberMemHeap[AT.NumberMemTop-1]);
2691
#endif
2692

2693
        DUMMYUSE(text);
2694
        return(AT.NumberMemHeap[--AT.NumberMemTop]);
2695
}
2696
 
2697
VOID NumberFree2(PHEAD UWORD *NumberMem, char *text)
2698
{
2699
#ifdef TERMMALLOCDEBUG
2700
        int i;
2701
        for ( i = 0; i < AT.NumberMemMax; i++ ) {
2702
                if ( NumberMem == DebugHeap3[i] ) break;
2703
        }
2704
        if ( i >= AT.NumberMemMax ) {
2705
                MesPrint(" ERROR: NumberFree called with an address not given by NumberMalloc.");
2706
                Terminate(-1);
2707
        }
2708
#endif
2709
        DUMMYUSE(text);
2710
        AT.NumberMemHeap[AT.NumberMemTop++] = NumberMem;
2711

2712
#ifdef MALLOCDEBUGOUTPUT
2713
        if ( (AT.NumberMemMax-AT.NumberMemTop) > 10 )
2714
        MesPrint("NumberFree: %s, %l/%l (%x)",text,AT.NumberMemTop,AT.NumberMemMax,NumberMem);
2715
#endif
2716
}
2717

2718
#endif
2719

2720
/*
2721
                 #] NumberMalloc : 
2722
                 #[ CacheNumberMalloc :
2723

2724
        Similar to NumberMalloc
2725
 */
2726

2727
VOID CacheNumberMallocAddMemory(PHEAD0)
×
2728
{
2729
        UWORD *newbufs;
×
2730
        WORD extra;
×
2731
        int i;
×
2732
        if ( AT.CacheNumberMemMax == 0 ) extra = NUMBERMEMSTARTNUM;
×
2733
        else                             extra = AT.CacheNumberMemMax;
×
2734
        if ( AT.CacheNumberMemHeap ) M_free(AT.CacheNumberMemHeap,"NumberMalloc");
×
2735
        newbufs = (UWORD *)Malloc1(extra*(AM.MaxTal+NUMBEREXTRAWORDS)*sizeof(UWORD),"CacheNumberMalloc");
×
2736
        AT.CacheNumberMemHeap = (UWORD **)Malloc1((extra+AT.NumberMemMax)*sizeof(UWORD *),"CacheNumberMalloc");
×
2737
        for ( i = 0; i < extra; i++ ) {
×
2738
                AT.CacheNumberMemHeap[i] = newbufs + i*(LONG)(AM.MaxTal+NUMBEREXTRAWORDS);
×
2739
        }
2740
        AT.CacheNumberMemTop = extra;
×
2741
        AT.CacheNumberMemMax += extra;
×
2742
}
×
2743

2744
#ifndef MEMORYMACROS
2745

2746
UWORD *CacheNumberMalloc2(PHEAD char *text)
2747
{
2748
        if ( AT.CacheNumberMemTop <= 0 ) CacheNumberMallocAddMemory(BHEAD0);
2749

2750
#ifdef MALLOCDEBUGOUTPUT
2751
        MesPrint("NumberMalloc: %s, %l/%l (%x)",text,AT.NumberMemTop,AT.NumberMemMax,AT.NumberMemHeap[AT.NumberMemTop-1]);
2752
#endif
2753

2754
        DUMMYUSE(text);
2755
        return(AT.CacheNumberMemHeap[--AT.CacheNumberMemTop]);
2756
}
2757
 
2758
VOID CacheNumberFree2(PHEAD UWORD *NumberMem, char *text)
2759
{
2760
        DUMMYUSE(text);
2761
        AT.CacheNumberMemHeap[AT.CacheNumberMemTop++] = NumberMem;
2762
        
2763
#ifdef MALLOCDEBUGOUTPUT
2764
        MesPrint("NumberFree: %s, %l/%l (%x)",text,AT.NumberMemTop,AT.NumberMemMax,NumberMem);
2765
#endif
2766
}
2767

2768
#endif
2769

2770
/*
2771
                 #] CacheNumberMalloc : 
2772
                 #[ FromList :
2773

2774
        Returns the next object in a list.
2775
        If the list has been exhausted we double it (like a realloc)
2776
        If the list has not been initialized yet we start with 12 elements.
2777
*/
2778

2779
VOID *FromList(LIST *L)
48,753✔
2780
{
2781
        void *newlist;
48,753✔
2782
        int i, *old, *newL;
48,753✔
2783
        if ( L->num >= L->maxnum || L->lijst == 0 ) {
48,753✔
2784
                if ( L->maxnum == 0 ) L->maxnum = 12;
4,746✔
2785
                else if ( L->lijst ) L->maxnum *= 2;
2,662✔
2786
                newlist = Malloc1(L->maxnum * L->size,L->message);
4,746✔
2787
                if ( L->lijst ) {
4,746✔
2788
                        i = ( L->num * L->size ) / sizeof(int);
2,662✔
2789
                        old = (int *)L->lijst; newL = (int *)newlist;
2,662✔
2790
                        while ( --i >= 0 ) *newL++ = *old++;
792,886✔
2791
                        if ( L->lijst ) M_free(L->lijst,"L->lijst FromList");
2,662✔
2792
                }
2793
                L->lijst = newlist;
4,746✔
2794
        }
2795
        return( ((char *)(L->lijst)) + L->size * (L->num)++ );
48,753✔
2796
}
2797

2798
/*
2799
                 #] FromList : 
2800
                 #[ From0List :
2801

2802
                Same as FromList, but we zero excess variables.
2803
*/
2804

2805
VOID *From0List(LIST *L)
×
2806
{
2807
        void *newlist;
×
2808
        int i, *old, *newL;
×
2809
        if ( L->num >= L->maxnum || L->lijst == 0 ) {
×
2810
                if ( L->maxnum == 0 ) L->maxnum = 12;
×
2811
                else if ( L->lijst ) L->maxnum *= 2;
×
2812
                newlist = Malloc1(L->maxnum * L->size,L->message);
×
2813
                i = ( L->num * L->size ) / sizeof(int);
×
2814
                old = (int *)(L->lijst); newL = (int *)newlist;
×
2815
                while ( --i >= 0 ) *newL++ = *old++;
×
2816
                i = ( L->maxnum - L->num ) / sizeof(int);
×
2817
                while ( --i >= 0 ) *newL++ = 0;
×
2818
                if ( L->lijst ) M_free(L->lijst,"L->lijst From0List");
×
2819
                L->lijst = newlist;
×
2820
        }
2821
        return( ((char *)(L->lijst)) + L->size * (L->num)++ );
×
2822
}
2823

2824
/*
2825
                 #] From0List : 
2826
                 #[ FromVarList :
2827

2828
        Returns the next object in a list of variables.
2829
        If the list has been exhausted we double it (like a realloc)
2830
        If the list has not been initialized yet we start with 12 elements.
2831
        We allow at most MAXVARIABLES elements!
2832
*/
2833

2834
VOID *FromVarList(LIST *L)
159,907✔
2835
{
2836
        void *newlist;
159,907✔
2837
        int i, *old, *newL;
159,907✔
2838
        if ( L->num >= L->maxnum || L->lijst == 0 ) {
159,907✔
2839
                if ( L->maxnum == 0 ) L->maxnum = 12;
11,755✔
2840
                else if ( L->lijst ) {
5,505✔
2841
                        L->maxnum *= 2;
5,505✔
2842
                        if ( L == &(AP.DollarList) ) {
5,505✔
2843
                                if ( L->maxnum > MAXDOLLARVARIABLES ) L->maxnum = MAXDOLLARVARIABLES;
×
2844
                                if ( L->num >= MAXDOLLARVARIABLES ) {
×
2845
                                        MesPrint("!!!More than %l objects in list of $-variables",
×
2846
                                                MAXDOLLARVARIABLES);
2847
                                        Terminate(-1);
×
2848
                                }
2849
                        }
2850
                        else {
2851
                                if ( L->maxnum > MAXVARIABLES ) L->maxnum = MAXVARIABLES;
5,505✔
2852
                                if ( L->num >= MAXVARIABLES ) {
5,505✔
2853
                                        MesPrint("!!!More than %l objects in list of variables",
×
2854
                                                MAXVARIABLES);
2855
                                        Terminate(-1);
×
2856
                                }
2857
                        }
2858
                }
2859
                newlist = Malloc1(L->maxnum * L->size,L->message);
11,755✔
2860
                if ( L->lijst ) {
11,755✔
2861
                        i = ( L->num * L->size ) / sizeof(int);
5,505✔
2862
                        old = (int *)(L->lijst); newL = (int *)newlist;
5,505✔
2863
                        while ( --i >= 0 ) *newL++ = *old++;
3,245,025✔
2864
                        if ( L->lijst ) M_free(L->lijst,"L->lijst from VarList");
5,505✔
2865
                }
2866
                L->lijst = newlist;
11,755✔
2867
        }
2868
        return( ((char *)(L->lijst)) + L->size * ((L->num)++) );
159,907✔
2869
}
2870

2871
/*
2872
                 #] FromVarList : 
2873
                 #[ DoubleList :
2874
*/
2875

2876
int DoubleList(VOID ***lijst, int *oldsize, int objectsize, char *nameoftype)
980✔
2877
{
2878
        VOID **newlist;
980✔
2879
        LONG i, newsize, fullsize;
980✔
2880
        VOID **to, **from;
980✔
2881
        static LONG maxlistsize = (LONG)(MAXPOSITIVE);
980✔
2882
        if ( *lijst == 0 ) {
980✔
2883
                if ( *oldsize > 0 ) newsize = *oldsize;
886✔
2884
                else newsize = 100;
2885
        }
2886
        else newsize = *oldsize * 2;
94✔
2887
        if ( newsize > maxlistsize ) {
980✔
2888
                if ( *oldsize == maxlistsize ) {
×
2889
                        MesPrint("No memory for extra space in %s",nameoftype);
×
2890
                        return(-1);
×
2891
                }
2892
                newsize = maxlistsize;
2893
        }
2894
        fullsize = ( newsize * objectsize + sizeof(VOID *)-1 ) & (-sizeof(VOID *));
980✔
2895
        newlist = (VOID **)Malloc1(fullsize,nameoftype);
980✔
2896
        if ( *lijst ) {        /* Now some punning. DANGEROUS CODE in principle */
980✔
2897
                to = newlist; from = *lijst; i = (*oldsize * objectsize)/sizeof(VOID *);
94✔
2898
/*
2899
#ifdef MALLOCDEBUG
2900
if ( filelist ) MesPrint("    oldsize: %l, objectsize: %d, fullsize: %l"
2901
                ,*oldsize,objectsize,fullsize);
2902
#endif
2903
*/
2904
                while ( --i >= 0 ) *to++ = *from++;
4,004✔
2905
        }
2906
        if ( *lijst ) M_free(*lijst,"DoubleLList");
980✔
2907
        *lijst = newlist;
980✔
2908
        *oldsize = newsize;
980✔
2909
        return(0);
980✔
2910
/*
2911
        int error;
2912
        LONG lsize = *oldsize;
2913

2914
        maxlistsize = (LONG)(MAXPOSITIVE);
2915
        error = DoubleLList(lijst,&lsize,objectsize,nameoftype);
2916
        *oldsize = lsize;
2917
        maxlistsize = (LONG)(MAXLONG);
2918

2919
        return(error);
2920
*/
2921
}
2922

2923
/*
2924
                 #] DoubleList : 
2925
                 #[ DoubleLList :
2926
*/
2927

2928
int DoubleLList(VOID ***lijst, LONG *oldsize, int objectsize, char *nameoftype)
213✔
2929
{
2930
        VOID **newlist;
213✔
2931
        LONG i, newsize, fullsize;
213✔
2932
        VOID **to, **from;
213✔
2933
        static LONG maxlistsize = (LONG)(MAXLONG);
213✔
2934
        if ( *lijst == 0 ) {
213✔
2935
                if ( *oldsize > 0 ) newsize = *oldsize;
×
2936
                else newsize = 100;
2937
        }
2938
        else newsize = *oldsize * 2;
213✔
2939
        if ( newsize > maxlistsize ) {
213✔
2940
                if ( *oldsize == maxlistsize ) {
×
2941
                        MesPrint("No memory for extra space in %s",nameoftype);
×
2942
                        return(-1);
×
2943
                }
2944
                newsize = maxlistsize;
2945
        }
2946
        fullsize = ( newsize * objectsize + sizeof(VOID *)-1 ) & (-sizeof(VOID *));
213✔
2947
        newlist = (VOID **)Malloc1(fullsize,nameoftype);
213✔
2948
        if ( *lijst ) {        /* Now some punning. DANGEROUS CODE in principle */
213✔
2949
                to = newlist; from = *lijst; i = (*oldsize * objectsize)/sizeof(VOID *);
213✔
2950
/*
2951
#ifdef MALLOCDEBUG
2952
if ( filelist ) MesPrint("    oldsize: %l, objectsize: %d, fullsize: %l"
2953
                ,*oldsize,objectsize,fullsize);
2954
#endif
2955
*/
2956
                while ( --i >= 0 ) *to++ = *from++;
385,365✔
2957
        }
2958
        if ( *lijst ) M_free(*lijst,"DoubleLList");
213✔
2959
        *lijst = newlist;
213✔
2960
        *oldsize = newsize;
213✔
2961
        return(0);
213✔
2962
}
2963

2964
/*
2965
                 #] DoubleLList : 
2966
                 #[ DoubleBuffer :
2967
*/
2968

2969
#define DODOUBLE(x) { x *s, *t, *u; if ( *start ) { \
2970
        oldsize = *(x **)stop - *(x **)start; newsize = 2*oldsize; \
2971
        t = u = (x *)Malloc1(newsize*sizeof(x),text); s = *(x **)start; \
2972
        for ( i = 0; i < oldsize; i++ ) {*t++ = *s++;} M_free(*start,"double"); } \
2973
        else { newsize = 100; u = (x *)Malloc1(newsize*sizeof(x),text); } \
2974
        *start = (void *)u; *stop = (void *)(u+newsize); }
2975

2976
void DoubleBuffer(void **start, void **stop, int size, char *text)
1,766✔
2977
{
2978
        LONG oldsize, newsize, i;
1,766✔
2979
        if ( size == sizeof(char) ) DODOUBLE(char)
4,688,666✔
2980
        else if ( size == sizeof(short) ) DODOUBLE(short)
463✔
2981
        else if ( size == sizeof(int) ) DODOUBLE(int)
463✔
2982
        else if ( size == sizeof(LONG) ) DODOUBLE(LONG)
81,463✔
2983
        else if ( size % sizeof(int) == 0 ) DODOUBLE(int)
×
2984
        else {
2985
                MesPrint("---Cannot handle doubling buffers of size %d",size);
×
2986
                Terminate(-1);
×
2987
        }
2988
}
1,766✔
2989

2990
/*
2991
                 #] DoubleBuffer : 
2992
                 #[ ExpandBuffer :
2993
*/
2994

2995
#define DOEXPAND(x) { x *newbuffer, *t, *m;                             \
2996
        t = newbuffer = (x *)Malloc1((newsize+2)*type,"ExpandBuffer");      \
2997
        if ( *buffer ) { m = (x *)*buffer; i = *oldsize;                    \
2998
                while ( --i >= 0 ) {*t++ = *m++;} M_free(*buffer,"ExpandBuffer"); \
2999
        } *buffer = newbuffer; *oldsize = newsize; }
3000

3001
void ExpandBuffer(void **buffer, LONG *oldsize, int type)
686✔
3002
{
3003
        LONG newsize, i;
686✔
3004
        if ( *oldsize <= 0 ) { newsize = 100; }
686✔
3005
        else newsize = 2*(*oldsize);
228✔
3006
        if ( type == sizeof(char) ) DOEXPAND(char)
686✔
3007
        else if ( type == sizeof(short) ) DOEXPAND(short)
686✔
3008
        else if ( type == sizeof(int) ) DOEXPAND(int)
686✔
3009
        else if ( type == sizeof(LONG) ) DOEXPAND(LONG)
2,617,286✔
3010
        else if ( type == sizeof(POSITION) ) DOEXPAND(POSITION)
×
3011
        else {
3012
                MesPrint("---Cannot handle expanding buffers with objects of size %d",type);
×
3013
                Terminate(-1);
×
3014
        }
3015
}
686✔
3016

3017
/*
3018
                 #] ExpandBuffer : 
3019
                 #[ iexp :
3020

3021
                Raises the long integer y to the power p.
3022
                Returnvalue is long, regardless of overflow.
3023
*/
3024

3025
LONG iexp(LONG x, int p)
24✔
3026
{
3027
        int sign;
24✔
3028
        ULONG y;
24✔
3029
        ULONG ux;
24✔
3030
        if ( x == 0 ) return(0);
24✔
3031
        if ( p == 0 ) return(1);
24✔
3032
        sign = x < 0 ? -1 : 1;
24✔
3033
        if ( sign < 0 && ( p & 1 ) == 0 ) sign = 1;
×
3034
        ux = LongAbs(x);
24✔
3035
        if ( ux == 1 ) return(sign);
24✔
3036
        if ( p < 0 ) return(0);
24✔
3037
        y = 1;
3038
        while ( p ) {
168✔
3039
                if ( ( p & 1 ) != 0 ) y *= ux;
144✔
3040
                p >>= 1;
144✔
3041
                ux = ux*ux;
144✔
3042
        }
3043
        if ( sign < 0 ) y = -y;
24✔
3044
        return ULongToLong(y);
24✔
3045
}
3046

3047
/*
3048
                 #] iexp : 
3049
                 #[ ToGeneral :
3050

3051
                Convert a fast argument to a general argument
3052
                Input in r, output in m.
3053
                If par == 0 we need the argument header also.
3054
*/
3055

3056
void ToGeneral(WORD *r, WORD *m, WORD par)
4,704✔
3057
{
3058
        WORD *mm = m, j, k;
4,704✔
3059
        if ( par ) m++;
4,704✔
3060
        else { m[1] = 0; m += ARGHEAD + 1; }
4,533✔
3061
        j = -*r++;
4,704✔
3062
        k = 3;
4,704✔
3063
/*                JV: Bugfix 1-feb-2016. Old code assumed FUNHEAD to be 2 */
3064
        if ( j >= FUNCTION ) { *m++ = j; *m++ = FUNHEAD; FILLFUN(m) }
4,704✔
3065
        else {
3066
                switch ( j ) {
4,704✔
3067
                        case SYMBOL: *m++ = j; *m++ = 4; *m++ = *r++; *m++ = 1; break;
4,512✔
3068
                        case SNUMBER:
186✔
3069
                                if ( *r > 0 ) { *m++ =  *r; *m++ = 1; *m++ =  3; }
186✔
3070
                                else if ( *r == 0 ) { m--; }
9✔
3071
                                else          { *m++ = -*r; *m++ = 1; *m++ = -3; }
9✔
3072
                                goto MakeSize;
186✔
3073
                        case MINVECTOR:
×
3074
                                k = -k;
×
3075
                                /* fall through */
3076
                        case INDEX:
6✔
3077
                        case VECTOR:
3078
                                *m++ = INDEX; *m++ = 3; *m++ = *r++;
6✔
3079
                                break;
6✔
3080
                }
3081
        }
3082
        *m++ = 1; *m++ = 1; *m++ = k;
4,518✔
3083
MakeSize:
4,704✔
3084
        *mm = m-mm;
4,704✔
3085
        if ( !par ) mm[ARGHEAD] = *mm-ARGHEAD;
4,704✔
3086
}
4,704✔
3087

3088
/*
3089
                 #] ToGeneral : 
3090
                 #[ ToFast :
3091

3092
                Checks whether an argument can be converted to fast notation
3093
                If this can be done it does it.
3094
                Important: m should be allowed to be equal to r!
3095
                Return value is 1 if conversion took place.
3096
                If there was conversion the answer is in m.
3097
                If there was no conversion m hasn't been touched.
3098
*/
3099

3100
int ToFast(WORD *r, WORD *m)
6,691,226✔
3101
{
3102
        WORD i;
6,691,226✔
3103
        if ( *r == ARGHEAD ) { *m++ = -SNUMBER; *m++ = 0; return(1); }
6,691,226✔
3104
        if ( *r != r[ARGHEAD]+ARGHEAD ) return(0);        /* > 1 term */
6,689,531✔
3105
        r += ARGHEAD;
1,138,420✔
3106
        if ( *r == 4 ) {
1,138,420✔
3107
                if ( r[2] != 1 || r[1] <= 0 ) return(0);
144,057✔
3108
                *m++ = -SNUMBER; *m = ( r[3] < 0 ) ? -r[1] : r[1]; return(1);
142,110✔
3109
        }
3110
        i = *r - 1;
994,363✔
3111
        if ( r[i-1] != 1 || r[i-2] != 1 ) return(0);
994,363✔
3112
        if ( r[i] != 3 ) {
987,851✔
3113
                if ( r[i] == -3 && r[2] == *r-4 && r[2] == 3 && r[1] == INDEX
1,052✔
3114
                && r[3] < MINSPEC ) {}
6✔
3115
                else return(0);
3116
        }
3117
        else if ( r[2] != *r - 4 ) return(0);
986,799✔
3118
        r++;
986,736✔
3119
        if ( *r >= FUNCTION ) {
986,736✔
3120
                if ( r[1] <= FUNHEAD ) { *m++ = -*r; return(1); }
4,815✔
3121
        }
3122
        else if ( *r == SYMBOL ) {
981,921✔
3123
                if ( r[1] == 4 && r[3] == 1 )
3,900✔
3124
                        { *m++ = -SYMBOL; *m++ = r[2]; return(1); }
846✔
3125
        }
3126
        else if ( *r == INDEX ) {
978,021✔
3127
                if ( r[1] == 3 ) {
12✔
3128
                        if ( r[2] >= MINSPEC ) {
12✔
3129
                                if ( r[2] >= 0 && r[2] < AM.OffsetIndex ) *m++ = -SNUMBER;
3✔
3130
                                else *m++ = -INDEX;
3✔
3131
                        }
3132
                        else {
3133
                                if ( r[5] == -3 ) *m++ = -MINVECTOR;
9✔
3134
                                else *m++ = -VECTOR;
9✔
3135
                        }
3136
                        *m++ = r[2];
12✔
3137
                        return(1);
12✔
3138
                }
3139
        }
3140
        return(0);
3141
}
3142

3143
/*
3144
                 #] ToFast : 
3145
                 #[ ToPolyFunGeneral :
3146

3147
        Routine forces a polyratfun into general notation if needed.
3148
        If no action was needed, the return value is zero.
3149
        A positive return value indicates how many arguments were converted.
3150
        The new term overwrite the old.
3151
*/
3152

3153
WORD ToPolyFunGeneral(PHEAD WORD *term)
×
3154
{
3155
        WORD *t = term+1, *tt, *to, *to1, *termout, *tstop, *tnext;
×
3156
        WORD numarg, i, change = 0;
×
3157
        tstop = term + *term; tstop -= ABS(tstop[-1]);
×
3158
        termout = to = AT.WorkPointer;
×
3159
        to++;
×
3160
        while ( t < tstop ) { /* go through the subterms */
×
3161
                if ( *t == AR.PolyFun ) {
×
3162
                        tt = t+FUNHEAD; tnext = t + t[1];
×
3163
                        numarg = 0;
×
3164
                        while ( tt < tnext ) { numarg++; NEXTARG(tt); }
×
3165
                        if ( numarg == 2 ) { /* this needs attention */
×
3166
                                tt = t + FUNHEAD;
×
3167
                                to1 = to;
3168
                                i = FUNHEAD; NCOPY(to,t,i);
×
3169
                                while ( tt < tnext ) { /* Do the arguments */
×
3170
                                        if ( *tt > 0 ) {
×
3171
                                                i = *tt; NCOPY(to,tt,i);
×
3172
                                        }
3173
                                        else if ( *tt == -SYMBOL ) {
×
3174
                                                to1[1] += 6+ARGHEAD; to1[2] |= MUSTCLEANPRF; change++;
×
3175
                                                *to++ = 8+ARGHEAD; *to++ = 0; FILLARG(to);
×
3176
                                                *to++ = 8; *to++ = SYMBOL; *to++ = 4; *to++ = tt[1];
×
3177
                                                *to++ = 1; *to++ = 1; *to++ = 1; *to++ = 3;
×
3178
                                                tt += 2;
×
3179
                                        }
3180
                                        else if ( *tt == -SNUMBER ) {
×
3181
                                                if ( tt[1] > 0 ) {
×
3182
                                                        to1[1] += 2+ARGHEAD; to1[2] |= MUSTCLEANPRF; change++;
×
3183
                                                        *to++ = 4+ARGHEAD; *to++ = 0; FILLARG(to);
×
3184
                                                        *to++ = 4; *to++ = tt[1]; *to++ = 1; *to++ = 3;
×
3185
                                                        tt += 2;
×
3186
                                                }
3187
                                                else if ( tt[1] < 0 ) {
×
3188
                                                        to1[1] += 2+ARGHEAD; to1[2] |= MUSTCLEANPRF; change++;
×
3189
                                                        *to++ = 4+ARGHEAD; *to++ = 0; FILLARG(to);
×
3190
                                                        *to++ = 4; *to++ = -tt[1]; *to++ = 1; *to++ = -3;
×
3191
                                                        tt += 2;
×
3192
                                                }
3193
                                                else {
3194
                                                        MLOCK(ErrorMessageLock);
×
3195
                                                        MesPrint("Internal error: Zero in PolyRatFun");
×
3196
                                                        MUNLOCK(ErrorMessageLock);
×
3197
                                                        Terminate(-1);
×
3198
                                                }
3199
                                        }
3200
                                }
3201
                                t = tnext;
×
3202
                                continue;
×
3203
                        }
3204
                }
3205
                i = t[1]; NCOPY(to,t,i)
×
3206
        }
3207
        if ( change ) {
×
3208
                tt = term + *term;
×
3209
        while ( t < tt ) *to++ = *t++;
×
3210
                *termout = to - termout;
×
3211
                t = term; i = *termout; tt = termout;
×
3212
                NCOPY(t,tt,i)
×
3213
                AT.WorkPointer = term + *term;
×
3214
        }
3215
        return(change);
×
3216
}
3217

3218
/*
3219
                 #] ToPolyFunGeneral : 
3220
                 #[ IsLikeVector :
3221

3222
                Routine determines whether a function argument is like a vector.
3223
                Returnvalue: 1: is vector or index
3224
                             0: is not vector or index
3225
                            -1: may be an index
3226
*/
3227

3228
int IsLikeVector(WORD *arg)
×
3229
{
3230
        WORD *sstop, *t, *tstop;
×
3231
        if ( *arg < 0 ) {
×
3232
                if ( *arg == -VECTOR || *arg == -INDEX ) return(1);
×
3233
                if ( *arg == -SNUMBER && arg[1] >= 0 && arg[1] < AM.OffsetIndex )
×
3234
                        return(-1);
3235
                return(0);
×
3236
        }
3237
        sstop = arg + *arg; arg += ARGHEAD;
×
3238
        while ( arg < sstop ) {
×
3239
                t = arg + *arg;
×
3240
                tstop = t - ABS(t[-1]);
×
3241
                arg++;
×
3242
                while ( arg < tstop ) {
×
3243
                        if ( *arg == INDEX ) return(1);
×
3244
                        arg += arg[1];
×
3245
                }
3246
                arg = t;
3247
        }
3248
        return(0);
3249
}
3250

3251
/*
3252
                 #] IsLikeVector : 
3253
                 #[ AreArgsEqual :
3254
*/
3255

3256
int AreArgsEqual(WORD *arg1, WORD *arg2)
36✔
3257
{
3258
        int i;
36✔
3259
        if ( *arg2 != *arg1 ) return(0);
36✔
3260
        if ( *arg1 > 0 ) {
36✔
3261
                i = *arg1;
3262
                while ( --i > 0 ) { if ( arg1[i] != arg2[i] ) return(0); }
×
3263
                return(1);
3264
        }
3265
        else if ( *arg1 <= -FUNCTION ) return(1);
36✔
3266
        else if ( arg1[1] == arg2[1] ) return(1);
36✔
3267
        return(0);
3268
}
3269

3270
/*
3271
                 #] AreArgsEqual : 
3272
                 #[ CompareArgs :
3273
*/
3274

3275
int CompareArgs(WORD *arg1, WORD *arg2)
×
3276
{
3277
        int i1,i2;
×
3278
        if ( *arg1 > 0 ) {
×
3279
                if ( *arg2 < 0 ) return(-1);
×
3280
                i1 = *arg1-ARGHEAD; arg1 += ARGHEAD;
×
3281
                i2 = *arg2-ARGHEAD; arg2 += ARGHEAD;
×
3282
                while ( i1 > 0 && i2 > 0 ) {
×
3283
                        if ( *arg1 != *arg2 ) return((int)(*arg1)-(int)(*arg2));
×
3284
                        i1--; i2--; arg1++; arg2++;
×
3285
                }
3286
                return(i1-i2);
×
3287
        }
3288
        else if ( *arg2 > 0 ) return(1);
×
3289
        else {
3290
                if ( *arg1 != *arg2 ) {
×
3291
                        if ( *arg1 < *arg2 ) return(-1);
×
3292
                        else return(1);
×
3293
                }
3294
                if ( *arg1 <= -FUNCTION ) return(0);
×
3295
                return((int)(arg1[1])-(int)(arg2[1]));
×
3296
        }
3297
}
3298

3299
/*
3300
                 #] CompareArgs : 
3301
                 #[ CompArg :
3302

3303
        returns 1 if arg1 comes first, -1 if arg2 comes first, 0 if equal
3304
*/
3305

3306
int CompArg(WORD *s1, WORD *s2)
1,074✔
3307
{
3308
        GETIDENTITY
716✔
3309
        WORD *st1, *st2, x[7];
1,074✔
3310
        int k;
1,074✔
3311
        if ( *s1 < 0 ) {
1,074✔
3312
                if ( *s2 < 0 ) {
120✔
3313
                        if ( *s1 <= -FUNCTION && *s2 <= -FUNCTION ) {
120✔
3314
                                if ( *s1 > *s2 ) return(-1);
×
3315
                                if ( *s1 < *s2 ) return(1);
×
3316
                                return(0);
×
3317
                        }
3318
                        if ( *s1 > *s2 ) return(1);
120✔
3319
                        if ( *s1 < *s2 ) return(-1);
120✔
3320
                        if ( *s1 <= -FUNCTION ) return(0);
120✔
3321
                        s1++; s2++;
120✔
3322
                        if ( *s1 > *s2 ) return(1);
120✔
3323
                        if ( *s1 < *s2 ) return(-1);
30✔
3324
                        return(0);
30✔
3325
                }
3326
                x[1] = AT.comsym[3];
×
3327
                x[2] = AT.comnum[1];
×
3328
                x[3] = AT.comnum[3];
×
3329
                x[4] = AT.comind[3];
×
3330
                x[5] = AT.comind[6];
×
3331
                x[6] = AT.comfun[1];
×
3332
                if ( *s1 == -SYMBOL ) {
×
3333
                        AT.comsym[3] = s1[1];
×
3334
                        st1 = AT.comsym+8; s1 = AT.comsym;
×
3335
                }
3336
                else if ( *s1 == -SNUMBER ) {
×
3337
                        if ( s1[1] < 0 ) {
×
3338
                                AT.comnum[1] = -s1[1]; AT.comnum[3] = -3;
×
3339
                        }
3340
                        else {
3341
                                AT.comnum[1] = s1[1]; AT.comnum[3] = 3;
×
3342
                        }
3343
                        st1 = AT.comnum+4;
3344
                        s1 = AT.comnum;
3345
                }
3346
                else if ( *s1 == -INDEX || *s1 == -VECTOR ) {
×
3347
                        AT.comind[3] = s1[1]; AT.comind[6] = 3;
×
3348
                        st1 = AT.comind+7; s1 = AT.comind;
×
3349
                }
3350
                else if ( *s1 == -MINVECTOR ) {
×
3351
                        AT.comind[3] = s1[1]; AT.comind[6] = -3;
×
3352
                        st1 = AT.comind+7; s1 = AT.comind;
×
3353
                }
3354
                else if ( *s1 <= -FUNCTION ) {
×
3355
                        AT.comfun[1] = -*s1;
×
3356
                        st1 = AT.comfun+FUNHEAD+4; s1 = AT.comfun;
×
3357
                }
3358
/*
3359
                        Symmetrize during compilation of id statement when properorder
3360
                        needs this one. Code added 10-nov-2001
3361
*/
3362
                else if ( *s1 == -ARGWILD ) {
×
3363
                         return(-1);
3364
                }
3365
                else { goto argerror; }
×
3366
                st2 = s2 + *s2; s2 += ARGHEAD;
×
3367
                goto docompare;
×
3368
        }
3369
        else if ( *s2 < 0 ) {
954✔
3370
                x[1] = AT.comsym[3];
×
3371
                x[2] = AT.comnum[1];
×
3372
                x[3] = AT.comnum[3];
×
3373
                x[4] = AT.comind[3];
×
3374
                x[5] = AT.comind[6];
×
3375
                x[6] = AT.comfun[1];
×
3376
                if ( *s2 == -SYMBOL ) {
×
3377
                        AT.comsym[3] = s2[1];
×
3378
                        st2 = AT.comsym+8; s2 = AT.comsym;
×
3379
                }
3380
                else if ( *s2 == -SNUMBER ) {
×
3381
                        if ( s2[1] < 0 ) {
×
3382
                                AT.comnum[1] = -s2[1]; AT.comnum[3] = -3;
×
3383
                                st2 = AT.comnum+4;
×
3384
                        }
3385
                        else if ( s2[1] == 0 ) {
×
3386
                                st2 = AT.comnum+4; s2 = st2;
3387
                        }
3388
                        else {
3389
                                AT.comnum[1] = s2[1]; AT.comnum[3] = 3;
×
3390
                                st2 = AT.comnum+4;
×
3391
                        }
3392
                        s2 = AT.comnum;
3393
                }
3394
                else if ( *s2 == -INDEX || *s2 == -VECTOR ) {
×
3395
                        AT.comind[3] = s2[1]; AT.comind[6] = 3;
×
3396
                        st2 = AT.comind+7; s2 = AT.comind;
×
3397
                }
3398
                else if ( *s2 == -MINVECTOR ) {
×
3399
                        AT.comind[3] = s2[1]; AT.comind[6] = -3;
×
3400
                        st2 = AT.comind+7; s2 = AT.comind;
×
3401
                }
3402
                else if ( *s2 <= -FUNCTION ) {
×
3403
                        AT.comfun[1] = -*s2;
×
3404
                        st2 = AT.comfun+FUNHEAD+4; s2 = AT.comfun;
×
3405
                }
3406
/*
3407
                        Symmetrize during compilation of id statement when properorder
3408
                        needs this one. Code added 10-nov-2001
3409
*/
3410
                else if ( *s2 == -ARGWILD ) {
×
3411
                         return(1);
3412
                }
3413
                else { goto argerror; }
×
3414
                st1 = s1 + *s1; s1 += ARGHEAD;
×
3415
                goto docompare;
×
3416
        }
3417
        else {
3418
                x[1] = AT.comsym[3];
954✔
3419
                x[2] = AT.comnum[1];
954✔
3420
                x[3] = AT.comnum[3];
954✔
3421
                x[4] = AT.comind[3];
954✔
3422
                x[5] = AT.comind[6];
954✔
3423
                x[6] = AT.comfun[1];
954✔
3424
                st1 = s1 + *s1; st2 = s2 + *s2;
954✔
3425
                s1 += ARGHEAD; s2 += ARGHEAD;
954✔
3426
docompare:
954✔
3427
                while ( s1 < st1 && s2 < st2 ) {
1,398✔
3428
                        if ( ( k = CompareTerms(BHEAD s1,s2,(WORD)2) ) != 0 ) {
1,278✔
3429
                                AT.comsym[3] = x[1];
834✔
3430
                                AT.comnum[1] = x[2];
834✔
3431
                                AT.comnum[3] = x[3];
834✔
3432
                                AT.comind[3] = x[4];
834✔
3433
                                AT.comind[6] = x[5];
834✔
3434
                                AT.comfun[1] = x[6];
834✔
3435
                                return(-k);
834✔
3436
                        }
3437
                        s1 += *s1; s2 += *s2;
444✔
3438
                }
3439
                AT.comsym[3] = x[1];
120✔
3440
                AT.comnum[1] = x[2];
120✔
3441
                AT.comnum[3] = x[3];
120✔
3442
                AT.comind[3] = x[4];
120✔
3443
                AT.comind[6] = x[5];
120✔
3444
                AT.comfun[1] = x[6];
120✔
3445
                if ( s1 < st1 ) return(1);
120✔
3446
                if ( s2 < st2 ) return(-1);
105✔
3447
        }
3448
        return(0);
3449
 
3450
argerror:
×
3451
        MesPrint("Illegal type of short function argument in Normalize");
×
3452
        Terminate(-1); return(0);
×
3453
}
3454

3455
/*
3456
                 #] CompArg : 
3457
                 #[ TimeWallClock :
3458
*/
3459

3460
#ifdef HAVE_CLOCK_GETTIME
3461
#include <time.h> /* for clock_gettime() */
3462
#else
3463
#ifdef HAVE_GETTIMEOFDAY
3464
#include <sys/time.h> /* for gettimeofday() */
3465
#else
3466
#include <sys/timeb.h> /* for ftime() */
3467
#endif
3468
#endif
3469

3470
/**
3471
 * Returns the wall-clock time.
3472
 *
3473
 * @param   par  If zero, the wall-clock time will be reset to 0.
3474
 * @return       The wall-clock time in centiseconds.
3475
 */
3476
LONG TimeWallClock(WORD par)
2,360✔
3477
{
3478
        /*
3479
         * NOTE: this function is not thread-safe. Operations on tp are not atomic.
3480
         */
3481

3482
#ifdef HAVE_CLOCK_GETTIME
3483
        struct timespec ts;
2,360✔
3484
        clock_gettime(CLOCK_MONOTONIC, &ts);
2,360✔
3485

3486
        if ( par ) {
2,360✔
3487
                return(((LONG)(ts.tv_sec)-AM.OldSecTime)*100 +
1,181✔
3488
                        ((LONG)(ts.tv_nsec / 1000000)-AM.OldMilliTime)/10);
1,181✔
3489
        }
3490
        else {
3491
                AM.OldSecTime   = (LONG)(ts.tv_sec);
1,179✔
3492
                AM.OldMilliTime = (LONG)(ts.tv_nsec / 1000000);
1,179✔
3493
                return(0L);
1,179✔
3494
        }
3495
#else
3496
#ifdef HAVE_GETTIMEOFDAY
3497
        struct timeval t;
3498
        LONG sec, msec;
3499
        gettimeofday(&t, NULL);
3500
        sec = (LONG)t.tv_sec;
3501
        msec = (LONG)(t.tv_usec/1000);
3502
        if ( par ) {
3503
                return (sec-AM.OldSecTime)*100 + (msec-AM.OldMilliTime)/10;
3504
        }
3505
        else {
3506
                AM.OldSecTime   = sec;
3507
                AM.OldMilliTime = msec;
3508
                return(0L);
3509
        }
3510
#else
3511
        struct timeb tp;
3512
        ftime(&tp);
3513

3514
        if ( par ) {
3515
                return(((LONG)(tp.time)-AM.OldSecTime)*100 + 
3516
                        ((LONG)(tp.millitm)-AM.OldMilliTime)/10);
3517
        }
3518
        else {
3519
                AM.OldSecTime   = (LONG)(tp.time);
3520
                AM.OldMilliTime = (LONG)(tp.millitm);
3521
                return(0L);
3522
        }
3523
#endif
3524
#endif
3525
}
3526

3527
/*
3528
                 #] TimeWallClock : 
3529
                 #[ TimeChildren :
3530
*/
3531

3532
LONG TimeChildren(WORD par)
883✔
3533
{
3534
        if ( par ) return(Timer(1)-AM.OldChildTime);
883✔
3535
        AM.OldChildTime = Timer(1);
883✔
3536
        return(0L);
883✔
3537
}
3538

3539
/*
3540
                 #] TimeChildren : 
3541
                 #[ TimeCPU :
3542
*/
3543

3544
/**
3545
 * Returns the CPU time.
3546
 *
3547
 * @param   par  If zero, the CPU time will be reset to 0.
3548
 * @return       The CPU time in milliseconds.
3549
 */
3550
LONG TimeCPU(WORD par)
33,113✔
3551
{
3552
        GETIDENTITY
31,006✔
3553
        if ( par ) return(Timer(0)-AR.OldTime);
33,113✔
3554
        AR.OldTime = Timer(0);
3,515✔
3555
        return(0L);
3,515✔
3556
}
3557

3558
/*
3559
                 #] TimeCPU : 
3560
                 #[ Timer :
3561
*/
3562
#if defined(WINDOWS)
3563

3564
LONG Timer(int par)
3565
{
3566
#ifndef WITHPTHREADS
3567
        static int initialized = 0;
3568
        static HANDLE hProcess;
3569
        FILETIME ftCreate, ftExit, ftKernel, ftUser;
3570
        DUMMYUSE(par);
3571

3572
        if ( !initialized ) {
3573
                hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
3574
        }
3575
        if ( GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser) ) {
3576
                PFILETIME pftKernel = &ftKernel;  /* to avoid strict-aliasing rule warnings */
3577
                PFILETIME pftUser   = &ftUser;
3578
                __int64 t = *(__int64 *)pftKernel + *(__int64 *)pftUser;  /* in 100 nsec. */
3579
                return (LONG)(t / 10000);  /* in msec. */
3580
        }
3581
        return 0;
3582
#else
3583
        LONG lResult = 0;
3584
        HANDLE hThread;
3585
        FILETIME ftCreate, ftExit, ftKernel, ftUser;
3586
        DUMMYUSE(par);
3587

3588
        hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, GetCurrentThreadId());
3589
        if ( hThread ) {
3590
                if ( GetThreadTimes(hThread, &ftCreate, &ftExit, &ftKernel, &ftUser) ) {
3591
                        PFILETIME pftKernel = &ftKernel;  /* to avoid strict-aliasing rule warnings */
3592
                        PFILETIME pftUser   = &ftUser;
3593
                        __int64 t = *(__int64 *)pftKernel + *(__int64 *)pftUser;  /* in 100 nsec. */
3594
                        lResult = (LONG)(t / 10000);  /* in msec. */
3595
                }
3596
                CloseHandle(hThread);
3597
        }
3598
        return lResult;
3599
#endif
3600
}
3601

3602
#elif defined(UNIX)
3603
#include <sys/time.h>
3604
#include <sys/resource.h>
3605
#ifdef WITHPOSIXCLOCK
3606
#include <time.h>
3607
/*
3608
        And include -lrt in the link statement (on blade02)
3609
*/
3610
#endif
3611

3612
LONG Timer(int par)
34,879✔
3613
{
3614
#ifdef WITHPOSIXCLOCK
3615
/*
3616
        Only to be used in combination with WITHPTHREADS
3617
        This clock seems to be supported by the standard.
3618
        The getrusage clock returns according to the standard only the combined
3619
        time of the whole process. But in older versions of Linux LinuxThreads
3620
        is used which gives a separate id to each thread and individual timings.
3621
        In NPTL we get, according to the standard, one combined timing.
3622
        To get individual timings we need to use
3623
                clock_gettime(CLOCK_THREAD_CPUTIME_ID, &timing)
3624
        with timing of the time
3625
        struct timespec {
3626
                time_t tv_sec;            Seconds.
3627
                long   tv_nsec;           Nanoseconds.
3628
        };
3629

3630
*/
3631
        struct timespec t;
32,182✔
3632
        if ( par == 0 ) {
32,182✔
3633
                if ( clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t) ) {
31,594✔
3634
                        MesPrint("Error in getting timing information");
3635
                }
3636
                return (LONG)t.tv_sec * 1000 + (LONG)t.tv_nsec / 1000000;
31,594✔
3637
        }
3638
        return(0);
3639
#else
3640
        struct rusage rusage;
2,697✔
3641
        if ( par == 1 ) {
2,697✔
3642
            getrusage(RUSAGE_CHILDREN,&rusage);
295✔
3643
            return(((LONG)(rusage.ru_utime.tv_sec)+(LONG)(rusage.ru_stime.tv_sec))*1000
295✔
3644
                      +(rusage.ru_utime.tv_usec/1000+rusage.ru_stime.tv_usec/1000));
295✔
3645
        }
3646
        else {
3647
            getrusage(RUSAGE_SELF,&rusage);
2,402✔
3648
            return(((LONG)(rusage.ru_utime.tv_sec)+(LONG)(rusage.ru_stime.tv_sec))*1000
2,402✔
3649
                      +(rusage.ru_utime.tv_usec/1000+rusage.ru_stime.tv_usec/1000));
2,402✔
3650
        }
3651
#endif
3652
}
3653

3654
#elif defined(SUN)
3655
#define _TIME_T_
3656
#include <sys/time.h>
3657
#include <sys/resource.h>
3658

3659
LONG Timer(int par)
3660
{
3661
    struct rusage rusage;
3662
        if ( par == 1 ) {
3663
            getrusage(RUSAGE_CHILDREN,&rusage);
3664
            return(((LONG)(rusage.ru_utime.tv_sec)+(LONG)(rusage.ru_stime.tv_sec))*1000
3665
                      +(rusage.ru_utime.tv_usec/1000+rusage.ru_stime.tv_usec/1000));
3666
        }
3667
        else {
3668
            getrusage(RUSAGE_SELF,&rusage);
3669
            return(((LONG)(rusage.ru_utime.tv_sec)+(LONG)(rusage.ru_stime.tv_sec))*1000
3670
                      +(rusage.ru_utime.tv_usec/1000+rusage.ru_stime.tv_usec/1000));
3671
        }
3672
}
3673

3674
#elif defined(RS6K)
3675
#include <sys/time.h>
3676
#include <sys/resource.h>
3677

3678
LONG Timer(int par)
3679
{
3680
    struct rusage rusage;
3681
        if ( par == 1 ) {
3682
            getrusage(RUSAGE_CHILDREN,&rusage);
3683
            return(((LONG)(rusage.ru_utime.tv_sec)+(LONG)(rusage.ru_stime.tv_sec))*1000
3684
                      +(rusage.ru_utime.tv_usec/1000+rusage.ru_stime.tv_usec/1000));
3685
        }
3686
        else {
3687
            getrusage(RUSAGE_SELF,&rusage);
3688
            return(((LONG)(rusage.ru_utime.tv_sec)+(LONG)(rusage.ru_stime.tv_sec))*1000
3689
                      +(rusage.ru_utime.tv_usec/1000+rusage.ru_stime.tv_usec/1000));
3690
        }
3691
}
3692

3693
#elif defined(ANSI)
3694
LONG Timer(int par)
3695
{
3696
#ifdef ALPHA
3697
/*         clock_t t,tikken = clock();                                                                          */
3698
/*         MesPrint("ALPHA-clock = %l",(LONG)tikken);                                          */
3699
/*         t = tikken % CLOCKS_PER_SEC;                                                                  */
3700
/*         tikken /= CLOCKS_PER_SEC;                                                                          */
3701
/*         tikken *= 1000;                                                                                                  */
3702
/*         tikken += (t*1000)/CLOCKS_PER_SEC;                                                          */
3703
/*         return((LONG)tikken);                                                                                  */
3704
/* #define _TIME_T_                                                                                                  */
3705
#include <sys/time.h>
3706
#include <sys/resource.h>
3707
    struct rusage rusage;
3708
        if ( par == 1 ) {
3709
            getrusage(RUSAGE_CHILDREN,&rusage);
3710
            return(((LONG)(rusage.ru_utime.tv_sec)+(LONG)(rusage.ru_stime.tv_sec))*1000
3711
                      +(rusage.ru_utime.tv_usec/1000+rusage.ru_stime.tv_usec/1000));
3712
        }
3713
        else {
3714
            getrusage(RUSAGE_SELF,&rusage);
3715
            return(((LONG)(rusage.ru_utime.tv_sec)+(LONG)(rusage.ru_stime.tv_sec))*1000
3716
                      +(rusage.ru_utime.tv_usec/1000+rusage.ru_stime.tv_usec/1000));
3717
        }
3718
#else
3719
#ifdef DEC_STATION
3720
        clock_t tikken = clock();
3721
        return((LONG)tikken/1000);
3722
#else
3723
        clock_t t, tikken = clock();
3724
        t = tikken % CLK_TCK;
3725
        tikken /= CLK_TCK;
3726
        tikken *= 1000;
3727
        tikken += (t*1000)/CLK_TCK;
3728
        return(tikken);
3729
#endif
3730
#endif
3731
}
3732
#elif defined(VMS)
3733

3734
#include <time.h>
3735
void times(tbuffer_t *buffer);
3736

3737
LONG
3738
Timer(int par)
3739
{
3740
        tbuffer_t buffer;
3741
        if ( par == 1 ) { return(0); }
3742
        else {
3743
                times(&buffer);
3744
                return(buffer.proc_user_time * 10);
3745
        }
3746
}
3747

3748
#elif defined(mBSD)
3749

3750
#ifdef MICROTIME
3751
/*
3752
        There is only a CP time clock in microseconds here
3753
        This can cause problems with AO.wrap around
3754
*/
3755
#else
3756
#ifdef mBSD2
3757
#include <sys/types.h>
3758
#include <sys/times.h>
3759
#include <time.h>
3760
LONG pretime = 0;
3761
#else
3762
#define _TIME_T_
3763
#include <sys/time.h>
3764
#include <sys/resource.h>
3765
#endif
3766
#endif
3767

3768
LONG Timer(int par)
3769
{
3770
#ifdef MICROTIME
3771
        LONG t;
3772
        if ( par == 1 ) { return(0); }
3773
        t = clock();
3774
        if ( ( AO.wrapnum & 1 ) != 0 ) t ^= 0x80000000;
3775
        if ( t < 0 ) {
3776
                t ^= 0x80000000;
3777
                warpnum++;
3778
                AO.wrap += 2147584;
3779
        }
3780
        return(AO.wrap+(t/1000));
3781
#else
3782
#ifdef mBSD2
3783
        struct tms buffer;
3784
        LONG ret;
3785
        ULONG a1, a2, a3, a4;
3786
        if ( par == 1 ) { return(0); }
3787
        times(&buffer);
3788
        a1 = (ULONG)buffer.tms_utime;
3789
        a2 = a1 >> 16;
3790
        a3 = a1 & 0xFFFFL;
3791
        a3 *= 1000;
3792
        a2 = 1000*a2 + (a3 >> 16);
3793
        a3 &= 0xFFFFL;
3794
        a4 = a2/CLK_TCK;
3795
        a2 %= CLK_TCK;
3796
        a3 += a2 << 16;
3797
        ret = (LONG)((a4 << 16) + a3 / CLK_TCK);
3798
/*        ret = ((LONG)buffer.tms_utime * 1000)/CLK_TCK; */
3799
        return(ret);
3800
#else
3801
#ifdef REALTIME
3802
        struct timeval tp;
3803
        struct timezone tzp;
3804
        if ( par == 1 ) { return(0); }
3805
        gettimeofday(&tp,&tzp); */
3806
        return(tp.tv_sec*1000+tp.tv_usec/1000);
3807
#else
3808
        struct rusage rusage;
3809
        if ( par == 1 ) {
3810
            getrusage(RUSAGE_CHILDREN,&rusage);
3811
            return((rusage.ru_utime.tv_sec+rusage.ru_stime.tv_sec)*1000
3812
                      +(rusage.ru_utime.tv_usec/1000+rusage.ru_stime.tv_usec/1000));
3813
        }
3814
        else {
3815
            getrusage(RUSAGE_SELF,&rusage);
3816
            return((rusage.ru_utime.tv_sec+rusage.ru_stime.tv_sec)*1000
3817
                      +(rusage.ru_utime.tv_usec/1000+rusage.ru_stime.tv_usec/1000));
3818
        }
3819
#endif
3820
#endif
3821
#endif
3822
}
3823

3824
#endif
3825

3826
/*
3827
                 #] Timer : 
3828
                 #[ Crash :
3829

3830
                Routine for debugging purposes
3831
*/
3832

3833
int Crash(VOID)
96✔
3834
{
3835
        int retval;
96✔
3836
#ifdef DEBUGGING
3837
        int *zero = 0;
96✔
3838
        retval = *zero;
96✔
3839
#else
3840
        retval = 0;
3841
#endif
3842
        return(retval);
96✔
3843
}
3844

3845
/*
3846
                 #] Crash : 
3847
                 #[ TestTerm :
3848
*/
3849

3850
/**
3851
 *        Tests the consistency of the term.
3852
 *        Returns 0 when the term is OK. Any nonzero value is trouble.
3853
 *        In the current version the testing isn't 100% complete.
3854
 *        For instance, we don't check the validity of the symbols nor
3855
 *        do we check the range of their powers. Etc.
3856
 *        This should be extended when the need is there.
3857
 *
3858
 *        @param term: the term to be tested
3859
 */
3860

3861
int TestTerm(WORD *term)
×
3862
{
3863
        int errorcode = 0, coeffsize;
×
3864
        WORD *t, *tt, *tstop, *endterm, *targ, *targstop, *funstop, *argterm;
×
3865
        endterm = term + *term;
×
3866
        coeffsize = ABS(endterm[-1]);
×
3867
        if ( coeffsize >= *term ) {
×
3868
                MLOCK(ErrorMessageLock);
×
3869
                MesPrint("TestTerm: Internal inconsistency in term. Coefficient too big.");
×
3870
                MUNLOCK(ErrorMessageLock);
×
3871
                errorcode = 1;
×
3872
                goto finish;
×
3873
        }
3874
        if ( ( coeffsize < 3 ) || ( ( coeffsize & 1 ) != 1 ) ) {
×
3875
                MLOCK(ErrorMessageLock);
×
3876
                MesPrint("TestTerm: Internal inconsistency in term. Wrong size coefficient.");
×
3877
                MUNLOCK(ErrorMessageLock);
×
3878
                errorcode = 2;
×
3879
                goto finish;
×
3880
        }
3881
        t = term+1;
×
3882
        tstop = endterm - coeffsize;
×
3883
        while ( t < tstop ) {
×
3884
                switch ( *t ) {
×
3885
                        case SYMBOL:
3886
                        case DOTPRODUCT:
3887
                        case INDEX:
3888
                        case VECTOR:
3889
                        case DELTA:
3890
                        case HAAKJE:
3891
                                break;
3892
                        case SNUMBER:
×
3893
                        case LNUMBER:
3894
                                MLOCK(ErrorMessageLock);
×
3895
                                MesPrint("TestTerm: Internal inconsistency in term. L or S number");
×
3896
                                MUNLOCK(ErrorMessageLock);
×
3897
                                errorcode = 3;
×
3898
                                goto finish;
×
3899
                                break;
3900
                        case EXPRESSION:
3901
                        case SUBEXPRESSION:
3902
                        case DOLLAREXPRESSION:
3903
/*
3904
                                MLOCK(ErrorMessageLock);
3905
                                MesPrint("TestTerm: Internal inconsistency in term. Expression survives.");
3906
                                MUNLOCK(ErrorMessageLock);
3907
                                errorcode = 4;
3908
                                goto finish;
3909
*/
3910
                                break;
3911
                        case SETSET:
×
3912
                        case MINVECTOR:
3913
                        case SETEXP:
3914
                        case ARGFIELD:
3915
                                MLOCK(ErrorMessageLock);
×
3916
                                MesPrint("TestTerm: Internal inconsistency in term. Illegal subterm.");
×
3917
                                MUNLOCK(ErrorMessageLock);
×
3918
                                errorcode = 5;
×
3919
                                goto finish;
×
3920
                                break;
3921
                        case ARGWILD:
3922
                                break;
3923
                        default:
×
3924
                                if ( *t <= 0 ) {
×
3925
                                        MLOCK(ErrorMessageLock);
×
3926
                                        MesPrint("TestTerm: Internal inconsistency in term. Illegal subterm number.");
×
3927
                                        MUNLOCK(ErrorMessageLock);
×
3928
                                        errorcode = 6;
×
3929
                                        goto finish;
×
3930
                                }
3931
/*
3932
                                This is a regular function.
3933
*/
3934
                                if ( *t-FUNCTION >= NumFunctions ) {
×
3935
                                        MLOCK(ErrorMessageLock);
×
3936
                                        MesPrint("TestTerm: Internal inconsistency in term. Illegal function number");
×
3937
                                        MUNLOCK(ErrorMessageLock);
×
3938
                                        errorcode = 7;
×
3939
                                        goto finish;
×
3940
                                }
3941
                                funstop = t + t[1];
×
3942
                                if ( funstop > tstop ) goto subtermsize;
×
3943
                                if ( t[2] != 0 ) {
×
3944
                                        MLOCK(ErrorMessageLock);
×
3945
                                        MesPrint("TestTerm: Internal inconsistency in term. Dirty flag nonzero.");
×
3946
                                        MUNLOCK(ErrorMessageLock);
×
3947
                                        errorcode = 8;
×
3948
                                        goto finish;
×
3949
                                }
3950
                                targ = t + FUNHEAD;
×
3951
                                if ( targ > funstop ) {
×
3952
                                        MLOCK(ErrorMessageLock);
×
3953
                                        MesPrint("TestTerm: Internal inconsistency in term. Illegal function size.");
×
3954
                                        MUNLOCK(ErrorMessageLock);
×
3955
                                        errorcode = 9;
×
3956
                                        goto finish;
×
3957
                                }
3958
                                if ( functions[*t-FUNCTION].spec >= TENSORFUNCTION ) {
×
3959
                                }
3960
                                else {
3961
                                  while ( targ < funstop ) {
×
3962
                                        if ( *targ < 0 ) {
×
3963
                                                if ( *targ <= -(FUNCTION+NumFunctions) ) {
×
3964
                                                        MLOCK(ErrorMessageLock);
×
3965
                                                        MesPrint("TestTerm: Internal inconsistency in term. Illegal function number in argument.");
×
3966
                                                        MUNLOCK(ErrorMessageLock);
×
3967
                                                        errorcode = 10;
×
3968
                                                        goto finish;
×
3969
                                                }
3970
                                                if ( *targ <= -FUNCTION ) { targ++; }
×
3971
                                                else {
3972
                                                        if ( ( *targ != -SYMBOL ) && ( *targ != -VECTOR )
×
3973
                                                        && ( *targ != -MINVECTOR )
3974
                                                        && ( *targ != -SNUMBER )
3975
                                                        && ( *targ != -ARGWILD )
3976
                                                        && ( *targ != -INDEX ) ) {
3977
                                                                MLOCK(ErrorMessageLock);
×
3978
                                                                MesPrint("TestTerm: Internal inconsistency in term. Illegal object in argument.");
×
3979
                                                                MUNLOCK(ErrorMessageLock);
×
3980
                                                                errorcode = 11;
×
3981
                                                                goto finish;
×
3982
                                                        }
3983
                                                        targ += 2;
×
3984
                                                }
3985
                                        }
3986
                                        else if ( ( *targ < ARGHEAD ) || ( targ+*targ > funstop ) ) {
×
3987
                                                MLOCK(ErrorMessageLock);
×
3988
                                                MesPrint("TestTerm: Internal inconsistency in term. Illegal size of argument.");
×
3989
                                                MUNLOCK(ErrorMessageLock);
×
3990
                                                errorcode = 12;
×
3991
                                                goto finish;
×
3992
                                        }
3993
                                        else if ( targ[1] != 0 ) {
×
3994
                                                MLOCK(ErrorMessageLock);
×
3995
                                                MesPrint("TestTerm: Internal inconsistency in term. Dirty flag in argument.");
×
3996
                                                MUNLOCK(ErrorMessageLock);
×
3997
                                                errorcode = 13;
×
3998
                                                goto finish;
×
3999
                                        }
4000
                                        else {
4001
                                                targstop = targ + *targ;
×
4002
                                                argterm = targ + ARGHEAD;
×
4003
                                                while ( argterm < targstop ) {
×
4004
                                                        if ( ( *argterm < 4 ) || ( argterm + *argterm > targstop ) ) {
×
4005
                                                                MLOCK(ErrorMessageLock);
×
4006
                                                                MesPrint("TestTerm: Internal inconsistency in term. Illegal termsize in argument.");
×
4007
                                                                MUNLOCK(ErrorMessageLock);
×
4008
                                                                errorcode = 14;
×
4009
                                                                goto finish;
×
4010
                                                        }
4011
                                                        if ( TestTerm(argterm) != 0 ) {
×
4012
                                                                MLOCK(ErrorMessageLock);
×
4013
                                                                MesPrint("TestTerm: Internal inconsistency in term. Called from TestTerm.");
×
4014
                                                                MUNLOCK(ErrorMessageLock);
×
4015
                                                                errorcode = 15;
×
4016
                                                                goto finish;
×
4017
                                                        }
4018
                                                        argterm += *argterm;
×
4019
                                                }
4020
                                                targ = targstop;
4021
                                        }
4022
                                  }
4023
                                }
4024
                                break;
4025
                }
4026
                tt = t + t[1];
×
4027
                if ( tt > tstop ) {
×
4028
subtermsize:
×
4029
                        MLOCK(ErrorMessageLock);
×
4030
                        MesPrint("TestTerm: Internal inconsistency in term. Illegal subterm size.");
×
4031
                        MUNLOCK(ErrorMessageLock);
×
4032
                        errorcode = 100;
×
4033
                        goto finish;
×
4034
                }
4035
                t = tt;
4036
        }
4037
        return(errorcode);
4038
finish:
4039
        return(errorcode);
4040
}
4041

4042
/*
4043
                 #] TestTerm : 
4044
                 #[ DistrN :
4045
*/
4046
 
4047
int DistrN(int n, int *cpl, int ncpl, int *scratch)
×
4048
{
4049
/*
4050
        Divides n objects over ncpl bins (cpl), each time returning one
4051
        of those distributions until there are no more after which the 
4052
        routine returns the value zero (otherwise one).
4053
        The array scratch (size n) is kept for the intermediate information.
4054
        The whole starts with scratch[0] == -2;
4055
*/
4056
        int i, j;
×
4057
        if ( ncpl == 0 ) {
×
4058
                if ( scratch[0] == -2 ) { scratch[0] = 0; return(1); }
×
4059
                else return(0);
4060
        }
4061
        if ( scratch[0] == ncpl-1 ) {
×
4062
                return(0);
4063
        }
4064
        else if ( scratch[0] == -2 ) {
×
4065
                for ( i = 0; i < n; i++ ) scratch[i] = 0;
×
4066
        }
4067
        else {
4068
                j = n-1;
×
4069
                while ( j >= 0 ) {
×
4070
                        scratch[j]++;
×
4071
                        if ( scratch[j] < ncpl ) break;
×
4072
                        j--;
×
4073
                }
4074
                j++;
×
4075
                while ( j < n ) { scratch[j] = scratch[j-1]; j++; }
×
4076
        }
4077
        for ( i = 0; i < ncpl; i++ ) cpl[i] = 0;
×
4078
        for ( i = 0; i < n; i++ ) { cpl[scratch[i]]++; }
×
4079
        return(1);
4080
}
4081

4082
/*
4083
                 #] DistrN : 
4084
          #] Mixed : 
4085
*/
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