This is Unofficial EPICS BASE Doxygen Site
postfix.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 /*
10  * Subroutines used to convert an infix expression to a postfix expression
11  *
12  * Original Author: Bob Dalesio
13  * Date: 12-12-86
14 */
15 
16 #include <stdio.h>
17 #include <string.h>
18 #include <ctype.h>
19 
20 #include "dbDefs.h"
21 #include "epicsAssert.h"
22 #include "epicsStdlib.h"
23 #include "epicsString.h"
24 #include "epicsTypes.h"
25 #include "postfix.h"
26 #include "postfixPvt.h"
27 #include "libComAPI.h"
28 
29 
30 /* declarations for postfix */
31 
32 /* element types */
33 typedef enum {
44 } element_type;
45 
46 
47 /* element table
48  *
49  * structure of an element
50  */
51 typedef struct expression_element{
52  char *name; /* character representation of an element */
53  char in_stack_pri; /* priority on translation stack */
54  char in_coming_pri; /* priority in input string */
55  signed char runtime_effect; /* stack change, positive means push */
56  element_type type; /* element type */
57  rpn_opcode code; /* postfix opcode */
58 } ELEMENT;
59 
60 /*
61  * NOTE: Keep these lists sorted. Elements are searched in reverse order,
62  * and where two names start with the same substring we must pick out the
63  * longest name first (hence the sort requirement).
64  * NOTE: All VARARG_OPERATORs have to be made known to the calcExprDump()
65  * routine at the end of this file.
66  */
67 static const ELEMENT operands[] = {
68 /* name prio's stack element type opcode */
69 {"!", 7, 8, 0, UNARY_OPERATOR, REL_NOT},
70 {"(", 0, 8, 0, UNARY_OPERATOR, NOT_GENERATED},
71 {"-", 7, 8, 0, UNARY_OPERATOR, UNARY_NEG},
72 {".", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
73 {"0", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
74 {"0X", 0, 0, 1, LITERAL_OPERAND,LITERAL_INT},
75 {"1", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
76 {"2", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
77 {"3", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
78 {"4", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
79 {"5", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
80 {"6", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
81 {"7", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
82 {"8", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
83 {"9", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
84 {"A", 0, 0, 1, OPERAND, FETCH_A},
85 {"ABS", 7, 8, 0, UNARY_OPERATOR, ABS_VAL},
86 {"ACOS", 7, 8, 0, UNARY_OPERATOR, ACOS},
87 {"ASIN", 7, 8, 0, UNARY_OPERATOR, ASIN},
88 {"ATAN", 7, 8, 0, UNARY_OPERATOR, ATAN},
89 {"ATAN2", 7, 8, -1, UNARY_OPERATOR, ATAN2},
90 {"B", 0, 0, 1, OPERAND, FETCH_B},
91 {"C", 0, 0, 1, OPERAND, FETCH_C},
92 {"CEIL", 7, 8, 0, UNARY_OPERATOR, CEIL},
93 {"COS", 7, 8, 0, UNARY_OPERATOR, COS},
94 {"COSH", 7, 8, 0, UNARY_OPERATOR, COSH},
95 {"D", 0, 0, 1, OPERAND, FETCH_D},
96 {"D2R", 0, 0, 1, OPERAND, CONST_D2R},
97 {"E", 0, 0, 1, OPERAND, FETCH_E},
98 {"EXP", 7, 8, 0, UNARY_OPERATOR, EXP},
99 {"F", 0, 0, 1, OPERAND, FETCH_F},
100 {"FINITE", 7, 8, 0, VARARG_OPERATOR,FINITE},
101 {"FLOOR", 7, 8, 0, UNARY_OPERATOR, FLOOR},
102 {"G", 0, 0, 1, OPERAND, FETCH_G},
103 {"H", 0, 0, 1, OPERAND, FETCH_H},
104 {"I", 0, 0, 1, OPERAND, FETCH_I},
105 {"INF", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
106 {"ISINF", 7, 8, 0, UNARY_OPERATOR, ISINF},
107 {"ISNAN", 7, 8, 0, VARARG_OPERATOR,ISNAN},
108 {"J", 0, 0, 1, OPERAND, FETCH_J},
109 {"K", 0, 0, 1, OPERAND, FETCH_K},
110 {"L", 0, 0, 1, OPERAND, FETCH_L},
111 {"LN", 7, 8, 0, UNARY_OPERATOR, LOG_E},
112 {"LOG", 7, 8, 0, UNARY_OPERATOR, LOG_10},
113 {"LOGE", 7, 8, 0, UNARY_OPERATOR, LOG_E},
114 {"MAX", 7, 8, 0, VARARG_OPERATOR,MAX},
115 {"MIN", 7, 8, 0, VARARG_OPERATOR,MIN},
116 {"NINT", 7, 8, 0, UNARY_OPERATOR, NINT},
117 {"NAN", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
118 {"NOT", 7, 8, 0, UNARY_OPERATOR, BIT_NOT},
119 {"PI", 0, 0, 1, OPERAND, CONST_PI},
120 {"R2D", 0, 0, 1, OPERAND, CONST_R2D},
121 {"RNDM", 0, 0, 1, OPERAND, RANDOM},
122 {"SIN", 7, 8, 0, UNARY_OPERATOR, SIN},
123 {"SINH", 7, 8, 0, UNARY_OPERATOR, SINH},
124 {"SQR", 7, 8, 0, UNARY_OPERATOR, SQU_RT},
125 {"SQRT", 7, 8, 0, UNARY_OPERATOR, SQU_RT},
126 {"TAN", 7, 8, 0, UNARY_OPERATOR, TAN},
127 {"TANH", 7, 8, 0, UNARY_OPERATOR, TANH},
128 {"VAL", 0, 0, 1, OPERAND, FETCH_VAL},
129 {"~", 7, 8, 0, UNARY_OPERATOR, BIT_NOT},
130 };
131 
132 static const ELEMENT operators[] = {
133 /* name prio's stack element type opcode */
134 {"!=", 3, 3, -1, BINARY_OPERATOR,NOT_EQ},
135 {"#", 3, 3, -1, BINARY_OPERATOR,NOT_EQ},
136 {"%", 5, 5, -1, BINARY_OPERATOR,MODULO},
137 {"&", 2, 2, -1, BINARY_OPERATOR,BIT_AND},
138 {"&&", 2, 2, -1, BINARY_OPERATOR,REL_AND},
139 {")", 0, 0, 0, CLOSE_PAREN, NOT_GENERATED},
140 {"*", 5, 5, -1, BINARY_OPERATOR,MULT},
141 {"**", 6, 6, -1, BINARY_OPERATOR,POWER},
142 {"+", 4, 4, -1, BINARY_OPERATOR,ADD},
143 {",", 0, 0, 0, SEPERATOR, NOT_GENERATED},
144 {"-", 4, 4, -1, BINARY_OPERATOR,SUB},
145 {"/", 5, 5, -1, BINARY_OPERATOR,DIV},
146 {":", 0, 0, -1, CONDITIONAL, COND_ELSE},
147 {":=", 0, 0, -1, STORE_OPERATOR, STORE_A},
148 {";", 0, 0, 0, EXPR_TERMINATOR,NOT_GENERATED},
149 {"<", 3, 3, -1, BINARY_OPERATOR,LESS_THAN},
150 {"<<", 2, 2, -1, BINARY_OPERATOR,LEFT_SHIFT_ARITH},
151 {"<=", 3, 3, -1, BINARY_OPERATOR,LESS_OR_EQ},
152 {"=", 3, 3, -1, BINARY_OPERATOR,EQUAL},
153 {"==", 3, 3, -1, BINARY_OPERATOR,EQUAL},
154 {">", 3, 3, -1, BINARY_OPERATOR,GR_THAN},
155 {">=", 3, 3, -1, BINARY_OPERATOR,GR_OR_EQ},
156 {">>", 2, 2, -1, BINARY_OPERATOR,RIGHT_SHIFT_ARITH},
157 {">>>", 2, 2, -1, BINARY_OPERATOR,RIGHT_SHIFT_LOGIC},
158 {"?", 0, 0, -1, CONDITIONAL, COND_IF},
159 {"AND", 2, 2, -1, BINARY_OPERATOR,BIT_AND},
160 {"OR", 1, 1, -1, BINARY_OPERATOR,BIT_OR},
161 {"XOR", 1, 1, -1, BINARY_OPERATOR,BIT_EXCL_OR},
162 {"^", 6, 6, -1, BINARY_OPERATOR,POWER},
163 {"|", 1, 1, -1, BINARY_OPERATOR,BIT_OR},
164 {"||", 1, 1, -1, BINARY_OPERATOR,REL_OR},
165 };
166 
167 
168 /* get_element
169  *
170  * find the next expression element in the infix expression
171  */
172 static int
173  get_element(int opnd, const char **ppsrc, const ELEMENT **ppel)
174 {
175  const ELEMENT *ptable, *pel;
176 
177  *ppel = NULL;
178 
179  while (isspace((int) (unsigned char) **ppsrc)) ++*ppsrc;
180  if (**ppsrc == '\0') return FALSE;
181 
182  if (opnd) {
183  ptable = operands;
184  pel = ptable + NELEMENTS(operands) - 1;
185  } else {
186  ptable = operators;
187  pel = ptable + NELEMENTS(operators) - 1;
188  }
189 
190  while (pel >= ptable) {
191  size_t len = strlen(pel->name);
192 
193  if (epicsStrnCaseCmp(*ppsrc, pel->name, len) == 0) {
194  *ppel = pel;
195  *ppsrc += len;
196  return TRUE;
197  }
198  --pel;
199  }
200  return FALSE;
201 }
202 
203 
204 /* postfix
205  *
206  * convert an infix expression to a postfix expression
207  */
208 LIBCOM_API long
209  postfix(const char *psrc, char *pout, short *perror)
210 {
211  ELEMENT stack[80];
212  ELEMENT *pstacktop = stack;
213  const ELEMENT *pel;
214  int operand_needed = TRUE;
215  int runtime_depth = 0;
216  int cond_count = 0;
217  char * const pdest = pout;
218  char *pnext;
219 
220  if (psrc == NULL || *psrc == '\0' ||
221  pout == NULL || perror == NULL) {
222  if (perror) *perror = CALC_ERR_NULL_ARG;
223  if (pout) *pout = END_EXPRESSION;
224  return -1;
225  }
226 
227  /* place the expression elements into postfix */
228  *pout = END_EXPRESSION;
229  *perror = CALC_ERR_NONE;
230 
231  while (get_element(operand_needed, &psrc, &pel)) {
232  switch (pel->type) {
233 
234  case OPERAND:
235  *pout++ = pel->code;
236  runtime_depth += pel->runtime_effect;
237  operand_needed = FALSE;
238  break;
239 
240  case LITERAL_OPERAND:
241  runtime_depth += pel->runtime_effect;
242 
243  psrc -= strlen(pel->name);
244  if (pel->code == LITERAL_DOUBLE) {
245  double lit_d;
246  epicsInt32 lit_i;
247 
248  if (epicsParseDouble(psrc, &lit_d, &pnext)) {
249  *perror = CALC_ERR_BAD_LITERAL;
250  goto bad;
251  }
252  psrc = pnext;
253  lit_i = (epicsInt32) lit_d;
254  if (lit_d != (double) lit_i) {
255  *pout++ = pel->code;
256  memcpy(pout, &lit_d, sizeof(double));
257  pout += sizeof(double);
258  } else {
259  *pout++ = LITERAL_INT;
260  memcpy(pout, &lit_i, sizeof(epicsInt32));
261  pout += sizeof(epicsInt32);
262  }
263  }
264  else {
265  epicsUInt32 lit_ui;
266 
267  assert(pel->code == LITERAL_INT);
268  if (epicsParseUInt32(psrc, &lit_ui, 0, &pnext)) {
269  *perror = CALC_ERR_BAD_LITERAL;
270  goto bad;
271  }
272  psrc = pnext;
273  *pout++ = LITERAL_INT;
274  memcpy(pout, &lit_ui, sizeof(epicsUInt32));
275  pout += sizeof(epicsUInt32);
276  }
277 
278  operand_needed = FALSE;
279  break;
280 
281  case STORE_OPERATOR:
282  if (pout == pdest || pstacktop > stack ||
283  *--pout < FETCH_A || *pout > FETCH_L) {
284  *perror = CALC_ERR_BAD_ASSIGNMENT;
285  goto bad;
286  }
287  /* Convert fetch into a store on the stack */
288  *++pstacktop = *pel;
289  pstacktop->code = STORE_A + *pout - FETCH_A;
290  runtime_depth -= 1;
291  operand_needed = TRUE;
292  break;
293 
294  case UNARY_OPERATOR:
295  case VARARG_OPERATOR:
296  /* Move operators of >= priority to the output */
297  while ((pstacktop > stack) &&
298  (pstacktop->in_stack_pri >= pel->in_coming_pri)) {
299  *pout++ = pstacktop->code;
300  if (pstacktop->type == VARARG_OPERATOR) {
301  *pout++ = 1 - pstacktop->runtime_effect;
302  }
303  runtime_depth += pstacktop->runtime_effect;
304  pstacktop--;
305  }
306 
307  /* Push new operator onto stack */
308  pstacktop++;
309  *pstacktop = *pel;
310  break;
311 
312  case BINARY_OPERATOR:
313  /* Move operators of >= priority to the output */
314  while ((pstacktop > stack) &&
315  (pstacktop->in_stack_pri >= pel->in_coming_pri)) {
316  *pout++ = pstacktop->code;
317  if (pstacktop->type == VARARG_OPERATOR) {
318  *pout++ = 1 - pstacktop->runtime_effect;
319  }
320  runtime_depth += pstacktop->runtime_effect;
321  pstacktop--;
322  }
323 
324  /* Push new operator onto stack */
325  pstacktop++;
326  *pstacktop = *pel;
327 
328  operand_needed = TRUE;
329  break;
330 
331  case SEPERATOR:
332  /* Move operators to the output until open paren */
333  while (pstacktop->name[0] != '(') {
334  if (pstacktop <= stack+1) {
335  *perror = CALC_ERR_BAD_SEPERATOR;
336  goto bad;
337  }
338  *pout++ = pstacktop->code;
339  if (pstacktop->type == VARARG_OPERATOR) {
340  *pout++ = 1 - pstacktop->runtime_effect;
341  }
342  runtime_depth += pstacktop->runtime_effect;
343  pstacktop--;
344  }
345  operand_needed = TRUE;
346  pstacktop->runtime_effect -= 1;
347  break;
348 
349  case CLOSE_PAREN:
350  /* Move operators to the output until matching paren */
351  while (pstacktop->name[0] != '(') {
352  if (pstacktop <= stack+1) {
353  *perror = CALC_ERR_PAREN_NOT_OPEN;
354  goto bad;
355  }
356  *pout++ = pstacktop->code;
357  if (pstacktop->type == VARARG_OPERATOR) {
358  *pout++ = 1 - pstacktop->runtime_effect;
359  }
360  runtime_depth += pstacktop->runtime_effect;
361  pstacktop--;
362  }
363  pstacktop--; /* remove ( from stack */
364  /* if there is a vararg operator before the opening paren,
365  it inherits the (opening) paren's stack effect */
366  if ((pstacktop > stack) &&
367  pstacktop->type == VARARG_OPERATOR) {
368  pstacktop->runtime_effect = (pstacktop+1)->runtime_effect;
369  /* check for no arguments */
370  if (pstacktop->runtime_effect > 0) {
371  *perror = CALC_ERR_INCOMPLETE;
372  goto bad;
373  }
374  }
375  break;
376 
377  case CONDITIONAL:
378  /* Move operators of > priority to the output */
379  while ((pstacktop > stack) &&
380  (pstacktop->in_stack_pri > pel->in_coming_pri)) {
381  *pout++ = pstacktop->code;
382  if (pstacktop->type == VARARG_OPERATOR) {
383  *pout++ = 1 - pstacktop->runtime_effect;
384  }
385  runtime_depth += pstacktop->runtime_effect;
386  pstacktop--;
387  }
388 
389  /* Add new element to the output */
390  *pout++ = pel->code;
391  runtime_depth += pel->runtime_effect;
392 
393  /* For : operator, also push COND_END code to stack */
394  if (pel->name[0] == ':') {
395  if (--cond_count < 0) {
396  *perror = CALC_ERR_CONDITIONAL;
397  goto bad;
398  }
399  pstacktop++;
400  *pstacktop = *pel;
401  pstacktop->code = COND_END;
402  pstacktop->runtime_effect = 0;
403  } else {
404  cond_count++;
405  }
406 
407  operand_needed = TRUE;
408  break;
409 
410  case EXPR_TERMINATOR:
411  /* Move everything from stack to the output */
412  while (pstacktop > stack) {
413  if (pstacktop->name[0] == '(') {
414  *perror = CALC_ERR_PAREN_OPEN;
415  goto bad;
416  }
417  *pout++ = pstacktop->code;
418  if (pstacktop->type == VARARG_OPERATOR) {
419  *pout++ = 1 - pstacktop->runtime_effect;
420  }
421  runtime_depth += pstacktop->runtime_effect;
422  pstacktop--;
423  }
424 
425  if (cond_count != 0) {
426  *perror = CALC_ERR_CONDITIONAL;
427  goto bad;
428  }
429  if (runtime_depth > 1) {
430  *perror = CALC_ERR_TOOMANY;
431  goto bad;
432  }
433 
434  operand_needed = TRUE;
435  break;
436 
437  default:
438  *perror = CALC_ERR_INTERNAL;
439  goto bad;
440  }
441 
442  if (runtime_depth < 0) {
443  *perror = CALC_ERR_UNDERFLOW;
444  goto bad;
445  }
446  if (runtime_depth >= CALCPERFORM_STACK) {
447  *perror = CALC_ERR_OVERFLOW;
448  goto bad;
449  }
450  }
451 
452  if (*psrc != '\0') {
453  *perror = CALC_ERR_SYNTAX;
454  goto bad;
455  }
456 
457  /* Move everything from stack to the output */
458  while (pstacktop > stack) {
459  if (pstacktop->name[0] == '(') {
460  *perror = CALC_ERR_PAREN_OPEN;
461  goto bad;
462  }
463  *pout++ = pstacktop->code;
464  if (pstacktop->type == VARARG_OPERATOR) {
465  *pout++ = 1 - pstacktop->runtime_effect;
466  }
467  runtime_depth += pstacktop->runtime_effect;
468  pstacktop--;
469  }
470  *pout = END_EXPRESSION;
471 
472  if (cond_count != 0) {
473  *perror = CALC_ERR_CONDITIONAL;
474  goto bad;
475  }
476  if (operand_needed || runtime_depth != 1) {
477  *perror = CALC_ERR_INCOMPLETE;
478  goto bad;
479  }
480  return 0;
481 
482 bad:
483  *pdest = END_EXPRESSION;
484  return -1;
485 }
486 
487 
488 /* calcErrorStr
489  *
490  * Return a message string appropriate for the given error code
491  */
492 LIBCOM_API const char *
493  calcErrorStr(short error)
494 {
495  static const char *errStrs[] = {
496  "No error",
497  "Too many results returned",
498  "Badly formed numeric literal",
499  "Bad assignment target",
500  "Comma without enclosing parentheses",
501  "Close parenthesis found without open",
502  "Parenthesis still open at end of expression",
503  "Unbalanced conditional ?: operators",
504  "Incomplete expression, operand missing",
505  "Not enough operands provided",
506  "Runtime stack overflow",
507  "Syntax error, unknown operator/operand",
508  "NULL or empty input argument to postfix()",
509  "Internal error, unknown element type",
510  };
511 
512  if (error < CALC_ERR_NONE || error > CALC_ERR_INTERNAL)
513  return NULL;
514  return errStrs[error];
515 }
516 
517 
518 /* calcExprDump
519  *
520  * Disassemble the given postfix instructions to stdout
521  */
522 LIBCOM_API void
523  calcExprDump(const char *pinst)
524 {
525  static const char *opcodes[] = {
526  "End Expression",
527  /* Operands */
528  "LITERAL_DOUBLE", "LITERAL_INT", "VAL",
529  "FETCH_A", "FETCH_B", "FETCH_C", "FETCH_D", "FETCH_E", "FETCH_F",
530  "FETCH_G", "FETCH_H", "FETCH_I", "FETCH_J", "FETCH_K", "FETCH_L",
531  /* Assignment */
532  "STORE_A", "STORE_B", "STORE_C", "STORE_D", "STORE_E", "STORE_F",
533  "STORE_G", "STORE_H", "STORE_I", "STORE_J", "STORE_K", "STORE_L",
534  /* Trigonometry Constants */
535  "CONST_PI",
536  "CONST_D2R",
537  "CONST_R2D",
538  /* Arithmetic */
539  "UNARY_NEG",
540  "ADD",
541  "SUB",
542  "MULT",
543  "DIV",
544  "MODULO",
545  "POWER",
546  /* Algebraic */
547  "ABS_VAL",
548  "EXP",
549  "LOG_10",
550  "LOG_E",
551  "MAX",
552  "MIN",
553  "SQU_RT",
554  /* Trigonometric */
555  "ACOS",
556  "ASIN",
557  "ATAN",
558  "ATAN2",
559  "COS",
560  "COSH",
561  "SIN",
562  "SINH",
563  "TAN",
564  "TANH",
565  /* Numeric */
566  "CEIL",
567  "FLOOR",
568  "FINITE",
569  "ISINF",
570  "ISNAN",
571  "NINT",
572  "RANDOM",
573  /* Boolean */
574  "REL_OR",
575  "REL_AND",
576  "REL_NOT",
577  /* Bitwise */
578  "BIT_OR",
579  "BIT_AND",
580  "BIT_EXCL_OR",
581  "BIT_NOT",
582  "RIGHT_SHIFT_ARITH",
583  "LEFT_SHIFT_ARITH",
584  "RIGHT_SHIFT_LOGIC",
585  /* Relationals */
586  "NOT_EQ",
587  "LESS_THAN",
588  "LESS_OR_EQ",
589  "EQUAL",
590  "GR_OR_EQ",
591  "GR_THAN",
592  /* Conditional */
593  "COND_IF",
594  "COND_ELSE",
595  "COND_END",
596  /* Misc */
597  "NOT_GENERATED"
598  };
599  char op;
600  double lit_d;
601  epicsInt32 lit_i;
602 
603  while ((op = *pinst) != END_EXPRESSION) {
604  switch (op) {
605  case LITERAL_DOUBLE:
606  memcpy(&lit_d, ++pinst, sizeof(double));
607  printf("\tDouble %g\n", lit_d);
608  pinst += sizeof(double);
609  break;
610  case LITERAL_INT:
611  memcpy(&lit_i, ++pinst, sizeof(epicsInt32));
612  printf("\tInteger %d (0x%x)\n", lit_i, lit_i);
613  pinst += sizeof(epicsInt32);
614  break;
615  case MIN:
616  case MAX:
617  case FINITE:
618  case ISNAN:
619  printf("\t%s, %d arg(s)\n", opcodes[(int) op], *++pinst);
620  pinst++;
621  break;
622  default:
623  printf("\t%s\n", opcodes[(int) op]);
624  pinst++;
625  }
626  }
627 }
#define CALC_ERR_NULL_ARG
NULL or empty input argument.
Definition: postfix.h:105
LIBCOM_API const char * calcErrorStr(short error)
Convert an error code to a string.
Definition: postfix.c:493
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
#define FALSE
Definition: dbDefs.h:32
Definition: postfixPvt.h:56
#define CALC_ERR_BAD_LITERAL
Bad numeric literal.
Definition: postfix.h:85
An EPICS-specific replacement for ANSI C&#39;s assert.
rpn_opcode
Definition: postfixPvt.h:30
The API for the EPICS Calculation Engine.
#define printf
Definition: epicsStdio.h:41
Definition: postfixPvt.h:45
#define NULL
Definition: catime.c:38
rpn_opcode code
Definition: postfix.c:57
unsigned int epicsUInt32
Definition: epicsTypes.h:43
Definition: postfixPvt.h:57
Miscellaneous macro definitions.
#define CALC_ERR_OVERFLOW
Runtime stack would overflow.
Definition: postfix.h:101
#define CALC_ERR_TOOMANY
Too many results returned.
Definition: postfix.h:83
#define CALC_ERR_INTERNAL
Internal error, bad element type.
Definition: postfix.h:107
#define CALC_ERR_UNDERFLOW
Runtime stack would underflow.
Definition: postfix.h:99
#define CALC_ERR_INCOMPLETE
Incomplete expression, operand missing.
Definition: postfix.h:97
#define CALC_ERR_PAREN_NOT_OPEN
Close parenthesis without open.
Definition: postfix.h:91
#define CALC_ERR_BAD_SEPERATOR
Comma without parentheses.
Definition: postfix.h:89
#define CALC_ERR_BAD_ASSIGNMENT
Bad assignment target.
Definition: postfix.h:87
LIBCOM_API int epicsParseDouble(const char *str, double *to, char **units)
Definition: epicsStdlib.c:149
LIBCOM_API void calcExprDump(const char *pinst)
Disassemble a postfix expression.
Definition: postfix.c:523
element_type type
Definition: postfix.c:56
Definition: postfixPvt.h:46
Definition: postfixPvt.h:64
#define NELEMENTS(A)
Definition: aToIPAddr.c:21
Definition: postfixPvt.h:68
signed char runtime_effect
Definition: postfix.c:55
Definition: postfixPvt.h:48
Definition: postfixPvt.h:53
int epicsStrnCaseCmp(const char *s1, const char *s2, size_t len)
Definition: epicsString.c:206
#define TRUE
Definition: dbDefs.h:27
#define CALCPERFORM_STACK
Size of the internal partial result stack.
Definition: postfix.h:27
LIBCOM_API int epicsParseUInt32(const char *str, epicsUInt32 *to, int base, char **units)
Definition: epicsStdlib.c:263
#define CALC_ERR_CONDITIONAL
Unbalanced conditional ?: operators.
Definition: postfix.h:95
char in_coming_pri
Definition: postfix.c:54
element_type
Definition: postfix.c:33
Definition: postfixPvt.h:66
ChannelPut::shared_pointer op
Definition: pvAccess.cpp:132
LIBCOM_API long postfix(const char *psrc, char *pout, short *perror)
Compile an infix expression into postfix byte-code.
Definition: postfix.c:209
struct expression_element ELEMENT
#define CALC_ERR_SYNTAX
Syntax error.
Definition: postfix.h:103
#define CALC_ERR_NONE
No error.
Definition: postfix.h:81
int epicsInt32
Definition: epicsTypes.h:42
#define CALC_ERR_PAREN_OPEN
Open parenthesis at end of expression.
Definition: postfix.h:93