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

vermaseren / form / 9364948935

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

Pull #526

github

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

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

32 existing lines in 2 files now uncovered.

41391 of 82816 relevant lines covered (49.98%)

878690.77 hits per line

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

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

36
#include "form3.h"
37

38
/*
39
          #] includes : 
40
          #[ Commentary :
41

42
        We use an array of SPECTATOR structs in AM.SpectatorFiles.
43
        When a spectator is removed this leaves a hole. This means that
44
        we cannot use AM.NumSpectatorFiles but always have to scan up to
45
        AM.SizeForSpectatorFiles which is the size of the array.
46
        An element is in use when it has a name. This is the name of the
47
        expression that is associated with it. There is also the number of
48
        the expression, but because the expressions are frequently renumbered
49
        at the end of a module, we always search for the spectators by name.
50
        The expression number is only valid in the current module.
51
        During execution we use the number of the spectator.
52

53
        The FILEHANDLE struct is borrowed from the structs for the scratch
54
        files, but we do not keep copies for all workers as with the scratch
55
        files. This brings some limitations (but saves much space). Basically
56
        the reading can only be done by one master or worker. And because
57
        we use the buffer both for writing and for reading we cannot read and
58
        write in the same module.
59

60
        Processor can see that an expression is to be filled with a spectator
61
        because we replace the compiler buffer number in the prototype by
62
        -specnum-1. Of course, after this filling has taken place we should
63
        make sure that in the next module there is a nonnegative number there.
64
        The input is then obtained from GetFromSpectator instead from GetTerm.
65
        This needed an extra argument in ThreadsProcessor. InParallelProcessor
66
        can figure it out by itself. ParFORM still needs to be treated for this.
67

68
        The writing is to a single buffer. Hence it needs a lock. It is possible
69
        to give all workers their own buffers (at great memory cost) and merge
70
        the results when needed. That would be friendlier on ParFORM. We ALWAYS
71
        assume that the order of the terms in the spectator file is random.
72

73
        In the first version there is no compression in the file. This could
74
        change in later versions because both the writing and the reading are
75
        purely sequential. Brackets are not possible.
76

77
        Currently, ParFORM allows use of spectators only in the sequential
78
        mode. The parallelization is switched off in modules containing
79
        ToSpectator or CopySpectator. Workers never create or access to
80
        spectator files. Their file handles are always -1. We leave the
81
        parallelization of modules with spectators for future work.
82

83
          #] Commentary : 
84
          #[ CoCreateSpectator :
85

86
        Syntax: CreateSpectator name_of_expr "filename";
87
*/
88

89
int CoCreateSpectator(UBYTE *inp)
77✔
90
{
91
        UBYTE *p, *q, *filename, c, cc;
77✔
92
        WORD c1, c2, numexpr = 0, specnum, HadOne = 0;
77✔
93
        FILEHANDLE *fh;
77✔
94
        while ( *inp == ',' ) inp++;
77✔
95
        if ( ( q = SkipAName(inp) ) == 0 || q[-1] == '_' ) {
77✔
96
                MesPrint("&Illegal name for expression");
×
97
                return(1);
×
98
        }
99
        c = *q; *q = 0;
77✔
100
        if ( GetVar(inp,&c1,&c2,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
77✔
101
                if ( c2 == CEXPRESSION && 
×
102
                                Expressions[c1].status == DROPSPECTATOREXPRESSION ) {
×
103
                        numexpr = c1;
×
104
                        Expressions[numexpr].status = SPECTATOREXPRESSION;
×
105
                        HadOne = 1;
×
106
                }
107
                else {
108
                        MesPrint("&The name %s has been used already.",inp);
×
109
                        *q = c;
×
110
                        return(1);
×
111
                }
112
        }
113
        p = q+1;
77✔
114
        while ( *p == ',' ) p++;
77✔
115
        if ( *p != '"' ) goto Syntax;
77✔
116
        p++; filename = p;
77✔
117
        while ( *p && *p != '"' ) {
595✔
118
                if ( *p == '\\' ) p++;
518✔
119
                p++;
518✔
120
        }
121
        if ( *p != '"' ) goto Syntax;
77✔
122
        q = p+1;
77✔
123
        while ( *q && ( *q == ',' || *q == ' ' || *q == '\t' ) ) q++;
77✔
124
        if ( *q ) goto Syntax;
77✔
125
        cc = *p; *p = 0;
77✔
126
/*
127
        Now we need to: create a struct for the spectator file.
128
*/
129
        if ( HadOne == 0 )
77✔
130
                numexpr = EntVar(CEXPRESSION,inp,SPECTATOREXPRESSION,0,0,0);
77✔
131
        fh = AllocFileHandle(1,(char *)filename);
77✔
132
/*
133
        Make sure there is space in the AM.spectatorfiles array
134
*/
135
        if ( AM.NumSpectatorFiles >= AM.SizeForSpectatorFiles || AM.SpectatorFiles == 0 ) {
77✔
136
                int newsize, i;
14✔
137
                SPECTATOR *newspectators;
14✔
138
                if ( AM.SizeForSpectatorFiles == 0 ) {
14✔
139
                        newsize = 10;
14✔
140
                        AM.NumSpectatorFiles = AM.SizeForSpectatorFiles = 0;
14✔
141
                }
142
                else newsize = AM.SizeForSpectatorFiles*2;
×
143
                newspectators = (SPECTATOR *)Malloc1(newsize*sizeof(SPECTATOR),"Spectators");
14✔
144
                for ( i = 0; i < AM.NumSpectatorFiles; i++ )
28✔
145
                        newspectators[i] = AM.SpectatorFiles[i];
×
146
                for ( ; i < newsize; i++ ) {
154✔
147
                        newspectators[i].fh = 0;
140✔
148
                        newspectators[i].name = 0;
140✔
149
                        newspectators[i].exprnumber = -1;
140✔
150
                        newspectators[i].flags = 0;
140✔
151
                        PUTZERO(newspectators[i].position);
140✔
152
                        PUTZERO(newspectators[i].readpos);
140✔
153
                }
154
                AM.SizeForSpectatorFiles = newsize;
14✔
155
                if ( AM.SpectatorFiles != 0 ) M_free(AM.SpectatorFiles,"Spectators");
14✔
156
                AM.SpectatorFiles = newspectators;
14✔
157
                specnum = AM.NumSpectatorFiles++;
14✔
158
        }
159
        else {
160
                for ( specnum = 0; specnum < AM.SizeForSpectatorFiles; specnum++ ) {
315✔
161
                        if ( AM.SpectatorFiles[specnum].name == 0 ) break;
315✔
162
                }
163
                AM.NumSpectatorFiles++;
63✔
164
        }
165
        PUTZERO(AM.SpectatorFiles[specnum].position);
77✔
166
        AM.SpectatorFiles[specnum].name = (char *)(strDup1(inp,"Spectator expression name"));
77✔
167
        AM.SpectatorFiles[specnum].fh = fh;
77✔
168
        AM.SpectatorFiles[specnum].exprnumber = numexpr;
77✔
169
        *p = cc;
77✔
170
        return(0);
77✔
171
Syntax:
×
172
        MesPrint("&Proper syntax is: CreateSpectator,exprname,\"filename\";");
×
173
        return(-1);
×
174
}
175

176
/*
177
          #] CoCreateSpectator : 
178
          #[ CoToSpectator :
179
*/
180

181
int CoToSpectator(UBYTE *inp)
14✔
182
{
183
        UBYTE *q;
14✔
184
        WORD c1, numexpr;
14✔
185
        int i;
14✔
186
        while ( *inp == ',' ) inp++;
14✔
187
        if ( ( q = SkipAName(inp) ) == 0 || q[-1] == '_' ) {
14✔
188
                MesPrint("&Illegal name for expression");
×
189
                return(1);
×
190
        }
191
        if ( *q != 0 ) goto Syntax;
14✔
192
        if ( GetVar(inp,&c1,&numexpr,ALLVARIABLES,NOAUTO) == NAMENOTFOUND ||
14✔
193
                        c1 != CEXPRESSION ) {
14✔
194
                MesPrint("&%s is not a valid expression.",inp);
×
195
                return(1);
×
196
        }
197
        if ( Expressions[numexpr].status != SPECTATOREXPRESSION ) {
14✔
198
                MesPrint("&%s is not an active spectator.",inp);
×
199
                return(1);
×
200
        }
201
        for ( i = 0; i < AM.SizeForSpectatorFiles; i++ ) {
35✔
202
          if ( AM.SpectatorFiles[i].name != 0 ) {
35✔
203
                if ( StrCmp((UBYTE *)(AM.SpectatorFiles[i].name),(UBYTE *)(inp)) == 0 ) break;
21✔
204
          }
205
        }
206
        if ( i >= AM.SizeForSpectatorFiles ) {
14✔
207
                MesPrint("&Spectator %s not found.",inp);
×
208
                return(1);
×
209
        }
210
        if ( ( AM.SpectatorFiles[i].flags & READSPECTATORFLAG ) != 0 ) {
14✔
211
                MesPrint("&Spectator %s: It is not permitted to read from and write to the same spectator in one module.",inp);
×
212
                return(1);
×
213
        }
214
        AM.SpectatorFiles[i].exprnumber = numexpr;
14✔
215
        Add3Com(TYPETOSPECTATOR,i);
14✔
216
#ifdef WITHMPI
217
        /*
218
         * In ParFORM, ToSpectator has to be executed on the master.
219
         */
220
        AC.mparallelflag |= NOPARALLEL_SPECTATOR;
8✔
221
#endif
222
        return(0);
14✔
223
Syntax:
×
224
        MesPrint("&Proper syntax is: ToSpectator,exprname;");
×
225
        return(-1);
×
226
}
227

228
/*
229
          #] CoToSpectator : 
230
          #[ CoRemoveSpectator :
231
*/
232

233
int CoRemoveSpectator(UBYTE *inp)
42✔
234
{
235
        UBYTE *q;
42✔
236
        WORD c1, numexpr;
42✔
237
        int i;
42✔
238
        SPECTATOR *sp;
42✔
239
        while ( *inp == ',' ) inp++;
42✔
240
        if ( ( q = SkipAName(inp) ) == 0 || q[-1] == '_' ) {
42✔
241
                MesPrint("&Illegal name for expression");
×
242
                return(1);
×
243
        }
244
        if ( *q != 0 ) goto Syntax;
42✔
245
        if ( GetVar(inp,&c1,&numexpr,ALLVARIABLES,NOAUTO) == NAMENOTFOUND ||
42✔
246
                        c1 != CEXPRESSION ) {
42✔
247
                MesPrint("&%s is not a valid expression.",inp);
×
248
                return(1);
×
249
        }
250
        if ( Expressions[numexpr].status != SPECTATOREXPRESSION ) {
42✔
251
                MesPrint("&%s is not a spectator.",inp);
×
252
                return(1);
×
253
        }
254
        for ( i = 0; i < AM.SizeForSpectatorFiles; i++ ) {
203✔
255
                if ( AM.SpectatorFiles[i].name != 0 ) {
203✔
256
                        if ( StrCmp((UBYTE *)(AM.SpectatorFiles[i].name),(UBYTE *)(inp)) == 0 ) {
119✔
257
                                break;
258
                        }
259
                }
260
        }
261
        if ( i >= AM.SizeForSpectatorFiles ) {
42✔
262
                MesPrint("&Spectator %s not found.",inp);
×
263
                return(1);
×
264
        }
265
        sp = AM.SpectatorFiles+i;
42✔
266
        Expressions[numexpr].status = DROPSPECTATOREXPRESSION;
42✔
267
        if ( sp->fh->handle != -1 ) {
42✔
268
                CloseFile(sp->fh->handle);
8✔
269
                sp->fh->handle = -1;
8✔
270
                remove(sp->fh->name);
8✔
271
        }
272
        M_free(sp->fh,"Temporary FileHandle");
42✔
273
        M_free(sp->name,"Spectator expression name");
42✔
274

275
        PUTZERO(sp->position);
42✔
276
        PUTZERO(sp->readpos);
42✔
277
        sp->fh = 0;
42✔
278
        sp->name = 0;
42✔
279
        sp->exprnumber = -1;
42✔
280
        sp->flags = 0;
42✔
281
        AM.NumSpectatorFiles--;
42✔
282
        return(0);
42✔
283
Syntax:
×
284
        MesPrint("&Proper syntax is: RemoveSpectator,exprname;");
×
285
        return(-1);
×
286
}
287

288
/*
289
          #] CoRemoveSpectator : 
290
          #[ CoEmptySpectator :
291
*/
292

293
int CoEmptySpectator(UBYTE *inp)
×
294
{
295
        UBYTE *q;
×
296
        WORD c1, numexpr;
×
297
        int i;
×
298
        SPECTATOR *sp;
×
299
        while ( *inp == ',' ) inp++;
×
300
        if ( ( q = SkipAName(inp) ) == 0 || q[-1] == '_' ) {
×
301
                MesPrint("&Illegal name for expression");
×
302
                return(1);
×
303
        }
304
        if ( *q != 0 ) goto Syntax;
×
305
        if ( GetVar(inp,&c1,&numexpr,ALLVARIABLES,NOAUTO) == NAMENOTFOUND ||
×
306
                        c1 != CEXPRESSION ) {
×
307
                MesPrint("&%s is not a valid expression.",inp);
×
308
                return(1);
×
309
        }
310
        if ( Expressions[numexpr].status != SPECTATOREXPRESSION ) {
×
311
                MesPrint("&%s is not a spectator.",inp);
×
312
                return(1);
×
313
        }
314
        for ( i = 0; i < AM.SizeForSpectatorFiles; i++ ) {
×
315
                if ( StrCmp((UBYTE *)(AM.SpectatorFiles[i].name),(UBYTE *)(inp)) == 0 ) break;
×
316
        }
317
        if ( i >= AM.SizeForSpectatorFiles ) {
×
318
                MesPrint("&Spectator %s not found.",inp);
×
319
                return(1);
×
320
        }
321
        sp = AM.SpectatorFiles+i;
×
322
        if ( sp->fh->handle != -1 ) {
×
323
                CloseFile(sp->fh->handle);
×
324
                sp->fh->handle = -1;
×
325
                remove(sp->fh->name);
×
326
        }
327
        sp->fh->POfill = sp->fh->POfull = sp->fh->PObuffer;
×
328
        PUTZERO(sp->position);
×
329
        PUTZERO(sp->readpos);
×
330
        return(0);
×
331
Syntax:
×
332
        MesPrint("&Proper syntax is: EmptySpectator,exprname;");
×
333
        return(-1);
×
334
}
335

336
/*
337
          #] CoEmptySpectator : 
338
          #[ PutInSpectator :
339

340
        We need to use locks! There is only one file.
341
        The code was copied (and modified) from PutOut.
342
        Here we use no compression.
343
*/
344

345
int PutInSpectator(WORD *term,WORD specnum)
8✔
346
{
347
        GETBIDENTITY
348
        WORD i, *p, ret;
8✔
349
        LONG RetCode;
8✔
350
        SPECTATOR *sp = &(AM.SpectatorFiles[specnum]);
8✔
351
        FILEHANDLE *fi = sp->fh;
8✔
352

353
        if ( ( i = *term ) <= 0 ) return(0);
8✔
354
        LOCK(fi->pthreadslock);
8✔
355
        ret = i;
8✔
356
        p = fi->POfill;
8✔
357
        do {
72✔
358
                if ( p >= fi->POstop ) {
72✔
359
                        if ( fi->handle < 0 ) {
×
360
                                if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
×
361
                                        fi->handle = (WORD)RetCode;
×
362
                                        PUTZERO(fi->filesize);
×
363
                                        PUTZERO(fi->POposition);
×
364
                                }
365
                                else {
366
                                        MLOCK(ErrorMessageLock);
×
367
                                        MesPrint("Cannot create spectator file %s",fi->name);
×
368
                                        MUNLOCK(ErrorMessageLock);
×
369
                                        UNLOCK(fi->pthreadslock);
×
370
                                        return(-1);
×
371
                                }
372
                        }
373
                        SeekFile(fi->handle,&(sp->position),SEEK_SET);
×
374
                        if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
×
375
                                MLOCK(ErrorMessageLock);
×
376
                                MesPrint("Error during spectator write. Disk full?");
×
377
                                MesPrint("Attempt to write %l bytes on file %d at position %15p",
×
378
                                                        fi->POsize,fi->handle,&(fi->POposition));
379
                                MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
×
380
                                MUNLOCK(ErrorMessageLock);
×
381
                                UNLOCK(fi->pthreadslock);
×
382
                                return(-1);
×
383
                        }
384
                        ADDPOS(fi->filesize,fi->POsize);
×
385
                        p = fi->PObuffer;
×
386
                        ADDPOS(sp->position,fi->POsize);
×
387
                        fi->POposition = sp->position;
×
388
                } 
389
                *p++ = *term++;
72✔
390
        } while ( --i > 0 );
72✔
391
        fi->POfull = fi->POfill = p;
8✔
392
        Expressions[AM.SpectatorFiles[specnum].exprnumber].counter++;
8✔
393
        UNLOCK(fi->pthreadslock);
8✔
394
        return(ret);
8✔
395
}
396

397
/*
398
          #] PutInSpectator : 
399
          #[ FlushSpectators :
400
*/
401

402
void FlushSpectators(VOID)
3,405✔
403
{
404
        SPECTATOR *sp = AM.SpectatorFiles;
3,405✔
405
        FILEHANDLE *fh;
3,405✔
406
        LONG RetCode;
3,405✔
407
        int i;
3,405✔
408
        LONG size;
3,405✔
409
        if ( AM.NumSpectatorFiles <= 0 ) return;
3,405✔
410
        for ( i = 0; i < AM.SizeForSpectatorFiles; i++, sp++ ) {
539✔
411
                if ( sp->name == 0 ) continue;
490✔
412
                fh = sp->fh;
182✔
413
                if ( ( sp->flags & READSPECTATORFLAG ) != 0 ) { /* reset for writing */
182✔
414
                        sp->flags &= ~READSPECTATORFLAG;
14✔
415
                        fh->POfill = fh->PObuffer;
14✔
416
                        if ( fh->handle >= 0 ) {
14✔
417
                                SeekFile(fh->handle,&(sp->position),SEEK_SET);
4✔
418
                                fh->POposition = sp->position;
4✔
419
                        }
420
                        continue;
14✔
421
                }
422
                if ( fh->POfill <= fh->PObuffer ) continue; /* is clean */
168✔
423
                if ( fh->handle < 0 ) {        /* File needs to be created */
8✔
424
                        if ( ( RetCode = CreateFile(fh->name) ) >= 0 ) {
8✔
425
                                PUTZERO(fh->filesize);
8✔
426
                                PUTZERO(fh->POposition);
8✔
427
                                fh->handle = (WORD)RetCode;
8✔
428
                        }
429
                        else {
430
                                MLOCK(ErrorMessageLock);
×
431
                                MesPrint("Cannot create spectator file %s",fh->name);
×
432
                                MUNLOCK(ErrorMessageLock);
×
NEW
433
                                TERMINATE(-1);
×
434
                        }
435
                        PUTZERO(sp->position);
8✔
436
                }
437
                SeekFile(fh->handle,&(sp->position),SEEK_SET);
8✔
438
                size = (fh->POfill - fh->PObuffer)*sizeof(WORD);
8✔
439
                if ( ( RetCode = WriteFile(fh->handle,(UBYTE *)(fh->PObuffer),size) ) != size ) {
8✔
440
                        MLOCK(ErrorMessageLock);
×
441
                        MesPrint("Write error synching spectator file. Disk full?");
×
442
                        MesPrint("Attempt to write %l bytes on file %s at position %15p",
×
443
                                                size,fh->name,&(sp->position));
444
                        MUNLOCK(ErrorMessageLock);
×
NEW
445
                        TERMINATE(-1);
×
446
                }
447
                fh->POfill = fh->PObuffer;
8✔
448
                SeekFile(fh->handle,&(sp->position),SEEK_END);
8✔
449
                fh->POposition = sp->position;
8✔
450
        }
451
        return;
452
}
453

454
/*
455
          #] FlushSpectators : 
456
          #[ CoCopySpectator :
457
*/
458

459
int CoCopySpectator(UBYTE *inp)
14✔
460
{
461
        GETIDENTITY
4✔
462
        UBYTE *q, c, *exprname, *p;
14✔
463
        WORD c1, c2, numexpr;
14✔
464
        int specnum, error = 0;
14✔
465
        SPECTATOR *sp;
14✔
466
        while ( *inp == ',' ) inp++;
14✔
467
        if ( ( q = SkipAName(inp) ) == 0 || q[-1] == '_' ) {
14✔
468
                MesPrint("&Illegal name for expression");
×
469
                return(1);
×
470
        }
471
        if ( *q == 0 ) goto Syntax;
14✔
472
        c = *q; *q = 0;
14✔
473
        if ( GetVar(inp,&c1,&c2,ALLVARIABLES,NOAUTO) != NAMENOTFOUND ) {
14✔
474
                MesPrint("&%s is the name of an existing variable.",inp);
×
475
                return(1);
×
476
        }
477
        numexpr = EntVar(CEXPRESSION,inp,LOCALEXPRESSION,0,0,0);
14✔
478
        p = q;
14✔
479
        exprname = inp;
14✔
480
        *q = c;
14✔
481
        while ( *q == ' ' || *q == ',' || *q == '\t' ) q++;
14✔
482
        if ( *q != '=' ) goto Syntax;
14✔
483
        q++;
14✔
484
        while ( *q == ' ' || *q == ',' || *q == '\t' ) q++;
14✔
485
        inp = q;
14✔
486
        if ( ( q = SkipAName(inp) ) == 0 || q[-1] == '_' ) {
14✔
487
                MesPrint("&Illegal name for spectator expression");
×
488
                return(1);
×
489
        }
490
        if ( *q != 0 ) goto Syntax;
14✔
491
        if ( AM.NumSpectatorFiles <= 0 ) {
14✔
492
                MesPrint("&CopySpectator: There are no spectator expressions!");
×
493
                return(1);
×
494
        }
495
        sp = AM.SpectatorFiles;
14✔
496
        for ( specnum = 0; specnum < AM.SizeForSpectatorFiles; specnum++, sp++ ) {
35✔
497
          if ( sp->name != 0 ) {
35✔
498
                if ( StrCmp((UBYTE *)(sp->name),(UBYTE *)(inp)) == 0 ) break;
21✔
499
          }
500
        }
501
        if ( specnum >= AM.SizeForSpectatorFiles ) {
14✔
502
                MesPrint("&Spectator %s not found.",inp);
×
503
                return(1);
×
504
        }
505
        sp->flags |= READSPECTATORFLAG;
14✔
506
        PUTZERO(sp->fh->POposition);
14✔
507
        PUTZERO(sp->readpos);
14✔
508
        sp->fh->POfill = sp->fh->PObuffer;
14✔
509
        if ( sp->fh->handle >= 0 ) {
14✔
510
                SeekFile(sp->fh->handle,&(sp->fh->POposition),SEEK_SET);
4✔
511
        }
512
/*
513
        Now we have:
514
        1: The name of the target expression: numexpr
515
        2: The spectator: sp (or specnum).
516
        Time for some action. We need:
517
        a: Write a prototype to create the expression
518
        b: Signal to Processor that this is a spectator.
519
           We do this by giving a negative compiler buffer number.
520
*/
521
        {
522
                WORD *OldWork, *w;
14✔
523
                POSITION pos;
14✔
524
                OldWork = w = AT.WorkPointer;
14✔
525
                *w++ = TYPEEXPRESSION;
14✔
526
                *w++ = 3+SUBEXPSIZE;
14✔
527
                *w++ = numexpr;
14✔
528
                AC.ProtoType = w;
14✔
529
                AR.CurExpr = numexpr;                                /* Block expression numexpr */
14✔
530
                *w++ = SUBEXPRESSION;
14✔
531
                *w++ = SUBEXPSIZE;
14✔
532
                *w++ = numexpr;
14✔
533
                *w++ = 1;
14✔
534
                *w++ = -specnum-1;                /* Indicates "spectator" to Processor */
14✔
535
                FILLSUB(w)
536
                *w++ = 1;
14✔
537
                *w++ = 1;
14✔
538
                *w++ = 3;
14✔
539
                *w++ = 0;
14✔
540
                SeekScratch(AR.outfile,&pos);
14✔
541
                Expressions[numexpr].counter = 1; 
14✔
542
                Expressions[numexpr].onfile = pos; 
14✔
543
                Expressions[numexpr].whichbuffer = 0;
14✔
544
#ifdef PARALLELCODE
545
                Expressions[numexpr].partodo = AC.inparallelflag; 
12✔
546
#endif
547
                OldWork[2] = w - OldWork - 3;
14✔
548
                AT.WorkPointer = w;
14✔
549

550
                if ( PutOut(BHEAD OldWork+2,&pos,AR.outfile,0) < 0 ) {
14✔
551
                        c = *p; *p = 0;
×
552
                        MesPrint("&Cannot create expression %s",exprname);
×
553
                        *p = c;
×
554
                        error = -1;
×
555
                }
556
                else {
557
                        OldWork[2] = 4+SUBEXPSIZE;
14✔
558
                        OldWork[4] = SUBEXPSIZE;
14✔
559
                        OldWork[5] = numexpr;
14✔
560
                        OldWork[SUBEXPSIZE+3] = 1;
14✔
561
                        OldWork[SUBEXPSIZE+4] = 1;
14✔
562
                        OldWork[SUBEXPSIZE+5] = 3;
14✔
563
                        OldWork[SUBEXPSIZE+6] = 0;
14✔
564
                        if ( PutOut(BHEAD OldWork+2,&pos,AR.outfile,0) < 0
14✔
565
                        || FlushOut(&pos,AR.outfile,0) ) {
14✔
566
                                c = *p; *p = 0;
×
567
                                MesPrint("&Cannot create expression %s",exprname);
×
568
                                *p = c;
×
569
                                error = -1;
×
570
                        }
571
                        AR.outfile->POfull = AR.outfile->POfill;
14✔
572
                }
573
                OldWork[2] = numexpr;
14✔
574
/*
575
                Seems unnecessary (13-feb-2018)
576

577
                AddNtoL(OldWork[1],OldWork);
578
*/
579
                AT.WorkPointer = OldWork;
14✔
580
                if ( AC.dumnumflag ) Add2Com(TYPEDETCURDUM)
14✔
581
        }
582
#ifdef WITHMPI
583
        /*
584
         * In ParFORM, substitutions of spectators has to be done on the master.
585
         */
586
        AC.mparallelflag |= NOPARALLEL_SPECTATOR;
8✔
587
#endif
588
        return(error);
14✔
589
Syntax:
×
590
        MesPrint("&Proper syntax is: CopySpectator,exprname=spectatorname;");
×
591
        return(-1);
×
592
}
593

594
/*
595
          #] CoCopySpectator : 
596
          #[ GetFromSpectator :
597

598
        Note that if we did things right, we do not need a lock for the reading.
599
*/
600

601
WORD GetFromSpectator(WORD *term,WORD specnum)
12✔
602
{
603
        SPECTATOR *sp = &(AM.SpectatorFiles[specnum]);
12✔
604
        FILEHANDLE *fh = sp->fh;
12✔
605
        WORD i, size, *t = term;
12✔
606
        LONG InIn;
12✔
607
        if ( fh-> handle < 0 ) {
12✔
608
                *term = 0;
4✔
609
                return(0);
4✔
610
        }
611
/*
612
        sp->position marks the 'end' of the file: the point where writing should
613
        take place. sp->readpos marks from where to read.
614
        fh->POposition marks where the file is currently positioned.
615
        Note that when we read, we need to 
616
*/
617
        if ( ISZEROPOS(sp->readpos) ) {        /* we start reading. Fill buffer. */
8✔
618
FillBuffer:
4✔
619
                SeekFile(fh->handle,&(sp->readpos),SEEK_SET);
4✔
620
                InIn = ReadFile(fh->handle,(UBYTE *)(fh->PObuffer),fh->POsize);
4✔
621
                if ( InIn < 0 || ( InIn & 1 ) ) {
4✔
622
                        MLOCK(ErrorMessageLock);
×
623
                        MesPrint("Error reading information for %s spectator",sp->name);
×
624
                        MUNLOCK(ErrorMessageLock);
×
NEW
625
                        TERMINATE(-1);
×
626
                }
627
                InIn /= sizeof(WORD);
4✔
628
                if ( InIn == 0 ) { *term = 0; return(0); }
4✔
629
                SeekFile(fh->handle,&(sp->readpos),SEEK_CUR);
4✔
630
                fh->POposition = sp->readpos;
4✔
631
                fh->POfull = fh->PObuffer+InIn;
4✔
632
                fh->POfill = fh->PObuffer;
4✔
633
        }
634
        if ( fh->POfill == fh->POfull ) { /* not even the size of the term! */
8✔
635
                if ( ISLESSPOS(sp->readpos,sp->position) ) goto FillBuffer;
4✔
636
                *term = 0;
4✔
637
                return(0);
4✔
638
        }
639
        size = *fh->POfill++; *t++ = size;
4✔
640
        for ( i = 1; i < size; i++ ) {
40✔
641
                if ( fh->POfill >= fh->POfull ) {
36✔
642
                        SeekFile(fh->handle,&(sp->readpos),SEEK_SET);
×
643
                        InIn = ReadFile(fh->handle,(UBYTE *)(fh->PObuffer),fh->POsize);
×
644
                        if ( InIn < 0 || ( InIn & 1 ) ) {
×
645
                                MLOCK(ErrorMessageLock);
×
646
                                MesPrint("Error reading information for %s spectator",sp->name);
×
647
                                MUNLOCK(ErrorMessageLock);
×
NEW
648
                                TERMINATE(-1);
×
649
                        }
650
                        InIn /= sizeof(WORD);
×
651
                        if ( InIn == 0 ) {
×
652
                                MLOCK(ErrorMessageLock);
×
653
                                MesPrint("Reading incomplete information for %s spectator",sp->name);
×
654
                                MUNLOCK(ErrorMessageLock);
×
NEW
655
                                TERMINATE(-1);
×
656
                        }
657
                        SeekFile(fh->handle,&(sp->readpos),SEEK_CUR);
×
658
                        fh->POposition = sp->readpos;
×
659
                        fh->POfull = fh->PObuffer+InIn;
×
660
                        fh->POfill = fh->PObuffer;
×
661
                }
662
                *t++ = *fh->POfill++;
36✔
663
        }
664
        return(size);
665
}
666

667
/*
668
          #] GetFromSpectator : 
669
          #[ ClearSpectators :
670

671
        Removes all spectators.
672
        In case of .store, the ones that are protected by .global stay.
673
*/
674

675
void ClearSpectators(WORD par)
1,804✔
676
{
677
        SPECTATOR *sp = AM.SpectatorFiles;
1,804✔
678
        WORD numexpr, c1;
1,804✔
679
        int i;
1,804✔
680
        if ( AM.NumSpectatorFiles > 0 ) {
1,804✔
681
                for ( i = 0; i < AM.SizeForSpectatorFiles; i++, sp++ ) {
154✔
682
                        if ( sp->name == 0 ) continue;
140✔
683
                        if ( ( sp->flags & GLOBALSPECTATORFLAG ) == 1 && par == STOREMODULE ) continue;
35✔
684

685
                        if ( GetVar((UBYTE *)(sp->name),&c1,&numexpr,ALLVARIABLES,NOAUTO) == NAMENOTFOUND ||
35✔
686
                                c1 != CEXPRESSION ) {
35✔
687
                                MesPrint("&%s is not a valid expression.",sp->name);
×
688
                                continue;
×
689
                        }
690
                        Expressions[numexpr].status = DROPPEDEXPRESSION;
35✔
691
                        if ( sp->fh->handle != -1 ) {
35✔
692
                                CloseFile(sp->fh->handle);
×
693
                                sp->fh->handle = -1;
×
694
                                remove(sp->fh->name);
×
695
                        }
696
                        M_free(sp->fh,"Temporary FileHandle");
35✔
697
                        M_free(sp->name,"Spectator expression name");
35✔
698
                        PUTZERO(sp->position);
35✔
699
                        sp->fh = 0;
35✔
700
                        sp->name = 0;
35✔
701
                        sp->exprnumber = -1;
35✔
702
                        sp->flags = 0;
35✔
703
                        AM.NumSpectatorFiles--;
35✔
704
                }
705
        }
706
}
1,804✔
707

708
/*
709
          #] ClearSpectators : 
710
*/
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc