epicsShareFunc int epicsParseDouble(const char *str, double *to, char **units) { int c; char *endp; double value; while ((c = *str) && isspace(c)) ++str; errno = 0; value = epicsStrtod(str, &endp); if (endp == str) return S_stdlib_noConversion; if (errno == ERANGE) return (value == 0) ? S_stdlib_underflow : S_stdlib_overflow; while ((c = *endp) && isspace(c)) ++endp; if (c && !units) return S_stdlib_extraneous; *to = value; if (units) *units = endp; return 0; }
/* * Internal commands */ static void varHandler(const iocshVarDef *v, const char *setString) { switch(v->type) { default: fprintf(epicsGetStderr(), "Can't handle variable %s of type %d.\n", v->name, v->type); return; case iocshArgInt: break; case iocshArgDouble: break; } if(setString == NULL) { switch(v->type) { default: break; case iocshArgInt: fprintf(epicsGetStdout(), "%s = %d\n", v->name, *(int *)v->pval); break; case iocshArgDouble: fprintf(epicsGetStdout(), "%s = %g\n", v->name, *(double *)v->pval); break; } } else { switch(v->type) { default: break; case iocshArgInt: { char *endp; long ltmp = strtol(setString, &endp, 0); if((*setString != '\0') && (*endp == '\0')) *(int *)v->pval = ltmp; else fprintf(epicsGetStderr(), "Invalid integer value. Var %s not changed.\n", v->name); break; } case iocshArgDouble: { char *endp; double dtmp = epicsStrtod(setString, &endp); if((*setString != '\0') && (*endp == '\0')) *(double *)v->pval = dtmp; else fprintf(epicsGetStderr(), "Invalid double value. Var %s not changed.\n", v->name); break; } } } }
int main (int argc, char *argv[]) { int i; int result; /* CA result */ OutputT format = plain; /* User specified format */ RequestT request = get; /* User specified request type */ int isArray = 0; /* Flag for array operation */ int enumAsString = 0; /* Force ENUM values to be strings */ int count = 1; int opt; /* getopt() current option */ chtype dbrType = DBR_STRING; char *pend; EpicsStr *sbuf; double *dbuf; char *cbuf = 0; char *ebuf = 0; void *pbuf; int len = 0; int waitStatus; struct dbr_gr_enum bufGrEnum; int nPvs; /* Number of PVs */ pv* pvs; /* Array of PV structures */ LINE_BUFFER(stdout); /* Configure stdout buffering */ putenv("POSIXLY_CORRECT="); /* Behave correct on GNU getopt systems */ while ((opt = getopt(argc, argv, ":cnlhatsS#:w:p:F:")) != -1) { switch (opt) { case 'h': /* Print usage */ usage(); return 0; case 'n': /* Force interpret ENUM as index number */ enumAsNr = 1; enumAsString = 0; break; case 's': /* Force interpret ENUM as menu string */ enumAsString = 1; enumAsNr = 0; break; case 'S': /* Treat char array as (long) string */ charArrAsStr = 1; isArray = 0; break; case 't': /* Select terse output format */ format = terse; break; case 'l': /* Select long output format */ format = all; break; case 'a': /* Select array mode */ isArray = 1; charArrAsStr = 0; break; case 'c': /* Select put_callback mode */ request = callback; break; case 'w': /* Set CA timeout value */ if(epicsScanDouble(optarg, &caTimeout) != 1) { fprintf(stderr, "'%s' is not a valid timeout value " "- ignored. ('caput -h' for help.)\n", optarg); caTimeout = DEFAULT_TIMEOUT; } break; case '#': /* Array count */ if (sscanf(optarg,"%d", &count) != 1) { fprintf(stderr, "'%s' is not a valid array element count " "- ignored. ('caput -h' for help.)\n", optarg); count = 0; } break; case 'p': /* CA priority */ if (sscanf(optarg,"%u", &caPriority) != 1) { fprintf(stderr, "'%s' is not a valid CA priority " "- ignored. ('caget -h' for help.)\n", optarg); caPriority = DEFAULT_CA_PRIORITY; } if (caPriority > CA_PRIORITY_MAX) caPriority = CA_PRIORITY_MAX; break; case 'F': /* Store this for output and tool_lib formatting */ fieldSeparator = (char) *optarg; break; case '?': fprintf(stderr, "Unrecognized option: '-%c'. ('caput -h' for help.)\n", optopt); return 1; case ':': fprintf(stderr, "Option '-%c' requires an argument. ('caput -h' for help.)\n", optopt); return 1; default : usage(); return 1; } } nPvs = argc - optind; /* Remaining arg list are PV names and values */ if (nPvs < 1) { fprintf(stderr, "No pv name specified. ('caput -h' for help.)\n"); return 1; } if (nPvs == 1) { fprintf(stderr, "No value specified. ('caput -h' for help.)\n"); return 1; } nPvs = 1; /* One PV - the rest is value(s) */ epId = epicsEventCreate(epicsEventEmpty); /* Create empty EPICS event (semaphore) */ /* Start up Channel Access */ result = ca_context_create(ca_enable_preemptive_callback); if (result != ECA_NORMAL) { fprintf(stderr, "CA error %s occurred while trying " "to start channel access.\n", ca_message(result)); return 1; } /* Allocate PV structure array */ pvs = calloc (nPvs, sizeof(pv)); if (!pvs) { fprintf(stderr, "Memory allocation for channel structure failed.\n"); return 1; } /* Connect channels */ pvs[0].name = argv[optind] ; /* Copy PV name from command line */ result = connect_pvs(pvs, nPvs); /* If the connection fails, we're done */ if (result) { ca_context_destroy(); return result; } /* Get values from command line */ optind++; if (isArray) { optind++; /* In case of array skip first value (nr * of elements) - actual number of values is used */ count = argc - optind; } else { /* Concatenate the remaining line to one string * (sucks but is compatible to the former version) */ for (i = optind; i < argc; i++) { len += strlen(argv[i]); len++; } cbuf = calloc(len, sizeof(char)); if (!cbuf) { fprintf(stderr, "Memory allocation failed.\n"); return 1; } strcpy(cbuf, argv[optind]); if (argc > optind+1) { for (i = optind + 1; i < argc; i++) { strcat(cbuf, " "); strcat(cbuf, argv[i]); } } if ((argc - optind) >= 1) count = 1; argv[optind] = cbuf; } sbuf = calloc (count, sizeof(EpicsStr)); dbuf = calloc (count, sizeof(double)); if(!sbuf || !dbuf) { fprintf(stderr, "Memory allocation failed\n"); return 1; } /* ENUM? Special treatment */ if (ca_field_type(pvs[0].chid) == DBR_ENUM) { /* Get the ENUM strings */ result = ca_array_get (DBR_GR_ENUM, 1, pvs[0].chid, &bufGrEnum); result = ca_pend_io(caTimeout); if (result == ECA_TIMEOUT) { fprintf(stderr, "Read operation timed out: ENUM data was not read.\n"); return 1; } if (enumAsNr) { /* Interpret values as numbers */ for (i = 0; i < count; ++i) { dbuf[i] = epicsStrtod(*(argv+optind+i), &pend); if (*(argv+optind+i) == pend) { /* Conversion didn't work */ fprintf(stderr, "Enum index value '%s' is not a number.\n", *(argv+optind+i)); return 1; } if (dbuf[i] >= bufGrEnum.no_str) { fprintf(stderr, "Warning: enum index value '%s' may be too large.\n", *(argv+optind+i)); } } dbrType = DBR_DOUBLE; } else { /* Interpret values as strings */ for (i = 0; i < count; ++i) { epicsStrnRawFromEscaped(sbuf[i], sizeof(EpicsStr), *(argv+optind+i), sizeof(EpicsStr)); *( sbuf[i]+sizeof(EpicsStr)-1 ) = '\0'; dbrType = DBR_STRING; /* Compare to ENUM strings */ for (len = 0; len < bufGrEnum.no_str; len++) if (!strcmp(sbuf[i], bufGrEnum.strs[len])) break; if (len >= bufGrEnum.no_str) { /* Not a string? Try as number */ dbuf[i] = epicsStrtod(sbuf[i], &pend); if (sbuf[i] == pend || enumAsString) { fprintf(stderr, "Enum string value '%s' invalid.\n", sbuf[i]); return 1; } if (dbuf[i] >= bufGrEnum.no_str) { fprintf(stderr, "Warning: enum index value '%s' may be too large.\n", sbuf[i]); } dbrType = DBR_DOUBLE; } } } } else { /* Not an ENUM */ if (charArrAsStr) { dbrType = DBR_CHAR; ebuf = calloc(len, sizeof(char)); if(!ebuf) { fprintf(stderr, "Memory allocation failed\n"); return 1; } count = epicsStrnRawFromEscaped(ebuf, len, cbuf, len-1) + 1; } else { for (i = 0; i < count; ++i) { epicsStrnRawFromEscaped(sbuf[i], sizeof(EpicsStr), *(argv+optind+i), sizeof(EpicsStr)); *( sbuf[i]+sizeof(EpicsStr)-1 ) = '\0'; } dbrType = DBR_STRING; } } /* Read and print old data */ if (format != terse) { printf("Old : "); result = caget(pvs, nPvs, format, 0, 0); } /* Write new data */ if (dbrType == DBR_STRING) pbuf = sbuf; else if (dbrType == DBR_CHAR) pbuf = ebuf; else pbuf = dbuf; if (request == callback) { /* Use callback version of put */ pvs[0].status = ECA_NORMAL; /* All ok at the moment */ result = ca_array_put_callback ( dbrType, count, pvs[0].chid, pbuf, put_event_handler, (void *) pvs); } else { /* Use standard put with defined timeout */ result = ca_array_put (dbrType, count, pvs[0].chid, pbuf); } result = ca_pend_io(caTimeout); if (result == ECA_TIMEOUT) { fprintf(stderr, "Write operation timed out: Data was not written.\n"); return 1; } if (request == callback) { /* Also wait for callbacks */ waitStatus = epicsEventWaitWithTimeout( epId, caTimeout ); if (waitStatus) fprintf(stderr, "Write callback operation timed out\n"); /* retrieve status from callback */ result = pvs[0].status; } if (result != ECA_NORMAL) { fprintf(stderr, "Error occured writing data.\n"); return 1; } /* Read and print new data */ if (format != terse) printf("New : "); result = caget(pvs, nPvs, format, 0, 0); /* Shut down Channel Access */ ca_context_destroy(); return result; }
static int cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf, const iocshArg *piocshArg) { char *endp; switch (piocshArg->type) { case iocshArgInt: if (arg && *arg) { errno = 0; argBuf->ival = strtol (arg, &endp, 0); if (errno == ERANGE) { errno = 0; argBuf->ival = strtoul (arg, &endp, 0); if (errno == ERANGE) { showError(filename, lineno, "Integer '%s' out of range", arg); return 0; } } if (*endp) { showError(filename, lineno, "Illegal integer '%s'", arg); return 0; } } else { argBuf->ival = 0; } break; case iocshArgDouble: if (arg && *arg) { argBuf->dval = epicsStrtod (arg, &endp); if (*endp) { showError(filename, lineno, "Illegal double '%s'", arg); return 0; } } else { argBuf->dval = 0.0; } break; case iocshArgString: argBuf->sval = arg; break; case iocshArgPersistentString: argBuf->sval = (char *) malloc(strlen(arg) + 1); if (argBuf->sval == NULL) { showError(filename, lineno, "Out of memory"); return 0; } strcpy(argBuf->sval, arg); break; case iocshArgPdbbase: /* Argument must be missing or 0 or pdbbase */ if(!arg || !*arg || (*arg == '0') || (strcmp(arg, "pdbbase") == 0)) { if(!iocshPpdbbase || !*iocshPpdbbase) { showError(filename, lineno, "pdbbase not present"); return 0; } argBuf->vval = *iocshPpdbbase; break; } showError(filename, lineno, "Expecting 'pdbbase' got '%s'", arg); return 0; default: showError(filename, lineno, "Illegal argument type %d", piocshArg->type); return 0; } return 1; }
/* sCalcPostfix * * convert an infix expression to a postfix expression */ epicsShareFunc long sCalcPostfix(const char *psrc, unsigned char * const ppostfix, short *perror) { ELEMENT stack[80]; ELEMENT *pstacktop = stack, *ps1; const ELEMENT *pel; int operand_needed = TRUE; int runtime_depth = 0; int cond_count = 0; unsigned char *pout = ppostfix; char *pnext; double lit_d; int lit_i; char c; int handled; if (psrc == NULL || pout == NULL || perror == NULL) { if (perror) *perror = CALC_ERR_NULL_ARG; if (pout) *pout = END_EXPRESSION; return -1; } if (*psrc == '\0') { if (pout) *pout = END_EXPRESSION; return 0; } /* place the expression elements into postfix */ *pout++ = NO_STRING; *pout = END_EXPRESSION; *perror = CALC_ERR_NONE; while (get_element(operand_needed, &psrc, &pel)) { if (sCalcPostfixDebug) printf("\tget_element:%s (%s) runtime_depth=%d\n", opcodes[(int) pel->code], pel->name, runtime_depth); if (*ppostfix != USES_STRING) { switch (pel->code) { case FETCH_AA: case FETCH_BB: case FETCH_CC: case FETCH_DD: case FETCH_EE: case FETCH_FF: case FETCH_GG: case FETCH_HH: case FETCH_II: case FETCH_JJ: case FETCH_KK: case FETCH_LL: case FETCH_SVAL: case TO_STRING: case PRINTF: case BIN_WRITE: case SSCANF: case BIN_READ: case LITERAL_STRING: case SUBRANGE: case REPLACE: case A_SFETCH: case TR_ESC: case ESC: case CRC16: case MODBUS: case LRC: case AMODBUS: case XOR8: case ADD_XOR8: case LEN: *ppostfix = USES_STRING; break; default: break; } } switch (pel->type) { case OPERAND: *pout++ = pel->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pel->code]); runtime_depth += pel->runtime_effect; operand_needed = FALSE; break; case LITERAL_OPERAND: runtime_depth += pel->runtime_effect; psrc -= strlen(pel->name); lit_d = epicsStrtod(psrc, &pnext); if (pnext == psrc) { if (sCalcPostfixDebug) printf("***LITERAL_OPERAND***\n"); *perror = CALC_ERR_BAD_LITERAL; goto bad; } psrc = pnext; lit_i = lit_d; if (lit_d != (double) lit_i) { *pout++ = pel->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pel->code]); memcpy(pout, (void *)&lit_d, sizeof(double)); pout += sizeof(double); } else { *pout++ = LITERAL_INT; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) LITERAL_INT]); memcpy(pout, (void *)&lit_i, sizeof(int)); pout += sizeof(int); } operand_needed = FALSE; break; case STORE_OPERATOR: handled = 0; /* search stack for A_FETCH (@) or A_SFETCH (@@) */ for (ps1=pstacktop; ps1>stack; ps1--) { if (sCalcPostfixDebug) printf("STORE_OPERATOR:stacktop code=%s (%d)\n", opcodes[(int) ps1->code], ps1->code); if ((ps1->code == A_FETCH) || (ps1->code == A_SFETCH)) break; } if (ps1->code == A_FETCH) { handled = 1; *ps1 = *pel; ps1->code = A_STORE; } else if (ps1->code == A_SFETCH) { handled = 1; *ps1 = *pel; ps1->code = A_SSTORE; } if (handled) { /* Move operators of >= priority to the output, but stop before ps1 */ while ((pstacktop > ps1) && (pstacktop > stack) && (pstacktop->in_stack_pri >= pel->in_coming_pri)) { *pout++ = pstacktop->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pstacktop->code]); if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; if (sCalcPostfixDebug>=5) printf("put run-time effect %d to postfix\n", 1 - pstacktop->runtime_effect); } runtime_depth += pstacktop->runtime_effect; pstacktop--; } } else { /* convert FETCH_x or FETCH_xx (already posted to postfix string) */ if (pout > ppostfix && pout[-1] >= FETCH_A && pout[-1] <= FETCH_P) { if (sCalcPostfixDebug) printf("STORE_OPERATOR:pout[-1] is a scalar fetch\n"); /* Convert fetch into a store on the stack */ pout--; if (sCalcPostfixDebug>=5) printf("retracted %s from postfix\n", opcodes[(int) pout[-1]]); *++pstacktop = *pel; pstacktop->code = STORE_A + *pout - FETCH_A; } else if (pout > ppostfix && pout[-1] >= FETCH_AA && pout[-1] <= FETCH_LL) { if (sCalcPostfixDebug) printf("STORE_OPERATOR:pout[-1] is a string fetch\n"); pout--; if (sCalcPostfixDebug>=5) printf("retracted %s from postfix\n", opcodes[(int) pout[-1]]); *++pstacktop = *pel; pstacktop->code = STORE_AA + *pout - FETCH_AA; } else { if (sCalcPostfixDebug) printf("***STORE_OPERATOR***\n"); *perror = CALC_ERR_BAD_ASSIGNMENT; goto bad; } } 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 (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pstacktop->code]); if (sCalcPostfixDebug) printf("UNARY/VARARG op '%s': moved '%s' from stack\n", pel->name, pstacktop->name); if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; if (sCalcPostfixDebug>=5) printf("put run-time effect %d to postfix\n", 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 (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pstacktop->code]); if (sCalcPostfixDebug) printf("BINARY op '%s': moved '%s' from stack\n", pel->name, pstacktop->name); if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; if (sCalcPostfixDebug>=5) printf("put run-time effect %d to postfix\n", 1 - pstacktop->runtime_effect); } runtime_depth += pstacktop->runtime_effect; pstacktop--; } /* Push new operator onto stack */ pstacktop++; *pstacktop = *pel; operand_needed = TRUE; break; case SEPARATOR: /* Move operators to the output until open paren or bracket or curly */ while ((pstacktop->name[0] != '(') && (pstacktop->name[0] != '[') && (pstacktop->name[0] != '{')) { if (pstacktop <= stack+1) { if (sCalcPostfixDebug) printf("***SEPARATOR***\n"); *perror = CALC_ERR_BAD_SEPARATOR; goto bad; } *pout++ = pstacktop->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pstacktop->code]); if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; if (sCalcPostfixDebug>=5) printf("put run-time effect %d to postfix\n", 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) { if (sCalcPostfixDebug) printf("***CLOSE_PAREN***\n"); *perror = CALC_ERR_PAREN_NOT_OPEN; goto bad; } *pout++ = pstacktop->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pstacktop->code]); if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; if (sCalcPostfixDebug>=5) printf("put run-time effect %d to postfix\n", 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) { if (sCalcPostfixDebug) printf("***CLOSE_PAREN_1***\n"); *perror = CALC_ERR_INCOMPLETE; goto bad; } } break; case CLOSE_BRACKET: if (sCalcPostfixDebug) printf("CLOSE_BRACKET: \n"); /* Move operators to the output until matching paren */ while (pstacktop->name[0] != '[') { if (sCalcPostfixDebug) printf("CLOSE_BRACKET: stacktop code=%s (%d)\n", opcodes[(int) pstacktop->code], pstacktop->code); if (pstacktop <= stack+1) { if (sCalcPostfixDebug) printf("***CLOSE_BRACKET***\n"); *perror = CALC_ERR_BRACKET_NOT_OPEN; goto bad; } *pout++ = pstacktop->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pstacktop->code]); if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; if (sCalcPostfixDebug>=5) printf("put run-time effect %d to postfix\n", 1 - pstacktop->runtime_effect); } runtime_depth += pstacktop->runtime_effect; pstacktop--; } /* add SUBRANGE operator to postfix */ *pout++ = pstacktop->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pstacktop->code]); runtime_depth += pstacktop->runtime_effect; pstacktop--; if (sCalcPostfixDebug) printf("CLOSE_BRACKET: stacktop code=%s (%d)\n", opcodes[(int) pstacktop->code], pstacktop->code); break; case CLOSE_CURLY: /* Move operators to the output until matching paren */ while (pstacktop->name[0] != '{') { if (pstacktop <= stack+1) { if (sCalcPostfixDebug) printf("***CLOSE_CURLY***\n"); *perror = CALC_ERR_CURLY_NOT_OPEN; goto bad; } *pout++ = pstacktop->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pstacktop->code]); if (sCalcPostfixDebug) printf("CLOSE_CURLY op '%s': moved '%s' from stack\n", pel->name, pstacktop->name); if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; if (sCalcPostfixDebug>=5) printf("put run-time effect %d to postfix\n", 1 - pstacktop->runtime_effect); } runtime_depth += pstacktop->runtime_effect; pstacktop--; } /* add REPLACE operator to postfix */ *pout++ = pstacktop->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pstacktop->code]); runtime_depth += pstacktop->runtime_effect; pstacktop--; 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 (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pstacktop->code]); if (sCalcPostfixDebug) printf("CONDITIONAL op '%s': moved '%s' from stack\n", pel->name, pstacktop->name); if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; if (sCalcPostfixDebug>=5) printf("put run-time effect %d to postfix\n", 1 - pstacktop->runtime_effect); } runtime_depth += pstacktop->runtime_effect; pstacktop--; } /* Add new element to the output */ *pout++ = pel->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pel->code]); runtime_depth += pel->runtime_effect; /* For : operator, also push COND_END code to stack */ if (pel->name[0] == ':') { if (--cond_count < 0) { if (sCalcPostfixDebug) printf("***CONDITIONAL(:)***\n"); *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 UNTIL_OPERATOR: /* Move operators of >= priority to the output */ while ((pstacktop > stack) && (pstacktop->in_stack_pri >= pel->in_coming_pri)) { *pout++ = pstacktop->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pstacktop->code]); if (sCalcPostfixDebug) printf("UNTIL_OPERATOR op '%s': moved '%s' from stack\n", pel->name, pstacktop->name); if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; if (sCalcPostfixDebug>=5) printf("put run-time effect %d to postfix\n", 1 - pstacktop->runtime_effect); } runtime_depth += pstacktop->runtime_effect; pstacktop--; } /* Push UNTIL to output */ *pout++ = pel->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pel->code]); runtime_depth += pel->runtime_effect; /* Push UNTIL_END code to stack */ pstacktop++; *pstacktop = *pel; pstacktop->code = UNTIL_END; pstacktop->runtime_effect = 0; break; case EXPR_TERMINATOR: /* Move everything from stack to the output */ /* while (pstacktop > stack) { */ while ((pstacktop > stack) && (pstacktop->name[0] != '(')) { *pout++ = pstacktop->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pstacktop->code]); if (sCalcPostfixDebug) printf("EXPR_TERMINATOR op '%s': moved '%s' from stack\n", pel->name, pstacktop->name); if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; if (sCalcPostfixDebug>=5) printf("put run-time effect %d to postfix\n", 1 - pstacktop->runtime_effect); } runtime_depth += pstacktop->runtime_effect; pstacktop--; } operand_needed = TRUE; break; case STRING_OPERAND: runtime_depth += pel->runtime_effect; *pout++ = pel->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pel->code]); c = psrc[-1]; /* " or ' character */ while (*psrc != c && *psrc) *pout++ = *psrc++; *pout++ = '\0'; if (*psrc) psrc++; operand_needed = FALSE; break; default: if (sCalcPostfixDebug) printf("***default***\n"); *perror = CALC_ERR_INTERNAL; goto bad; } if (runtime_depth < 0) { if (sCalcPostfixDebug) printf("***runtime_depth<0***\n"); *perror = CALC_ERR_UNDERFLOW; goto bad; } if (runtime_depth >= SCALC_STACKSIZE) { if (sCalcPostfixDebug) printf("***runtime_depth>=SCALC_STACKSIZE***\n"); *perror = CALC_ERR_OVERFLOW; goto bad; } } if (*psrc != '\0') { if (sCalcPostfixDebug) printf("*** *psrc != 0 ***\n"); *perror = CALC_ERR_SYNTAX; goto bad; } /* Move everything from stack to the output */ while (pstacktop > stack) { if (pstacktop->name[0] == '(') { if (sCalcPostfixDebug) printf("*** pstacktop->name[0] == ( ***\n"); *perror = CALC_ERR_PAREN_OPEN; goto bad; } *pout++ = pstacktop->code; if (sCalcPostfixDebug>=5) printf("put %s to postfix\n", opcodes[(int) pstacktop->code]); if (sCalcPostfixDebug) printf("done parsing: moved '%s' from stack\n", pstacktop->name); if (pstacktop->type == VARARG_OPERATOR) { *pout++ = 1 - pstacktop->runtime_effect; if (sCalcPostfixDebug>=5) printf("put run-time effect %d to postfix\n", 1 - pstacktop->runtime_effect); } runtime_depth += pstacktop->runtime_effect; pstacktop--; } *pout = END_EXPRESSION; if (cond_count != 0) { if (sCalcPostfixDebug) printf("*** cond_count != 0 ***\n"); *perror = CALC_ERR_CONDITIONAL; goto bad; } if (operand_needed) { if (sCalcPostfixDebug) printf("*** operand_needed ***\n"); *perror = CALC_ERR_INCOMPLETE; goto bad; } if (runtime_depth != 1) { if (sCalcPostfixDebug) printf("*** runtime_depth!=1 (==%d) ***\n", runtime_depth); *perror = CALC_ERR_INCOMPLETE; goto bad; } if (sCalcPostfixDebug) printf("\nsCalcPostfix: returning success\n"); return 0; bad: if (sCalcPostfixDebug) { printf("\n***error*** '%s'\n", sCalcErrorStr(*perror)); sCalcExprDump(ppostfix); } *ppostfix = END_EXPRESSION; return -1; }