/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include #include #include #include #include #include "pmodflags.h" #include "d.h" #include "_macro.h" #include "log.h" #include "utils.h" #include "parse.h" #include "context.h" #include "attribute.h" typedef char EXC_4[4]; static node *ExExtractAttrs(char *attrstr); static node *ExCreateAttrNode(char *attrstr, int attrval); Error _dxf_ExFunctionDone () { #if 0 char *key; int n; node **nodes = NULL; EXC_4 *strs = NULL; int i; #endif return (OK); #if 0 /* * Count up the number of defined modules. */ _dxf_ExDictionaryBeginIterate (_dxd_exMacroDict); for (n = 0; _dxf_ExDictionaryIterate (_dxd_exMacroDict, &key) != NULL; n++) ; _dxf_ExDictionaryEndIterate (_dxd_exMacroDict); /* * Get all of the modules. */ nodes = (node **) DXAllocate (n * sizeof (node *)); strs = (EXC_4 *) DXAllocate (n * sizeof (EXC_4)); if (nodes == NULL || strs == NULL) goto cleanup; ExZero (strs, n * sizeof (EXC_4)); _dxf_ExDictionaryBeginIterate (_dxd_exMacroDict); for (i = 0; i < n; i++) nodes[i] = (node *) _dxf_ExDictionaryIterate (_dxd_exMacroDict, &key); _dxf_ExDictionaryEndIterate (_dxd_exMacroDict); /* * $$$$$ When we have more time we will generate the 3 letter tags * $$$$$ for the modules here. Using the method ifdefed out below. */ cleanup: DXFree ((Pointer) nodes); DXFree ((Pointer) strs); return (OK); #endif } #if 0 Error XXXExFunctionDone () { int i, j, k, l; char led[4]; char *name; int last; /* * For each entry we create a label by first taking all of its upper * case letters and then filling in with the letters following the * last one. We then check to see whether we have a collision or * not. If we do then we keep advancing the last letter untill either * there are none left or we no longer collide. */ for (k = 0; k < uled; k++) { name = leds[k].name; led[0] = led[1] = led[2] = led[3] = '\000'; for (i = 0, j = 0, last = 0; j < 3 && name[i] != '\000'; i++) { if (isupper (name[i])) { last = i; led[j++] = name[i]; } } retry: for (i = last + 1; j < 3 && name[i] != '\000'; i++) { last = i; led[j++] = name[i]; } for (l = 0; name[last] && l < k; l++) { if (! strcmp (led, leds[l].led)) { led[--j] = '\000'; goto retry; } } } } #endif DXAddMacro (node *macro) { node *par; int nin; int nout; int ret; if (macro == NULL) { DXWarning ("#4640"); return (-1); } /* Count the number of input and output parameters */ for (nin = 0, par = macro->v.macro.in; par; par = par->next, nin++) ; for (nout = 0, par = macro->v.macro.out; par; par = par->next, nout++) ; macro->v.macro.nin = nin; macro->v.macro.nout = nout; ret = _dxf_ExMacroInsert (macro->v.macro.id->v.id.id, (EXObj) macro); return (ret); } /* * the non-varargs version of DXAddModule. * */ Error DXAddModuleV (char *name, PFI func, int flags, int nin, char *inlist[], int nout, char *outlist[], char *exec, char *host) { int n; char *par; int i; node *module; node *id; node *list; int ret; char *sname; char *attrstart; int argcnt; sname = _dxf_ExCopyString (name); module = _dxf_ExPCreateNode (NT_MODULE); module->v.module.id = _dxf_ExPCreateId (sname); module->v.module.def.func = func; module->v.module.flags = flags; module->v.module.varargs = FALSE; /* * handle inputs. * new code added to optionally prepend private inputs, * then the existing code which adds one input per input parm * in the addmodule call, * then more new code to optionally append more private inputs. */ argcnt = 0; list = NULL; /* * if the module is outboard, you need five extra hidden inputs * to the module: the executable file, the host machine name, the * module flags, and the number of inputs and outputs to the * outboard module. */ if (flags & MODULE_OUTBOARD) { id = _dxf_ExPCreateId (_dxf_ExCopyString ("_outboard_name")); LIST_APPEND (list, id); argcnt++; id = _dxf_ExPCreateId (_dxf_ExCopyString ("_outboard_host")); LIST_APPEND (list, id); argcnt++; id = _dxf_ExPCreateId (_dxf_ExCopyString ("_outboard_flags")); LIST_APPEND (list, id); argcnt++; id = _dxf_ExPCreateId (_dxf_ExCopyString ("_outboard_inputs")); LIST_APPEND (list, id); argcnt++; id = _dxf_ExPCreateId (_dxf_ExCopyString ("_outboard_outputs")); LIST_APPEND (list, id); argcnt++; module->v.module.prehidden = 5; } /* Get the input names */ for (i = 0; i < nin; i++) { /* * Only allow the ... construct to be the last formal in the * input declaration list. */ if (module->v.module.varargs) { DXWarning ("#4650", name); _dxf_ExPDestroyNode (module); return (OK); } par = inlist[i]; if (! strcmp (par, "...")) { module->v.module.varargs = TRUE; continue; /* Don't save ... as a formal */ } /* * look for parameter attributes: parmname[attr:val,attr:val] * and create an attribute node associated with the input parm. */ if (attrstart = strchr (par, '[')) { id = _dxf_ExPCreateId (_dxf_ExCopyStringN (par, attrstart-par)); id->attr = ExExtractAttrs (attrstart); } else { id = _dxf_ExPCreateId (_dxf_ExCopyString (par)); } LIST_APPEND (list, id); argcnt++; } /* * if the module is asynchronous, you need two extra hidden inputs * to the module: the name and the value of a private input */ if (flags & (MODULE_ASYNC | MODULE_ASYNCLOCAL)) { id = _dxf_ExPCreateId (_dxf_ExCopyString ("_asyncflag_name")); LIST_APPEND (list, id); argcnt++; id = _dxf_ExPCreateId (_dxf_ExCopyString ("_asyncflag_value")); LIST_APPEND (list, id); argcnt++; module->v.module.posthidden = 2; } module->v.module.nin = argcnt; module->v.module.in = list; /* * output section. */ /* Get the output names */ argcnt = 0; list = NULL; for (i = 0; i < nout; i++) { par = outlist[i]; /* * there isn't code here to handle varargs style outputs. * it should probably be handled at some point. */ /* * look for parameter attributes: parmname[attr:val,attr:val] * and create an attribute node associated with the output parm. */ if (attrstart = strchr (par, '[')) { id = _dxf_ExPCreateId (_dxf_ExCopyStringN (par, attrstart-par)); id->attr = ExExtractAttrs (attrstart); } else { id = _dxf_ExPCreateId (_dxf_ExCopyString (par)); } LIST_APPEND (list, id); argcnt++; } module->v.module.nout = argcnt; module->v.module.out = list; /* * now we can fill in the number of inputs and outputs. * there should be a way to pass these into any module which * has a variable number of parameters. maybe as the first input/output? */ if (flags & MODULE_OUTBOARD) { char *h = host; if (!exec || !exec[0]) { DXWarning ("#4652", name); _dxf_ExPDestroyNode (module); return (OK); } if (!h || !h[0]) h = "localhost"; /* * store the values for the first 5 inputs as the defaults. */ id = module->v.module.in; _dxf_ExEvaluateConstants (FALSE); id->v.id.dflt = _dxf_ExPCreateConst (TYPE_UBYTE, CATEGORY_REAL, strlen (exec) + 1, exec); id = id->next; id->v.id.dflt = _dxf_ExPCreateConst (TYPE_UBYTE, CATEGORY_REAL, strlen (h) + 1, h); id = id->next; id->v.id.dflt = _dxf_ExPCreateConst (TYPE_INT, CATEGORY_REAL, 1, &module->v.module.flags); id = id->next; id->v.id.dflt = _dxf_ExPCreateConst (TYPE_INT, CATEGORY_REAL, 1, &module->v.module.nin); id = id->next; id->v.id.dflt = _dxf_ExPCreateConst (TYPE_INT, CATEGORY_REAL, 1, &module->v.module.nout); _dxf_ExEvaluateConstants (TRUE); /* if outboard is persistent and this is an MP architecture, * the module must be PINNED to work correctly. */ #ifdef DXD_IS_MP if (flags & MODULE_PERSISTENT) module->v.module.flags |= MODULE_PIN; #endif if ((flags & (MODULE_ASYNC | MODULE_ASYNCLOCAL)) && !(flags & MODULE_PERSISTENT)) { DXWarning("Outboard module must be PERSISTENT to be ASYNC; ASYNC flag ignored"); /* this could be an error; for now just continue */ } } /* * check here before you add the module that the func pointer isn't null. */ if (func == NULL) { DXWarning ("#4654", name); _dxf_ExPDestroyNode (module); return (OK); } ret = _dxf_ExMacroInsert (module->v.module.id->v.id.id, (EXObj) module); /* * Now that it's in the dictionary we don't need the reference that * _dxf_ExPCreateNode put on the module any more, e.g. we have transferred * ownership from the routine to the dictionary. */ ExDelete (module); return (ret); } /* * usage: * DXAddModule (name, func, flags, nin, in1, ..., inn, nout, out1, ..., outn) * or if flags has the OUTBOARD flag set: * DXAddModule (name, func, flags, nin, in1, ..., inn, nout, out1, ..., outn, * exec, host) * * */ /*VARARGS*/ Error DXAddModule (char *name, ...) { va_list args; PFI func; int flags; int nin; char **inlist; int nout; char **outlist; char *exec; char *host; int i; va_start (args,name); func = va_arg (args,PFI); flags = va_arg (args,int); nin = va_arg (args,int); inlist = DXAllocateLocalZero(nin * sizeof(char **)); if (!inlist) return ERROR; for (i=0; iname, arg->nin, arg->in, arg->nout, arg->out)); } void DXModSetObjectInput(ModuleInput *in, char *name, Object obj) { in->name = name; in->value = obj; } void DXModSetObjectOutput(ModuleOutput *out, char *name, Object *obj) { out->name = name; out->value = obj; } Object DXModSetIntegerInput(ModuleInput *in, char *name, int n) { Object ret_array = NULL; ret_array = (Object)DXMakeInteger(n); DXModSetObjectInput(in, name, ret_array); return(ret_array); } Object DXModSetFloatInput(ModuleInput *in, char *name, float f) { Object ret_array = NULL; ret_array = (Object)DXMakeFloat(f); DXModSetObjectInput(in, name, ret_array); return(ret_array); } Object DXModSetStringInput(ModuleInput *in, char *name, char *s) { Object ret_string = NULL; ret_string = (Object)DXMakeString(s); DXModSetObjectInput(in, name, ret_string); return(ret_string); } Error CallModuleSetupTask(char *name, int nin, ModuleInput *in, int nout, ModuleOutput *out) { cm_args *cmargs = NULL; int i, ret; ret = ERROR; cmargs = DXAllocate(sizeof(cm_args)); if(cmargs == NULL) goto error_return; cmargs->name = _dxf_ExCopyString(name); if(cmargs->name == NULL) goto error_return; cmargs->nin = nin; cmargs->in = (ModuleInput *)DXAllocate(nin * sizeof(ModuleInput)); if(cmargs->in == NULL) goto error_return; for(i = 0; i < nin; i++) cmargs->in[i].name = NULL; for(i = 0; i < nin; i++) { cmargs->in[i].name = _dxf_ExCopyString(in[i].name); cmargs->in[i].value = in[i].value; } cmargs->nout = nout; cmargs->out = (ModuleOutput *)DXAllocate(nout * sizeof(ModuleOutput)); for(i = 0; i < nout; i++) { cmargs->out[i].name = NULL; cmargs->out[i].value = NULL; } for(i = 0; i < nout; i++) { cmargs->out[i].name = _dxf_ExCopyString(out[i].name); cmargs->out[i].value = (Object *)DXAllocate(sizeof(Object *)); if(cmargs->out[i].value == NULL) goto error_return; } ret = _dxf_ExRunOn(1, CallModuleTask, (Pointer)cmargs, 0); /* copy outputs to original structure. */ for(i = 0; i < nout; i++) *out[i].value = *cmargs->out[i].value; error_return: if(cmargs) { DXFree(cmargs->name); if(cmargs->in) for(i = 0; i < nin; i++) DXFree(cmargs->in[i].name); DXFree(cmargs->in); if(cmargs->out) for(i = 0; i < nout; i++) { DXFree(cmargs->out[i].name); DXFree(cmargs->out[i].value); } DXFree(cmargs->out); } DXFree(cmargs); return(ret); } Error DXCallModule(char *name, int nin, ModuleInput *in, int nout, ModuleOutput *out) { node *module; node *formal; int i; int index; int anyNamed; Object *inputs = NULL; Object *outputs = NULL; int retval = OK; int errorexit; if(exJID != 1) return(CallModuleSetupTask(name, nin, in, nout, out)); module = (node*)_dxf_ExMacroSearch(name); if (module == NULL) { DXSetError(ERROR_BAD_PARAMETER, "#8370", name); return ERROR; } if (module->type != NT_MODULE || module->v.function.def.func == NULL) { DXSetError(ERROR_BAD_PARAMETER, "#8370", name); return ERROR; } if (nin > module->v.function.nin) { DXSetError(ERROR_BAD_PARAMETER, "#8380", name, module->v.function.nin); return ERROR; } if (nout > module->v.function.nout) { DXSetError(ERROR_BAD_PARAMETER, "#8381", name, module->v.function.nout); return ERROR; } inputs = (Object*)DXAllocateLocalZero( module->v.function.nin * sizeof (Object)); outputs = (Object*)DXAllocateLocalZero( module->v.function.nout * sizeof (Object)); anyNamed = 0; for (i = 0; i < nin; ++i) { if (in[i].name == NULL) { if (anyNamed) { DXSetError(ERROR_BAD_PARAMETER, "#8390", name); retval = ERROR; goto deref; } inputs[i] = in[i].value; } else { anyNamed = 1; for (index = 0, formal = module->v.function.in; formal; formal = formal->next, ++index) { if (strcmp(in[i].name, formal->v.id.id) == 0) { inputs[index] = in[i].value; break; } } if (formal == NULL) { DXSetError(ERROR_BAD_PARAMETER, "#8400", in[i].name, name); retval = ERROR; goto deref; } } } for (i = 0; i < module->v.function.nin; ++i) if (inputs[i]) DXReference(inputs[i]); /* some modules set error when they do not want to print or exit */ /* save error exit state so we can reset after module is called. */ errorexit = DXGetErrorExit(); DXSetErrorExit(0); retval = (*module->v.function.def.func)(inputs, outputs); DXSetErrorExit(errorexit); if(retval == ERROR) { if(errorexit == 1) DXPrintError(name); else if(errorexit >= 2) DXErrorExit(name); goto deref; } anyNamed = 0; for (i = 0; i < nout; ++i) { if (out[i].name == NULL) { if (anyNamed) { DXSetError(ERROR_BAD_PARAMETER, "#8391", name); retval = ERROR; goto deref; } *out[i].value = outputs[i]; outputs[i] = NULL; } else { anyNamed = 1; for (index = 0, formal = module->v.function.out; formal; formal = formal->next, ++index) { if (strcmp(out[i].name, formal->v.id.id) == 0) { *out[i].value = outputs[index]; outputs[index] = NULL; break; } } if (formal == NULL) { DXSetError(ERROR_BAD_PARAMETER, "#8401", out[i].name, name); retval = ERROR; goto deref; } } } /* delete unused outputs */ if (outputs) { for (i = 0; i < module->v.function.nout; ++i) if (outputs[i]) DXDelete(outputs[i]); } deref: if(out) { for (i = 0; i < nout; ++i) DXReference(*out[i].value); } for (i = 0; i < module->v.function.nin; ++i) DXDelete(inputs[i]); if (out) { for (i = 0; i < nout; ++i) if (out[i].value) DXUnreference(*out[i].value); } DXFree((Pointer)inputs); DXFree((Pointer)outputs); return retval; } /* if we are redefining a module, make sure that it matches the old * definition exactly for a compiled in module, or make sure the * entry point is provided for a loadable module, or make sure it's * an outboard module. */ Error DXCompareModule(char *name, PFI func, int flags, int nin, char *inlist[], int nout, char *outlist[], char *exec, char *host) { int n; char *par; int i; node *module; node *prev_defn; node *id; node *list; int ret; char *sname; char *attrstart; int argcnt; ret = OK; /* does this add a reference? */ prev_defn = (node*)_dxf_ExMacroSearch(name); if (prev_defn == NULL) { DXSetError(ERROR_BAD_PARAMETER, "%s is not defined", name); goto error; } if (flags != prev_defn->v.function.flags) { DXSetError(ERROR_BAD_PARAMETER, "inconsistent definition of %s for %s: %d not same as %d", "flags", name, flags, prev_defn->v.function.flags); goto error; } if (nin != prev_defn->v.function.nin) { DXSetError(ERROR_BAD_PARAMETER, "inconsistent definition of %s for %s: %d not same as %d", "number of inputs", name, nin, prev_defn->v.function.nin); goto error; } if (nout != prev_defn->v.function.nout) { DXSetError(ERROR_BAD_PARAMETER, "inconsistent definition of %s for %s: %d not same as %d", "number of outputs", name, nout, prev_defn->v.function.nout); goto error; } #if 0 /* fix this to be sure the input names and attributes match what's * already been defined */ argcnt = 0; list = NULL; /* Get the input names */ for (i = 0; i < nin; i++) { /* * Only allow the ... construct to be the last formal in the * input declaration list. */ if (module->v.module.varargs) { DXWarning ("#4650", name); _dxf_ExPDestroyNode (module); return (OK); } par = inlist[i]; if (! strcmp (par, "...")) { module->v.module.varargs = TRUE; continue; /* Don't save ... as a formal */ } /* * look for parameter attributes: parmname[attr:val,attr:val] * and create an attribute node associated with the input parm. */ if (attrstart = strchr (par, '[')) { id = _dxf_ExPCreateId (_dxf_ExCopyStringN (par, attrstart-par)); id->attr = ExExtractAttrs (attrstart); } else { id = _dxf_ExPCreateId (_dxf_ExCopyString (par)); } LIST_APPEND (list, id); argcnt++; } module->v.module.nin = argcnt; module->v.module.in = list; /* * output section. */ /* Get the output names */ argcnt = 0; list = NULL; for (i = 0; i < nout; i++) { par = outlist[i]; /* there was attribute code here which i should put back * to verify the attrs match. */ LIST_APPEND (list, id); argcnt++; } module->v.module.nout = argcnt; module->v.module.out = list; #endif ExDelete (prev_defn); return OK; error: ExDelete (prev_defn); return ERROR; }