/*-------------------------------------------------------------- Evaluate arguments before building into the given data type. Use in returning calculations using local variables from a FUN. Some arguments may be "unevaluated" by using an AS_IS(arg). This can be used to pass back expressions evaluated in an outer FUN. So BUILD_xxx(x,y,...) is the same as MAKE_xxx(AS_IS(x),AS_IS(y),...). */ int Tdi1Make(int opcode, int narg, struct descriptor *list[], struct descriptor_xd *out_ptr) { int status = 1; struct descriptor *ptr; int j, k, modif; struct TdiFunctionStruct *fun_ptr = (struct TdiFunctionStruct *)&TdiRefFunction[opcode]; DESCRIPTOR_FUNCTION(build, 0, 255); struct descriptor_xd xd[255]; unsigned char modif_c; unsigned short modif_s; build.length = 0; build.dtype = fun_ptr->o1; build.ndesc = (unsigned char)narg; if (fun_ptr->o2 != fun_ptr->o1) { status = TdiGetLong(list[0], &modif); switch (fun_ptr->o2) { case DTYPE_BU: build.length = 1; modif_c = (unsigned char)modif; build.pointer = &modif_c; break; case DTYPE_WU: build.length = 2; modif_s = (unsigned short)modif; build.pointer = (unsigned char *)&modif_s; break; default: status = TdiINVDTYDSC; break; } --build.ndesc; j = 1; } else j = 0; for (k = 0; j < narg && status & 1; ++j, ++k) { xd[k] = EMPTY_XD; if (list[j]) status = TdiEvaluate(list[j], &xd[k] MDS_END_ARG); ptr = (struct descriptor *)&xd[k]; while (ptr && ptr->dtype == DTYPE_DSC) ptr = (struct descriptor *)ptr->pointer; if (ptr && ptr->dtype == DTYPE_MISSING) ptr = 0; build.arguments[k] = ptr; } if (status & 1) status = MdsCopyDxXd((struct descriptor *)&build, out_ptr); for (; --k >= 0;) MdsFree1Dx(&xd[k], NULL); return status; }
/*-------------------------------------------------------------- Make a class-R record of pointers. Standard generic call: result = BUILD_xxxx(arg1,...) The first argument is evaluated for BUILD_CONDITION (byte modifier) BUILD_DEPENDENCY (byte op_code) BUILD_DISPATCH (byte type) BUILD_FUNCTION (word opcode) BUILD_CALL (byte dtype) and the remaining arguments are shifted by one. Each argument is NOT evaluated to get "real" data or to do further builds: BUILD_ACTION(BUILD_DISPATCH(...),BUILD_TASK(...)) Limitations: 254 arguments in some uses plus 1 for output. No type checking at build time. No arrays of descriptors. */ int Tdi1Build(int opcode, int narg, struct descriptor *list[], struct descriptor_xd *out_ptr) { int status = 1; struct descriptor *ptr; struct TdiFunctionStruct *fun_ptr = (struct TdiFunctionStruct *)&TdiRefFunction[opcode]; DESCRIPTOR_FUNCTION(build, 0, 255); int j, k, modif; unsigned short modif_s; unsigned char modif_c; build.length = 0; build.dtype = fun_ptr->o1; build.ndesc = (unsigned char)narg; if (fun_ptr->o2 != fun_ptr->o1) { status = TdiGetLong(list[0], &modif); switch (fun_ptr->o2) { case DTYPE_BU: build.length = 1; modif_c = (unsigned char)modif; build.pointer = &modif_c; break; case DTYPE_WU: build.length = 2; modif_s = (unsigned short)modif; build.pointer = (unsigned char *)&modif_s; break; default: status = TdiINVDTYDSC; break; } --build.ndesc; j = 1; } else j = 0; for (k = 0; j < narg; ++j, ++k) { ptr = list[j]; while (ptr && ptr->dtype == DTYPE_DSC) ptr = (struct descriptor *)ptr->pointer; build.arguments[k] = ptr; } if (status & 1) status = MdsCopyDxXd((struct descriptor *)&build, out_ptr); return status; }
int TdiGetSlope( struct descriptor_window *window_ptr, struct descriptor_slope *slope_ptr, struct descriptor_xd *out_ptr) { struct descriptor_xd xat0 = EMPTY_XD; int ndesc = slope_ptr->ndesc; int nseg = (ndesc + 2)/3; int status=0, jseg, kseg; int k0, k1, left, right; struct descriptor k0_dsc = {sizeof(int),DTYPE_L,CLASS_S,0}; struct descriptor k1_dsc = {sizeof(int),DTYPE_L,CLASS_S,0}; k0_dsc.pointer = (char *)&k0; k1_dsc.pointer = (char *)&k1; /***************** Get window limits. *****************/ if (ndesc <= 0) status = TdiMISS_ARG; else if (window_ptr && window_ptr->startidx) status = TdiGetLong(window_ptr->startidx, &k0); else k0 = -HUGE; if (status & 1 && window_ptr && window_ptr->endingidx) status = TdiGetLong(window_ptr->endingidx, &k1); else k1 = HUGE; if (status & 1 && window_ptr) status = TdiData(window_ptr->value_at_idx0, &xat0); else if (status & 1) status = TdiData(window_ptr, &xat0); /******************************************** Single slope with no begin or end. X[i] = (dX/di)*RANGE(startidx,endidx) + X[0]. ********************************************/ if ((ndesc<2 || !slope_ptr->segment[0].begin) && (ndesc<3 || !slope_ptr->segment[0].ending)) { if (status & 1) status = TdiRange(&k0_dsc, &k1_dsc, out_ptr); if (status & 1) status = TdiMultiply(slope_ptr->segment[0].slope, out_ptr, out_ptr); if (status & 1 && xat0.pointer) status = TdiAdd(&xat0, out_ptr, out_ptr); } /********************************* Multiple segments. Get each slope, begin, and end. May omit first begin and last end. *********************************/ else if (status & 1) { struct descriptor left_dsc = {sizeof(left),DTYPE_L,CLASS_S,0}; struct descriptor right_dsc = {sizeof(right),DTYPE_L,CLASS_S,0}; DESCRIPTOR_RANGE(ramp, 0, 0, 0); struct descriptor_xd (*pbegin)[], (*pend)[]=0, (*pslope)[]=0, *(*pvlist)[]=0, tmp1; int (*pcnt)[]=0; int virt = (sizeof(struct descriptor_xd)*3 + sizeof(struct descriptor_xd *))*nseg + sizeof(int)*(nseg + 1); left_dsc.pointer = (char *)&left; right_dsc.pointer = (char *)&right; ramp.begin = &left_dsc; ramp.ending = &right_dsc; /************************************** Dynamic allocation of descriptors. Memory for begin[nseg], end[nseg], slope[nseg], *vlist[nseg], cnt[nseg+1]. **************************************/ status = (pbegin = malloc(virt)) != NULL; if (status & 1) { pend = (struct descriptor_xd (*)[])&(*pbegin)[nseg]; pslope = (struct descriptor_xd (*)[])&(*pend)[nseg]; pvlist = (struct descriptor_xd *(*)[])&(*pslope)[nseg]; pcnt = (int (*)[])&(*pvlist)[nseg]; } /************************************************************************************* Find the number of points in interior segments, if any. For 1ms sampling, begin=0s, 1000 points, end=.999s, no sample is taken at 1s. Ideal expression: FLOOR((end - begin)/slope + 1) but not less than zero. WARNING: round-off may change by +-1, could change next by -+1 if end(j)==begin(j+1). WARNING: to prevent swings, ASSUME that divisor is close and round. Must be exact int. Expression: NINT((end - begin)/slope + 1) *************************************************************************************/ tmp1 = EMPTY_XD; for (jseg = 0; jseg < nseg; ++jseg) { (*pslope)[jseg] = (*pbegin)[jseg] = (*pend)[jseg] = EMPTY_XD; if (status & 1) status = TdiEvaluate(slope_ptr->segment[jseg].slope, &(*pslope)[jseg]); if (status & 1 && jseg*3+1 < ndesc) status = TdiEvaluate(slope_ptr->segment[jseg].begin, &(*pbegin)[jseg]); if (status & 1 && jseg*3+2 < ndesc) status = TdiEvaluate(slope_ptr->segment[jseg].ending, &(*pend)[jseg]); if (jseg == 0 && !slope_ptr->segment[0].begin) {(*pcnt)[1] = HUGE; continue;} if (jseg == nseg-1 && !slope_ptr->segment[jseg].ending) {(*pcnt)[nseg] = HUGE; continue;} if (status & 1) status = TdiSubtract((*pend)[jseg].pointer, (*pbegin)[jseg].pointer, &tmp1); if (status & 1) status = TdiDivide(&tmp1, (*pslope)[jseg].pointer, &tmp1); if (status & 1) status = TdiNint(&tmp1, &tmp1); if (status & 1) status = TdiGetLong(&tmp1, &left); (*pcnt)[jseg+1] = MAX(left + 1, 0); } /******************************************** Find the segment with value at index 0. Use first segment where expression is true: (0 LE slope[0]) EQV (x[0] LT begin[kseg+1]]). WARNING use .pointer to not free it. ********************************************/ if (status & 1) status = TdiLe(0, (*pslope)[0].pointer, &tmp1); if (status & 1) status = TdiGetLong(&tmp1, &left); for (kseg = 0; status & 1 && kseg < nseg-1; ++kseg) { status = TdiLt(xat0.pointer, (*pbegin)[kseg+1].pointer, &tmp1); if (status & 1) status = TdiGetLong(&tmp1, &right); if (left == right) break; } /******************************************** With index 0 in kseg, what is index at begin? left = (begin[kseg] - xat0)/slope[kseg] right = (end[0] - xat0)/slope[0]+1 for kseg=0. Trigger time xat0 implies next clock is at index 0, thus round down, more negative. Then adjust and accumulate counts. ********************************************/ if (kseg == 0 && !slope_ptr->segment[0].begin) { if (status & 1) status = TdiSubtract((*pend)[0].pointer, &xat0, &tmp1); if (status & 1) status = TdiDivide(&tmp1, (*pslope)[0].pointer, &tmp1); if (status & 1) status = TdiGetLong(&tmp1, &right); (*pcnt)[0] = MAX(right + 1, 0) - (*pcnt)[1]; } else { /******************************************* To make FLOOR work, must be floating divide. Generally, result is a negative number. *******************************************/ if (status & 1) status = TdiSubtract((*pbegin)[kseg].pointer, &xat0, &tmp1); if (status & 1) status = TdiFloat(&tmp1, &tmp1); if (status & 1) status = TdiDivide(&tmp1, (*pslope)[kseg].pointer, &tmp1); if (status & 1) status = TdiFloor(&tmp1, &tmp1); if (status & 1) status = TdiGetLong(&tmp1, &left); /*************************************** Definition of kseg gives cnt[kseg] <= 0. Check that cnt[kseg+1] >= 0. For xat0 near start[kseg+1], get cnt[kseg+1] = 0. ***************************************/ (*pcnt)[0] = MAX(left, -(*pcnt)[kseg+1]); for (jseg = kseg; --jseg >= 0;) (*pcnt)[0] -= (*pcnt)[jseg+1]; } for (jseg = 0; jseg < nseg; ++jseg) (*pcnt)[jseg+1] += (*pcnt)[jseg]; if (k0 < (*pcnt)[0]) k0 = (*pcnt)[0]; if (k1 >= (*pcnt)[nseg]) k1 = (*pcnt)[nseg] - 1; /******************************** For each segment generate result. ASSUMES ramp < 0 is 0 elements. [*:0] * slope[0] + end[0] or [0:*] * slope[jseg] + begin[jseg] Reuse slope as segment dsc. ********************************/ for (jseg = nseg; --jseg >= 0;) { left = MAX(k0 - (*pcnt)[jseg], 0); right = MIN((*pcnt)[jseg+1] - 1, k1) - (*pcnt)[jseg]; if (left > right) (*pvlist)[jseg] = 0; else if (jseg == 0 && !slope_ptr->segment[0].begin) { left -= (*pcnt)[1] - (*pcnt)[0] - 1; right -= (*pcnt)[1] - (*pcnt)[0] - 1; if (status & 1) status = TdiMultiply(&ramp, &(*pslope)[0], &tmp1); if (status & 1) status = TdiAdd(&tmp1, &(*pend)[0], &(*pslope)[0]); (*pvlist)[0] = &(*pslope)[0]; } else { if (status & 1) status = TdiMultiply(&ramp, &(*pslope)[jseg], &tmp1); if (status & 1) status = TdiAdd(&tmp1, &(*pbegin)[jseg], &(*pslope)[jseg]); (*pvlist)[jseg] = &(*pslope)[jseg]; } } /************************ Make segments into whole. ************************/ if (status & 1) status = Tdi1Vector(0, nseg, (*pvlist), out_ptr); MdsFree1Dx(&tmp1, NULL); for (jseg = nseg; --jseg >= 0;) { MdsFree1Dx(&(*pslope)[jseg], NULL); MdsFree1Dx(&(*pbegin)[jseg], NULL); MdsFree1Dx(&(*pend)[jseg], NULL); } if (pbegin != NULL) free(pbegin); } MdsFree1Dx(&xat0, NULL); /********************************************* When first index is not 0, we must set bounds. *********************************************/ if (window_ptr && status & 1 && k0 != 0) { DESCRIPTOR_RANGE(range, 0, 0, 0); range.begin = &k0_dsc; range.ending = &k1_dsc; status = TdiSetRange(&range, out_ptr, out_ptr); } return status; }
int Tdi1GetDbi(int opcode, int narg, struct descriptor *list[], struct descriptor_xd *out_ptr) { int status = 1; struct descriptor_d string = { 0, DTYPE_T, CLASS_D, 0 }; struct descriptor_xd tmp = EMPTY_XD; struct item *key_ptr = 0; int index; DBI_ITM lst[] = { {sizeof(index), DbiINDEX, 0, 0} , EOL, EOL }; lst[0].pointer = (unsigned char *)&index; /********************** String of item to find. **********************/ status = TdiData(list[0], &tmp MDS_END_ARG); if (status & 1) status = TdiUpcase(&tmp, &string MDS_END_ARG); if (status & 1) { key_ptr = (struct item *)bsearch(&string, table, numtab, siztab, (int (*)(const void *, const void *)) compare); if (key_ptr == 0) status = TdiBAD_INDEX; } StrFree1Dx(&string); MdsFree1Dx(&tmp, NULL); /********************************** Somebody might want others in pool. **********************************/ if (status & 1 && narg > 1) status = TdiGetLong(list[1], &index); else index = 0; /*********************** Get the item asked for. Fixed length or varying. ***********************/ if (status & 1) { lst[1].code = key_ptr->item_code; if ((lst[1].buffer_length = key_ptr->item_length) != 0) { status = MdsGet1DxS((unsigned short *)&lst[1].buffer_length, &key_ptr->item_dtype, out_ptr); if (status & 1) { lst[1].pointer = (unsigned char *)out_ptr->pointer->pointer; status = TreeGetDbi(lst); } } else { lst[1].buffer_length = 0; lst[1].pointer = NULL; status = TreeGetDbi(lst); if (status & 1) { struct descriptor ans = { 0, DTYPE_T, CLASS_S, 0 }; if (lst[1].pointer) { ans.length = strlen((char *)lst[1].pointer); ans.pointer = (char *)lst[1].pointer; } status = MdsCopyDxXd(&ans, out_ptr); if (ans.pointer) TreeFree(ans.pointer); } } } return status; }
int Tdi1Using(int opcode, int narg, struct descriptor *list[], struct descriptor_xd *out_ptr) { int status = 1; void *ctx; int reset_ctx = 0; int nid, shot, stat1; struct descriptor def = { 0, DTYPE_T, CLASS_D, 0 }, expt = def; unsigned char omits[] = { DTYPE_PATH, 0 }; /********************** Evaluate with current. Use current if omitted. Must get expt if shot. **********************/ if (narg > 1 && status & 1) { if (list[1]) { struct descriptor_xd xd = EMPTY_XD; status = TdiGetData(omits, list[1], &xd); if (status & 1 && xd.pointer) switch (xd.pointer->dtype) { case DTYPE_T: case DTYPE_PATH: status = StrCopyDx(&def, xd.pointer); break; default: status = TdiINVDTYDSC; break; } MdsFree1Dx(&xd, NULL); } if (!list[1] || def.length == 0) { DBI_ITM def_itm[] = { {0, DbiDEFAULT, 0, 0} , EOL }; status = TreeGetDbi(def_itm); if (def_itm[0].pointer == NULL) { STATIC_CONSTANT DESCRIPTOR(top, "\\TOP"); StrCopyDx(&def, &top); status = 1; } else { unsigned short len = (unsigned short)strlen((char *)def_itm[0].pointer); StrCopyR(&def, &len, def_itm[0].pointer); TreeFree(def_itm[0].pointer); } if (status & 1) { stat1 = StrPosition(&def, &coloncolon, 0) + 1; status = StrRight(&def, &def, &stat1); } if (status & 1) *def.pointer = '\\'; } } if ((narg > 2) && ((list[2] != 0) || ((narg > 3) && (list[3] != 0))) && ((status & 1) != 0)) { if (list[2]) status = TdiGetLong(list[2], &shot); else { DBI_ITM shot_itm[] = { {sizeof(shot), DbiSHOTID, 0, 0} , EOL }; shot_itm[0].pointer = (unsigned char *)&shot; status = TreeGetDbi(shot_itm); } if (status & 1) { if (narg > 3 && list[3]) status = TdiData(list[3], &expt MDS_END_ARG); else { DBI_ITM expt_itm[] = { {0, DbiNAME, 0, 0} , EOL }; status = TreeGetDbi(expt_itm); if (expt_itm[0].pointer) { unsigned short len = (unsigned short)strlen((char *)expt_itm[0].pointer); StrCopyR(&expt, &len, expt_itm[0].pointer); TreeFree(expt_itm[0].pointer); } } } /********************* Set new tree and path. Allow some rel paths. *********************/ if (status & 1) { char *tree = MdsDescrToCstring(&expt); ctx = TreeSwitchDbid(0); reset_ctx = 1; status = TreeOpen(tree, shot, 1); MdsFree(tree); } } if (narg > 1) { char *path = MdsDescrToCstring(&def); if (status & 1) status = TreeSetDefault(path, &nid); MdsFree(path); if (narg > 2) StrFree1Dx(&expt); StrFree1Dx(&def); } /*********************** Evaluate with temporary. ***********************/ if (status & 1) { struct descriptor_xd tmp = EMPTY_XD; status = TdiEvaluate(list[0], &tmp MDS_END_ARG); if (status & 1) status = MdsCopyDxXdZ((struct descriptor *)&tmp, out_ptr, NULL, fixup_nid, NULL, fixup_path, NULL); MdsFree1Dx(&tmp, NULL); } if (reset_ctx) { while (TreeClose(0, 0) & 1) ; TreeFreeDbid(TreeSwitchDbid(ctx)); } return status; }