static void initPeriodic(void) { dbMenu *pmenu = dbFindMenu(pdbbase, "menuScan"); double quantum = epicsThreadSleepQuantum(); int i; if (!pmenu) { errlogPrintf("initPeriodic: menuScan not present\n"); return; } nPeriodic = pmenu->nChoice - SCAN_1ST_PERIODIC; papPeriodic = dbCalloc(nPeriodic, sizeof(periodic_scan_list*)); periodicTaskId = dbCalloc(nPeriodic, sizeof(void *)); for (i = 0; i < nPeriodic; i++) { periodic_scan_list *ppsl = dbCalloc(1, sizeof(periodic_scan_list)); const char *choice = pmenu->papChoiceValue[i + SCAN_1ST_PERIODIC]; double number; char *unit; int status = epicsParseDouble(choice, &number, &unit); ppsl->scan_list.lock = epicsMutexMustCreate(); ellInit(&ppsl->scan_list.list); ppsl->name = choice; if (status || number == 0) { errlogPrintf("initPeriodic: Bad menuScan choice '%s'\n", choice); ppsl->period = i; } else if (!*unit || !epicsStrCaseCmp(unit, "second") || !epicsStrCaseCmp(unit, "seconds")) { ppsl->period = number; } else if (!epicsStrCaseCmp(unit, "minute") || !epicsStrCaseCmp(unit, "minutes")) { ppsl->period = number * 60; } else if (!epicsStrCaseCmp(unit, "hour") || !epicsStrCaseCmp(unit, "hours")) { ppsl->period = number * 60 * 60; } else if (!epicsStrCaseCmp(unit, "Hz") || !epicsStrCaseCmp(unit, "Hertz")) { ppsl->period = 1 / number; } else { errlogPrintf("initPeriodic: Bad menuScan choice '%s'\n", choice); ppsl->period = i; } number = ppsl->period / quantum; if ((ppsl->period < 2 * quantum) || (number / floor(number) > 1.1)) { errlogPrintf("initPeriodic: Scan rate '%s' is not achievable.\n", choice); } ppsl->scanCtl = ctlPause; ppsl->loopEvent = epicsEventMustCreate(epicsEventEmpty); papPeriodic[i] = ppsl; } }
epicsShareFunc int epicsParseFloat(const char *str, float *to, char **units) { double value, abs; int status = epicsParseDouble(str, &value, units); if (status) return status; abs = fabs(value); if (value > 0 && abs <= FLT_MIN) return S_stdlib_underflow; if (finite(value) && abs >= FLT_MAX) return S_stdlib_overflow; *to = (float) value; return 0; }
/* postfix * * convert an infix expression to a postfix expression */ epicsShareFunc long postfix(const char *psrc, char *pout, short *perror) { ELEMENT stack[80]; ELEMENT *pstacktop = stack; const ELEMENT *pel; int operand_needed = TRUE; int runtime_depth = 0; int cond_count = 0; char * const pdest = pout; char *pnext; if (psrc == NULL || *psrc == '\0' || pout == NULL || perror == NULL) { if (perror) *perror = CALC_ERR_NULL_ARG; if (pout) *pout = END_EXPRESSION; return -1; } /* place the expression elements into postfix */ *pout = END_EXPRESSION; *perror = CALC_ERR_NONE; while (get_element(operand_needed, &psrc, &pel)) { switch (pel->type) { case OPERAND: *pout++ = pel->code; runtime_depth += pel->runtime_effect; operand_needed = FALSE; break; case LITERAL_OPERAND: runtime_depth += pel->runtime_effect; psrc -= strlen(pel->name); if (pel->code == LITERAL_DOUBLE) { double lit_d; epicsInt32 lit_i; if (epicsParseDouble(psrc, &lit_d, &pnext)) { *perror = CALC_ERR_BAD_LITERAL; goto bad; } psrc = pnext; lit_i = (int) lit_d; if (lit_d != (double) lit_i) { *pout++ = pel->code; memcpy(pout, &lit_d, sizeof(double)); pout += sizeof(double); } else { *pout++ = LITERAL_INT; memcpy(pout, &lit_i, sizeof(epicsInt32)); pout += sizeof(epicsInt32); } } else { epicsUInt32 lit_ui; assert(pel->code == LITERAL_INT); if (epicsParseUInt32(psrc, &lit_ui, 0, &pnext)) { *perror = CALC_ERR_BAD_LITERAL; goto bad; } psrc = pnext; *pout++ = LITERAL_INT; memcpy(pout, &lit_ui, sizeof(epicsInt32)); pout += sizeof(epicsInt32); } operand_needed = FALSE; break; case STORE_OPERATOR: if (pout == pdest || pstacktop > stack || *--pout < FETCH_A || *pout > FETCH_L) { *perror = CALC_ERR_BAD_ASSIGNMENT; goto bad; } /* Convert fetch into a store on the stack */ *++pstacktop = *pel; pstacktop->code = STORE_A + *pout - FETCH_A; runtime_depth -= 1; operand_needed = TRUE; break; case UNARY_OPERATOR: case VARARG_OPERATOR: /* Move operators of >= priority to the output */ while ((pstacktop > stack) && (pstacktop->in_stack_pri >= pel->in_coming_pri)) { *pout++ = pstacktop->code; if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; } runtime_depth += pstacktop->runtime_effect; pstacktop--; } /* Push new operator onto stack */ pstacktop++; *pstacktop = *pel; break; case BINARY_OPERATOR: /* Move operators of >= priority to the output */ while ((pstacktop > stack) && (pstacktop->in_stack_pri >= pel->in_coming_pri)) { *pout++ = pstacktop->code; if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; } runtime_depth += pstacktop->runtime_effect; pstacktop--; } /* Push new operator onto stack */ pstacktop++; *pstacktop = *pel; operand_needed = TRUE; break; case SEPERATOR: /* Move operators to the output until open paren */ while (pstacktop->name[0] != '(') { if (pstacktop <= stack+1) { *perror = CALC_ERR_BAD_SEPERATOR; goto bad; } *pout++ = pstacktop->code; if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; } runtime_depth += pstacktop->runtime_effect; pstacktop--; } operand_needed = TRUE; pstacktop->runtime_effect -= 1; break; case CLOSE_PAREN: /* Move operators to the output until matching paren */ while (pstacktop->name[0] != '(') { if (pstacktop <= stack+1) { *perror = CALC_ERR_PAREN_NOT_OPEN; goto bad; } *pout++ = pstacktop->code; if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; } runtime_depth += pstacktop->runtime_effect; pstacktop--; } pstacktop--; /* remove ( from stack */ /* if there is a vararg operator before the opening paren, it inherits the (opening) paren's stack effect */ if ((pstacktop > stack) && pstacktop->type == VARARG_OPERATOR) { pstacktop->runtime_effect = (pstacktop+1)->runtime_effect; /* check for no arguments */ if (pstacktop->runtime_effect > 0) { *perror = CALC_ERR_INCOMPLETE; goto bad; } } break; case CONDITIONAL: /* Move operators of > priority to the output */ while ((pstacktop > stack) && (pstacktop->in_stack_pri > pel->in_coming_pri)) { *pout++ = pstacktop->code; if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; } runtime_depth += pstacktop->runtime_effect; pstacktop--; } /* Add new element to the output */ *pout++ = pel->code; runtime_depth += pel->runtime_effect; /* For : operator, also push COND_END code to stack */ if (pel->name[0] == ':') { if (--cond_count < 0) { *perror = CALC_ERR_CONDITIONAL; goto bad; } pstacktop++; *pstacktop = *pel; pstacktop->code = COND_END; pstacktop->runtime_effect = 0; } else { cond_count++; } operand_needed = TRUE; break; case EXPR_TERMINATOR: /* Move everything from stack to the output */ while (pstacktop > stack) { if (pstacktop->name[0] == '(') { *perror = CALC_ERR_PAREN_OPEN; goto bad; } *pout++ = pstacktop->code; if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; } runtime_depth += pstacktop->runtime_effect; pstacktop--; } if (cond_count != 0) { *perror = CALC_ERR_CONDITIONAL; goto bad; } if (runtime_depth > 1) { *perror = CALC_ERR_TOOMANY; goto bad; } operand_needed = TRUE; break; default: *perror = CALC_ERR_INTERNAL; goto bad; } if (runtime_depth < 0) { *perror = CALC_ERR_UNDERFLOW; goto bad; } if (runtime_depth >= CALCPERFORM_STACK) { *perror = CALC_ERR_OVERFLOW; goto bad; } } if (*psrc != '\0') { *perror = CALC_ERR_SYNTAX; goto bad; } /* Move everything from stack to the output */ while (pstacktop > stack) { if (pstacktop->name[0] == '(') { *perror = CALC_ERR_PAREN_OPEN; goto bad; } *pout++ = pstacktop->code; if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; } runtime_depth += pstacktop->runtime_effect; pstacktop--; } *pout = END_EXPRESSION; if (cond_count != 0) { *perror = CALC_ERR_CONDITIONAL; goto bad; } if (operand_needed || runtime_depth != 1) { *perror = CALC_ERR_INCOMPLETE; goto bad; } return 0; bad: *pdest = END_EXPRESSION; return -1; }