FORM v5.0.0-35-g6318119
module.c
Go to the documentation of this file.
1
7/* #[ License : */
8/*
9 * Copyright (C) 1984-2026 J.A.M. Vermaseren
10 * When using this file you are requested to refer to the publication
11 * J.A.M.Vermaseren "New features of FORM" math-ph/0010025
12 * This is considered a matter of courtesy as the development was paid
13 * for by FOM the Dutch physics granting agency and we would like to
14 * be able to track its scientific use to convince FOM of its value
15 * for the community.
16 *
17 * This file is part of FORM.
18 *
19 * FORM is free software: you can redistribute it and/or modify it under the
20 * terms of the GNU General Public License as published by the Free Software
21 * Foundation, either version 3 of the License, or (at your option) any later
22 * version.
23 *
24 * FORM is distributed in the hope that it will be useful, but WITHOUT ANY
25 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
26 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
27 * details.
28 *
29 * You should have received a copy of the GNU General Public License along
30 * with FORM. If not, see <http://www.gnu.org/licenses/>.
31 */
32/* #] License : */
33/*
34 #[ Includes :
35*/
36
37#include "form3.h"
38
39/*
40 #] Includes :
41 #[ Modules :
42 #[ ModuleInstruction :
43
44 Enters after the . of .sort etc
45 We have word[[(options)][:commentary];]
46 Word is one of 'clear end global sort store'
47 Options are 'polyfun, endloopifunchanged, endloopifzero'
48 Additions for solving equations can be added to 'word'
49
50 The flag in the moduleoptions is for telling whether the current
51 option can be followed by others. If it is > 0 it cannot.
52*/
53
54static KEYWORD ModuleWords[] = {
55 {"clear", (TFUN)0, CLEARMODULE, 0}
56 ,{"end", (TFUN)0, ENDMODULE, 0}
57 ,{"global", (TFUN)0, GLOBALMODULE, 0}
58 ,{"sort", (TFUN)0, SORTMODULE, 0}
59 ,{"store", (TFUN)0, STOREMODULE, 0}
60};
61
62static KEYWORD ModuleOptions[] = {
63 {"inparallel", DoinParallel, 1, 1}
64 ,{"local", DoModLocal, MODLOCAL, 0}
65 ,{"maximum", DoModMax, MODMAX, 0}
66 ,{"minimum", DoModMin, MODMIN, 0}
67 ,{"noparallel", DoNoParallel, NOPARALLEL_USER,0}
68 ,{"notinparallel", DonotinParallel,0, 1}
69 ,{"parallel", DoParallel, PARALLELFLAG, 0}
70 ,{"polyfun", DoPolyfun, POLYFUN, 0}
71 ,{"polyratfun", DoPolyratfun, POLYFUN, 0}
72 ,{"processbucketsize", DoProcessBucket,0, 0}
73 ,{"sum", DoModSum, MODSUM, 0}
74};
75
76int ModuleInstruction(int *moduletype, int *specialtype)
77{
78 UBYTE *t, *s, *u, c;
79 KEYWORD *key;
80 int addit = 0, error = 0, i, j;
81 DUMMYUSE(specialtype);
82 LoadInstruction(0);
83 AC.firstctypemessage = 0;
84 s = AP.preStart; SKIPBLANKS(s)
85 t = EndOfToken(s); c = *t; *t = 0;
86 AC.origin = FROMPOINTINSTRUCTION;
87 key = FindKeyWord(AP.preStart,ModuleWords,sizeof(ModuleWords)/sizeof(KEYWORD));
88 if ( key == 0 ) {
89 MesPrint("@Unrecognized module terminator: %s",s);
90 error = 1;
91 key = ModuleWords;
92 while ( StrCmp((UBYTE *)key->name,(UBYTE *)"end") ) key++;
93 }
94 *t = c;
95 *moduletype = key->type;
96 SKIPBLANKS(t);
97 while ( *t == '(' ) { /* There are options */
98 s = t+1; SKIPBRA3(t)
99 if ( *t == 0 ) {
100 MesPrint("@Improper options field in . instruction");
101 error = 1;
102 }
103 else {
104 *t = 0;
105 if ( CoModOption(s) ) error = 1;
106 *t++ = ')';
107 }
108 }
109 if ( *t == ':' ) { /* There is an 'advertisement' */
110 t++;
111 SKIPBLANKS(t)
112 s = t; i = 0;
113 while ( *t && *t != ';' ) {
114 if ( *t == '\\' ) t++;
115 t++; i++;
116 }
117 u = t;
118 while ( u > s && u[-1] == ' ' ) { u--; i--; }
119 if ( *u == '\\' ) { u++; i++; }
120 for ( j = COMMERCIALSIZE-1; j >= 0; j-- ) {
121 if ( i <= 0 ) break;
122 AC.Commercial[j] = *--u; i--;
123 if ( u > s && u[-1] == '\\' ) u--;
124 }
125 for ( ; j >= 0; j-- ) AC.Commercial[j] = ' ';
126 AC.Commercial[COMMERCIALSIZE] = 0;
127 addit += 2;
128 }
129 if ( addit && *t != ';' ) {
130 MesPrint("@Improper ending of . instruction");
131 error = -1;
132 }
133 return(error);
134}
135
136/*
137 #] ModuleInstruction :
138 #[ CoModuleOption :
139
140 ModuleOption, options;
141*/
142
143int CoModuleOption(UBYTE *s)
144{
145 UBYTE *t,*tt,c;
146 KEYWORD *option;
147 int error = 0, polyflag = 0;
148 AC.origin = FROMMODULEOPTION;
149 if ( *s ) do {
150 s = ToToken(s);
151 t = EndOfToken(s);
152 c = *t; *t = 0;
153 option = FindKeyWord(s,ModuleOptions,
154 sizeof(ModuleOptions)/sizeof(KEYWORD));
155 if ( option == 0 ) {
156 if ( polyflag ) {
157 *t = c; t++; s = SkipAName(t);
158 polyflag = 0;
159 continue;
160 }
161 else {
162 MesPrint("@Unrecognized module option: %s",s);
163 error = 1;
164 polyflag = 0;
165 *t = c;
166 }
167 }
168 else {
169 *t = c;
170 SKIPBLANKS(t)
171 if ( (option->func)(t) ) error = 1;
172 }
173 if ( error ) return(error);
174 if ( StrCmp((UBYTE *)(option->name),(UBYTE *)("polyfun")) == 0
175 || StrCmp((UBYTE *)(option->name),(UBYTE *)("polyratfun")) == 0 ) {
176 polyflag = 1;
177 t++;
178 t = SkipAName(t);
179 }
180 else polyflag = 0;
181 if ( option->flags > 0 ) return(error);
182 while ( *t ) {
183 if ( *t == ',' ) {
184 tt = t+1;
185 while ( *tt == ',' ) tt++;
186 if ( *tt != '$' ) break;
187 t = tt+1;
188 }
189 if ( *t == ')' ) break;
190 if ( *t == '(' ) SKIPBRA3(t)
191 else if ( *t == '{' ) SKIPBRA2(t)
192 else if ( *t == '[' ) SKIPBRA1(t)
193 t++;
194 }
195 s = t;
196 } while ( *s == ',' );
197 if ( *s ) {
198 MesPrint("@Unrecognized module option: %s",s);
199 error = 1;
200 }
201 return(error);
202}
203
204/*
205 #] CoModuleOption :
206 #[ CoModOption :
207
208 To be called from a .instruction.
209 Only recognizes polyfun. The newer ones should be via the
210 ModuleOption statement.
211*/
212
213int CoModOption(UBYTE *s)
214{
215 UBYTE *t,c;
216 int error = 0;
217 AC.origin = FROMPOINTINSTRUCTION;
218 if ( *s ) do {
219 s = ToToken(s);
220 t = EndOfToken(s);
221 c = *t; *t = 0;
222 if ( StrICmp(s,(UBYTE *)"polyfun") == 0 ) {
223 *t = c;
224 SKIPBLANKS(t)
225 if ( DoPolyfun(t) ) error = 1;
226 }
227 else if ( StrICmp(s,(UBYTE *)"polyratfun") == 0 ) {
228 *t = c;
229 SKIPBLANKS(t)
230 if ( DoPolyratfun(t) ) error = 1;
231 }
232 else {
233 MesPrint("@Unrecognized module option in .instruction: %s",s);
234 error = 1;
235 *t = c;
236 }
237 while ( *t ) {
238 if ( *t == ',' || *t == ')' ) break;
239 if ( *t == '(' ) SKIPBRA3(t)
240 else if ( *t == '{' ) SKIPBRA2(t)
241 else if ( *t == '[' ) SKIPBRA1(t)
242 t++;
243 }
244 s = t;
245 } while ( *s == ',' );
246 if ( *s ) {
247 MesPrint("@Unrecognized module option in .instruction: %s",s);
248 error = 1;
249 }
250 return(error);
251}
252
253/*
254 #] CoModOption :
255 #[ SetSpecialMode :
256*/
257
258void SetSpecialMode(int moduletype, int specialtype)
259{
260 DUMMYUSE(moduletype); DUMMYUSE(specialtype);
261}
262
263/*
264 #] SetSpecialMode :
265 #[ MakeGlobal :
266
267void MakeGlobal()
268{
269}
270
271 #] MakeGlobal :
272 #[ ExecModule :
273*/
274
275int ExecModule(int moduletype)
276{
277/*
278 Here we check module options and other things that should
279 be done at the start of a module.
280*/
281#ifdef WITHFLOAT
282 if ( ( AC.tMaxWeight != 0 && AC.tMaxWeight != AC.MaxWeight )
283 || ( AC.tDefaultPrecision != 0 && AC.tDefaultPrecision != AC.DefaultPrecision ) ) {
284 AC.DefaultPrecision = AC.tDefaultPrecision;
285 AC.tDefaultPrecision = 0;
286 AC.MaxWeight = AC.tMaxWeight;
287 AC.tMaxWeight = 0;
288 ClearMZVTables();
289 SetupMZVTables();
290 }
291#endif
292 return(DoExecute(moduletype,0));
293}
294
295/*
296 #] ExecModule :
297 #[ ExecStore :
298*/
299
300int ExecStore(void)
301{
302 return(0);
303}
304
305/*
306 #] ExecStore :
307 #[ FullCleanUp :
308
309 Remark 27-oct-2005 by JV
310 This routine (and CleanUp in startup.c) may still need some work:
311 What to do with preprocessor variables
312 What to do with files we write to
313*/
314
315void FullCleanUp(void)
316{
317 int j;
318
319 while ( AC.CurrentStream->previous >= 0 )
320 AC.CurrentStream = CloseStream(AC.CurrentStream);
321 AP.PreSwitchLevel = AP.PreIfLevel = 0;
322
323 for ( j = NumProcedures-1; j >= 0; j-- ) {
324 if ( Procedures[j].name ) M_free(Procedures[j].name,"name of procedure");
325 if ( Procedures[j].p.buffer ) M_free(Procedures[j].p.buffer,"buffer of procedure");
326 }
327 NumProcedures = 0;
328
329 while ( NumPre > AP.gNumPre ) {
330 NumPre--;
331 M_free(PreVar[NumPre].name,"PreVar[NumPre].name");
332 PreVar[NumPre].name = PreVar[NumPre].value = 0;
333 }
334
335 AC.DidClean = 0;
336 for ( j = 0; j < NumExpressions; j++ ) {
337 AC.exprnames->namenode[Expressions[j].node].type = CDELETE;
338 AC.DidClean = 1;
339 }
340
341 CompactifyTree(AC.exprnames,EXPRNAMES);
342
343 for ( j = AO.NumDictionaries-1; j >= 0; j-- ) {
344 RemoveDictionary(AO.Dictionaries[j]);
345 M_free(AO.Dictionaries[j],"Dictionary");
346 }
347 AO.NumDictionaries = AO.gNumDictionaries = 0;
348 M_free(AO.Dictionaries,"Dictionaries");
349 AO.Dictionaries = 0;
350 AO.SizeDictionaries = 0;
351 AP.OpenDictionary = 0;
352 AO.CurrentDictionary = 0;
353
354 AP.ComChar = AP.cComChar;
355 if ( AP.procedureExtension ) M_free(AP.procedureExtension,"procedureextension");
356 AP.procedureExtension = strDup1(AP.cprocedureExtension,"procedureextension");
357
358 AC.StatsFlag = AM.gStatsFlag = AM.ggStatsFlag;
359 AC.extrasymbols = AM.gextrasymbols = AM.ggextrasymbols;
360 AC.extrasym[0] = AM.gextrasym[0] = AM.ggextrasym[0] = 'Z';
361 AC.extrasym[1] = AM.gextrasym[1] = AM.ggextrasym[1] = 0;
362 AO.NoSpacesInNumbers = AM.gNoSpacesInNumbers = AM.ggNoSpacesInNumbers;
363 AO.IndentSpace = AM.gIndentSpace = AM.ggIndentSpace;
364 AC.ThreadStats = AM.gThreadStats = AM.ggThreadStats;
365 AC.OldFactArgFlag = AM.gOldFactArgFlag = AM.ggOldFactArgFlag;
366 AC.FinalStats = AM.gFinalStats = AM.ggFinalStats;
367 AC.OldGCDflag = AM.gOldGCDflag = AM.ggOldGCDflag;
368 AC.ThreadsFlag = AM.gThreadsFlag = AM.ggThreadsFlag;
369 if ( AC.ThreadsFlag && AM.totalnumberofthreads > 1 ) AS.MultiThreaded = 1;
370 AC.ThreadBucketSize = AM.gThreadBucketSize = AM.ggThreadBucketSize;
371 AC.ThreadBalancing = AM.gThreadBalancing = AM.ggThreadBalancing;
372 AC.ThreadSortFileSynch = AM.gThreadSortFileSynch = AM.ggThreadSortFileSynch;
373 AC.ShortStatsMax = AM.gShortStatsMax = AM.ggShortStatsMax;
374 AC.SizeCommuteInSet = AM.gSizeCommuteInSet = 0;
375#ifdef WITHFLOAT
376 AC.MaxWeight = AM.gMaxWeight = AM.ggMaxWeight;
377 AC.DefaultPrecision = AM.gDefaultPrecision = AM.ggDefaultPrecision;
378#endif
379
380 NumExpressions = 0;
381 if ( DeleteStore(0) < 0 ) {
382 MesPrint("@Cannot restart the storage file");
383 Terminate(-1);
384 }
385 RemoveDollars();
386 CleanUp(1);
387 ResetVariables(2);
388 IniVars();
389}
390
391/*
392 #] FullCleanUp :
393 #[ DoPolyfun :
394*/
395
396int DoPolyfun(UBYTE *s)
397{
398 GETIDENTITY
399 UBYTE *t, c;
400 WORD funnum, eqsign = 0;
401 if ( AC.origin == FROMPOINTINSTRUCTION ) {
402 if ( *s == 0 || *s == ',' || *s == ')' ) {
403 AR.PolyFun = 0; AR.PolyFunType = 0;
404 return(0);
405 }
406 if ( *s != '=' ) {
407 MesPrint("@Proper use in point instructions is: PolyFun[=functionname]");
408 return(-1);
409 }
410 eqsign = 1;
411 }
412 else {
413 if ( *s == 0 ) {
414 AR.PolyFun = 0; AR.PolyFunType = 0;
415 return(0);
416 }
417 if ( *s != '=' && *s != ',' ) {
418 MesPrint("@Proper use is: PolyFun[{ ,=}functionname]");
419 return(-1);
420 }
421 if ( *s == '=' ) eqsign = 1;
422 }
423 s++;
424 SKIPBLANKS(s)
425 t = EndOfToken(s);
426 c = *t; *t = 0;
427
428 if ( GetName(AC.varnames,s,&funnum,WITHAUTO) != CFUNCTION ) {
429 if ( AC.origin != FROMPOINTINSTRUCTION && eqsign == 0 ) {
430 AR.PolyFun = 0; AR.PolyFunType = 0;
431 return(0);
432 }
433 MesPrint("@ %s is not a properly declared function",s);
434 *t = c;
435 return(-1);
436 }
437 if ( functions[funnum].spec > 0 || functions[funnum].commute != 0 ) {
438 MesPrint("@The PolyFun must be a regular commuting function!");
439 *t = c;
440 return(-1);
441 }
442 AR.PolyFun = funnum+FUNCTION; AR.PolyFunType = 1;
443 *t = c;
444 SKIPBLANKS(t)
445 if ( *t && *t != ',' && *t != ')' ) {
446 t++; c = *t; *t = 0;
447 MesPrint("@Improper ending of end-of-module instruction: %s",s);
448 *t = c;
449 return(-1);
450 }
451 return(0);
452}
453
454/*
455 #] DoPolyfun :
456 #[ DoPolyratfun :
457*/
458
459int DoPolyratfun(UBYTE *s)
460{
461 GETIDENTITY
462 UBYTE *t, c;
463 WORD funnum;
464 if ( AC.origin == FROMPOINTINSTRUCTION ) {
465 if ( *s == 0 || *s == ',' || *s == ')' ) {
466 AR.PolyFun = 0; AR.PolyFunType = 0; AR.PolyFunInv = 0; AR.PolyFunExp = 0;
467 return(0);
468 }
469 if ( *s != '=' ) {
470 MesPrint("@Proper use in point instructions is: PolyRatFun[=functionname[+functionname]]");
471 return(-1);
472 }
473 }
474 else {
475 if ( *s == 0 ) {
476 AR.PolyFun = 0; AR.PolyFunType = 0; AR.PolyFunInv = 0; AR.PolyFunExp = 0;
477 return(0);
478 }
479 if ( *s != '=' && *s != ',' ) {
480 MesPrint("@Proper use is: PolyRatFun[{ ,=}functionname[+functionname]]");
481 return(-1);
482 }
483 }
484 s++;
485 SKIPBLANKS(s)
486 t = EndOfToken(s);
487 c = *t; *t = 0;
488
489 if ( GetName(AC.varnames,s,&funnum,WITHAUTO) != CFUNCTION ) {
490Error1:;
491 MesPrint("@ %s is not a properly declared function",s);
492 *t = c;
493 return(-1);
494 }
495 if ( functions[funnum].spec > 0 || functions[funnum].commute != 0 ) {
496Error2:;
497 MesPrint("@The PolyRatFun must be a regular commuting function!");
498 *t = c;
499 return(-1);
500 }
501 AR.PolyFun = funnum+FUNCTION; AR.PolyFunType = 2;
502 AR.PolyFunInv = 0;
503 AR.PolyFunExp = 0;
504 AC.PolyRatFunChanged = 1;
505 *t = c;
506 if ( *t == '+' ) {
507 t++; s = t;
508 t = EndOfToken(s);
509 c = *t; *t = 0;
510 if ( GetName(AC.varnames,s,&funnum,WITHAUTO) != CFUNCTION ) goto Error1;
511 if ( functions[funnum].spec > 0 || functions[funnum].commute != 0 ) goto Error2;
512 AR.PolyFunInv = funnum+FUNCTION;
513 *t = c;
514 }
515 SKIPBLANKS(t)
516 if ( *t && *t != ',' && *t != ')' ) {
517 t++; c = *t; *t = 0;
518 MesPrint("@Improper ending of end-of-module instruction: %s",s);
519 *t = c;
520 return(-1);
521 }
522 return(0);
523}
524
525/*
526 #] DoPolyratfun :
527 #[ DoNoParallel :
528*/
529
530int DoNoParallel(UBYTE *s)
531{
532 if ( *s == 0 || *s == ',' || *s == ')' ) {
533 AC.mparallelflag |= NOPARALLEL_USER;
534 return(0);
535 }
536 MesPrint("@NoParallel should not have extra parameters");
537 return(-1);
538}
539
540/*
541 #] DoNoParallel :
542 #[ DoParallel :
543*/
544
545int DoParallel(UBYTE *s)
546{
547 if ( *s == 0 || *s == ',' || *s == ')' ) {
548 AC.mparallelflag &= ~NOPARALLEL_USER;
549 return(0);
550 }
551 MesPrint("@Parallel should not have extra parameters");
552 return(-1);
553}
554
555/*
556 #] DoParallel :
557 #[ DoModSum :
558*/
559
560int DoModSum(UBYTE *s)
561{
562 while ( *s == ',' ) s++;
563 if ( *s != '$' ) {
564 MesPrint("@Module Sum should mention which $-variables");
565 return(-1);
566 }
567 s = DoModDollar(s,MODSUM);
568 if ( s && *s != 0 && *s != ')' ) {
569 MesPrint("@Irregular end of Sum option of Module statement");
570 return(-1);
571 }
572 return(0);
573}
574
575/*
576 #] DoModSum :
577 #[ DoModMax :
578*/
579
580int DoModMax(UBYTE *s)
581{
582 while ( *s == ',' ) s++;
583 if ( *s != '$' ) {
584 MesPrint("@Module Maximum should mention which $-variables");
585 return(-1);
586 }
587 s = DoModDollar(s,MODMAX);
588 if ( s && *s != 0 ) {
589 MesPrint("@Irregular end of Maximum option of Module statement");
590 return(-1);
591 }
592 return(0);
593}
594
595/*
596 #] DoModMax :
597 #[ DoModMin :
598*/
599
600int DoModMin(UBYTE *s)
601{
602 while ( *s == ',' ) s++;
603 if ( *s != '$' ) {
604 MesPrint("@Module Minimum should mention which $-variables");
605 return(-1);
606 }
607 s = DoModDollar(s,MODMIN);
608 if ( s && *s != 0 ) {
609 MesPrint("@Irregular end of Minimum option of Module statement");
610 return(-1);
611 }
612 return(0);
613}
614
615/*
616 #] DoModMin :
617 #[ DoModLocal :
618*/
619
620int DoModLocal(UBYTE *s)
621{
622 while ( *s == ',' ) s++;
623 if ( *s != '$' ) {
624 MesPrint("@ModuleOption Local should mention which $-variables");
625 return(-1);
626 }
627 s = DoModDollar(s,MODLOCAL);
628 if ( s && *s != 0 ) {
629 MesPrint("@Irregular end of Local option of ModuleOption statement");
630 return(-1);
631 }
632 return(0);
633}
634
635/*
636 #] DoModLocal :
637 #[ DoProcessBucket :
638*/
639
640int DoProcessBucket(UBYTE *s)
641{
642 LONG x;
643 while ( *s == ',' || *s == '=' ) s++;
644 ParseNumber(x,s)
645 if ( *s && *s != ' ' && *s != '\t' ) {
646 MesPrint("&Numerical value expected for ProcessBucketSize");
647 return(1);
648 }
649 AC.mProcessBucketSize = x;
650 return(0);
651}
652
653/*
654 #] DoProcessBucket :
655 #[ DoModDollar :
656*/
657
658UBYTE * DoModDollar(UBYTE *s, int type)
659{
660 UBYTE *name, c;
661 WORD number;
662 MODOPTDOLLAR *md;
663 int nummodopt;
664 while ( *s == '$' ) {
665/*
666 Read the name of the dollar
667 Mark the type
668*/
669 s++;
670 name = s;
671 if ( FG.cTable[*s] == 0 ) {
672 while ( FG.cTable[*s] == 0 || FG.cTable[*s] == 1 ) s++;
673 c = *s; *s = 0;
674 number = GetDollar(name);
675 if ( number < 0 ) {
676 UBYTE *s1;
677 number = AddDollar(s,0,0,0);
678 s1 = strDup1((UBYTE *)"Undefined $-variable in module option; option ignored: $","Undefined $-variable in ModuleOption");
679 s1 = AddToString(s1,name,0);
680 Warning((char *)s1);
681 M_free(s1,"Undefined $-variable in ModuleOption");
682 }
683 for ( nummodopt = 0; nummodopt < NumModOptdollars; nummodopt++ ) {
684 if ( number == ModOptdollars[nummodopt].number && type != ModOptdollars[nummodopt].type ) {
685 UBYTE *s1;
686 s1 = strDup1((UBYTE *)"Conflicting module options for $-variable; later option ignored: $","Conflicting $-variable in ModuleOption");
687 s1 = AddToString(s1,name,0);
688 Warning((char *)s1);
689 M_free(s1,"Conflicting $-variable in ModuleOption");
690 break;
691 }
692 }
693 md = (MODOPTDOLLAR *)FromList(&AC.ModOptDolList);
694 md->number = number;
695 md->type = type;
696#ifdef WITHPTHREADS
697 if ( type == MODLOCAL ) {
698 int j, i;
699 DOLLARS dglobal, dlocal;
700 md->dstruct = (DOLLARS)Malloc1(
701 sizeof(struct DoLlArS)*AM.totalnumberofthreads,"Local DOLLARS");
702/*
703 Now copy the global dollar into the local copies.
704 This can be nontrivial if the value needs an allocation.
705 We don't really need the locks.
706*/
707 dglobal = Dollars + number;
708 for ( j = 0; j < AM.totalnumberofthreads; j++ ) {
709 dlocal = md->dstruct + j;
710 dlocal->index = dglobal->index;
711 dlocal->node = dglobal->node;
712 dlocal->type = dglobal->type;
713 dlocal->name = dglobal->name;
714 dlocal->size = dglobal->size;
715 dlocal->where = dglobal->where;
716 if ( dlocal->size > 0 ) {
717 dlocal->where = (WORD *)Malloc1((dlocal->size+1)*sizeof(WORD),"Local dollar value");
718 for ( i = 0; i < dlocal->size; i++ )
719 dlocal->where[i] = dglobal->where[i];
720 dlocal->where[dlocal->size] = 0;
721 }
722 INIRECLOCK(dlocal->pthreadslock);
723 dlocal->nfactors = dglobal->nfactors;
724 if ( dglobal->nfactors > 1 ) {
725 int nsize;
726 WORD *t, *m;
727 dlocal->factors = (FACDOLLAR *)Malloc1(dglobal->nfactors*sizeof(FACDOLLAR),"Dollar factors");
728 for ( i = 0; i < dglobal->nfactors; i++ ) {
729 nsize = dglobal->factors[i].size;
730 dlocal->factors[i].type = DOLUNDEFINED;
731 dlocal->factors[i].value = dglobal->factors[i].value;
732 if ( ( dlocal->factors[i].size = nsize ) > 0 ) {
733 dlocal->factors[i].where = t = (WORD *)Malloc1(sizeof(WORD)*(nsize+1),"DollarCopyFactor");
734 m = dglobal->factors[i].where;
735 NCOPY(t,m,nsize);
736 *t = 0;
737 }
738 else {
739 dlocal->factors[i].where = 0;
740 }
741 }
742 }
743 else { dlocal->factors = 0; }
744 }
745 }
746 else {
747 md->dstruct = 0;
748 }
749#endif
750 *s = c;
751 }
752 else {
753 MesPrint("&Illegal name for $-variable in module option");
754 while ( *s != ',' && *s != 0 && *s != ')' ) s++;
755 }
756 while ( *s == ',' ) s++;
757 }
758 return(s);
759}
760
761/*
762 #] DoModDollar :
763 #[ DoinParallel :
764
765 The idea is that we should have the commands
766 ModuleOption,InParallel;
767 ModuleOption,InParallel,name1,name2,...,namen;
768 ModuleOption,NotInParallel,name1,name2,...,namen;
769 The advantage over the InParallel statement is that this statement
770 comes after the definition of the expressions.
771*/
772
773int DoinParallel(UBYTE *s)
774{
775 return(DoInParallel(s,1));
776}
777
778/*
779 #] DoinParallel :
780 #[ DonotinParallel :
781*/
782
783int DonotinParallel(UBYTE *s)
784{
785 return(DoInParallel(s,0));
786}
787
788/*
789 #] DonotinParallel :
790 #] Modules :
791 #[ External :
792 #[ DoExecStatement :
793*/
794
795int DoExecStatement(void)
796{
797#ifdef WITHSYSTEM
798 FLUSHCONSOLE;
799 if ( system((char *)(AP.preStart)) ) return(-1);
800 return(0);
801#else
802 Error0("External programs not implemented on this computer/system");
803 return(-1);
804#endif
805}
806
807/*
808 #] DoExecStatement :
809 #[ DoPipeStatement :
810*/
811
812int DoPipeStatement(void)
813{
814#ifdef WITHPIPE
815 FLUSHCONSOLE;
816 if ( OpenStream(AP.preStart,PIPESTREAM,0,PRENOACTION) == 0 ) return(-1);
817 return(0);
818#else
819 Error0("Pipes not implemented on this computer/system");
820 return(-1);
821#endif
822}
823
824/*
825 #] DoPipeStatement :
826 #] External :
827*/
UBYTE * SkipAName(UBYTE *s)
Definition compiler.c:443
UBYTE * ToToken(UBYTE *)
Definition tools.c:1955
UBYTE * EndOfToken(UBYTE *)
Definition tools.c:1932