enable embedded expressions in ()

This commit is contained in:
2018-04-18 16:31:24 +02:00
parent cb2c4c01ac
commit 4dd59a05f0
+50 -39
View File
@@ -57,18 +57,29 @@ static int parseValue(const char** pp, int* v)
{
int val;
const char *p = *pp;
int neg = 0;
char o;
/* A value is optionally prefixed with a sign + -.
/* A value is optionally prefixed with an unary operator + - ! ~.
* It is either a number (decimal, octal or hex)
* or an expression in ().
* Allowed chars after a number: operators, closing parenthesis, whitespace, quotes, end of string
*/
while (isspace((unsigned char)*p)) p++;
if (*p == '+' || *p == '-') neg = *p++ == '-';
while (isspace((unsigned char)*p)) p++;
if (*p == '(')
*/
do {
while (isspace((unsigned char)*p)) p++;
} while (*p == '+' && p++);
o = *p;
if (strchr("-~!", o))
{
p++;
if (!parseValue(&p, &val)) return 0;
if (o == '-') val=-val;
else if (o == '~') val=~val;
else if (o == '!') val=!val;
}
else if (o == '(')
{
if (runScriptDebug > 1) printf("parseValue: subexpression '%s'\n", p);
p++;
if (!parseExpr(&p, &val)) return 0;
while (isspace((unsigned char)*p)) p++;
@@ -82,20 +93,14 @@ static int parseValue(const char** pp, int* v)
if (*e && !isspace((unsigned char)*e) && !strchr("+-*/%?)'\"",*e))
{
/* followed by rubbish */
if (runScriptDebug > 1) printf("parseValue: bail out from %s at %s\n", *pp, e);
if (runScriptDebug > 1) printf("parseValue: bail out from '%s' at '%s'\n", *pp, e);
return 0;
}
p = e;
}
if (neg) val = -val;
if (*p == '?')
{
p++;
val = (val != 0);
}
if (runScriptDebug > 1) printf("parseValue: '%.*s' = %d rest '%s'\n", (int)(p-*pp), *pp, val, p);
*pp = p;
*v = val;
if (runScriptDebug > 1) printf("parseValue: %d rest=\"%s\"\n", *v, p);
return 1;
}
@@ -103,12 +108,10 @@ static int parseExpr(const char** pp, int* v)
{
const char *p = *pp;
const char *q;
int o;
int val;
int val2;
int sum = 0, val, val2;
int status = 0;
char o;
*v = 0;
/* An expression is a value optionally followed by an operator and another value.
* Outer loop: low priority operators + -
* Inner loop: high priority operators * / %
@@ -117,14 +120,13 @@ static int parseExpr(const char** pp, int* v)
*/
do {
if (!parseValue(&p, &val)) return status;
if (runScriptDebug > 1) printf("parseExpr: val=%d rest=%s\n", val, p);
q = p;
while (isspace((unsigned char)*q)) q++;
o = *q;
while (o == '*' || o == '/' || o == '%')
{
q++;
if (!parseValue(&q, &val2)) break;
if (!parseValue(&q, &val2)) return status;
if (o == '*') val *= val2;
else if (val2 == 0) val = 0; /* define devision by zero as 0 */
else if (o == '/') val /= val2;
@@ -134,10 +136,16 @@ static int parseExpr(const char** pp, int* v)
o = *p;
}
status = 1;
*v += val;
if (runScriptDebug > 1) printf("parseExpr: sum %d rest=\"%s\"\n", *v, p);
sum += val;
} while (o == '+' || o == '-');
if (*p == '?')
{
p++;
sum = (sum != 0);
}
if (runScriptDebug > 1) printf("parseExpr: '%.*s' = %d\n", (int)(p-*pp), *pp, sum);
*pp = p;
*v = sum;
return 1;
}
@@ -149,13 +157,10 @@ const char* getFormat(const char** pp)
if (runScriptDebug > 1) printf ("getFormat %s\n", p);
if ((format[0] = *p++) == '%')
{
if (runScriptDebug > 1) printf ("getFormat0 %s\n", p);
while (i < sizeof(format) && strchr(" #-+0", *p))
format[i++] = *p++;
if (runScriptDebug > 1) printf ("getFormat1 %s\n", p);
while (i < sizeof(format) && strchr("0123456789", *p))
format[i++] = *p++;
if (runScriptDebug > 1) printf ("getFormat2 %s\n", p);
if (i < sizeof(format) && strchr("diouxXc", *p))
{
format[i++] = *p++;
@@ -293,6 +298,7 @@ int runScript(const char* filename, const char* args)
if (fgets(line_raw + len, line_raw_size - len, file) == NULL) break;
}
while (len > 0 && isspace((unsigned char)line_raw[len-1])) line_raw[--len] = 0; /* get rid of '\n' and friends */
if (len == 0) continue;
if (runScriptDebug)
printf("runScript raw line (%ld chars): '%s'\n", len, line_raw);
/* expand and check the buffer size (different epics versions write different may number of bytes)*/
@@ -320,7 +326,7 @@ int runScript(const char* filename, const char* args)
if ((x = strpbrk(p, "=(, \t\n\r")) != NULL && *x=='=')
{
const char* r;
const char* s;
char* s;
char* w;
int val;
@@ -329,17 +335,15 @@ int runScript(const char* filename, const char* args)
w = line_raw;
while (*r)
{
/* Resolve any integer expression that is not embedded in a
* string. A string is anything in single or double quotes or
* a word that is not an integer expression. An expression
* consists of an optional format specifier (such as %x),
* numbers (including 0x prefixed hex numbers), arithmetic
* operators (at the moment +-*%/) and and parentheses ().
/* Resolve integer expressions:
* Any free standing expression.
* Any expression in parentheses () embedded in an unquoted word.
* Do not resolve expressions in single or double quoted strings.
* An expression optionally starts with a format such as %x.
* It consists of integer numbers (including 0x prefixed hex numbers),
* unary (+-!~) and binary (+-*%/) oprators and parentheses ().
*/
while (isspace((unsigned char)*r)) *w++ = *r++;
if (!*r) break;
s = w;
if (*r == '"' || *r == '\'')
{
/* quoted strings */
@@ -358,10 +362,16 @@ int runScript(const char* filename, const char* args)
/* formatted expression */
const char* r2 = r;
const char* f;
if (runScriptDebug > 1) printf ("formatted expression after '%s'\n", s);
if ((f = getFormat(&r2)) && parseExpr(&r2, &val))
{
w += sprintf(w, f , val);
r = r2;
if (*s == '(' && *r2++ == ')')
{
w = s;
r = r2;
}
w += sprintf(w, f , val);
if (runScriptDebug > 1) printf ("formatted expression %s\n", s);
continue;
}
@@ -376,9 +386,10 @@ int runScript(const char* filename, const char* args)
/* unquoted string (i.e plain word) */
do {
*w++ = *r++;
} while (*r && !strchr("(\"' \t\n",*r));
} while (*r && !strchr("%(\"', \t\n",*r));
while (isspace((unsigned char)*r)) *w++ = *r++;
*w = 0;
if (runScriptDebug > 1) printf ("plain word %s\n", s);
if (runScriptDebug > 1) printf ("plain word '%s'\n", s);
}
if (runScriptDebug)
printf("runScript: assign %s=%s\n", p, line_raw);