diff --git a/runScript.c b/runScript.c
index d056b70a2e2b69addd5a88c5be6b9a115a1051ee..ebe0976e3b0cc276c6ab830fe31b23ccbbcd941c 100644
--- a/runScript.c
+++ b/runScript.c
@@ -51,11 +51,11 @@ epicsShareFunc int epicsShareAPI iocshCmd(const char *cmd);
 
 int runScriptDebug=0;
 
-static int parseExpr(const char** pp, int* v);
+static int parseExpr(const char** pp, long* v, int op);
 
-static int parseValue(const char** pp, int* v)
+static int parseValue(const char** pp, long* v)
 {
-    int val;
+    long val;
     const char *p = *pp;
     char o;
 
@@ -65,32 +65,35 @@ static int parseValue(const char** pp, int* v)
      * Allowed chars after a number: operators, closing parenthesis, whitespace, quotes, end of string
      */
 
-    do {
-        while (isspace((unsigned char)*p)) p++;
-    } while (*p == '+' && p++);
+    /* first look for value */
+    while (isspace((unsigned char)*p)) p++;
     o = *p;
-    if (memchr("-~!", o, 3))
+    if (memchr("+-~!", o, 4))
     {
+        /* handle unary operators */
         p++;
-        if (!parseValue(&p, &val)) return 0;
+        if (!parseValue(&p, &val)) return 0; /* no valid value */
         if (o == '-') val=-val;
         else if (o == '~') val=~val;
         else if (o == '!') val=!val;
     }
     else if (o == '(')
     {
+        /*  handle sub-expression */
         if (runScriptDebug > 1) printf("parseValue: subexpression '%s'\n", p);
         p++;
-        if (!parseExpr(&p, &val)) return 0;
+        if (parseExpr(&p, &val, 0) < 0) return 0; /* no valid expression */
         while (isspace((unsigned char)*p)) p++;
-        if (*p++ != ')') return 0;
+        if (*p++ != ')') return 0; /* missing ) */
     }
     else
     {
+        /* get number */
         char* e;
         val = strtol(p, &e, 0);
         if (e == p) return 0; /* no number */
-        if (*e && !isspace((unsigned char)*e) && !strchr("+-*/%|&^?)'\",", *e))
+        
+        if (isalpha((unsigned char)*p))
         {
             /* followed by rubbish */
             if (runScriptDebug > 1) printf("parseValue: bail out from '%s' at '%s'\n", *pp, e);
@@ -98,55 +101,110 @@ static int parseValue(const char** pp, int* v)
         }
         p = e;
     }
-    if (runScriptDebug > 1) printf("parseValue: '%.*s' = %d rest '%s'\n", (int)(p-*pp), *pp, val, p);
+    if (runScriptDebug > 1) printf("parseValue: '%.*s' = %ld rest '%s'\n", (int)(p-*pp), *pp, val, p);
     *pp = p;
     *v = val;
     return 1;
 }
 
-static int parseExpr(const char** pp, int* v)
+static long ipow(long base, long exp)
+{
+    long v;
+    if (exp < 0) return 0;
+    if (exp == 0) return 1;
+    v = base;
+    while (--exp) v *= base; /* optimize this! */
+    return v;
+}
+
+struct {char str[3]; char pr;} ops[] = {
+    {"",0},
+    {"**",2},
+    {"*", 3},{"/",3},{"%",3},
+    {"+",4},{"-",4},
+    {"<<",5},{">>>",5},{">>",5},
+    {"<=>",6},{"<=",6},{">=",6},{"<",6},{">",6},
+    {"==",7},{"!=",7},
+    {"&&",11},{"||",12},
+    {"&",8},{"^",9},{"|",10}
+};
+
+static int startsWith(const char* p, const char* s)
+{
+    int i = 0;
+    while (*s) { i++; if (*p++ != *s++) return 0; }
+    return i;
+}
+
+static int parseOp(const char** pp)
 {
     const char *p = *pp;
-    const char *q;
-    int sum = 0, val, val2;
-    char o;
+    int o, l;
 
-    /* An expression is a value optionally followed by an operator and another value.
-     * Outer loop: low priority operators + -
-     * Inner loop: high priority operators * / %
-     * A value is a number or an expression in ().
-     * Allowed chars after a expression: quotes, space, end of string
-     */
-    do {
-        if (!parseValue(&p, &val)) return 0;
-        q = p;
-        while (isspace((unsigned char)*q)) q++;
-        o = *q;
-        while (memchr("*/%&|^", o, 6))
+    while (isspace((unsigned char)*p)) p++;
+    if (runScriptDebug > 1) printf("parseOp: check %s\n", p);
+    if (ispunct((unsigned char)*p))
+    {
+        for (o = 1; o < (int)(sizeof(ops)/sizeof(ops[0])); o++)
         {
-            q++;
-            if (!parseValue(&q, &val2)) return 0;
-            if (o == '*') val *= val2;
-            else if (o == '&') val &= val2;
-            else if (o == '|') val |= val2;
-            else if (o == '^') val ^= val2;
-            else if (val2 == 0) val = 0; /* define division by zero as 0 */
-            else if (o == '/') val /= val2;
-            else val %= val2;
-            p = q;
-            o = *p;
+            if ((l = startsWith(p, ops[o].str)))
+            {
+                /* operator found */
+                if (runScriptDebug > 1) printf("parseOp: %.3s\n", ops[0].str);
+                *pp = p+l;
+                return o;
+            }
         }
-        sum += val;
-    } while (o == '+' || o == '-');
-    if (*p == '?')
-    {
-        p++;
-        sum = (sum != 0);
     }
-    if (runScriptDebug > 1) printf("parseExpr: '%.*s' = %d\n", (int)(p-*pp), *pp, sum);
+    if (runScriptDebug > 1) printf("parseOp: end\n");
+    return 0;
+}
+
+static int parseExpr(const char** pp, long* v, int o)
+{
+    const char *p = *pp;
+    long val = 0;
+    long val2;
+    int o2 = o;
+    int pr = ops[o].pr;
+
+    if (runScriptDebug > 1) printf("parseExpr: o = %.3s\n", ops[o].str);
+    do {
+        if (!parseValue(&p, &val2)) return -1;
+        if ((o2 = parseOp(&p)) != 0 && ops[o2].pr < pr)
+            if ((o2 = parseExpr(&p, &val2, o2)) < 0) return -1;
+        if (runScriptDebug > 1) printf("parseExpr: %ld %.3s %ld\n", val, ops[o].str, val2);
+        switch(o)
+        {
+            case  0: val = val2; break;
+            case  1: val = ipow(val, val2); break;
+            case  2: val *= val2; break;
+            case  3: val /= val2; break;
+            case  4: val %= val2; break;
+            case  5: val += val2; break;
+            case  6: val -= val2; break;
+            case  7: val <<= val2; break;
+            case  8: val = (unsigned long)val >> val2; break;
+            case  9: val >>= val2; break;
+            case 10: val = val < val2 ? -1 : val == val2 ? 0 : 1; break;
+            case 11: val = val <= val2; break;
+            case 12: val = val >= val2; break;
+            case 13: val = val < val2; break;
+            case 14: val = val > val2; break;
+            case 15: val = val == val2; break;
+            case 16: val = val != val2; break;
+            case 17: val = val && val2; break;
+            case 18: val = val || val2; break;
+            case 19: val &= val2; break;
+            case 20: val ^= val2; break;
+            case 21: val |= val2; break;
+        }
+        o = o2;
+    } while (o && pr <= ops[o].pr);
+    if (runScriptDebug > 1) printf("parseExpr: result %ld\n", val);
     *pp = p;
-    *v = sum;
-    return 1;
+    *v = val;
+    return o;
 }
 
 const char* getFormat(const char** pp)
@@ -154,23 +212,25 @@ const char* getFormat(const char** pp)
     static char format [20];
     const char* p = *pp;
     unsigned int i = 1;
-    if (runScriptDebug > 1) printf ("getFormat %s\n", p);
+    if (runScriptDebug > 1) printf("getFormat %s\n", p);
     if ((format[0] = *p++) == '%')
     {
         while (i < sizeof(format) && memchr(" #-+0", *p, 5))
             format[i++] = *p++;
         while (i < sizeof(format) && *p >= '0' && *p <= '9')
             format[i++] = *p++;
+        if (i < sizeof(format))
+            format[i++] = 'l';
         if (i < sizeof(format) && memchr("diouxXc", *p, 7))
         {
             format[i++] = *p++;
             format[i] = 0;
             *pp = p;
-            if (runScriptDebug > 1) printf ("format=%s\n", format);
+            if (runScriptDebug > 1) printf("format = '%s'\n", format);
             return format;
         }
     }
-    if (runScriptDebug > 1) printf ("no format\n");
+    if (runScriptDebug > 1) printf("no format\n");
     return NULL;
 }
 
@@ -327,20 +387,18 @@ int runScript(const char* filename, const char* args)
             const char* r;
             char* s;
             char* w;
-            int val;
+            long val;
 
             *x++ = 0;
             r = x;
             w = line_raw;
             while (*r)
             {
-                /* Resolve integer expressions:
-                 * Any free standing expression.
-                 * Any expression in parentheses () embedded in an unquoted word.
+                /* Resolve integer expressions that are either free standing
+                 * or 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 ().
+                 * An expression optionally starts with a integer format such as %x.
+                 * It consists of integer numbers, operators and parentheses ().
                  */
                 s = w;
                 if (*r == '"' || *r == '\'')
@@ -353,15 +411,15 @@ int runScript(const char* filename, const char* args)
                     }
                     if (*r) *w++ = *r++;
                     *w = 0;
-                    if (runScriptDebug > 1) printf ("quoted string %s\n", s);
+                    if (runScriptDebug > 1) printf("quoted string %s\n", s);
                 }
                 else if (*r == '%')
                 {
                     /* 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))
+                    if (runScriptDebug > 1) printf("formatted expression after '%s'\n", s);
+                    if ((f = getFormat(&r2)) && parseExpr(&r2, &val, 0) == 0)
                     {
                         r = r2;
                         if (*s == '(' && *r2++ == ')')
@@ -370,15 +428,15 @@ int runScript(const char* filename, const char* args)
                             r = r2;
                         }
                         w += sprintf(w, f , val);
-                        if (runScriptDebug > 1) printf ("formatted expression %s\n", s);
+                        if (runScriptDebug > 1) printf("formatted expression %s\n", s);
                     }
                 }
-                else if (parseExpr(&r, &val))
+                else if (parseExpr(&r, &val, 0) == 0)
                 {
                     /* unformatted expression */
-                    w += sprintf(w, "%d", val);
+                    w += sprintf(w, "%ld", val);
                     *w = 0;
-                    if (runScriptDebug > 1) printf ("simple expression %s\n", s);
+                    if (runScriptDebug > 1) printf("simple expression %s\n", s);
                 }
                 else if (*r == ',')
                 {
@@ -391,7 +449,7 @@ int runScript(const char* filename, const char* args)
                         *w++ = *r++;
                     } while (*r && !strchr("%(\"', \t\n", *r));
                     *w = 0;
-                    if (runScriptDebug > 1) printf ("plain word '%s'\n", s);
+                    if (runScriptDebug > 1) printf("plain word '%s'\n", s);
                 }
                 /* copy space */
                 while (isspace((unsigned char)*r)) *w++ = *r++;