1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10
11
12 /*
13 * Description:
14 * This module defines operations on several basic types:
15 * 1) The gvar. This is the executives basic handle for Objects. It
16 * gets put in the cache, held on to by Programs, etc.
17 * 2) The Program. It is the basic executable unit. Parse trees are
18 * turned into a Program, which contains lists of:
19 * -- All inputs, outputs, and undefined variables
20 * -- All variables used as either the above or intermediates
21 * -- All functions (modules) that need execution
22 * Also, it provides the ability to turn a parse tree into a Program.
23 * _dxf_ExGraph is called with a parse tree. It creates and returns a program
24 * ExGraphTraverse traverses a parse tree, resolving the easy cases
25 * ExGraphExpression handles the expression cases (x-1, ...)
26 * ExGraphCall handles calls to either Modules or Macros.
27 */
28
29 #include <dx/dx.h>
30 #include "pmodflags.h"
31
32 #include "config.h"
33 #include "_macro.h"
34 #include "_variable.h"
35 #include "attribute.h"
36 #include "background.h"
37 #include "cache.h"
38 #include "graph.h"
39 #include "parse.h"
40 #include "utils.h"
41 #include "log.h"
42 #include "packet.h"
43 #include "path.h"
44 #include "context.h"
45 #include "graphIntr.h"
46 #include "obmodule.h"
47 #include "sysvars.h"
48 #include "distp.h"
49 #include "rq.h"
50 #include "function.h"
51
52 #define DICT_SIZE 64
53
54 static int graphing_error = FALSE; /* error while constructing graph */
55 static int subgraph_id = 0;
56 EXDictionary _dxd_exGraphCache = NULL;
57 gfunc *_dxd_exCurrentFunc = NULL;
58
59 typedef struct indexobj {
60 exo_object obj;
61 int index;
62 } indexobj;
63
64 typedef struct progobj {
65 exo_object obj;
66 Program *p;
67 } progobj;
68
69 typedef LIST(int) list_int;
70
71 #ifdef ALLOC_UPFRONT
72 #define MAX_FREED 2
73 static Program *freedProgs[MAX_FREED] = {NULL};
74 #endif
75
76 #define REINIT_LIST(list) ( (list).nused = 0 )
77 /*
78 * Stack of dictionaries used to resolve variable scope
79 */
80
81 Group _dxfQueryImportInfo (char *filename);
82
83 static void ExMakeGfunc(node_function ndfunc, _ntype type, int instance,
84 _excache excache, node *n, node **inAttrs, Program *p,
85 int *inArgs, list_int *out, Program *macro);
86 static void ExCopySubP(Program *toP, Program *fromP, int top);
87 static Program *GetNewMacro(Program *p, int *map, int *resolved);
88 static void ExGraphAssignment (Program *p, node *n, int top,
89 EXDictionary dict);
90 static void ExGraphTraverse (Program *p, node *n, int top, EXDictionary dict);
91 static void ExGraphCall (Program *p, node *n, int top, list_int *out,
92 EXDictionary dict, int *flags);
93 static void ExCreateSendModules (Program *p);
94 static void ExBuildSendModule (Program *p, gfunc *sgf, gfunc *tgf, int srcfn,
95 int tgfn, int in_tab, int out_tab, int *outdex);
96 static int GvarDelete (gvar *p);
97 static int progobjDelete (progobj *p);
98 static void ExRemapVars(Program *p, Program *subP, int *map, int *resolved, char *fname, int inst);
99 static void ExFixAsyncVarName(Program *p,
100 ProgramVariable *pv, char *fname, int instance);
101
102 static int _dxf_ExPathStringLen( ModPath *path );
103 static void _dxf_ExGFuncPathToStringBuf( gfunc *fnode, char *path_str );
104 static void _dxf_ExGFuncPathToCacheStringBuf( gfunc *fnode, char *path_str );
105 static void _dxf_ExPathSet( Program *p, char fname[], int instance, gfunc *fnode );
106 static void _dxf_ExPathPrepend( Program *p, char fname[], int instance,
107 gfunc *fnode );
108 static void _dxf_ExPathAppend( Program *p, char fname[], int instance,
109 gfunc *fnode );
110 static int _dxf_ExPathCacheStringLen( ModPath *path );
111
112 static char *_dxf_ExCacheStrPrepend( Program *p, char *name,
113 int instance, char *path );
114
m__badfunc(Object * in,Object * out)115 Error m__badfunc(Object *in, Object *out)
116 {
117 DXSetError(ERROR_NOT_IMPLEMENTED, "function does not exist");
118 return ERROR;
119 }
120
121 static PFIP gvar_methods[] =
122 {
123 GvarDelete
124 };
125
126 static PFIP progobj_methods[] =
127 {
128 progobjDelete
129 };
130
ResetSubGraphIds()131 void ResetSubGraphIds()
132 {
133 subgraph_id = 0;
134 }
135
NextSubGraphId()136 int NextSubGraphId()
137 {
138 int sgid;
139
140 sgid = ++(subgraph_id);
141 return (sgid);
142 }
143
144
145 /*
146 * Initialize the code which constructs graphs from parse trees
147 */
148 void
_dxf_ExGraphInit(void)149 _dxf_ExGraphInit (void)
150 {
151 ExDebug("*1","In _dxf_ExGraphInit");
152 _dxd_exCurrentFunc = NULL;
153 graphing_error = FALSE;
154 _dxf_ExMacroRecursionInit ();
155 if (_dxd_exGraphCache == NULL)
156 _dxd_exGraphCache = _dxf_ExDictionaryCreate (32, TRUE, FALSE);
157 }
158
159 int
DXGetModulePathLen()160 DXGetModulePathLen()
161 {
162 return _dxf_ExPathStringLen( &_dxd_exCurrentFunc->mod_path );
163 }
164
165 int
DXGetModulePath(char * path)166 DXGetModulePath(char *path)
167 {
168 _dxf_ExGFuncPathToStringBuf( _dxd_exCurrentFunc, path );
169 return(OK);
170 }
171
172 int
DXGetModuleCacheStrLen()173 DXGetModuleCacheStrLen()
174 {
175 return _dxf_ExPathCacheStringLen( &_dxd_exCurrentFunc->mod_path );
176 }
177
178 int
DXGetModuleCacheStr(char * path)179 DXGetModuleCacheStr(char *path)
180 {
181 _dxf_ExGFuncPathToCacheStringBuf( _dxd_exCurrentFunc, path );
182 return(OK);
183 }
184
185
186
187 int
_dxf_ExGetCurrentInstance()188 _dxf_ExGetCurrentInstance()
189 {
190 return(_dxd_exCurrentFunc->instance);
191 }
192
193
194 /*
195 * Create a new gvar node. These nodes represent the interconnections
196 * between the gfunc nodes which are the executable nodes. They are used
197 * as place holders to allow an indirect access to the data.
198 */
CreateIndex(int ind)199 static indexobj *CreateIndex (int ind)
200 {
201 indexobj *n;
202
203 n = (indexobj *) _dxf_EXO_create_object_local (EXO_CLASS_TASK,
204 sizeof (indexobj),
205 NULL);
206 n->index = ind;
207 return (n);
208 }
209
210 /*
211 * Create a new gvar node. These nodes represent the interconnections
212 * between the gfunc nodes which are the executable nodes. They are used
213 * as place holders to allow an indirect access to the data.
214 */
CreateProgobj(Program * p)215 static progobj *CreateProgobj (Program *p)
216 {
217 progobj *n;
218
219 n = (progobj *) _dxf_EXO_create_object_local (EXO_CLASS_TASK,
220 sizeof (progobj),
221 progobj_methods);
222 n->p = p;
223 return (n);
224 }
225 /*
226 * Create a new gvar node. These nodes represent the interconnections
227 * between the gfunc nodes which are the executable nodes. They are used
228 * as place holders to allow an indirect access to the data.
229 */
_dxf_ExCreateGvar(_gvtype type)230 gvar *_dxf_ExCreateGvar (_gvtype type)
231 {
232 gvar *n;
233
234 n = (gvar *) _dxf_EXO_create_object (EXO_CLASS_GVAR,
235 sizeof (gvar),
236 gvar_methods);
237 n->type = type;
238
239 return (n);
240 }
241
242 /*
243 * procId == 0 OK to delete, created somewhere, all global
244 * procId != pin proc OK to delete, created somewhere and must
245 * be all global since can't guarantee where
246 * it will be run.
247 * procId == exJID OK to delete, created here
248 * 1 processor OK to delete, created here
249 */
250
251 static void
DeleteGvarObj(gvar * var)252 DeleteGvarObj(gvar *var)
253 {
254 int procId;
255 Object obj = var->obj;
256
257 if (obj != NULL)
258 {
259 procId = var->procId;
260 if (var->type != GV_CACHE ||
261 procId == 0 ||
262 procId != EX_PIN_PROC ||
263 procId == exJID ||
264 DXProcessors (0) == 1)
265 DXDelete (obj);
266 else
267 {
268 #if 0
269 /*
270 * $$$$$ THIS IS A TEMPORARY SOLUTION BELOW, THE CORRECT IS DESCRIBED
271 * $$$$$ What we really need is to augment the ExReclaimDisable function
272 * $$$$$ so that it loops on a DXtry_lock, which if it doesn't get causes
273 * $$$$$ it to look for high priority jobs destined for its JID since
274 * $$$$$ they may be deletes issued from within some other invocation
275 * $$$$$ of the memory reclaimer that MUST run on that processor
276 * $$$$$ before the world, e.g. the running reclaimer, can really
277 * $$$$$ continue.
278 */
279 _dxf_ExRunOn (procId, DXDelete, (Pointer) obj, 0);
280 #endif
281 _dxf_ExRQEnqueue (DXDelete, (Pointer) obj, 1, 0, procId, TRUE);
282 }
283 }
284 }
285
286
287 /*
288 * Defines a gvar to have a value.
289 */
290 void
_dxf_ExDefineGvar(gvar * gv,Object o)291 _dxf_ExDefineGvar (gvar *gv, Object o)
292 {
293 DXReference (o);
294
295 if (gv->obj && gv->type != GV_UNRESOLVED)
296 DeleteGvarObj(gv);
297
298 gv->obj = o;
299 if (gv->type == GV_UNRESOLVED)
300 gv->type = GV_DEFINED;
301 }
302
303 /*
304 * Makes the gvar unresolved and deletes previous object
305 * leaves the reference counts alone.
306 */
307 void
_dxf_ExUndefineGvar(gvar * gv)308 _dxf_ExUndefineGvar (gvar *gv)
309 {
310 if (gv->obj && gv->type != GV_UNRESOLVED)
311 DeleteGvarObj(gv);
312
313 gv->obj = NULL;
314 gv->skip = GV_DONTSKIP;
315 gv->type = GV_UNRESOLVED;
316 gv->reccrc = 0;
317 gv->cost = 0;
318 gv->disable_cache = 0;
319 gv->procId = 0;
320 }
321
322 /*
323 * DXDelete a gvar
324 */
325 static int
GvarDelete(gvar * var)326 GvarDelete (gvar *var)
327 {
328 #if OLD_DEBUG
329 ExDebug ("*6", "DELETING: [%08x] with cache tag 0x%08x", var, var->reccrc);
330 #endif
331
332 if (var->oneshot)
333 {
334 DXDelete(var->oneshot);
335 var->oneshot = NULL;
336 }
337 DeleteGvarObj(var);
338
339 #if OLD_DEBUG
340 ExDebug ("*6", "DELETED: [%08x]", var);
341 #endif
342 return (OK);
343 }
344
345 static int
progobjDelete(progobj * var)346 progobjDelete (progobj *var)
347 {
348 _dxf_ExGraphDelete (var->p);
349
350 return (OK);
351 }
352
353 /*
354 * Create and initialize a new gfunc node. These nodes represent the
355 * executable entities of the graph.
356 */
_dxf_ExInitGfunc(gfunc * n)357 gfunc *_dxf_ExInitGfunc (gfunc *n)
358 {
359 bzero (n, sizeof (gfunc));
360
361 n->required = -1;
362 INIT_LIST(n->inputs);
363 INIT_LIST(n->outputs);
364 INIT_LIST(n->reroute);
365 INIT_LIST(n->cache_ddi);
366 return (n);
367 }
368
369 #if 0
370 /*
371 * Delete a gfunc node and remove it from the enclosing graph
372 */
373 static int
374 exGfuncFree (gfunc *p)
375 {
376 char s[100];
377 strcpy (s, ">GfDel ");
378 strcat (s, p->name);
379
380 ExDebug ("*1", "DELETING: [%08x] %d::%s", p, p->cpath);
381
382 FREE_LIST(p->inputs);
383 FREE_LIST(p->outputs);
384 FREE_LIST(p->attrs);
385 DXFree(p->name);
386 DXDelete((Object)p->path);
387 ExDebug ("*1", "DELETED: [%08x] <gone>", p);
388
389 return (OK);
390 }
391 #endif
392
InitProgram(Program * p)393 static void InitProgram(Program *p)
394 {
395 p->runable = 0;
396 p->deleted = FALSE;
397 p->loopctl.first = TRUE;
398 p->loopctl.done = TRUE;
399 p->loopctl.counter = 0;
400 p->loopctl.isdoneset = 0;
401 p->returnP = NULL;
402 }
403
404 static Program *
AllocateProgram(void)405 AllocateProgram(void)
406 {
407 Program *p = NULL;
408
409 #ifdef ALLOC_UPFRONT
410 int i;
411 for (i = 0; i < MAX_FREED; ++i)
412 {
413 if (freedProgs[i] != NULL)
414 {
415 p = freedProgs[i];
416 freedProgs[i] = NULL;
417 return (p);
418 }
419 }
420 #endif
421
422 p = (Program*)DXAllocateZero (sizeof (Program));
423 if (p == NULL)
424 return (NULL);
425
426 #if ALLOC_UPFRONT
427 p->local = FALSE;
428 #endif
429 INIT_LIST (p->inputs);
430 INIT_LIST (p->outputs);
431 INIT_LIST (p->undefineds);
432 INIT_LIST (p->wiredvars);
433 INIT_LIST (p->macros);
434 INIT_LIST (p->async_vars);
435 INIT_LIST (p->vars);
436 INIT_LIST (p->funcs);
437 INIT_LIST (p->foreach_id);
438
439 InitProgram(p);
440
441 return (p);
442 }
443
444 static Program *
AllocateProgramLocal(void)445 AllocateProgramLocal(void)
446 {
447 Program *p = NULL;
448 p = (Program*)DXAllocateLocalZero (sizeof (Program));
449 if (p == NULL)
450 return (NULL);
451
452 #if ALLOC_UPFRONT
453 p->local = TRUE;
454 #endif
455 if (INIT_LIST_LOCAL (ProgramRef, p->inputs) == NULL)
456 return (NULL);
457 if (INIT_LIST_LOCAL (ProgramRef, p->outputs) == NULL)
458 return (NULL);
459 if (INIT_LIST_LOCAL (ProgramRef, p->undefineds) == NULL)
460 return (NULL);
461 if (INIT_LIST_LOCAL (int, p->wiredvars) == NULL)
462 return (NULL);
463 if (INIT_LIST_LOCAL (MacroRef, p->macros) == NULL)
464 return (NULL);
465 if (INIT_LIST_LOCAL (AsyncVars, p->async_vars) == NULL)
466 return (NULL);
467 if (INIT_LIST_LOCAL (ProgramVariable, p->vars) == NULL)
468 return (NULL);
469 if (INIT_LIST_LOCAL (gfunc, p->funcs) == NULL)
470 return (NULL);
471 if (INIT_LIST_LOCAL (char *, p->foreach_id) == NULL)
472 return (NULL);
473
474 InitProgram(p);
475
476 return (p);
477 }
478
479 void
ExSubGraphDelete(Program * subp,int top)480 ExSubGraphDelete(Program *subp, int top)
481 {
482 gfunc *gf;
483 ProgramRef *pr;
484 int i, j, limit, jlimit;
485
486 for (i = 0, limit = SIZE_LIST(subp->funcs); i < limit; ++i)
487 {
488 gf = FETCH_LIST(subp->funcs, i);
489 if(gf->ftype == F_MACRO)
490 DXFree(gf->name);
491 FREE_LIST(gf->inputs);
492 FREE_LIST(gf->outputs);
493 FREE_LIST(gf->cache_ddi);
494 FREE_LIST(gf->reroute);
495 if((gf->ftype == F_MACRO) && gf->func.subP) {
496 jlimit = SIZE_LIST(gf->func.subP->undefineds);
497 for (j = 0; j < jlimit; ++j) {
498 pr = FETCH_LIST(gf->func.subP->undefineds, j);
499 DXFree(pr->name);
500 pr->name = NULL;
501 }
502 ExSubGraphDelete(gf->func.subP, top+1);
503 FREE_LIST(gf->func.subP->funcs);
504 FREE_LIST(gf->func.subP->undefineds);
505 FREE_LIST(gf->func.subP->wiredvars);
506 FREE_LIST(gf->func.subP->async_vars);
507 DXFree((Pointer)gf->func.subP);
508 }
509 }
510 }
511
512 void
_dxf_ExGraphDelete(Program * p)513 _dxf_ExGraphDelete(Program *p)
514 {
515 ProgramVariable *pv;
516 ProgramRef *pr;
517 MacroRef *mr;
518 int i;
519 int limit;
520
521 #ifdef ALLOC_UPFRONT
522 int delete;
523 #endif
524
525 if (p == NULL)
526 return;
527
528 ExDebug("3", "In ExGraphDelete");
529 if (p == _dxd_exContext->program) {
530 _dxd_exContext->program = NULL;
531 if(_dxd_exContext->subp) {
532 DXFree(_dxd_exContext->subp);
533 _dxd_exContext->subp = NULL;
534 }
535 }
536
537 p->error = FALSE;
538
539 for (i = 0, limit = SIZE_LIST(p->inputs); i < limit; ++i)
540 {
541 pr = FETCH_LIST(p->inputs, i);
542 DXFree(pr->name);
543 pr->name = NULL;
544 }
545 for (i = 0, limit = SIZE_LIST(p->outputs); i < limit; ++i)
546 {
547 pr = FETCH_LIST(p->outputs, i);
548 DXFree(pr->name);
549 pr->name = NULL;
550 }
551 for (i = 0, limit = SIZE_LIST(p->undefineds); i < limit; ++i)
552 {
553 pr = FETCH_LIST(p->undefineds, i);
554 DXFree(pr->name);
555 pr->name = NULL;
556 }
557 for (i = 0, limit = SIZE_LIST(p->macros); i < limit; ++i)
558 {
559 mr = FETCH_LIST(p->macros, i);
560 DXFree(mr->name);
561 mr->name = NULL;
562 }
563 for (i = 0, limit = SIZE_LIST(p->vars); i < limit; ++i)
564 {
565 pv = FETCH_LIST(p->vars, i);
566 if (pv->defined)
567 DXDelete(pv->obj);
568 DXDelete(pv->dflt);
569 pv->defined = FALSE;
570 pv->obj = NULL;
571
572 #ifdef CPV_DEBUG
573 if (pv->refs > 0 && pv->refs > pv->gv->object.refs)
574 printf("wierd during graph cleanup\n");
575 #endif
576
577 for (;pv->refs > 0; --pv->refs)
578 ExDelete(pv->gv);
579 FREE_LIST(pv->cts);
580
581 /* The execution code covers the following deletion
582 * ExDelete((FETCH_LIST(p->vars, i))->gv);
583 */
584 }
585
586 #ifdef ALLOC_UPFRONT
587 delete = TRUE;
588 for (i = 0; !p->local && i < MAX_FREED; ++i)
589 {
590 if (freedProgs[i] == NULL)
591 {
592 freedProgs[i] = p;
593 delete = FALSE;
594 break;
595 }
596 }
597
598 if (delete)
599 {
600 #endif
601 FREE_LIST(p->inputs);
602 FREE_LIST(p->outputs);
603 FREE_LIST(p->undefineds);
604 FREE_LIST(p->wiredvars);
605 FREE_LIST(p->macros);
606 FREE_LIST(p->async_vars);
607 FREE_LIST(p->vars);
608 FREE_LIST(p->foreach_id);
609 #ifdef ALLOC_UPFRONT
610 }
611 else
612 {
613 REINIT_LIST(p->inputs);
614 REINIT_LIST(p->outputs);
615 REINIT_LIST(p->undefineds);
616 REINIT_LIST(p->wiredvars);
617 REINIT_LIST(p->macros);
618 REINIT_LIST(p->async_vars);
619 REINIT_LIST(p->vars);
620 REINIT_LIST(p->foreach_id);
621 }
622 #endif
623
624 if(SIZE_LIST(p->funcs) > 0)
625 ExSubGraphDelete(p, 0);
626
627 #ifdef ALLOC_UPFRONT
628 if (delete)
629 {
630 #endif
631 FREE_LIST(p->funcs);
632 DXFree((Pointer)p);
633 #ifdef ALLOC_UPFRONT
634 }
635 else
636 {
637 REINIT_LIST(p->funcs);
638 }
639 #endif
640 }
641
642 int
_dxf_ExGraphCompact(void)643 _dxf_ExGraphCompact (void)
644 {
645 if (exJID == 1 && _dxd_exGraphCache != NULL)
646 {
647 if (_dxf_ExDictionaryPurge(_dxd_exGraphCache))
648 return (_dxf_ExDictionaryCompact(_dxd_exGraphCache));
649 }
650 return (FALSE);
651
652 }
653
654 /*
655 * Construct a graph from a parse tree. The graph consists of 'gfunc' and
656 * 'gvar' nodes. The 'gfunc' nodes represent the executable modules in the
657 * graph. The 'gvar' nodes represent the connections between the executable
658 * nodes.
659 */
_dxf_ExGraph(node * n)660 Program *_dxf_ExGraph (node *n)
661 {
662 Program *p;
663 EXDictionary dict;
664
665 ExMarkTime(0x10, ">_graph");
666 if (n == NULL)
667 {
668 ExMarkTime(0x10, "<_graph");
669 return (NULL);
670 }
671 p = AllocateProgram();
672 p->graphId = _dxf_NextGraphId();
673 ResetSubGraphIds();
674
675 dict = _dxf_ExDictionaryCreate (DICT_SIZE, TRUE, FALSE);
676 ExGraphTraverse(p, n, 0, dict);
677
678 _dxf_ExDictionaryDestroy (dict);
679
680 if (graphing_error ||
681 (SIZE_LIST(p->funcs) == 0 &&
682 SIZE_LIST(p->outputs) == 0))
683 {
684 _dxf_ExGraphDelete(p);
685 p = NULL;
686 }
687
688 if (p != NULL && SIZE_LIST(p->outputs) != 0)
689 _dxf_ExBackgroundChange();
690
691 ExMarkTime(0x10, "<_graph");
692 return (p);
693 }
694
695 /*
696 * Recursively traverse the parse tree and construct an equivalent
697 * graph structure which is more easily executed
698 */
ExGraphTraverse(Program * p,node * n,int top,EXDictionary dict)699 static void ExGraphTraverse (Program *p, node *n, int top, EXDictionary dict)
700 {
701 int nout;
702 char *name;
703 char *is_are;
704 list_int out;
705 int flags;
706
707 if (graphing_error)
708 return;
709
710 for (; n; n = n->next)
711 {
712 switch (n->type)
713 {
714 case NT_MACRO: /* macro definition */
715 _dxf_ExDictionaryPurge (_dxd_exGraphCache);
716 _dxf_ExMacroInsert (n->v.macro.id->v.id.id, (EXObj) n);
717 _dxf_ExBackgroundRedo();
718 break;
719
720 case NT_CALL: /* function call */
721 INIT_LIST(out);
722 ExGraphCall (p, n, top, &out, dict, &flags);
723 nout = SIZE_LIST(out);
724 FREE_LIST(out);
725 if ((nout != 0) && !(flags & MODULE_SIDE_EFFECT))
726 {
727 name = n->v.call.id->v.id.id;
728 is_are = (nout == 1) ? "value is" : "values are";
729 DXWarning ("#4730", is_are, name);
730 }
731
732 break;
733
734 case NT_ASSIGNMENT: /* assignment statement */
735 ExGraphAssignment (p, n, top, dict);
736 break;
737
738 case NT_PACKET: /* packet command */
739 _dxd_exContext->graphId = p->graphId = n->v.packet.number;
740 switch (n->v.packet.type)
741 {
742 case PK_INTERRUPT:
743 break;
744
745 case PK_SYSTEM:
746 case PK_MACRO:
747 case PK_FOREGROUND:
748 case PK_BACKGROUND:
749 ExGraphTraverse (p, n->v.packet.packet, top, dict);
750
751 case PK_LINQ:
752 case PK_SINQ:
753 case PK_VINQ:
754 break;
755
756 case PK_IMPORT:
757 {
758 Group info;
759 int i;
760 int len;
761 String string;
762 char *buffer;
763 char *p;
764
765 info = _dxfQueryImportInfo (n->v.packet.packet->v.data.data);
766 if (info)
767 {
768 DXReference ((Object) info);
769 len = 0;
770 for (i = 0; ; i++)
771 {
772 string =
773 (String) DXGetEnumeratedMember (info, i, NULL);
774 if (string == NULL)
775 break;
776 len += strlen (DXGetString (string));
777 }
778 buffer = (char *) DXAllocateLocal (len + 1);
779 if (buffer == NULL)
780 {
781 DXWarning ("#4740");
782 return;
783 }
784 buffer[0] = '\0';
785 for (i = 0, p = buffer; ; i++)
786 {
787 string =
788 (String) DXGetEnumeratedMember (info, i, NULL);
789 if (string == NULL)
790 break;
791
792 strcat (p, DXGetString (string));
793 p += strlen (p);
794 }
795 _dxf_ExSPack (PACK_IMPORTINFO, n->v.packet.number,
796 buffer, strlen (buffer));
797 DXFree ((Pointer) buffer);
798 DXDelete ((Object) info);
799 }
800 else
801 {
802 _dxf_ExSPack (PACK_IMPORTINFO, n->v.packet.number, NULL, 0);
803 }
804 break;
805 }
806 default:
807 break;
808 }
809 break;
810
811 default:
812 DXWarning ("#4750", n->type);
813 break;
814 }
815 }
816 }
817
ExParseExprLeaves(node * n,int loc,char * opstr,node * args)818 static int ExParseExprLeaves (node *n, int loc, char *opstr, node *args)
819 {
820 char *id;
821 _op op;
822 int unary;
823 char buf[64];
824
825 if (n == NULL)
826 return (loc);
827
828 if (n->type != NT_LOGICAL && n->type != NT_ARITHMETIC)
829 {
830 sprintf (buf, "$%d", loc);
831 strcat (opstr, buf);
832 args[loc].v.arg.val = n;
833 return (loc + 1);
834 }
835
836 op = n->v.expr.op;
837 unary = (op == AO_NEGATE || op == LO_NOT);
838
839 strcat (opstr, "(");
840
841 /*
842 * If we have a unary op it stores its single argument in the lhs rather
843 * than the rhs of the expression parse node. This gives rise to the
844 * unary check here and below.
845 */
846
847 if (! unary)
848 loc = ExParseExprLeaves (n->v.expr.lhs, loc, opstr, args);
849
850 switch (op)
851 {
852 case LO_LT: id = " < " ; break;
853 case LO_GT: id = " > " ; break;
854 case LO_LEQ: id = " <= "; break;
855 case LO_GEQ: id = " >= "; break;
856 case LO_EQ: id = " == "; break;
857 case LO_NEQ: id = " != "; break;
858 case LO_AND: id = " && "; break;
859 case LO_OR: id = " || "; break;
860 case LO_NOT: id = " ! " ; break;
861 case AO_EXP: id = " ^ " ; break;
862 case AO_TIMES: id = " * " ; break;
863 case AO_DIV: id = " / " ; break;
864 case AO_IDIV: id = " / " ; break;
865 case AO_MOD: id = " % " ; break;
866 case AO_PLUS: id = " + " ; break;
867 case AO_MINUS: id = " - " ; break;
868 case AO_NEGATE: id = " - " ; break;
869 default: id = " ?? "; break;
870 }
871 strcat (opstr, id);
872
873 loc = ExParseExprLeaves (unary ? n->v.expr.lhs : n->v.expr.rhs,
874 loc, opstr, args);
875 strcat (opstr, ")");
876
877 return (loc);
878 }
879
880
ExCountExprLeaves(node * n,int cnt)881 static int ExCountExprLeaves (node *n, int cnt)
882 {
883 _op op;
884 int unary;
885
886 if (n == NULL)
887 return (cnt);
888
889 if (n->type != NT_LOGICAL && n->type != NT_ARITHMETIC)
890 return (cnt + 1);
891
892 op = n->v.expr.op;
893 unary = (op == AO_NEGATE || op == LO_NOT);
894
895 if (! unary)
896 cnt = ExCountExprLeaves (n->v.expr.lhs, cnt);
897
898 cnt = ExCountExprLeaves (unary ? n->v.expr.lhs : n->v.expr.rhs, cnt);
899 return (cnt);
900 }
901
902
903 /*
904 * Convert a parse tree expression into the a call to Compute
905 */
906
ExGraphExpression(Program * p,node * n,int top,list_int * out,EXDictionary dict)907 static void ExGraphExpression (Program *p, node *n, int top, list_int *out, EXDictionary dict)
908 {
909 int cnt;
910 int size;
911 char *opstr = NULL;
912 node *nodes = NULL;
913 node *name;
914 node *func;
915 node *cons;
916 node *args;
917 int i, flags;
918
919 cnt = ExCountExprLeaves (n, 0);
920
921 /*
922 * We're assuming a varargs Compute here by allocating as many arg blocks
923 * as there are parameters.
924 * We allocate 4 extra, 1 for the name, 1 for the function call, 1 for
925 * the constant to hold the format string and 1 for the format string
926 * argument itself.
927 */
928
929 if (cnt > 16)
930 {
931 graphing_error = TRUE;
932 DXWarning ("#4760");
933 return;
934 }
935
936 /*
937 * $$$$$
938 * $$$$$ Until the assumption is true we will have to check for > 16 args,
939 * $$$$$ hence the test above.
940 * $$$$$
941 */
942
943 size = (cnt + 4) * sizeof (node);
944 nodes = (node *) DXAllocateLocal (size);
945 if (nodes == NULL)
946 goto error;
947 memset (nodes, 0, size);
948
949 /*
950 * We'll be conservative and use 16 although each leaf of the expression
951 * probably won't add more than 6 characters to the operation description
952 * string.
953 */
954
955 size = cnt * 16;
956 opstr = (char *) DXAllocateLocal (size);
957 if (opstr == NULL)
958 goto error;
959 memset (opstr, 0, size);
960
961 /*
962 * Now we dummy up the parse tree nodes that we need to construct a
963 * call to Compute.
964 */
965
966 name = nodes;
967 func = nodes + 1;
968 cons = nodes + 2;
969 args = nodes + 3;
970
971 name->type = NT_ID;
972 name->v.id.id = "Compute";
973
974 func->type = NT_CALL;
975 func->v.call.id = name;
976 func->v.call.arg = args;
977
978 cons->type = NT_CONSTANT;
979 /* value filled in below */
980
981 args[0].v.arg.val = cons;
982
983 for (i = 0; i <= cnt; i++)
984 {
985 args[i].type = NT_ARGUMENT;
986 args[i].next = &args[i+1];
987 args[i].prev = &args[i-1];
988 }
989 args[0 ].prev = NULL;
990 args[cnt].next = NULL;
991
992 /*
993 * We reserve arg0 for the format string thus we must step forward by one.
994 */
995
996 ExParseExprLeaves (n, 0, opstr, args + 1);
997
998 cons->v.constant.obj = (Array)DXNewString(opstr);
999 if (!cons->v.constant.obj)
1000 goto error;
1001
1002 ExGraphCall (p, func, top, out, dict, &flags);
1003 DXFree ((Pointer) nodes);
1004 DXFree ((Pointer) opstr);
1005 return;
1006
1007 error:
1008 _dxf_ExDie ("ExGraphExpression: can't allocate memory");
1009 return;
1010 }
1011
1012
1013 /*
1014 * Convert a parse tree assignment into the proper graph structure.
1015 * Insert the assigned variables into the current dictionary.
1016 */
1017 static void
ExGraphAssignment(Program * p,node * n,int top,EXDictionary dict)1018 ExGraphAssignment (Program *p, node *n, int top, EXDictionary dict)
1019 {
1020 node *lhs, *rhs;
1021 node *function;
1022 int rvals[64];
1023 int i;
1024 _excache excache;
1025 int attr_flag;
1026 int nout, flags;
1027
1028 ProgramRef r;
1029 ProgramVariable pv;
1030 ProgramVariable *ppv;
1031 indexobj *ind;
1032 list_int out;
1033
1034 if (graphing_error)
1035 return;
1036
1037 INIT_LIST(out);
1038
1039 /* Insert all outputs in either output list (if at top), or
1040 * local list.
1041 */
1042 for (i = 0, rhs = n->v.assign.rval;
1043 rhs && i < 64;
1044 ++i, rhs = rhs->next)
1045 {
1046 switch (rhs->type)
1047 {
1048 case NT_CONSTANT:
1049 /* Create a variable and stick its index in rvals */
1050 INIT_PVAR(pv);
1051 pv.obj = DXReference ((Object) rhs->v.constant.obj);
1052 pv.defined = TRUE;
1053 APPEND_LIST (ProgramVariable, p->vars, pv);
1054 rvals[i] = SIZE_LIST (p->vars) - 1;
1055 break;
1056
1057 case NT_ID:
1058 /* Look up a variable and stick its index in rvals,
1059 * if it isn't found, stick a note in the "undefineds"
1060 */
1061 ind = (indexobj *)_dxf_ExVariableSearch (rhs->v.id.id, dict);
1062 if (ind == NULL)
1063 {
1064 r.name = _dxf_ExCopyString/*Local*/ (rhs->v.id.id);
1065 rvals[i] = r.index = SIZE_LIST (p->vars);
1066 APPEND_LIST (ProgramRef, p->undefineds, r);
1067 INIT_PVAR(pv);
1068 APPEND_LIST (ProgramVariable, p->vars, pv);
1069 }
1070 else
1071 {
1072 rvals[i] = ind->index;
1073 ExDelete(ind);
1074 }
1075 break;
1076
1077 case NT_LOGICAL:
1078 case NT_ARITHMETIC:
1079 /* Create a variable and stick its index in rvals.
1080 * Make up a (or set of) Compute operation(s), and stick
1081 * them in the list.
1082 */
1083 ExGraphExpression (p, rhs, top, &out, dict);
1084 if (graphing_error)
1085 return;
1086 break;
1087
1088 case NT_CALL:
1089 function = n->v.assign.rval;
1090 ExGraphCall (p, function, top, &out, dict, &flags);
1091 if (graphing_error)
1092 return;
1093 nout = SIZE_LIST(out);
1094 if (nout == 0)
1095 DXWarning ("#4732", function->v.function.id->v.id.id);
1096 break;
1097
1098 default:
1099 DXWarning ("#4770");
1100 break;
1101 }
1102 }
1103
1104 /* Loop through the left hand sides, and set up the assignments
1105 */
1106 for (i = 0, lhs = n->v.assign.lval, rhs = n->v.assign.rval;
1107 lhs && i < 64;
1108 ++i, lhs = lhs->next)
1109 {
1110 if (_dxf_ExHasIntegerAttribute (lhs->attr, ATTR_CACHE, (int *)&excache))
1111 attr_flag = TRUE;
1112 else
1113 {
1114 excache = CACHE_ALL;
1115 attr_flag = FALSE;
1116 }
1117
1118 /* If there is no rhs, make a null one */
1119 if (rhs == NULL)
1120 {
1121 /* Create a variable and stick its index in rvals */
1122 INIT_PVAR(pv);
1123 pv.obj = NULL;
1124 pv.defined = TRUE;
1125 pv.excache = excache;
1126 pv.cacheattr = attr_flag;
1127 APPEND_LIST (ProgramVariable, p->vars, pv);
1128 rvals[i] = SIZE_LIST (p->vars) - 1;
1129 }
1130 /* If the rhs is a module, */
1131 else if (rhs->type == NT_CALL ||
1132 rhs->type == NT_LOGICAL ||
1133 rhs->type == NT_ARITHMETIC)
1134 {
1135 /* if the module defines this output */
1136 if (i < SIZE_LIST(out))
1137 {
1138 /* Create a variable and stick its index in rvals */
1139 INIT_PVAR(pv);
1140 pv.excache = excache;
1141 pv.cacheattr = attr_flag;
1142 APPEND_LIST (int, p->wiredvars, SIZE_LIST(p->vars));
1143 APPEND_LIST (ProgramVariable, p->vars, pv);
1144 rvals[i] = *FETCH_LIST(out, i);
1145 ppv = FETCH_LIST(p->vars, rvals[i]);
1146 ppv->excache = excache;
1147 ppv->cacheattr = attr_flag;
1148 }
1149 /* if the module doesn't define this output (x,y,z = Compute...) */
1150 else
1151 {
1152 /* Create a variable and stick its index in rvals */
1153 INIT_PVAR(pv);
1154 pv.obj = NULL;
1155 pv.defined = TRUE;
1156 pv.excache = excache;
1157 pv.cacheattr = attr_flag;
1158 APPEND_LIST (ProgramVariable, p->vars, pv);
1159 rvals[i] = SIZE_LIST (p->vars) - 1;
1160 rhs = NULL;
1161 }
1162 }
1163 /* Else we've got a simple assignment */
1164 else
1165 {
1166 rhs = rhs->next;
1167 }
1168
1169 ind = CreateIndex(rvals[i]);
1170 /* Check to see if variable name is NULL, if we don't check here
1171 * we will get two warnings about NULL assignment, one now and
1172 * one later when the actual variable assignment happens.
1173 */
1174 if (strcmp (lhs->v.id.id, "NULL"))
1175 _dxf_ExVariableInsert (lhs->v.id.id, dict, (EXO_Object) ind);
1176 if (top == 0)
1177 {
1178 r.index = rvals[i];
1179 r.name = _dxf_ExCopyString/*Local*/(lhs->v.id.id);
1180 r.oneshot =
1181 DXReference (_dxf_ExGetAttribute (lhs->attr, ATTR_ONESHOT));
1182 APPEND_LIST (ProgramRef, p->outputs, r);
1183 }
1184 }
1185 if (SIZE_LIST(out) > 0)
1186 FREE_LIST(out);
1187 }
1188
1189 /*
1190 * Translate a parse tree call statment (macro expansion or module call)
1191 * into the appropriate graph structure. This function takes a parse node,
1192 * program, and dictionary. It modifies the program and produces a list
1193 * of indices into the programs "vars" list that are the functions
1194 * output. "top" is used when recursing.
1195 */
1196 static void
ExGraphCall(Program * p,node * n,int top,list_int * out,EXDictionary dict,int * flags)1197 ExGraphCall (Program *p, node *n, int top, list_int *out, EXDictionary dict, int *flags)
1198 {
1199 char *fname;
1200 char *name;
1201 node *function=NULL;
1202 node *formal;
1203 node *arg;
1204 int slot;
1205 gfunc fnode;
1206 gfunc *pFnode;
1207 node *val;
1208 _ntype t;
1209 int instance;
1210 _excache excache;
1211 char *macro_procgroupid;
1212 int keep_caching;
1213 int *inArgs;
1214 node **inAttrs = NULL;
1215 ReRouteMap *reroutem, rr_map;
1216 int nin;
1217 int namedArgs;
1218 int prehidden;
1219 int posthidden;
1220 node_function localFunct;
1221 _ntype functionType;
1222 int i, j;
1223
1224 ProgramVariable pv;
1225 ProgramRef pr;
1226 MacroRef mr;
1227 AsyncVars *avars, av;
1228 indexobj *ind;
1229 list_int subOut;
1230
1231 Program *subP, *copyP;
1232 EXDictionary subDict;
1233 progobj *pobj;
1234 int *mapping;
1235 int *resolved, numresolved;
1236 ProgramVariable *pPv;
1237 ProgramRef *pPr;
1238 int ilimit;
1239 int jlimit;
1240
1241 if (graphing_error)
1242 goto graphing_error_return;
1243
1244 /*
1245 * Look up the identifier in the function dictionary.
1246 */
1247 fname = name = n->v.call.id->v.id.id;
1248 #ifdef INPUT_TIMING
1249 DXMarkTimeLocal (name);
1250 #endif
1251
1252 function = (node *)_dxf_ExMacroSearch (name);
1253 if (function == NULL)
1254 {
1255 char *modname;
1256 modname = DXAllocateLocal(strlen(name) + 1);
1257 strcpy(modname, name);
1258 DXAddModule(modname, m__badfunc, 0,
1259 21, "input1", "input2", "input3", "input4", "input5", "input6",
1260 "input7", "input8", "input9", "input10", "input11", "input12",
1261 "input13", "input14", "input15", "input16", "input17", "input18",
1262 "input19", "input20", "input21",
1263 21, "output", "output1", "output2", "output3", "output4", "output5",
1264 "output6", "output7", "output8", "output9", "output10", "output11",
1265 "output12", "output13", "output14", "output15", "output16",
1266 "output17", "output18", "output19", "output20");
1267 function = (node *)_dxf_ExMacroSearch (name);
1268 }
1269 if(function->v.function.def.func == m__badfunc) {
1270 if(!_dxd_exRemoteSlave)
1271 DXUIMessage ("ERROR", "%s: function does not exist", name);
1272 else
1273 DXUIMessage ("ERROR",
1274 "%s: function does not exist on host %s", name, _dxd_exHostName);
1275 }
1276
1277 functionType = function->type;
1278
1279 if (_dxf_ExMacroRecursionCheck (name, functionType))
1280 {
1281 graphing_error = TRUE;
1282 goto graphing_error_return;
1283 }
1284
1285 localFunct = function->v.function;
1286 *flags = localFunct.flags;
1287
1288 /*
1289 * Setup positional formal inputs
1290 */
1291 #ifdef INPUT_TIMING
1292 DXMarkTimeLocal ("init inputs");
1293 #endif
1294
1295 nin = fnode.nin = localFunct.nin;
1296 prehidden = localFunct.prehidden;
1297 posthidden = localFunct.posthidden;
1298
1299 fnode.nout = localFunct.nout;
1300 inArgs = (int*) DXAllocateLocal (nin * sizeof (int));
1301 inAttrs = (node **) DXAllocateLocal (nin * sizeof (node*));
1302
1303 for (i = 0; i < nin; ++i) {
1304 inArgs[i] = -1;
1305 inAttrs[i] = NULL;
1306 }
1307
1308 for (i = 0, formal = localFunct.in;
1309 i < prehidden;
1310 ++i, formal = formal->next);
1311
1312 namedArgs = FALSE;
1313 for (arg = n->v.call.arg, slot = prehidden;
1314 slot < nin - posthidden;
1315 arg = (arg) ? arg->next : arg, slot++,formal = formal->next)
1316 {
1317 /* A name substitution has been found, no more positional args */
1318 if (arg)
1319 {
1320 if (arg->v.arg.id) {
1321 namedArgs = TRUE;
1322 }
1323 else if (namedArgs)
1324 DXWarning ("#4780", fname);
1325 }
1326
1327 /*
1328 * If an constant argument was specified, create a defined variable.
1329 * If it is an ID, look it up in the dictionary (defining it to be
1330 * undefined if it's not there).
1331 * If it's an expression, recurse.
1332 */
1333 if (!namedArgs && arg)
1334 {
1335 val = arg->v.arg.val;
1336 t = val->type;
1337
1338 switch (t)
1339 {
1340 case NT_CONSTANT:
1341 INIT_PVAR(pv);
1342 pv.obj = DXReference ((Object) val->v.constant.obj);
1343 pv.defined = TRUE;
1344 APPEND_LIST (ProgramVariable, p->vars, pv);
1345 inArgs[slot] = SIZE_LIST(p->vars) - 1;
1346 inAttrs[slot] = (node *) formal->attr;
1347 break;
1348
1349 case NT_ID:
1350 ind = (indexobj *)_dxf_ExVariableSearch (val->v.id.id, dict);
1351 if (ind == NULL)
1352 {
1353 pr.name = _dxf_ExCopyString/*Local*/ (val->v.id.id);
1354 pr.oneshot = NULL;
1355 inArgs[slot] = pr.index = SIZE_LIST (p->vars);
1356 ExDebug("1","pr.name %s, pr.index %d\n", pr.name, pr.index);
1357 APPEND_LIST (ProgramRef, p->undefineds, pr);
1358 INIT_PVAR(pv);
1359 inAttrs[slot] = (node *) formal->attr;
1360 APPEND_LIST (ProgramVariable, p->vars, pv);
1361 }
1362 else
1363 {
1364 inArgs[slot] = ind->index;
1365 inAttrs[slot] = (node *) formal->attr;
1366 ExDelete (ind);
1367 }
1368 break;
1369
1370 case NT_LOGICAL:
1371 case NT_ARITHMETIC:
1372 INIT_LIST(subOut);
1373 ExGraphExpression (p, val, top, &subOut, dict);
1374 if (graphing_error)
1375 goto graphing_error_return;
1376 inArgs[slot] = *FETCH_LIST(subOut, 0);
1377 FREE_LIST(subOut);
1378 break;
1379
1380 default:
1381 if(!_dxd_exRemoteSlave)
1382 DXUIMessage ("ERROR",
1383 "_graphCall Internal: invalid argument type = %d", t);
1384 graphing_error = TRUE;
1385 goto call_error;
1386 }
1387 }
1388 }
1389 if (arg)
1390 DXWarning ("#4790", fname);
1391 #ifdef INPUT_TIMING
1392 DXMarkTimeLocal ("inited unnamed");
1393 #endif
1394
1395 /*
1396 * Setup explicitly named formals
1397 */
1398 if (namedArgs)
1399 {
1400 for (arg = n->v.call.arg; arg; arg = arg->next)
1401 {
1402 /*
1403 * this is not a name substitution argument, don't bother
1404 */
1405 if (! arg->v.arg.id)
1406 continue;
1407
1408 /*
1409 * look up formal name in formal list
1410 */
1411 for (slot = 0, formal = localFunct.in;
1412 formal;
1413 formal = formal->next, slot++)
1414 {
1415 if (strcmp (arg->v.arg.id->v.id.id, formal->v.id.id) == 0)
1416 {
1417 break;
1418 }
1419 }
1420
1421 if (slot >= nin)
1422 {
1423 DXWarning ("#4800", fname, arg->v.arg.id->v.id.id);
1424 continue;
1425 }
1426
1427 /*
1428 * If an constant argument was specified,
1429 * create a defined variable.
1430 * If it is an ID, look it up in the dictionary (defining it to be
1431 * undefined if it's not there).
1432 * If it's an expression, recurse.
1433 */
1434 val = arg->v.arg.val;
1435 t = val->type;
1436 switch (t)
1437 {
1438 case NT_CONSTANT:
1439 INIT_PVAR(pv);
1440 pv.obj = DXReference ((Object) val->v.constant.obj);
1441 pv.defined = TRUE;
1442 APPEND_LIST (ProgramVariable, p->vars, pv);
1443 inArgs[slot] = SIZE_LIST(p->vars) - 1;
1444 inAttrs[slot] = (node *) formal->attr;
1445 break;
1446
1447 case NT_ID:
1448 ind = (indexobj *)_dxf_ExVariableSearch (val->v.id.id, dict);
1449 if (ind == NULL)
1450 {
1451 pr.name = _dxf_ExCopyString/*Local*/ (val->v.id.id);
1452 inArgs[slot] = pr.index = SIZE_LIST (p->vars);
1453 ExDebug("1","pr.name %s, pr.index %d\n", pr.name, pr.index);
1454 APPEND_LIST (ProgramRef, p->undefineds, pr);
1455 INIT_PVAR(pv);
1456 inAttrs[slot] = (node *) formal->attr;
1457 APPEND_LIST (ProgramVariable, p->vars, pv);
1458 }
1459 else
1460 {
1461 inArgs[slot] = ind->index;
1462 inAttrs[slot] = (node *) formal->attr;
1463 ExDelete (ind);
1464 }
1465 break;
1466
1467 case NT_LOGICAL:
1468 case NT_ARITHMETIC:
1469 INIT_LIST(subOut);
1470 ExGraphExpression (p, val, top, &subOut, dict);
1471 if (graphing_error)
1472 goto graphing_error_return;
1473 inArgs[slot] = *FETCH_LIST(subOut, 0);
1474 break;
1475
1476 default:
1477 if(!_dxd_exRemoteSlave)
1478 DXUIMessage ("ERROR",
1479 "_graphCall Internal: invalid argument type = %d", t);
1480 graphing_error = TRUE;
1481 goto call_error;
1482 }
1483 }
1484 }
1485
1486 /*
1487 * Fill in defaults, where they exist. Set the default value even if
1488 * something has been assigned to this input, because if it ends up
1489 * being evaluated to NULL, the default should be used instead.
1490 */
1491 for (formal = localFunct.in, slot = 0;
1492 slot < nin;
1493 ++slot, formal = formal->next)
1494 {
1495 /*
1496 * if no default, don't bother
1497 */
1498 if (!formal->v.id.dflt)
1499 continue;
1500
1501
1502 if (inArgs[slot] < 0)
1503 {
1504 INIT_PVAR(pv);
1505 APPEND_LIST (ProgramVariable, p->vars, pv);
1506 inArgs[slot] = SIZE_LIST(p->vars) - 1;
1507 }
1508 pPv = FETCH_LIST(p->vars, inArgs[slot]);
1509 if (formal->v.id.dflt->type != NT_CONSTANT)
1510 {
1511 if(!_dxd_exRemoteSlave)
1512 DXUIMessage ("ERROR",
1513 "%s: default values must be constants", fname);
1514 graphing_error = TRUE;
1515 goto call_error;
1516 }
1517 else
1518 {
1519 pPv->dflt =
1520 DXReference ((Object)formal->v.id.dflt->v.constant.obj);
1521 }
1522 }
1523 #ifdef INPUT_TIMING
1524 DXMarkTimeLocal ("inited named");
1525 #endif
1526
1527 /*
1528 * Find the function's attributes, e.g. instance and caching if it
1529 * has any attributed to it
1530 */
1531 instance = _dxf_ExGetIntegerAttribute (n->attr, ATTR_INSTANCE);
1532
1533 if (! _dxf_ExHasIntegerAttribute (n->attr, ATTR_CACHE, (int *)&excache))
1534 excache = CACHE_ALL;
1535
1536 /*
1537 * ExNoCachePush expects an on/off flag. Since all values > 0 imply some
1538 * kind of caching, pass a 1 to ExNoCachePush for all values > 0, and
1539 * set excache to the cache attr value unless a 0 is returned, in which
1540 * case caching should be suppressed. (is this OK? )
1541 */
1542 keep_caching = _dxf_ExNoCachePush (excache != CACHE_OFF);
1543 if (!keep_caching)
1544 excache = CACHE_OFF;
1545
1546 /*
1547 * Macro calls are expanded recursively. Module calls create input
1548 * and output lists, and insert the gfunc structure into the program.
1549 */
1550 switch (functionType)
1551 {
1552 case NT_MACRO:
1553
1554 /* Look up the macro in the graph cache, and make one (inserting
1555 * it) if it's not found.
1556 */
1557
1558 macro_procgroupid = _dxf_ExGetStringAttribute (n->attr, ATTR_PGRP);
1559
1560 pobj = (progobj*) _dxf_ExDictionarySearch (_dxd_exGraphCache, name);
1561 if (pobj == NULL)
1562 {
1563 #ifdef INPUT_TIMING
1564 DXMarkTimeLocal ("init formals");
1565 #endif
1566 /* Create sub{dictionary,program} */
1567 subDict = _dxf_ExDictionaryCreate (DICT_SIZE, TRUE, FALSE);
1568 subP = AllocateProgramLocal();
1569
1570 /* Insert supplied inputs into new local dictionary */
1571 for (formal = localFunct.in, slot = 0;
1572 formal;
1573 formal = formal->next, slot++)
1574 {
1575 pr.index = SIZE_LIST(subP->vars);
1576 pr.name = _dxf_ExCopyString/*Local*/ (formal->v.id.id);
1577 ExDebug("1","pr.name %s, pr.index %d\n", pr.name, pr.index);
1578 APPEND_LIST (ProgramRef, subP->inputs, pr);
1579 ind = CreateIndex(pr.index);
1580 _dxf_ExVariableInsert (pr.name, subDict, (EXObj) ind);
1581 INIT_PVAR (pv);
1582 APPEND_LIST (ProgramVariable, subP->vars, pv);
1583 }
1584
1585 #ifdef INPUT_TIMING
1586 DXMarkTimeLocal ("inited formals");
1587 #endif
1588 /* Recurse */
1589 ExGraphTraverse (subP, localFunct.def.stmt, top + 1, subDict);
1590 if(graphing_error)
1591 goto graphing_error_return;
1592
1593 /* add itself to it's list of macros */
1594 mr.name = _dxf_ExCopyString(name);
1595 mr.index = localFunct.index;
1596 APPEND_LIST(MacroRef, subP->macros, mr);
1597
1598 /* Extract outputs from the dictionary and put them in the
1599 * output list
1600 */
1601 for (formal = localFunct.out, slot = 0;
1602 formal;
1603 formal = formal->next, slot++)
1604 {
1605 ind = (indexobj*) _dxf_ExVariableSearch (formal->v.id.id,
1606 subDict);
1607 /* If there was no definition for this output, set to null */
1608 if (ind == NULL)
1609 {
1610 INIT_PVAR (pv);
1611 pv.defined = TRUE;
1612 APPEND_LIST (ProgramVariable, subP->vars, pv);
1613 i = SIZE_LIST (subP->vars) - 1;
1614 }
1615 else
1616 {
1617 i = ind->index;
1618 ExDelete(ind);
1619 }
1620 pr.index = i;
1621 pr.name = _dxf_ExCopyString/*Local*/ (formal->v.id.id);
1622 ExDebug("1","pr.name %s, pr.index %d\n", pr.name, pr.index);
1623 APPEND_LIST (ProgramRef, subP->outputs, pr);
1624 }
1625
1626 /* Clean up the dictionary and create the cached object */
1627 _dxf_ExDictionaryDestroy (subDict);
1628 pobj = CreateProgobj (subP);
1629 ExReference (pobj);
1630
1631 if (top == 0)
1632 {
1633 /* Insert any SendModules that may be required */
1634 ExDebug("*1","Before ExCreateSendModules with nbr gfuncs = %d",
1635 SIZE_LIST(subP->funcs));
1636 ExCreateSendModules(subP);
1637 ExDebug("*1","After ExCreateSendModules with nbr gfuncs = %d",
1638 SIZE_LIST(subP->funcs));
1639 }
1640 _dxf_ExDictionaryInsert (_dxd_exGraphCache, name, (EXObj)pobj);
1641 }
1642 else
1643 subP = pobj->p;
1644
1645 /* parent program gets a copy of all macros in it's children */
1646 GROW_LIST(MacroRef, p->macros, SIZE_LIST(subP->macros));
1647
1648 for (i = 0, ilimit = SIZE_LIST(subP->macros); i < ilimit; ++i)
1649 {
1650 MacroRef *macro;
1651 macro = FETCH_LIST(subP->macros, i);
1652 mr.name = _dxf_ExCopyString(macro->name);
1653 mr.index = macro->index;
1654 APPEND_LIST(MacroRef, p->macros, mr);
1655 }
1656 /* From here on, we're copying the relocatable (compiled) version
1657 * of the macro into the caller's program.
1658 *
1659 * Start by Create a mapping array... mapping [i] is valid
1660 * iff resolved[i] is TRUE. p->vars[mapping[subPindex]]
1661 */
1662 mapping = (int*)DXAllocateLocal (SIZE_LIST(subP->vars) *
1663 sizeof(int));
1664 resolved = (int*)DXAllocateLocalZero (SIZE_LIST(subP->vars) *
1665 sizeof(int));
1666 numresolved = 0;
1667 if (mapping == NULL || resolved == NULL)
1668 {
1669 graphing_error = TRUE;
1670 _dxf_ExDie ("ExGraphCall: can't allocate memory");
1671 }
1672
1673 /* Define mappings for the inputs in the caller's variable list */
1674 for (i = 0, ilimit = SIZE_LIST(subP->inputs); i < ilimit; ++i)
1675 {
1676 pPr = FETCH_LIST(subP->inputs, i);
1677 mapping [pPr->index] = inArgs[i];
1678 resolved[pPr->index] = TRUE;
1679 numresolved++;
1680 }
1681
1682 /* Try to define all undefineds. If it exists in the caller's
1683 * dictionary, define the value (that's the new mapping). If it's not
1684 * there, create a new undefined.
1685 */
1686 GROW_LIST(ProgramVariable, p->vars, SIZE_LIST(subP->undefineds));
1687 GROW_LIST(ProgramRef, p->undefineds, SIZE_LIST(subP->undefineds));
1688 for (i = 0, ilimit = SIZE_LIST(subP->undefineds); i < ilimit; ++i)
1689 {
1690 pPr = FETCH_LIST(subP->undefineds, i);
1691 ind = (indexobj *) _dxf_ExVariableSearch(pPr->name, dict);
1692 if (ind == NULL)
1693 {
1694 pr.index = SIZE_LIST(p->vars);
1695 pr.name = _dxf_ExCopyString/*Local*/ (pPr->name);
1696 ExDebug("1","pr.name %s, pr.index %d\n", pr.name, pr.index);
1697 mapping [pPr->index] = pr.index;
1698 resolved[pPr->index] = TRUE;
1699 numresolved++;
1700 pPv = FETCH_LIST(subP->vars, pPr->index);
1701 pv = *pPv;
1702 if (pPv->defined)
1703 DXReference (pPv->obj);
1704 if (pPv->dflt != NULL)
1705 DXReference (pPv->dflt);
1706 APPEND_LIST (ProgramVariable, p->vars, pv);
1707 APPEND_LIST (ProgramRef, p->undefineds, pr);
1708 }
1709 else
1710 {
1711 mapping [pPr->index] = ind->index;
1712 resolved[pPr->index] = TRUE;
1713 numresolved++;
1714 ExDelete (ind);
1715 }
1716 }
1717
1718 /* Loop through and create mappings for the other variables */
1719 ilimit = SIZE_LIST(subP->vars);
1720 GROW_LIST(ProgramVariable, p->vars, ilimit-numresolved);
1721 for (i = 0; i < ilimit; ++i)
1722 {
1723 pPv = FETCH_LIST(subP->vars, i);
1724 if (!resolved[i])
1725 {
1726 pv = *pPv;
1727 mapping [i] = SIZE_LIST(p->vars);
1728 resolved[i] = TRUE;
1729 APPEND_LIST (ProgramVariable, p->vars, pv);
1730 if (pPv->defined)
1731 DXReference (pPv->obj);
1732 if (pPv->dflt != NULL)
1733 DXReference (pPv->dflt);
1734 }
1735 }
1736
1737 /* Put the outputs in the "out" list which is used by the
1738 * macro caller.
1739 */
1740 for (i = 0, ilimit = SIZE_LIST(subP->outputs); i < ilimit; ++i)
1741 {
1742 pPr = FETCH_LIST(subP->outputs, i);
1743 APPEND_LIST(int, *out, mapping[pPr->index]);
1744 }
1745
1746 /* parent program gets a copy of all async variable in it's children */
1747 for (i = 0, ilimit = SIZE_LIST(subP->async_vars); i < ilimit; ++i)
1748 {
1749 avars = FETCH_LIST(subP->async_vars, i);
1750 av.nameindx = mapping[avars->nameindx];
1751 av.valueindx = mapping[avars->valueindx];
1752 APPEND_LIST(int, p->wiredvars, av.valueindx);
1753 APPEND_LIST(AsyncVars, p->async_vars, av);
1754 }
1755
1756 /* We will copy each function into a separate subprogram that will
1757 * be referenced from the caller's program.
1758 */
1759
1760 copyP = GetNewMacro(subP, mapping, resolved);
1761 if(top == 0)
1762 copyP->subgraphId = NextSubGraphId();
1763
1764 for(i = 0; i < SIZE_LIST(subP->async_vars); i++) {
1765 avars = FETCH_LIST(subP->async_vars, i);
1766 slot = avars->nameindx;
1767 if(slot != -1) {
1768 if (!resolved[slot])
1769 _dxf_ExDie ("Executive inconsistency -- ExGraphCall 001");
1770 av.nameindx = mapping[slot];
1771 }
1772 else av.nameindx = slot;
1773 pPv = FETCH_LIST(p->vars, mapping[slot]);
1774 ExFixAsyncVarName(p, pPv, fname, instance);
1775
1776 slot = avars->valueindx;
1777 if(slot != -1) {
1778 if (!resolved[slot])
1779 _dxf_ExDie ("Executive inconsistency -- ExGraphCall 002");
1780 av.valueindx = mapping[slot];
1781 }
1782 else av.valueindx = slot;
1783 APPEND_LIST (AsyncVars, copyP->async_vars, av);
1784 }
1785
1786 GROW_LIST(gfunc, copyP->funcs, SIZE_LIST(subP->funcs));
1787
1788 for (i = 0, ilimit = SIZE_LIST(subP->funcs); i < ilimit; ++i)
1789 {
1790 pFnode = FETCH_LIST(subP->funcs, i);
1791 fnode = *pFnode;
1792 if(fnode.ftype == F_MACRO) {
1793 Program *newp;
1794 newp = AllocateProgram();
1795 ExCopySubP(newp, fnode.func.subP, top);
1796 if(top == 0)
1797 newp->subgraphId = NextSubGraphId();
1798 ExRemapVars(p, newp, mapping, resolved, fname, instance);
1799 fnode.name = _dxf_ExCopyString(pFnode->name);
1800 fnode.func.subP = newp;
1801 if(fnode.flags & MODULE_SIDE_EFFECT)
1802 localFunct.flags |= MODULE_SIDE_EFFECT;
1803 /* we are going to make state macros ASYNCLOCAL */
1804 /* so that they get the extra 2 hidden inputs */
1805 /* added. They are a bit different but share */
1806 /* enough code that they should use this flag. */
1807 if(fnode.flags & MODULE_CONTAINS_STATE) {
1808 localFunct.flags |= MODULE_CONTAINS_STATE;
1809 localFunct.flags |= MODULE_ASYNCLOCAL;
1810 }
1811 if(fnode.flags & MODULE_CHANGES_STATE) {
1812 localFunct.flags |= MODULE_CONTAINS_STATE;
1813 localFunct.flags |= MODULE_ASYNCLOCAL;
1814 }
1815 }
1816 else {
1817 if(fnode.flags & MODULE_CHANGES_STATE) {
1818 localFunct.flags |= MODULE_CHANGES_STATE;
1819 localFunct.flags |= MODULE_ASYNCLOCAL;
1820 }
1821 if(fnode.flags & MODULE_SIDE_EFFECT)
1822 localFunct.flags |= MODULE_SIDE_EFFECT;
1823 }
1824
1825 /*
1826 * make changes to the copy of the fnode just created.
1827 */
1828 _dxf_ExPathPrepend( subP, fname, instance, &fnode );
1829
1830
1831 /*
1832 * macro process group assignments override individual settings.
1833 * included function if it has one.
1834 */
1835 if (macro_procgroupid)
1836 fnode.procgroupid = _dxf_ExCopyString (macro_procgroupid);
1837
1838
1839 INIT_LIST (fnode.inputs);
1840 INIT_LIST (fnode.outputs);
1841 INIT_LIST (fnode.reroute);
1842 INIT_LIST (fnode.cache_ddi);
1843
1844 GROW_LIST(int, fnode.inputs, SIZE_LIST(pFnode->inputs));
1845 GROW_LIST(int, fnode.outputs, SIZE_LIST(pFnode->outputs));
1846 GROW_LIST(ReRouteMap, fnode.reroute, SIZE_LIST(pFnode->reroute));
1847 GROW_LIST(int, fnode.cache_ddi, SIZE_LIST(pFnode->cache_ddi));
1848
1849 for (j = 0, jlimit = SIZE_LIST(pFnode->inputs); j < jlimit; ++j)
1850 {
1851 slot = *FETCH_LIST(pFnode->inputs, j);
1852 if (slot == -1)
1853 {
1854 APPEND_LIST(int, fnode.inputs, slot);
1855 }
1856 else
1857 {
1858 if (!resolved[slot])
1859 _dxf_ExDie ("Executive inconsistency -- ExGraphCall 003");
1860 APPEND_LIST(int, fnode.inputs, mapping[slot]);
1861 }
1862 }
1863
1864 /* The name of the async variable is fixed for ASYNC modules */
1865 /* above in the call to ExFixAsyncVarName. Here we already */
1866 /* fixed the path name of the module so we just use that. */
1867 if(fnode.flags & MODULE_ASYNCLOCAL) {
1868 Object new_path;
1869
1870 slot = *FETCH_LIST(fnode.inputs, fnode.nin - 2);
1871 pPv = FETCH_LIST(p->vars, slot);
1872
1873 new_path = (Object)DXNewString( _dxf_ExGFuncPathToCacheString(&fnode) );
1874 DXReference ((Object)new_path);
1875 if(pPv->obj)
1876 DXDelete((Object)pPv->obj);
1877 pPv->obj = new_path;
1878 }
1879
1880 for (j = 0, jlimit = SIZE_LIST(pFnode->outputs); j < jlimit; ++j)
1881 {
1882 slot = *FETCH_LIST(pFnode->outputs, j);
1883 if (slot == -1)
1884 {
1885 APPEND_LIST(int, fnode.outputs, slot);
1886 }
1887 else
1888 {
1889 if (!resolved[slot])
1890 _dxf_ExDie ("Executive inconsistency -- ExGraphCall 004");
1891 APPEND_LIST(int, fnode.outputs, mapping[slot]);
1892 }
1893 }
1894
1895 for (j = 0, jlimit = SIZE_LIST(pFnode->reroute); j < jlimit; ++j)
1896 {
1897 reroutem = FETCH_LIST(pFnode->reroute, j);
1898 rr_map = *reroutem;
1899 APPEND_LIST(ReRouteMap, fnode.reroute, rr_map);
1900 }
1901
1902 for (j = 0, jlimit = SIZE_LIST(pFnode->cache_ddi); j < jlimit; ++j)
1903 {
1904 slot = *FETCH_LIST(pFnode->cache_ddi, j);
1905 APPEND_LIST(int, fnode.cache_ddi, slot);
1906 }
1907
1908
1909 APPEND_LIST(gfunc, copyP->funcs, fnode);
1910 }
1911
1912 ExMakeGfunc(localFunct, NT_MACRO, instance, excache, n, inAttrs, p,
1913 inArgs, out, copyP);
1914
1915 ExDelete (pobj);
1916 DXFree ((Pointer)mapping);
1917 DXFree ((Pointer)resolved);
1918 break;
1919
1920 case NT_MODULE:
1921 #ifdef INPUT_TIMING
1922 DXMarkTimeLocal ("create gfunc");
1923 #endif
1924 ExMakeGfunc(localFunct, NT_MODULE, instance, excache, n, inAttrs, p,
1925 inArgs, out, NULL);
1926
1927 #ifdef INPUT_TIMING
1928 DXMarkTimeLocal ("created gfunc");
1929 #endif
1930 break;
1931
1932 default:
1933 break;
1934 }
1935
1936 call_error:
1937 _dxf_ExNoCachePop ();
1938 _dxf_ExMacroRecursionPop (name, functionType);
1939 DXFree ((Pointer) inArgs);
1940 DXFree ((Pointer) inAttrs);
1941
1942
1943 graphing_error_return:
1944
1945 ExDelete(function);
1946
1947 #ifdef INPUT_TIMING
1948 DXMarkTimeLocal (fname);
1949 #endif
1950 }
1951
GetNewMacro(Program * p,int * map,int * resolved)1952 static Program *GetNewMacro(Program *p, int *map, int *resolved)
1953 {
1954 Program *newp;
1955 int i, slot;
1956 ProgramRef pr, *pPr;
1957
1958 newp = AllocateProgram();
1959 GROW_LIST(ProgramRef, newp->undefineds, SIZE_LIST(p->undefineds));
1960 for(i = 0; i < SIZE_LIST(p->undefineds); i++) {
1961 pPr = FETCH_LIST(p->undefineds, i);
1962 slot = pPr->index;
1963 if(slot != -1) {
1964 if (!resolved[slot])
1965 _dxf_ExDie ("Executive inconsistency -- GetNewMacro 001");
1966 pr.index = map[slot];
1967 }
1968 else pr.index = slot;
1969 pr.name = _dxf_ExCopyString(pPr->name);
1970 pr.oneshot = NULL;
1971 ExDebug("1","pr.name %s, pr.index %d\n", pr.name, pr.index);
1972 APPEND_LIST (ProgramRef, newp->undefineds, pr);
1973 }
1974
1975 GROW_LIST(int, newp->wiredvars, SIZE_LIST(p->wiredvars));
1976 for(i = 0; i < SIZE_LIST(p->wiredvars); i++) {
1977 slot = *FETCH_LIST(p->wiredvars, i);
1978 if(slot != -1) {
1979 if(!resolved[slot])
1980 _dxf_ExDie ("Executive inconsistency -- GetNewMacro 001");
1981
1982 APPEND_LIST(int, newp->wiredvars, map[slot]);
1983 }
1984 else APPEND_LIST(int, newp->wiredvars, slot);
1985 }
1986
1987 COPY_LIST(newp->macros, p->macros);
1988 newp->vars = p->vars;
1989 newp->loopctl = p->loopctl;
1990 return(newp);
1991 }
1992
ExCopySubP(Program * toP,Program * fromP,int top)1993 static void ExCopySubP(Program *toP, Program *fromP, int top)
1994 {
1995 Program *mp;
1996 gfunc *pFnode, fnode;
1997 int i, ilimit, j, jlimit, slot;
1998 ReRouteMap *reroutem, rr_map;
1999 ProgramRef pr, *pPr;
2000 AsyncVars *avars, av;
2001
2002 *toP = *fromP;
2003 INIT_LIST(toP->undefineds);
2004 GROW_LIST(ProgramRef, toP->undefineds, SIZE_LIST(fromP->undefineds));
2005 for(i = 0; i < SIZE_LIST(fromP->undefineds); i++) {
2006 pPr = FETCH_LIST(fromP->undefineds, i);
2007 pr.index = pPr->index;
2008 pr.name = _dxf_ExCopyString(pPr->name);
2009 pr.oneshot = NULL;
2010 ExDebug("1","pr.name %s, pr.index %d\n", pr.name, pr.index);
2011 APPEND_LIST (ProgramRef, toP->undefineds, pr);
2012 }
2013
2014 INIT_LIST(toP->wiredvars);
2015 GROW_LIST(int, toP->wiredvars, SIZE_LIST(fromP->wiredvars));
2016 for(i = 0; i < SIZE_LIST(fromP->wiredvars); i++) {
2017 slot = *FETCH_LIST(fromP->wiredvars, i);
2018 APPEND_LIST (int, toP->wiredvars, slot);
2019 }
2020
2021 INIT_LIST(toP->async_vars);
2022 GROW_LIST(AsyncVars, toP->async_vars, SIZE_LIST(fromP->async_vars));
2023 for(i = 0; i < SIZE_LIST(fromP->async_vars); i++) {
2024 avars = FETCH_LIST(fromP->async_vars, i);
2025 av.nameindx = avars->nameindx;
2026 av.valueindx = avars->valueindx;
2027 APPEND_LIST (AsyncVars, toP->async_vars, av);
2028 }
2029 COPY_LIST(toP->macros, fromP->macros);
2030 INIT_LIST (toP->funcs);
2031
2032 GROW_LIST(gfunc, toP->funcs, SIZE_LIST(fromP->funcs));
2033
2034 for (i = 0, ilimit = SIZE_LIST(fromP->funcs); i < ilimit; ++i)
2035 {
2036 pFnode = FETCH_LIST(fromP->funcs, i);
2037 fnode = *pFnode;
2038
2039 if(fnode.ftype == F_MACRO) {
2040 fnode.name = _dxf_ExCopyString(pFnode->name);
2041 mp = AllocateProgram();
2042 ExCopySubP(mp, fnode.func.subP, top);
2043 if(top == 0)
2044 mp->subgraphId = NextSubGraphId();
2045 fnode.func.subP = mp;
2046 }
2047
2048 INIT_LIST (fnode.inputs);
2049 INIT_LIST (fnode.outputs);
2050 INIT_LIST (fnode.reroute);
2051 INIT_LIST (fnode.cache_ddi);
2052
2053 GROW_LIST(int, fnode.inputs, SIZE_LIST(pFnode->inputs));
2054 GROW_LIST(int, fnode.outputs, SIZE_LIST(pFnode->outputs));
2055 GROW_LIST(ReRouteMap, fnode.reroute, SIZE_LIST(pFnode->reroute));
2056 GROW_LIST(int, fnode.cache_ddi, SIZE_LIST(pFnode->cache_ddi));
2057
2058 for (j = 0, jlimit = SIZE_LIST(pFnode->inputs); j < jlimit; ++j)
2059 {
2060 slot = *FETCH_LIST(pFnode->inputs, j);
2061 APPEND_LIST(int, fnode.inputs, slot);
2062 }
2063
2064 for (j = 0, jlimit = SIZE_LIST(pFnode->outputs); j < jlimit; ++j)
2065 {
2066 slot = *FETCH_LIST(pFnode->outputs, j);
2067 APPEND_LIST(int, fnode.outputs, slot);
2068 }
2069
2070 for (j = 0, jlimit = SIZE_LIST(pFnode->reroute); j < jlimit; ++j)
2071 {
2072 reroutem = FETCH_LIST(pFnode->reroute, j);
2073 rr_map = *reroutem;
2074 APPEND_LIST(ReRouteMap, fnode.reroute, rr_map);
2075 }
2076
2077 for (j = 0, jlimit = SIZE_LIST(pFnode->cache_ddi); j < jlimit; ++j)
2078 {
2079 slot = *FETCH_LIST(pFnode->cache_ddi, j);
2080 APPEND_LIST(int, fnode.cache_ddi, slot);
2081 }
2082
2083 APPEND_LIST(gfunc, toP->funcs, fnode);
2084 }
2085 }
2086
ExMakeGfunc(node_function ndfunc,_ntype type,int instance,_excache excache,node * n,node ** inAttrs,Program * p,int * inArgs,list_int * out,Program * macro)2087 static void ExMakeGfunc(node_function ndfunc, _ntype type, int instance,
2088 _excache excache, node *n, node **inAttrs, Program *p,
2089 int *inArgs, list_int *out, Program *macro)
2090 {
2091 gfunc fnode;
2092 int slot, i;
2093 ProgramVariable pv;
2094 ProgramRef *pr;
2095 node *nodep;
2096 int nin = ndfunc.nin;
2097 int nout = ndfunc.nout;
2098 int found = FALSE;
2099
2100 _dxf_ExInitGfunc(&fnode);
2101
2102 switch(type) {
2103 case NT_MACRO: /* macro definition */
2104 fnode.ftype = F_MACRO;
2105 fnode.func.subP = macro;
2106 fnode.name = _dxf_ExCopyString(ndfunc.id->v.id.id);
2107 break;
2108 case NT_MODULE: /* module definition */
2109 fnode.ftype = F_MODULE;
2110 fnode.func.module = ndfunc.def.func;
2111 #if 0
2112 if(ndfunc.flags & MODULE_SIDE_EFFECT)
2113 p->loopctl.side_effects = TRUE;
2114 #endif
2115 fnode.name = ndfunc.id->v.id.id;
2116 break;
2117 default:
2118 break;
2119 }
2120 fnode.instance = instance;
2121 fnode.excache = excache;
2122
2123 _dxf_ExPathSet( p, n->v.call.id->v.id.id, instance, &fnode );
2124
2125 fnode.procgroupid =
2126 _dxf_ExCopyString (_dxf_ExGetStringAttribute (n->attr, ATTR_PGRP));
2127
2128 #if 0
2129 fnode.led[0] = ndfunc.led[0];
2130 fnode.led[1] = ndfunc.led[1];
2131 fnode.led[2] = ndfunc.led[2];
2132 fnode.led[3] = ndfunc.led[3];
2133 #endif
2134 fnode.flags = ndfunc.flags;
2135 #if 0
2136 if(fnode.ftype == F_MACRO && (macro->loopctl.side_effects ||
2137 (ndfunc.nout == 0 && ndfunc.nin == 0))) {
2138 fnode.flags = MODULE_SIDE_EFFECT;
2139 p->loopctl.side_effects = TRUE;
2140 }
2141 #endif
2142 if(fnode.ftype == F_MACRO && ndfunc.nout == 0 && ndfunc.nin == 0)
2143 fnode.flags = MODULE_SIDE_EFFECT;
2144 fnode.nout = ndfunc.nout;
2145 fnode.nin = ndfunc.nin;
2146
2147 if(fnode.ftype == F_MODULE) {
2148 /*
2149 * if asynchronous, the last two inputs are special and need to
2150 * have their default values modified.
2151 */
2152
2153 if (ndfunc.flags & (MODULE_ASYNC | MODULE_ASYNCLOCAL))
2154 {
2155 AsyncVars avars;
2156 slot = nin - 2;
2157 if (inArgs[slot] < 0)
2158 {
2159 Object new_path;
2160
2161 INIT_PVAR(pv);
2162 avars.nameindx = inArgs[slot] = SIZE_LIST(p->vars);
2163 pv.defined = TRUE;
2164
2165 new_path = (Object)DXNewString( _dxf_ExGFuncPathToString(&fnode) );
2166 DXReference ((Object)new_path);
2167 pv.obj = new_path;
2168 APPEND_LIST (ProgramVariable, p->vars, pv);
2169 }
2170
2171 slot = nin - 1;
2172 if (inArgs[slot] < 0)
2173 {
2174 INIT_PVAR(pv);
2175 avars.valueindx = inArgs[slot] = SIZE_LIST(p->vars);
2176 APPEND_LIST (int, p->wiredvars, avars.valueindx);
2177 APPEND_LIST (ProgramVariable, p->vars, pv);
2178 }
2179 if(ndfunc.flags & MODULE_ASYNC)
2180 APPEND_LIST(AsyncVars, p->async_vars, avars);
2181 }
2182
2183 /*
2184 * mark these as special, because unlike other modules, you have to
2185 * compute part of their inputs before you can tell which of their
2186 * other inputs/outputs should be generated.
2187 */
2188
2189 if (strcmp (fnode.name, "Switch") == 0)
2190 fnode.flowtype = SwitchFlag;
2191 else if (strcmp (fnode.name, "Route") == 0)
2192 fnode.flowtype = RouteFlag;
2193
2194 if (ndfunc.flags & MODULE_REROUTABLE) {
2195 Object _attr;
2196 ReRouteMap rr_map;
2197
2198 for (i = 0; i < nin; ++i) {
2199 nodep = inAttrs[i];
2200 if(nodep == NULL)
2201 continue;
2202
2203 _attr = _dxf_ExGetAttribute(nodep, ATTR_DIREROUTE);
2204 if (_attr)
2205 {
2206 DXExtractInteger(_attr, &(rr_map.output_n));
2207 rr_map.input_n = i;
2208 APPEND_LIST(ReRouteMap, fnode.reroute, rr_map);
2209 }
2210
2211 _attr = _dxf_ExGetAttribute(nodep, ATTR_CACHE);
2212 /* for inputs the cache value is always 2. I am only
2213 * storing which input # needs to be cached and not
2214 * the integer value of the cache attribute since it
2215 * is currently never used.
2216 */
2217 if(_attr)
2218 APPEND_LIST(int, fnode.cache_ddi, i);
2219 }
2220 }
2221 } /* type is F_MODULE */
2222
2223 /* Add each input to the function's input array, and define new
2224 * variables for each output.
2225 */
2226
2227 GROW_LIST(int, fnode.inputs, nin);
2228
2229 for (i = 0; i < nin; ++i) {
2230 if (fnode.ftype == F_MODULE &&
2231 (ndfunc.flags & (MODULE_ASYNC | MODULE_ASYNCLOCAL))) {
2232 int rerun_attr;
2233 if(_dxf_ExHasIntegerAttribute(inAttrs[i], ATTR_RERUNKEY, &rerun_attr)) {
2234 if(found)
2235 DXWarning("Multiple rerun keys found for module %s, using first occurence of rerun key");
2236 else {
2237 fnode.flags |= MODULE_ASYNCNAMED;
2238 fnode.rerun_index = i;
2239 found = TRUE;
2240 }
2241 }
2242 }
2243 APPEND_LIST(int, fnode.inputs, inArgs[i]);
2244 }
2245
2246 /* do not append to input list if macro has no input and no outputs */
2247 /* ie. main() */
2248 if(fnode.ftype == F_MACRO && !(nin == 0 && nout == 0)) {
2249 /* add named undefineds to end of input list */
2250 for (i = 0; i < SIZE_LIST(macro->undefineds); i++) {
2251 pr = FETCH_LIST(macro->undefineds, i);
2252 if (strcmp(pr->name, "NULL") != 0) {
2253 APPEND_LIST(int, fnode.inputs, pr->index);
2254 fnode.nin++;
2255 }
2256 }
2257 /* add last 2 inputs for macros marked asynclocal */
2258 if (ndfunc.flags & MODULE_ASYNCLOCAL)
2259 {
2260 Object new_path;
2261
2262 INIT_PVAR(pv);
2263 pv.defined = TRUE;
2264
2265 new_path = (Object)DXNewString( _dxf_ExGFuncPathToCacheString(&fnode) );
2266 DXReference ((Object)new_path);
2267 pv.obj = new_path;
2268
2269 APPEND_LIST(int, fnode.inputs, SIZE_LIST(p->vars));
2270 fnode.nin++;
2271 APPEND_LIST (ProgramVariable, p->vars, pv);
2272 INIT_PVAR(pv);
2273 APPEND_LIST(int, fnode.inputs, SIZE_LIST(p->vars));
2274 fnode.nin++;
2275 APPEND_LIST (int, p->wiredvars, SIZE_LIST(p->vars));
2276 APPEND_LIST (ProgramVariable, p->vars, pv);
2277 }
2278 }
2279
2280 for (i = 0; i < nout; ++i)
2281 {
2282 if(fnode.ftype == F_MODULE) {
2283 INIT_PVAR(pv);
2284 APPEND_LIST(int, p->wiredvars, SIZE_LIST(p->vars));
2285 APPEND_LIST(ProgramVariable, p->vars, pv);
2286 APPEND_LIST(int, *out, SIZE_LIST(p->vars) - 1);
2287 APPEND_LIST(int, fnode.outputs, SIZE_LIST(p->vars) - 1);
2288 }
2289 else {
2290 slot = *FETCH_LIST(*out, i);
2291 APPEND_LIST(int, p->wiredvars, slot);
2292 APPEND_LIST(int, fnode.outputs, slot);
2293 }
2294 }
2295
2296 APPEND_LIST(gfunc, p->funcs, fnode);
2297 }
2298
2299 /*
2300 * Generate SEND modules where outputs to modules are inputs to modules
2301 * that cross process groups.
2302 *
2303 * For each output of each gfunc:
2304 * Match var index # against var index # of each input of each
2305 * other gfunc. When match, compare process group name, and create
2306 * a SEND module when they don't match.
2307 */
ExCreateSendModules(Program * p)2308 static void ExCreateSendModules(Program *p)
2309 {
2310 int srcfn, tgfn, in_tab, out_tab;
2311 int *index, *outdex;
2312 gfunc *sgf, *tgf;
2313
2314 for (srcfn = 0; srcfn < SIZE_LIST(p->funcs); ++srcfn) {
2315 sgf = FETCH_LIST(p->funcs,srcfn);
2316 if(!strcmp(sgf->name, "DPSEND"))
2317 continue;
2318
2319 for (tgfn = srcfn + 1; tgfn < SIZE_LIST(p->funcs); ++tgfn) {
2320 tgf = FETCH_LIST(p->funcs,tgfn);
2321 /* if target and source functions belong to same execution
2322 * group then we don't need to build a DPSEND module.
2323 */
2324 if (sgf->procgroupid == NULL && tgf->procgroupid == NULL)
2325 continue;
2326 if (sgf->procgroupid != NULL && tgf->procgroupid != NULL &&
2327 !strcmp(sgf->procgroupid, tgf->procgroupid))
2328 continue;
2329
2330 for (out_tab = 0; out_tab < SIZE_LIST(sgf->outputs); ++out_tab) {
2331 outdex = FETCH_LIST (sgf->outputs, out_tab);
2332 if (outdex == NULL)
2333 _dxf_ExDie("Inconsistency building distributed graph");
2334 if (*outdex < 0)
2335 continue;
2336
2337 for (in_tab = 0; in_tab < SIZE_LIST(tgf->inputs); ++in_tab) {
2338 index = FETCH_LIST (tgf->inputs, in_tab);
2339 if (index == NULL)
2340 _dxf_ExDie("Inconsistency building distributed graph");
2341 if (*index < 0)
2342 continue;
2343 if (*index == *outdex) {
2344 ExBuildSendModule(p, sgf, tgf, srcfn, tgfn,
2345 in_tab, out_tab, outdex);
2346 /* new module was inserted in list and list may
2347 * have been moved to new location in memory
2348 * so do list lookup again.
2349 */
2350 sgf = FETCH_LIST(p->funcs,srcfn);
2351 tgfn++; /* to account for module inserted in list */
2352 tgf = FETCH_LIST(p->funcs,tgfn);
2353 } /* output of one mod points to input of other */
2354 } /* end of input loop for inner-most function */
2355
2356 } /* end of output loop for outer-most function */
2357
2358 } /* end of inner-most function loop */
2359
2360 } /* end of outer-most function loop */
2361
2362
2363 if(_dxd_exDebug) {
2364 for (srcfn = 0; srcfn < SIZE_LIST(p->funcs); ++srcfn) {
2365 sgf = FETCH_LIST(p->funcs,srcfn);
2366 printf("%s ", sgf->name);
2367 }
2368 if(srcfn > 0)
2369 printf("\n");
2370 }
2371 }
2372
2373 static void
ExBuildSendModule(Program * p,gfunc * sgf,gfunc * tgf,int srcfn,int tgfn,int in_tab,int out_tab,int * outdex)2374 ExBuildSendModule(Program *p,
2375 gfunc *sgf,
2376 gfunc *tgf,
2377 int srcfn,
2378 int tgfn,
2379 int in_tab,
2380 int out_tab,
2381 int *outdex)
2382 {
2383 gfunc fnode;
2384 int invars[2];
2385 int *inArgs;
2386 int i;
2387 ProgramVariable pv;
2388 node *val;
2389 int slot,*index;
2390
2391 ExDebug("*1","In ExBuildSendModule:");
2392 ExDebug("*1",
2393 "Sending ouput %d from module %s in procgroup %s at var index %d to:",
2394 out_tab, _dxf_ExGFuncPathToString(sgf), sgf->procgroupid, *outdex);
2395
2396 ExDebug("*1", "input %d of module %s in procgroup %s ",
2397 in_tab, _dxf_ExGFuncPathToString(tgf), tgf->procgroupid);
2398
2399 _dxf_ExInitGfunc(&fnode);
2400
2401 /* will never be calling a function in execGnode for DPSENDs */
2402 fnode.ftype = F_MODULE;
2403 fnode.func.module = NULL;
2404 fnode.name = _dxf_ExCopyString/*Local*/ ("DPSEND");
2405 fnode.instance = 0;
2406 fnode.excache = CACHE_ALL;
2407 fnode.procgroupid = _dxf_ExCopyString (sgf->procgroupid);
2408
2409
2410 /* fix this */
2411 /* FIXME: Assumes these are in the same program (common string table) */
2412 _dxf_ExPathCopy( &fnode.mod_path, &sgf->mod_path );
2413 _dxf_ExPathAppend( p, fnode.name, fnode.instance, &fnode );
2414
2415 fnode.nin = 5;
2416 fnode.nout = 1;
2417 fnode.flags = MODULE_ERR_CONT;
2418 invars[0] = tgfn;
2419 invars[1] = in_tab;
2420
2421 inArgs = (int*) DXAllocate/*Local*/ (fnode.nin * sizeof (int));
2422
2423 /* Create PVARs for DPSEND module inputs */
2424 /* 0th = target module procid */
2425 /* 1st = source module procid */
2426 /* 2nd = target module gfunc# */
2427 /* 3rd = target module input tab nbr */
2428 /* 4th = index# of pvar being sent */
2429
2430 for (i = 0; i < fnode.nin - 1 ; ++i)
2431 {
2432 INIT_PVAR(pv);
2433 if (i == 0) {
2434 pv.obj = DXReference ((Object) DXNewString(tgf->procgroupid));
2435 }
2436 else if (i == 1) {
2437 pv.obj = DXReference ((Object) DXNewString(sgf->procgroupid));
2438 }
2439 else {
2440 _dxf_ExEvaluateConstants (FALSE);
2441 val = _dxf_ExPCreateConst (TYPE_INT, CATEGORY_REAL, 1,
2442 (Pointer) &invars[i-2]);
2443 _dxf_ExEvaluateConstants (TRUE);
2444 pv.obj = DXReference ((Object) val->v.constant.obj);
2445 }
2446 pv.defined = TRUE;
2447 APPEND_LIST (ProgramVariable, p->vars, pv);
2448 inArgs[i] = SIZE_LIST(p->vars) - 1;
2449 APPEND_LIST(int, fnode.inputs, inArgs[i]);
2450 if (i > 2 ) {
2451 ExDebug("*1",
2452 "Appending fnode.input at %d with index (%d) to input %d",
2453 i, inArgs[i], invars[i-2]);
2454 }
2455 }
2456
2457 /* input object is output (pointed to by outdex) being sent */
2458 APPEND_LIST(int, fnode.inputs, *outdex);
2459
2460 /* create an output object */
2461 INIT_PVAR(pv);
2462 pv.obj = NULL;
2463 APPEND_LIST (ProgramVariable, p->vars, pv);
2464 slot = SIZE_LIST(p->vars) - 1;
2465 APPEND_LIST(int, p->wiredvars, slot);
2466 APPEND_LIST(int, fnode.outputs, slot);
2467
2468 /* also need to update the var index of the input tab of the target gfunc */
2469 index = FETCH_LIST(tgf->inputs,in_tab);
2470 ExDebug("*1","Changing index # of %s/%d from %d to %d in BuildSendModule",
2471 _dxf_ExGFuncPathToString(tgf), in_tab, *index,slot);
2472
2473 UPDATE_LIST(tgf->inputs,slot,in_tab);
2474 if(tgf->ftype == F_MACRO) {
2475 gfunc *mstartgf;
2476 /* We know that MacroStart is the first module in macro */
2477 mstartgf = FETCH_LIST(tgf->func.subP->funcs, 0);
2478 /* The first input to MacroStart is a count so we must use in_tab+1 */
2479 UPDATE_LIST(mstartgf->inputs, slot, in_tab+1);
2480 }
2481
2482 INSERT_LIST(gfunc, p->funcs, fnode, srcfn+1);
2483 DXFree ((Pointer) inArgs);
2484 }
2485
2486 static void
ExRemapVars(Program * p,Program * subP,int * map,int * resolved,char * fname,int inst)2487 ExRemapVars(Program *p, Program *subP, int *map, int *resolved, char *fname, int inst)
2488 {
2489 int i, ilimit, j, jlimit, slot;
2490 gfunc *gf;
2491 ProgramRef *pr;
2492 ProgramVariable *pv;
2493 AsyncVars *avars;
2494
2495 for (i = 0, ilimit = SIZE_LIST(subP->funcs); i < ilimit; ++i) {
2496 gf = FETCH_LIST(subP->funcs, i);
2497 if(gf->ftype == F_MACRO)
2498 ExRemapVars(p, gf->func.subP, map, resolved, fname, inst);
2499 for (j = 0, jlimit = SIZE_LIST(gf->inputs); j < jlimit; ++j) {
2500 slot = *FETCH_LIST(gf->inputs, j);
2501 if (slot != -1) {
2502 if (!resolved[slot])
2503 _dxf_ExDie ("Executive inconsistency -- ExRemapVars 001");
2504 UPDATE_LIST(gf->inputs, map[slot], j);
2505 }
2506 }
2507 for (j = 0, jlimit = SIZE_LIST(gf->outputs); j < jlimit; ++j) {
2508 slot = *FETCH_LIST(gf->outputs, j);
2509 if (slot != -1) {
2510 if (!resolved[slot])
2511 _dxf_ExDie ("Executive inconsistency -- ExRemapVars 002");
2512 UPDATE_LIST(gf->outputs, map[slot], j);
2513 }
2514 }
2515 _dxf_ExPathPrepend( subP, fname, inst, gf );
2516
2517 if(gf->flags & (MODULE_ASYNC | MODULE_ASYNCLOCAL)) {
2518 Object new_path;
2519
2520 slot = *FETCH_LIST(gf->inputs, gf->nin - 2);
2521 pv = FETCH_LIST(p->vars, slot);
2522
2523 new_path = (Object)DXNewString( _dxf_ExGFuncPathToCacheString(gf) );
2524 DXReference ((Object)new_path);
2525 if(pv->obj)
2526 DXDelete((Object)pv->obj);
2527 pv->obj = new_path;
2528 }
2529 }
2530 for (i = 0, ilimit = SIZE_LIST(subP->undefineds); i < ilimit; ++i)
2531 {
2532 pr = FETCH_LIST(subP->undefineds, i);
2533 slot = pr->index;
2534 if(slot != -1) {
2535 if (!resolved[slot])
2536 _dxf_ExDie ("Executive inconsistency -- ExRemapVars 003");
2537 pr->index = map[slot];
2538 }
2539 }
2540
2541 for (i = 0, ilimit = SIZE_LIST(subP->wiredvars); i < ilimit; ++i)
2542 {
2543 slot = *FETCH_LIST(subP->wiredvars, i);
2544 if(slot != -1) {
2545 if (!resolved[slot])
2546 _dxf_ExDie ("Executive inconsistency -- ExRemapVars 003");
2547 UPDATE_LIST(subP->wiredvars, map[slot], i);
2548 }
2549 }
2550
2551 for(i = 0; i < SIZE_LIST(subP->async_vars); i++) {
2552 avars = FETCH_LIST(subP->async_vars, i);
2553 slot = avars->nameindx;
2554 if(slot != -1) {
2555 if (!resolved[slot])
2556 _dxf_ExDie ("Executive inconsistency -- ExRemapVars 004");
2557 avars->nameindx = map[slot];
2558 }
2559 else avars->nameindx = slot;
2560
2561 slot = avars->valueindx;
2562 if(slot != -1) {
2563 if (!resolved[slot])
2564 _dxf_ExDie ("Executive inconsistency -- ExRemapVars 005");
2565 avars->valueindx = map[slot];
2566 }
2567 else avars->valueindx = slot;
2568 }
2569 }
2570
2571 static void
ExFixAsyncVarName(Program * program,ProgramVariable * pv,char * fname,int instance)2572 ExFixAsyncVarName(Program *program, ProgramVariable *pv, char *fname, int instance)
2573 {
2574 Object saveobj;
2575 char *path;
2576
2577 if(!pv->obj)
2578 _dxf_ExDie("Executive inconsistency -- bad async variable name");
2579 saveobj = pv->obj;
2580 path = DXGetString((String)pv->obj);
2581 pv->obj = (Object)DXNewString (_dxf_ExCacheStrPrepend(program, fname, instance, path));
2582 DXReference ((Object)pv->obj);
2583 DXDelete((Object)saveobj);
2584 }
2585
2586 /*----------------------------------------------------------------------------*/
2587
2588 #define ARRAY_LEN(a) (sizeof(a)/sizeof(a[0]))
2589
2590 struct mod_name_info {
2591 PseudoKey key; /* psuedokey: based on string contents */
2592 char *str; /* value: actual string value */
2593 int index; /* key: string index */
2594 };
2595
2596 static lock_type *mod_name_tables_lock;
2597 static LIST(char *) *mod_name_str_table; /* FIXME: Attach to pgm */
2598 static HashTable mod_name_hash; /* FIXME: Attach to pgm */
2599
2600
2601
hashCompare(Key search,Element matched)2602 static int hashCompare(Key search, Element matched)
2603 {
2604 return (strcmp(((struct mod_name_info *)search)->str,
2605 ((struct mod_name_info *)matched)->str));
2606 }
2607
hashFunc(char * str)2608 static PseudoKey hashFunc(char *str)
2609 {
2610 unsigned long h = 1;
2611 while(*str)
2612 h = (17*h + *str++);
2613 return (PseudoKey)h;
2614
2615 }
2616
_dxf_ModNameTablesInit()2617 Error _dxf_ModNameTablesInit()
2618 {
2619 /* Initialize mutex lock */
2620 if ((mod_name_tables_lock =
2621 (lock_type *) DXAllocate (sizeof (lock_type))) == NULL) {
2622 _dxf_ExDie ("_dxf_ModNameTablesInit: lock create failed");
2623 return ERROR;
2624 }
2625
2626 DXcreate_lock(mod_name_tables_lock, NULL);
2627
2628 /* FIXME: Attach this list and its hash to the program structure */
2629 mod_name_str_table = DXAllocate( sizeof( LIST(char *) ) );
2630
2631 INIT_LIST(*mod_name_str_table);
2632
2633 mod_name_hash = DXCreateHash( sizeof( struct mod_name_info ), NULL,
2634 hashCompare );
2635 if ( !mod_name_hash ) {
2636 _dxf_ExDie("_dxf_ModNameTablesInit: hash create failed");
2637 return ERROR;
2638 }
2639 return OK;
2640 }
2641
_dxf_ExGraphInsertAndLookupName(Program * p,char name[])2642 static uint32 _dxf_ExGraphInsertAndLookupName( Program *p, char name[] )
2643 {
2644 uint32 i;
2645 char *new;
2646 struct mod_name_info search, *found, info;
2647
2648 DXlock (mod_name_tables_lock, 0);
2649
2650 /* See if string is already in the list (via hash table) */
2651 search.key = hashFunc(name);
2652 search.str = name;
2653
2654 if ((found = (struct mod_name_info *)
2655 DXQueryHashElement( mod_name_hash,
2656 (Pointer)&search)) != NULL)
2657 {
2658 DXunlock (mod_name_tables_lock, 0);
2659 return found->index;
2660 }
2661
2662 /* It's not there, so add it to the list, and to the lookup hash */
2663 new = (char *) DXAllocate (strlen (name) + 1);
2664 if ( !new ) {
2665 _dxf_ExDie("_dxf_ExGraphInsertAndLookupName: DXAllocate failed");
2666 DXunlock (mod_name_tables_lock, 0);
2667 return (uint32) -1;
2668 }
2669 strcpy (new, name);
2670
2671 APPEND_LIST( char *, *mod_name_str_table, new );
2672
2673 i = SIZE_LIST( *mod_name_str_table ) - 1;
2674
2675 info.key = hashFunc( name );
2676 info.str = new;
2677 info.index = i;
2678
2679 if ( !DXInsertHashElement( mod_name_hash, (Pointer)&info) ) {
2680 _dxf_ExDie("_dxf_ExGraphInsertAndLookupName: DXInsertHashElement failed");
2681 DXunlock (mod_name_tables_lock, 0);
2682 return (uint32) -1;
2683 }
2684
2685 DXunlock (mod_name_tables_lock, 0);
2686
2687 return info.index;
2688 }
2689
2690 /* FIXME: These are duplicated in path.c */
2691 #define EX_I_SEP ':' /* instance # separator */
2692 #define EX_M_SEP '/' /* macro/module separator */
2693
2694
_dxf_BuildInstanceNumString(int instance)2695 static char *_dxf_BuildInstanceNumString(int instance)
2696 {
2697 static char localstr[10];
2698 char *tail = localstr;
2699 int np;
2700
2701 if (instance < 0 || instance > 999)
2702 {
2703 /* sprintf automatically puts a \0 at the end of a string
2704 so why print a second one? */
2705 /* sprintf(tail, "%d\0", instance); */
2706 sprintf(tail, "%d", instance);
2707 tail += strlen(tail);
2708 }
2709 else if (instance > 99)
2710 {
2711 np = instance / 100;
2712 *(tail++) = np + '0';
2713 instance -= np * 100;
2714 np = instance / 10;
2715 *(tail++) = np + '0';
2716 instance -= np * 10;
2717 *(tail++) = instance + '0';
2718 }
2719 else if (instance > 9)
2720 {
2721 np = instance / 10;
2722 *(tail++) = np + '0';
2723 instance -= np * 10;
2724 *(tail++) = instance + '0';
2725 }
2726 else
2727 *(tail++) = instance + '0';
2728 *(tail) = '\0';
2729
2730 return localstr;
2731 }
2732
_dxf_GetInstanceNumStringLen(int instance)2733 static int _dxf_GetInstanceNumStringLen(int instance)
2734 {
2735 if ( instance < 0 || instance > 999 )
2736 return strlen( _dxf_BuildInstanceNumString( instance ) );
2737 else if ( instance > 99 )
2738 return 3;
2739 else if ( instance > 9 )
2740 return 2;
2741 else
2742 return 1;
2743 }
2744
2745
_dxf_ExPathStringLen(ModPath * path)2746 static int _dxf_ExPathStringLen( ModPath *path )
2747 {
2748 int32 i;
2749 int len = 0;
2750
2751 for ( i = path->num_comp-1; i >= 0; i-- )
2752 len += 1 /*EX_M_SEP*/ +
2753 strlen( *FETCH_LIST( *mod_name_str_table, path->modules[i] ) ) +
2754 1 /*EX_I_SEP*/ +
2755 _dxf_GetInstanceNumStringLen( path->instances[i] ) +
2756 1 /*'\0'*/;
2757
2758 return len;
2759 }
2760
_dxf_ExPathToStringBuf(ModPath * path,char * path_str)2761 static void _dxf_ExPathToStringBuf( ModPath *path, char *path_str )
2762 {
2763 int32 i;
2764 char *p = path_str;
2765 char *module_name;
2766
2767 for ( i = path->num_comp-1; i >= 0; i-- ) {
2768 module_name = *FETCH_LIST( *mod_name_str_table, path->modules[i] );
2769 p[0] = EX_M_SEP;
2770 strcpy( p+1, module_name );
2771 p += strlen(p);
2772 p[0] = EX_I_SEP;
2773 strcpy( p+1, _dxf_BuildInstanceNumString( path->instances[i] ) );
2774 p += strlen(p);
2775 }
2776 }
2777
_dxf_ExPathToString(ModPath * path)2778 char *_dxf_ExPathToString( ModPath *path )
2779 {
2780 static char str[ MAX_PATH_STR_LEN ];
2781 int len;
2782
2783 len = _dxf_ExPathStringLen( path );
2784
2785 if ( len >= sizeof(str) ) {
2786 _dxf_ExDie ("_dxf_ExPathToString: Path is too long");
2787 return NULL;
2788 }
2789
2790 _dxf_ExPathToStringBuf( path, str );
2791 return str;
2792 }
2793
2794 static char *
int16tohex(char * buf,int16 l)2795 int16tohex (char *buf, int16 l)
2796 {
2797 static char *htab = "0123456789abcdef";
2798
2799 buf[4] = '\0';
2800 buf[3] = htab[l & 0xf]; l >>= 4;
2801 buf[2] = htab[l & 0xf]; l >>= 4;
2802 buf[1] = htab[l & 0xf]; l >>= 4;
2803 buf[0] = htab[l & 0xf];
2804
2805 return (buf + 4);
2806 }
2807
2808 static int16
hextoint16(char * buf)2809 hextoint16 (char *buf)
2810 {
2811 static char *htab = "0123456789abcdef";
2812 int16 val = 0;
2813 int i;
2814
2815 for ( i = 0; i < 4; i++ )
2816 val = ( val << 4 ) | ( strchr( htab, buf[i] ) - htab );
2817 return val;
2818 }
2819
2820 #define MODPATH_COMP_STR_LEN \
2821 (sizeof(_dxd_exCurrentFunc->mod_path.modules [0]) * 2 + \
2822 sizeof(_dxd_exCurrentFunc->mod_path.instances[0]) * 2)
2823
2824
2825 /* compare the macro portion of two module ids
2826 */
DXCompareModuleMacroBase(Pointer id1,Pointer id2)2827 Error DXCompareModuleMacroBase(Pointer id1, Pointer id2)
2828 {
2829 int len;
2830 char *str1 = (char *)id1;
2831 char *str2 = (char *)id2;
2832
2833 if (str1 == NULL || str2 == NULL)
2834 return ERROR;
2835
2836 /* Module ID's are hexified ModPaths: <mod1><inst1><mod2><inst2>..., */
2837 /* stored from highest call level to lowest. */
2838 len = strlen(str1);
2839 if ( len < MODPATH_COMP_STR_LEN )
2840 return ERROR;
2841
2842 return ((strncmp(str1, str2,
2843 len - MODPATH_COMP_STR_LEN) == 0) ? OK : ERROR);
2844 }
2845
2846 /* obtain a string for the i'th component of the module ID (e.g. "GetLocal")
2847 */
DXGetModuleComponentName(Pointer id,int index)2848 const char *DXGetModuleComponentName(Pointer id, int index)
2849 {
2850 int i;
2851 int len = strlen(id);
2852 int num_comp;
2853 char *str = (char *)id;
2854
2855 /* First, determine which component. Support Python-like negative */
2856 /* indices to count back from the end. */
2857 if ( !str || ( len % MODPATH_COMP_STR_LEN ) != 0 )
2858 return NULL;
2859
2860 num_comp = strlen(str) / MODPATH_COMP_STR_LEN;
2861
2862 if (( index >= num_comp ) || ( index < -num_comp ))
2863 return NULL;
2864 else if ( index >= 0 )
2865 i = index;
2866 else
2867 i = num_comp + index;
2868 i *= MODPATH_COMP_STR_LEN;
2869
2870 return *FETCH_LIST( *mod_name_str_table, hextoint16( &str[i] ) );
2871 }
2872
2873
_dxf_ExPathCacheStringLen(ModPath * path)2874 static int _dxf_ExPathCacheStringLen( ModPath *path )
2875 {
2876 return (path->num_comp * MODPATH_COMP_STR_LEN);
2877 }
2878
2879
_dxf_ExPathToCacheStringBuf(ModPath * path,char * path_str)2880 static void _dxf_ExPathToCacheStringBuf( ModPath *path, char *path_str )
2881 {
2882 int32 i;
2883 char *p = path_str;
2884
2885 for ( i = path->num_comp-1; i >= 0; i-- ) {
2886 p = int16tohex( p, path->modules[i] );
2887 p = int16tohex( p, path->instances[i] );
2888 }
2889 }
2890
_dxf_ExPathToCacheString(ModPath * path)2891 char *_dxf_ExPathToCacheString( ModPath *path )
2892 {
2893 static char str[ MAX_PATH_STR_LEN ];
2894
2895 _dxf_ExPathToCacheStringBuf( path, str );
2896 return str;
2897 }
2898
_dxf_ExCacheStrPrepend(Program * program,char * name,int instance,char * path)2899 static char *_dxf_ExCacheStrPrepend( Program *program,
2900 char *name, int instance, char *path )
2901 {
2902 static char str[ MAX_PATH_STR_LEN ];
2903 static char tmp[ MAX_PATH_STR_LEN ];
2904 char *p = str, *colon;
2905
2906 /* This oddball cache-string hacking rtn is only used in one place. */
2907
2908 /* Prepend the IDs for the module name and instance as specified. */
2909 p = int16tohex( p, _dxf_ExGraphInsertAndLookupName( program, name ) );
2910 p = int16tohex( p, instance );
2911
2912 strcpy(tmp, path);
2913 /*
2914 if (tmp[0] != '/')
2915 s = tmp;
2916 else
2917 s = tmp + 1;
2918 */
2919
2920 colon = strchr(tmp, ':');
2921 if (colon)
2922 *colon = '\0';
2923
2924 p = int16tohex( p, _dxf_ExGraphInsertAndLookupName( program, tmp+1 ));
2925
2926 if (colon)
2927 p = int16tohex( p, atoi(colon+1));
2928 else
2929 p = int16tohex( p, 0);
2930
2931 /*
2932 strcpy( p, path );
2933 */
2934 return str;
2935 }
2936
2937 #ifdef TESTING
_dxf_ExPathPrint(Program * p,gfunc * fnode,char * header)2938 static void _dxf_ExPathPrint( Program *p, gfunc *fnode, char *header )
2939 {
2940 int i;
2941 ModPath *path = &fnode->mod_path;
2942
2943 if ( header )
2944 printf( "\t%s: ", header );
2945 else
2946 printf( "\t" );
2947
2948 for ( i = path->num_comp-1; i >= 0; i-- )
2949 printf( "/%s:%d",
2950 *FETCH_LIST( *mod_name_str_table, path->modules[i] ),
2951 path->instances[i] );
2952 printf( "\n" );
2953 }
2954 #endif
2955
_dxf_ExPathSet(Program * p,char fname[],int instance,gfunc * fnode)2956 static void _dxf_ExPathSet( Program *p, char fname[], int instance, gfunc *fnode )
2957 {
2958 uint32 fname_key;
2959 ModPath *path = &fnode->mod_path;
2960
2961 /* Note, we store paths in reverse order in mod_path, */
2962 /* so prepend is actually append. */
2963 fname_key = _dxf_ExGraphInsertAndLookupName( p, fname );
2964
2965 path->modules [ 0 ] = fname_key;
2966 path->instances[ 0 ] = instance;
2967 path->num_comp = 1;
2968
2969 #ifdef TESTING
2970 _dxf_ExPathPrint( p, fnode, "_dxf_ExPathSet" );
2971 #endif
2972 }
2973
2974
2975
2976
_dxf_ExPathPrepend(Program * p,char fname[],int instance,gfunc * fnode)2977 static void _dxf_ExPathPrepend( Program *p, char fname[], int instance,
2978 gfunc *fnode )
2979 {
2980 uint32 fname_key;
2981 ModPath *path = &fnode->mod_path;
2982
2983 /* Note, we store paths in reverse order in mod_path, */
2984 /* so prepend is fast (it's an append). */
2985 if ( path->num_comp >= ARRAY_LEN( path->modules ) )
2986 {
2987 DXSetError(ERROR_NOT_IMPLEMENTED, "gfunc execution path too deep");
2988 printf( "gfunc execution path too deep: %d", path->num_comp );
2989 _dxf_ExDie("gfunc execution path too deep");
2990 return;
2991 }
2992
2993 fname_key = _dxf_ExGraphInsertAndLookupName( p, fname );
2994
2995 path->modules [ path->num_comp ] = fname_key;
2996 path->instances[ path->num_comp ] = instance;
2997 path->num_comp++;
2998
2999 #ifdef TESTING
3000 _dxf_ExPathPrint( p, fnode, "_dxf_ExPathPrepend" );
3001 #endif
3002 }
3003
_dxf_ExPathAppend(Program * p,char fname[],int instance,gfunc * fnode)3004 static void _dxf_ExPathAppend( Program *p, char fname[], int instance,
3005 gfunc *fnode )
3006 {
3007 uint32 fname_key;
3008 ModPath *path = &fnode->mod_path;
3009
3010 /* Note, we store paths in reverse order in mod_path, */
3011 /* so append is really a prepend. */
3012 if ( path->num_comp >= ARRAY_LEN( path->modules ) )
3013 {
3014 DXSetError(ERROR_NOT_IMPLEMENTED, "gfunc execution path too deep");
3015 printf( "gfunc execution path too deep: %d", path->num_comp );
3016 _dxf_ExDie("gfunc execution path too deep");
3017 return;
3018 }
3019
3020 fname_key = _dxf_ExGraphInsertAndLookupName( p, fname );
3021
3022 memmove( &path->modules[1], &path->modules[0],
3023 sizeof(path->modules[0]) * path->num_comp );
3024
3025 path->modules [ 0 ] = fname_key;
3026 path->instances[ 0 ] = instance;
3027 path->num_comp++;
3028
3029 #ifdef TESTING
3030 _dxf_ExPathPrint( p, fnode, "_dxf_ExPathAppend" );
3031 #endif
3032 }
3033
_dxf_ExPathsEqual(ModPath * p1,ModPath * p2)3034 int _dxf_ExPathsEqual( ModPath *p1, ModPath *p2 )
3035 {
3036 int cmp;
3037
3038 /* We use the same string table for all ModPaths, so this comparison */
3039 /* is quick and simple. f */
3040 cmp = ( p1->num_comp == p2->num_comp ) &&
3041 ( memcmp( p1->modules, p2->modules,
3042 sizeof(p1->modules[0]) * p1->num_comp ) == 0 ) &&
3043 ( memcmp( p1->instances, p2->instances,
3044 sizeof(p1->instances[0]) * p1->num_comp ) == 0 );
3045 return cmp;
3046 }
3047
_dxf_ExPathCopy(ModPath * dest,ModPath * src)3048 void _dxf_ExPathCopy( ModPath *dest, ModPath *src )
3049 {
3050 memcpy( dest, src, sizeof( *dest ) );
3051 }
3052
_dxf_ExGFuncPathToString(gfunc * fnode)3053 char *_dxf_ExGFuncPathToString( gfunc *fnode )
3054 {
3055 return _dxf_ExPathToString( &fnode->mod_path );
3056 }
3057
_dxf_ExGFuncPathToStringBuf(gfunc * fnode,char * path_str)3058 static void _dxf_ExGFuncPathToStringBuf( gfunc *fnode, char *path_str )
3059 {
3060 _dxf_ExPathToStringBuf( &fnode->mod_path, path_str );
3061 }
3062
_dxf_ExGFuncPathToCacheStringBuf(gfunc * fnode,char * path_str)3063 static void _dxf_ExGFuncPathToCacheStringBuf( gfunc *fnode, char *path_str )
3064 {
3065 _dxf_ExPathToCacheStringBuf( &fnode->mod_path, path_str );
3066 }
3067
_dxf_ExGFuncPathToCacheString(gfunc * fnode)3068 char *_dxf_ExGFuncPathToCacheString( gfunc *fnode )
3069 {
3070 return _dxf_ExPathToCacheString( &fnode->mod_path );
3071 }
3072
3073