FORM  4.1
module.c
Go to the documentation of this file.
1 
7 /* #[ License : */
8 /*
9  * Copyright (C) 1984-2013 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 
54 static 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 
62 static 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 
76 int 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 
143 int 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 ( StrCmp((UBYTE *)(option->name),(UBYTE *)("polyfun")) == 0
174  || StrCmp((UBYTE *)(option->name),(UBYTE *)("polyratfun")) == 0 ) {
175  polyflag = 1;
176  }
177  else polyflag = 0;
178  if ( option->flags > 0 ) return(error);
179  while ( *t ) {
180  if ( *t == ',' ) {
181  tt = t+1;
182  while ( *tt == ',' ) tt++;
183  if ( *tt != '$' ) break;
184  t = tt+1;
185  }
186  if ( *t == ')' ) break;
187  if ( *t == '(' ) SKIPBRA3(t)
188  else if ( *t == '{' ) SKIPBRA2(t)
189  else if ( *t == '[' ) SKIPBRA1(t)
190  t++;
191  }
192  s = t;
193  } while ( *s == ',' );
194  if ( *s ) {
195  MesPrint("@Unrecognized module option: %s",s);
196  error = 1;
197  }
198  return(error);
199 }
200 
201 /*
202  #] CoModuleOption :
203  #[ CoModOption :
204 
205  To be called from a .instruction.
206  Only recognizes polyfun. The newer ones should be via the
207  ModuleOption statement.
208 */
209 
210 int CoModOption(UBYTE *s)
211 {
212  UBYTE *t,c;
213  int error = 0;
214  AC.origin = FROMPOINTINSTRUCTION;
215  if ( *s ) do {
216  s = ToToken(s);
217  t = EndOfToken(s);
218  c = *t; *t = 0;
219  if ( StrICmp(s,(UBYTE *)"polyfun") == 0 ) {
220  *t = c;
221  SKIPBLANKS(t)
222  if ( DoPolyfun(t) ) error = 1;
223  }
224  else if ( StrICmp(s,(UBYTE *)"polyratfun") == 0 ) {
225  *t = c;
226  SKIPBLANKS(t)
227  if ( DoPolyratfun(t) ) error = 1;
228  }
229  else {
230  MesPrint("@Unrecognized module option in .instruction: %s",s);
231  error = 1;
232  *t = c;
233  }
234  while ( *t ) {
235  if ( *t == ',' || *t == ')' ) break;
236  if ( *t == '(' ) SKIPBRA3(t)
237  else if ( *t == '{' ) SKIPBRA2(t)
238  else if ( *t == '[' ) SKIPBRA1(t)
239  t++;
240  }
241  s = t;
242  } while ( *s == ',' );
243  if ( *s ) {
244  MesPrint("@Unrecognized module option in .instruction: %s",s);
245  error = 1;
246  }
247  return(error);
248 }
249 
250 /*
251  #] CoModOption :
252  #[ SetSpecialMode :
253 */
254 
255 VOID SetSpecialMode(int moduletype, int specialtype)
256 {
257  DUMMYUSE(moduletype); DUMMYUSE(specialtype);
258 }
259 
260 /*
261  #] SetSpecialMode :
262  #[ MakeGlobal :
263 
264 VOID MakeGlobal()
265 {
266 }
267 
268  #] MakeGlobal :
269  #[ ExecModule :
270 */
271 
272 int ExecModule(int moduletype)
273 {
274  return(DoExecute(moduletype,0));
275 }
276 
277 /*
278  #] ExecModule :
279  #[ ExecStore :
280 */
281 
282 int ExecStore()
283 {
284  return(0);
285 }
286 
287 /*
288  #] ExecStore :
289  #[ FullCleanUp :
290 
291  Remark 27-oct-2005 by JV
292  This routine (and CleanUp in startup.c) may still need some work:
293  What to do with preprocessor variables
294  What to do with files we write to
295 */
296 
297 VOID FullCleanUp()
298 {
299  int j;
300 
301  while ( AC.CurrentStream->previous >= 0 )
302  AC.CurrentStream = CloseStream(AC.CurrentStream);
303  AP.PreSwitchLevel = AP.PreIfLevel = 0;
304 
305  for ( j = NumProcedures-1; j >= 0; j-- ) {
306  if ( Procedures[j].name ) M_free(Procedures[j].name,"name of procedure");
307  if ( Procedures[j].p.buffer ) M_free(Procedures[j].p.buffer,"buffer of procedure");
308  }
309  NumProcedures = 0;
310 
311  while ( NumPre > AP.gNumPre ) {
312  NumPre--;
313  M_free(PreVar[NumPre].name,"PreVar[NumPre].name");
314  PreVar[NumPre].name = PreVar[NumPre].value = 0;
315  }
316 
317  AC.DidClean = 0;
318  for ( j = 0; j < NumExpressions; j++ ) {
319  AC.exprnames->namenode[Expressions[j].node].type = CDELETE;
320  AC.DidClean = 1;
321  }
322 
323  CompactifyTree(AC.exprnames,EXPRNAMES);
324 
325  AP.ComChar = AP.cComChar;
326  if ( AP.procedureExtension ) M_free(AP.procedureExtension,"procedureextension");
327  AP.procedureExtension = strDup1(AP.cprocedureExtension,"procedureextension");
328 
329  AC.StatsFlag = AM.gStatsFlag = AM.ggStatsFlag;
330  AC.extrasymbols = AM.gextrasymbols = AM.ggextrasymbols;
331  AC.extrasym[0] = AM.gextrasym[0] = AM.ggextrasym[0] = 'Z';
332  AC.extrasym[1] = AM.gextrasym[1] = AM.ggextrasym[1] = 0;
333  AO.NoSpacesInNumbers = AM.gNoSpacesInNumbers = AM.ggNoSpacesInNumbers;
334  AO.IndentSpace = AM.gIndentSpace = AM.ggIndentSpace;
335  AC.ThreadStats = AM.gThreadStats = AM.ggThreadStats;
336  AC.OldFactArgFlag = AM.gOldFactArgFlag = AM.ggOldFactArgFlag;
337  AC.FinalStats = AM.gFinalStats = AM.ggFinalStats;
338  AC.ThreadsFlag = AM.gThreadsFlag = AM.ggThreadsFlag;
339  if ( AC.ThreadsFlag && AM.totalnumberofthreads > 1 ) AS.MultiThreaded = 1;
340  AC.ThreadBucketSize = AM.gThreadBucketSize = AM.ggThreadBucketSize;
341  AC.ThreadBalancing = AM.gThreadBalancing = AM.ggThreadBalancing;
342  AC.ThreadSortFileSynch = AM.gThreadSortFileSynch = AM.ggThreadSortFileSynch;
343  AC.ShortStatsMax = AM.gShortStatsMax = AM.ggShortStatsMax;
344 
345  NumExpressions = 0;
346  if ( DeleteStore(0) < 0 ) {
347  MesPrint("@Cannot restart the storage file");
348  Terminate(-1);
349  }
350  RemoveDollars();
351  CleanUp(1);
352  ResetVariables(2);
353  IniVars();
354 }
355 
356 /*
357  #] FullCleanUp :
358  #[ DoPolyfun :
359 */
360 
361 int DoPolyfun(UBYTE *s)
362 {
363  GETIDENTITY
364  UBYTE *t, c;
365  WORD funnum, eqsign = 0;
366  if ( AC.origin == FROMPOINTINSTRUCTION ) {
367  if ( *s == 0 || *s == ',' || *s == ')' ) {
368  AR.PolyFun = 0; AR.PolyFunType = 0;
369  return(0);
370  }
371  if ( *s != '=' ) {
372  MesPrint("@Proper use in point instructions is: PolyFun[=functionname]");
373  return(-1);
374  }
375  eqsign = 1;
376  }
377  else {
378  if ( *s == 0 ) {
379  AR.PolyFun = 0; AR.PolyFunType = 0;
380  return(0);
381  }
382  if ( *s != '=' && *s != ',' ) {
383  MesPrint("@Proper use is: PolyFun[{ ,=}functionname]");
384  return(-1);
385  }
386  if ( *s == '=' ) eqsign = 1;
387  }
388  s++;
389  SKIPBLANKS(s)
390  t = EndOfToken(s);
391  c = *t; *t = 0;
392 
393  if ( GetName(AC.varnames,s,&funnum,WITHAUTO) != CFUNCTION ) {
394  if ( AC.origin != FROMPOINTINSTRUCTION && eqsign == 0 ) {
395  AR.PolyFun = 0; AR.PolyFunType = 0;
396  return(0);
397  }
398  MesPrint("@ %s is not a properly declared function",s);
399  *t = c;
400  return(-1);
401  }
402  if ( functions[funnum].spec != 0 || functions[funnum].commute != 0 ) {
403  MesPrint("@The PolyFun must be a regular commuting function!");
404  *t = c;
405  return(-1);
406  }
407  AR.PolyFun = funnum+FUNCTION; AR.PolyFunType = 1;
408  *t = c;
409  SKIPBLANKS(t)
410  if ( *t && *t != ',' && *t != ')' ) {
411  t++; c = *t; *t = 0;
412  MesPrint("@Improper ending of end-of-module instruction: %s",s);
413  *t = c;
414  return(-1);
415  }
416  return(0);
417 }
418 
419 /*
420  #] DoPolyfun :
421  #[ DoPolyratfun :
422 */
423 
424 int DoPolyratfun(UBYTE *s)
425 {
426  GETIDENTITY
427  UBYTE *t, c;
428  WORD funnum;
429  if ( AC.origin == FROMPOINTINSTRUCTION ) {
430  if ( *s == 0 || *s == ',' || *s == ')' ) {
431  AR.PolyFun = 0; AR.PolyFunType = 0;
432  return(0);
433  }
434  if ( *s != '=' ) {
435  MesPrint("@Proper use in point instructions is: PolyRatFun[=functionname]");
436  return(-1);
437  }
438  }
439  else {
440  if ( *s == 0 ) {
441  AR.PolyFun = 0; AR.PolyFunType = 0;
442  return(0);
443  }
444  if ( *s != '=' && *s != ',' ) {
445  MesPrint("@Proper use is: PolyRatFun[{ ,=}functionname]");
446  return(-1);
447  }
448  }
449  s++;
450  SKIPBLANKS(s)
451  t = EndOfToken(s);
452  c = *t; *t = 0;
453 
454  if ( GetName(AC.varnames,s,&funnum,WITHAUTO) != CFUNCTION ) {
455  MesPrint("@ %s is not a properly declared function",s);
456  *t = c;
457  return(-1);
458  }
459  if ( functions[funnum].spec != 0 || functions[funnum].commute != 0 ) {
460  MesPrint("@The PolyRatFun must be a regular commuting function!");
461  *t = c;
462  return(-1);
463  }
464  AR.PolyFun = funnum+FUNCTION; AR.PolyFunType = 2;
465  AC.PolyRatFunChanged = 1;
466  *t = c;
467  SKIPBLANKS(t)
468  if ( *t && *t != ',' && *t != ')' ) {
469  t++; c = *t; *t = 0;
470  MesPrint("@Improper ending of end-of-module instruction: %s",s);
471  *t = c;
472  return(-1);
473  }
474  return(0);
475 }
476 
477 /*
478  #] DoPolyratfun :
479  #[ DoNoParallel :
480 */
481 
482 int DoNoParallel(UBYTE *s)
483 {
484  if ( *s == 0 || *s == ',' || *s == ')' ) {
485  AC.mparallelflag |= NOPARALLEL_USER;
486  return(0);
487  }
488  MesPrint("@NoParallel should not have extra parameters");
489  return(-1);
490 }
491 
492 /*
493  #] DoNoParallel :
494  #[ DoParallel :
495 */
496 
497 int DoParallel(UBYTE *s)
498 {
499  if ( *s == 0 || *s == ',' || *s == ')' ) {
500  AC.mparallelflag &= ~NOPARALLEL_USER;
501  return(0);
502  }
503  MesPrint("@Parallel should not have extra parameters");
504  return(-1);
505 }
506 
507 /*
508  #] DoParallel :
509  #[ DoModSum :
510 */
511 
512 int DoModSum(UBYTE *s)
513 {
514  while ( *s == ',' ) s++;
515  if ( *s != '$' ) {
516  MesPrint("@Module Sum should mention which $-variables");
517  return(-1);
518  }
519  s = DoModDollar(s,MODSUM);
520  if ( s && *s != 0 && *s != ')' ) {
521  MesPrint("@Irregular end of Sum option of Module statement");
522  return(-1);
523  }
524  return(0);
525 }
526 
527 /*
528  #] DoModSum :
529  #[ DoModMax :
530 */
531 
532 int DoModMax(UBYTE *s)
533 {
534  while ( *s == ',' ) s++;
535  if ( *s != '$' ) {
536  MesPrint("@Module Maximum should mention which $-variables");
537  return(-1);
538  }
539  s = DoModDollar(s,MODMAX);
540  if ( s && *s != 0 ) {
541  MesPrint("@Irregular end of Maximum option of Module statement");
542  return(-1);
543  }
544  return(0);
545 }
546 
547 /*
548  #] DoModMax :
549  #[ DoModMin :
550 */
551 
552 int DoModMin(UBYTE *s)
553 {
554  while ( *s == ',' ) s++;
555  if ( *s != '$' ) {
556  MesPrint("@Module Minimum should mention which $-variables");
557  return(-1);
558  }
559  s = DoModDollar(s,MODMIN);
560  if ( s && *s != 0 ) {
561  MesPrint("@Irregular end of Minimum option of Module statement");
562  return(-1);
563  }
564  return(0);
565 }
566 
567 /*
568  #] DoModMin :
569  #[ DoModLocal :
570 */
571 
572 int DoModLocal(UBYTE *s)
573 {
574  while ( *s == ',' ) s++;
575  if ( *s != '$' ) {
576  MesPrint("@ModuleOption Local should mention which $-variables");
577  return(-1);
578  }
579  s = DoModDollar(s,MODLOCAL);
580  if ( s && *s != 0 ) {
581  MesPrint("@Irregular end of Local option of ModuleOption statement");
582  return(-1);
583  }
584  return(0);
585 }
586 
587 /*
588  #] DoModLocal :
589  #[ DoProcessBucket :
590 */
591 
592 int DoProcessBucket(UBYTE *s)
593 {
594  LONG x;
595  while ( *s == ',' || *s == '=' ) s++;
596  ParseNumber(x,s)
597  if ( *s && *s != ' ' && *s != '\t' ) {
598  MesPrint("&Numerical value expected for ProcessBucketSize");
599  return(1);
600  }
601  AC.mProcessBucketSize = x;
602  return(0);
603 }
604 
605 /*
606  #] DoProcessBucket :
607  #[ DoModDollar :
608 */
609 
610 UBYTE * DoModDollar(UBYTE *s, int type)
611 {
612  UBYTE *name, c;
613  WORD number;
614  MODOPTDOLLAR *md;
615  while ( *s == '$' ) {
616 /*
617  Read the name of the dollar
618  Mark the type
619 */
620  s++;
621  name = s;
622  if ( FG.cTable[*s] == 0 ) {
623  while ( FG.cTable[*s] == 0 || FG.cTable[*s] == 1 ) s++;
624  c = *s; *s = 0;
625  number = GetDollar(name);
626  if ( number < 0 ) {
627  number = AddDollar(s,0,0,0);
628  Warning("&Undefined $-variable in module statement");
629  }
630  md = (MODOPTDOLLAR *)FromList(&AC.ModOptDolList);
631  md->number = number;
632  md->type = type;
633 #ifdef WITHPTHREADS
634  if ( type == MODLOCAL ) {
635  int j, i;
636  DOLLARS dglobal, dlocal;
637  md->dstruct = (DOLLARS)Malloc1(
638  sizeof(struct DoLlArS)*AM.totalnumberofthreads,"Local DOLLARS");
639 /*
640  Now copy the global dollar into the local copies.
641  This can be nontrivial if the value needs an allocation.
642  We don't really need the locks.
643 */
644  dglobal = Dollars + number;
645  for ( j = 0; j < AM.totalnumberofthreads; j++ ) {
646  dlocal = md->dstruct + j;
647  dlocal->index = dglobal->index;
648  dlocal->node = dglobal->node;
649  dlocal->type = dglobal->type;
650  dlocal->name = dglobal->name;
651  dlocal->size = dglobal->size;
652  dlocal->where = dglobal->where;
653  if ( dlocal->size > 0 ) {
654  dlocal->where = (WORD *)Malloc1((dlocal->size+1)*sizeof(WORD),"Local dollar value");
655  for ( i = 0; i < dlocal->size; i++ )
656  dlocal->where[i] = dglobal->where[i];
657  dlocal->where[dlocal->size] = 0;
658  }
659  dlocal->pthreadslockread = dummylock;
660  dlocal->pthreadslockwrite = dummylock;
661  dlocal->nfactors = dglobal->nfactors;
662  if ( dglobal->nfactors > 1 ) {
663  int nsize;
664  WORD *t, *m;
665  dlocal->factors = (FACDOLLAR *)Malloc1(dglobal->nfactors*sizeof(FACDOLLAR),"Dollar factors");
666  for ( i = 0; i < dglobal->nfactors; i++ ) {
667  nsize = dglobal->factors[i].size;
668  dlocal->factors[i].type = DOLUNDEFINED;
669  dlocal->factors[i].value = dglobal->factors[i].value;
670  if ( ( dlocal->factors[i].size = nsize ) > 0 ) {
671  dlocal->factors[i].where = t = (WORD *)Malloc1(sizeof(WORD)*(nsize+1),"DollarCopyFactor");
672  m = dglobal->factors[i].where;
673  NCOPY(t,m,nsize);
674  *t = 0;
675  }
676  else {
677  dlocal->factors[i].where = 0;
678  }
679  }
680  }
681  else { dlocal->factors = 0; }
682  }
683  }
684  else {
685  md->dstruct = 0;
686  }
687 #endif
688  *s = c;
689  }
690  else {
691  MesPrint("&Illegal name for $-variable in module option");
692  while ( *s != ',' && *s != 0 && *s != ')' ) s++;
693  }
694  while ( *s == ',' ) s++;
695  }
696  return(s);
697 }
698 
699 /*
700  #] DoModDollar :
701  #[ DoinParallel :
702 
703  The idea is that we should have the commands
704  ModuleOption,InParallel;
705  ModuleOption,InParallel,name1,name2,...,namen;
706  ModuleOption,NotInParallel,name1,name2,...,namen;
707  The advantage over the InParallel statement is that this statement
708  comes after the definition of the expressions.
709 */
710 
711 int DoinParallel(UBYTE *s)
712 {
713  return(DoInParallel(s,1));
714 }
715 
716 /*
717  #] DoinParallel :
718  #[ DonotinParallel :
719 */
720 
721 int DonotinParallel(UBYTE *s)
722 {
723  return(DoInParallel(s,0));
724 }
725 
726 /*
727  #] DonotinParallel :
728  #] Modules :
729  #[ External :
730  #[ DoExecStatement :
731 */
732 
733 int DoExecStatement()
734 {
735 #ifdef WITHSYSTEM
736  FLUSHCONSOLE;
737  if ( system((char *)(AP.preStart)) ) return(-1);
738  return(0);
739 #else
740  Error0("External programs not implemented on this computer/system");
741  return(-1);
742 #endif
743 }
744 
745 /*
746  #] DoExecStatement :
747  #[ DoPipeStatement :
748 */
749 
750 int DoPipeStatement()
751 {
752 #ifdef WITHPIPE
753  FLUSHCONSOLE;
754  if ( OpenStream(AP.preStart,PIPESTREAM,0,PRENOACTION) == 0 ) return(-1);
755  return(0);
756 #else
757  Error0("Pipes not implemented on this computer/system");
758  return(-1);
759 #endif
760 }
761 
762 /*
763  #] DoPipeStatement :
764  #] External :
765 */