]> granicus.if.org Git - graphviz/commitdiff
Update libexpr to include Glenn's more recent additions, including variable scopes;
authorEmden Gansner <erg@research.att.com>
Wed, 15 Feb 2012 16:28:38 +0000 (11:28 -0500)
committerEmden Gansner <erg@research.att.com>
Wed, 15 Feb 2012 16:28:38 +0000 (11:28 -0500)
reverted back to Glenn's format so that future diffs and updates will be easier.

17 files changed:
lib/expr/Makefile.am
lib/expr/excc.c
lib/expr/excontext.c
lib/expr/exdata.c
lib/expr/exerror.c
lib/expr/exeval.c
lib/expr/exexpr.c
lib/expr/exgram.h
lib/expr/exlexname.c
lib/expr/exlib.h
lib/expr/exopen.c
lib/expr/exparse.y
lib/expr/expr.h
lib/expr/exrewind.c
lib/expr/extoken.c
lib/expr/extype.c
lib/expr/exzero.c

index 57881258d5f7f255eb9e5c43525851293758686b..a40a80584806d50b9959d70eac60e97b73ba9bbd 100644 (file)
@@ -30,7 +30,7 @@ pdf_DATA = expr.3.pdf
 
 libexpr_C_la_SOURCES = excc.c excontext.c exdata.c exerror.c \
        exeval.c exexpr.c exlexname.c exopen.c exrewind.c extoken.c \
-       extype.c exzero.c exparse.y
+       extype.c exzero.c exparse.y exnospace.c exstash.c 
 libexpr_C_la_LIBADD = \
        $(top_builddir)/lib/ast/libast_C.la \
        $(top_builddir)/lib/vmalloc/libvmalloc_C.la \
index 25020c8a86137ceed26dfa1708558de7a9277702..f408bb83edf8198b2191c0311bfe30ff3e97fe35 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
+/* vim:set shiftwidth=4 ts=4: */
 
 /*************************************************************************
  * Copyright (c) 2011 AT&T Intellectual Property 
        char*           id;             /* prefix + _                   */ \
        int             lastop;         /* last op                      */ \
        int             tmp;            /* temp var index               */ \
-       Exccdisc_t*     ccdisc; /* excc() discipline            */
+       Exccdisc_t*     ccdisc;         /* excc() discipline            */
 
 #include "exlib.h"
 #include <string.h>
 
 #define EX_CC_DUMP     0x8000
 
-static const char quote[] = "\"";
+static const char      quote[] = "\"";
 
-static void gen(Excc_t *, Exnode_t *);
+static void            gen(Excc_t*, Exnode_t*);
 
 /*
  * return C name for op
  */
 
-char *exopname(int op)
+char*
+exopname(int op)
 {
-    static char buf[16];
-
-    switch (op) {
-    case '!':
-       return "!";
-    case '%':
-       return "%";
-    case '&':
-       return "&";
-    case '(':
-       return "(";
-    case '*':
-       return "*";
-    case '+':
-       return "+";
-    case ',':
-       return ",";
-    case '-':
-       return "-";
-    case '/':
-       return "/";
-    case ':':
-       return ":";
-    case '<':
-       return "<";
-    case '=':
-       return "=";
-    case '>':
-       return ">";
-    case '?':
-       return "?";
-    case '^':
-       return "^";
-    case '|':
-       return "|";
-    case '~':
-       return "~";
-    case AND:
-       return "&&";
-    case EQ:
-       return "==";
-    case GE:
-       return ">=";
-    case LE:
-       return "<=";
-    case LS:
-       return "<<";
-    case NE:
-       return "!=";
-    case OR:
-       return "||";
-    case RS:
-       return ">>";
-    }
-    sfsprintf(buf, sizeof(buf) - 1, "(OP=%03d)", op);
-    return buf;
+       static char     buf[16];
+
+       switch (op)
+       {
+       case '!':
+               return "!";
+       case '%':
+               return "%";
+       case '&':
+               return "&";
+       case '(':
+               return "(";
+       case '*':
+               return "*";
+       case '+':
+               return "+";
+       case ',':
+               return ",";
+       case '-':
+               return "-";
+       case '/':
+               return "/";
+       case ':':
+               return ":";
+       case '<':
+               return "<";
+       case '=':
+               return "=";
+       case '>':
+               return ">";
+       case '?':
+               return "?";
+       case '^':
+               return "^";
+       case '|':
+               return "|";
+       case '~':
+               return "~";
+       case AND:
+               return "&&";
+       case EQ:
+               return "==";
+       case GE:
+               return ">=";
+       case LE:
+               return "<=";
+       case LS:
+               return "<<";
+       case NE:
+               return "!=";
+       case OR:
+               return "||";
+       case RS:
+               return ">>";
+       }
+       sfsprintf(buf, sizeof(buf) - 1, "(OP=%03o)", op);
+       return buf;
 }
 
 /*
  * generate printf()
  */
 
-static void print(Excc_t * cc, Exnode_t * expr)
+static void
+print(Excc_t* cc, Exnode_t* expr)
 {
-    register Print_t *x;
-    register int i;
-
-    if ((x = expr->data.print.args)) {
-       sfprintf(cc->ccdisc->text, "sfprintf(%s, \"%s",
-                expr->data.print.descriptor->op == CONSTANT
-                && expr->data.print.descriptor->data.constant.value.
-                integer == 2 ? "sfstderr" : "sfstdout", fmtesq(x->format,
-                                                               quote));
-       while ((x = x->next))
-           sfprintf(cc->ccdisc->text, "%s", fmtesq(x->format, quote));
-       sfprintf(cc->ccdisc->text, "\"");
-       for (x = expr->data.print.args; x; x = x->next) {
-           if (x->arg) {
-               for (i = 0; i < elementsof(x->param) && x->param[i]; i++) {
-                   sfprintf(cc->ccdisc->text, ", (");
-                   gen(cc, x->param[i]);
-                   sfprintf(cc->ccdisc->text, ")");
+       register Print_t*       x;
+       register int            i;
+
+       if ((x = expr->data.print.args))
+       {
+               sfprintf(cc->ccdisc->text, "sfprintf(%s, \"%s", expr->data.print.descriptor->op == CONSTANT && expr->data.print.descriptor->data.constant.value.integer == 2 ? "sfstderr" : "sfstdout", fmtesq(x->format, quote));
+               while ((x = x->next))
+                       sfprintf(cc->ccdisc->text, "%s", fmtesq(x->format, quote));
+               sfprintf(cc->ccdisc->text, "\"");
+               for (x = expr->data.print.args; x; x = x->next)
+               {
+                       if (x->arg)
+                       {
+                               for (i = 0; i < elementsof(x->param) && x->param[i]; i++)
+                               {
+                                       sfprintf(cc->ccdisc->text, ", (");
+                                       gen(cc, x->param[i]);
+                                       sfprintf(cc->ccdisc->text, ")");
+                               }
+                               sfprintf(cc->ccdisc->text, ", (");
+                               gen(cc, x->arg);
+                               sfprintf(cc->ccdisc->text, ")");
+                       }
                }
-               sfprintf(cc->ccdisc->text, ", (");
-               gen(cc, x->arg);
-               sfprintf(cc->ccdisc->text, ")");
-           }
+               sfprintf(cc->ccdisc->text, ");\n");
        }
-       sfprintf(cc->ccdisc->text, ");\n");
-    }
 }
 
 /*
  * generate scanf()
  */
 
-static void scan(Excc_t * cc, Exnode_t * expr)
+static void
+scan(Excc_t* cc, Exnode_t* expr)
 {
-    register Print_t *x;
-    register int i;
-
-    if ((x = expr->data.print.args)) {
-       sfprintf(cc->ccdisc->text, "sfscanf(sfstdin, \"%s",
-                fmtesq(x->format, quote));
-       while ((x = x->next))
-           sfprintf(cc->ccdisc->text, "%s", fmtesq(x->format, quote));
-       sfprintf(cc->ccdisc->text, "\"");
-       for (x = expr->data.print.args; x; x = x->next) {
-           if (x->arg) {
-               for (i = 0; i < elementsof(x->param) && x->param[i]; i++) {
-                   sfprintf(cc->ccdisc->text, ", &(");
-                   gen(cc, x->param[i]);
-                   sfprintf(cc->ccdisc->text, ")");
+       register Print_t*       x;
+       register int            i;
+
+       if ((x = expr->data.print.args))
+       {
+               sfprintf(cc->ccdisc->text, "sfscanf(sfstdin, \"%s", fmtesq(x->format, quote));
+               while ((x = x->next))
+                       sfprintf(cc->ccdisc->text, "%s", fmtesq(x->format, quote));
+               sfprintf(cc->ccdisc->text, "\"");
+               for (x = expr->data.print.args; x; x = x->next)
+               {
+                       if (x->arg)
+                       {
+                               for (i = 0; i < elementsof(x->param) && x->param[i]; i++)
+                               {
+                                       sfprintf(cc->ccdisc->text, ", &(");
+                                       gen(cc, x->param[i]);
+                                       sfprintf(cc->ccdisc->text, ")");
+                               }
+                               sfprintf(cc->ccdisc->text, ", &(");
+                               gen(cc, x->arg);
+                               sfprintf(cc->ccdisc->text, ")");
+                       }
                }
-               sfprintf(cc->ccdisc->text, ", &(");
-               gen(cc, x->arg);
-               sfprintf(cc->ccdisc->text, ")");
-           }
+               sfprintf(cc->ccdisc->text, ");\n");
        }
-       sfprintf(cc->ccdisc->text, ");\n");
-    }
 }
 
 /*
  * internal excc
  */
 
-static void gen(Excc_t * cc, register Exnode_t * expr)
+static void
+gen(Excc_t* cc, register Exnode_t* expr)
 {
-    register Exnode_t *x;
-    register Exnode_t *y;
-    register int n;
-    register int m;
-    register int t;
-    char *s;
-    Extype_t *v;
-    Extype_t **p;
-
-    if (!expr)
-       return;
-    if (expr->op == CALL) {
-       sfprintf(cc->ccdisc->text, "%s(", expr->data.call.procedure->name);
-       if (expr->data.call.args)
-           gen(cc, expr->data.call.args);
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-    }
-    x = expr->data.operand.left;
-    switch (expr->op) {
-    case BREAK:
-       sfprintf(cc->ccdisc->text, "break;\n");
-       return;
-    case CONTINUE:
-       sfprintf(cc->ccdisc->text, "continue;\n");
-       return;
-    case CONSTANT:
-       switch (expr->type) {
-       case FLOATING:
-           sfprintf(cc->ccdisc->text, "%g",
-                    expr->data.constant.value.floating);
-           break;
-       case STRING:
-           sfprintf(cc->ccdisc->text, "\"%s\"",
-                    fmtesq(expr->data.constant.value.string, quote));
-           break;
-       case UNSIGNED:
-           sfprintf(cc->ccdisc->text, "%I*u",
-                    sizeof(expr->data.constant.value.integer),
-                    expr->data.constant.value.integer);
-           break;
-       default:
-           sfprintf(cc->ccdisc->text, "%I*d",
-                    sizeof(expr->data.constant.value.integer),
-                    expr->data.constant.value.integer);
-           break;
-       }
-       return;
-    case DEC:
-       sfprintf(cc->ccdisc->text, "%s--", x->data.variable.symbol->name);
-       return;
-    case DYNAMIC:
-       sfprintf(cc->ccdisc->text, "%s", expr->data.variable.symbol->name);
-       return;
-    case EXIT:
-       sfprintf(cc->ccdisc->text, "exit(");
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ");\n");
-       return;
-    case FUNCTION:
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, "(");
-       if ((y = expr->data.operand.right)) {
-           gen(cc, y);
-       }
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-    case RAND:
-       sfprintf(cc->ccdisc->text, "rand();\n");
-       return;
-    case SRAND:
-       if (expr->binary) {
-           sfprintf(cc->ccdisc->text, "srand(");
-           gen(cc, x);
-           sfprintf(cc->ccdisc->text, ");\n");
-       } else
-           sfprintf(cc->ccdisc->text, "srand();\n");
-       return;
-    case GSUB:
-    case SUB:
-    case SUBSTR:
-       s = (expr->op == GSUB ? "gsub(" : expr->op ==
-            SUB ? "sub(" : "substr(");
-       sfprintf(cc->ccdisc->text, s);
-       gen(cc, expr->data.string.base);
-       sfprintf(cc->ccdisc->text, ", ");
-       gen(cc, expr->data.string.pat);
-       if (expr->data.string.repl) {
-           sfprintf(cc->ccdisc->text, ", ");
-           gen(cc, expr->data.string.repl);
-       }
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-    case IN_OP:
-        gen(cc, expr->data.variable.index);
-       sfprintf(cc->ccdisc->text, " in %s", expr->data.variable.symbol->name);
-       return;
-    case IF:
-       sfprintf(cc->ccdisc->text, "if (");
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ") {\n");
-       gen(cc, expr->data.operand.right->data.operand.left);
-       if (expr->data.operand.right->data.operand.right) {
-           sfprintf(cc->ccdisc->text, "} else {\n");
-           gen(cc, expr->data.operand.right->data.operand.right);
-       }
-       sfprintf(cc->ccdisc->text, "}\n");
-       return;
-    case FOR:
-       sfprintf(cc->ccdisc->text, "for (");
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ");");
-       if (expr->data.operand.left) {
-           sfprintf(cc->ccdisc->text, "(");
-           gen(cc, expr->data.operand.left);
-           sfprintf(cc->ccdisc->text, ")");
-       }
-       sfprintf(cc->ccdisc->text, ") {");
-       if (expr->data.operand.right)
-           gen(cc, expr->data.operand.right);
-       sfprintf(cc->ccdisc->text, "}");
-       return;
-    case ID:
-       if (cc->ccdisc->ccf)
-           (*cc->ccdisc->ccf) (cc, expr, expr->data.variable.symbol,
-                               expr->data.variable.reference,
-                               expr->data.variable.index, cc->ccdisc);
-       else
-           sfprintf(cc->ccdisc->text, "%s",
-                    expr->data.variable.symbol->name);
-       return;
-    case INC:
-       sfprintf(cc->ccdisc->text, "%s++", x->data.variable.symbol->name);
-       return;
-    case ITERATE:
-    case ITERATER:
-       if (expr->op == DYNAMIC) {
-           sfprintf(cc->ccdisc->text, "{ Exassoc_t* %stmp_%d;", cc->id,
-                    ++cc->tmp);
-           sfprintf(cc->ccdisc->text,
-                    "for (%stmp_%d = (Exassoc_t*)dtfirst(%s); %stmp_%d && (%s = %stmp_%d->name); %stmp_%d = (Exassoc_t*)dtnext(%s, %stmp_%d)) {",
-                    cc->id, cc->tmp,
-                    expr->data.generate.array->data.variable.symbol->name,
-                    cc->id, cc->tmp, expr->data.generate.index->name,
-                    cc->id, cc->tmp, cc->id, cc->tmp,
-                    expr->data.generate.array->data.variable.symbol->name,
-                    cc->id, cc->tmp);
-           gen(cc, expr->data.generate.statement);
-           sfprintf(cc->ccdisc->text, "} }");
+       register Exnode_t*      x;
+       register Exnode_t*      y;
+       register int            n;
+       register int            m;
+       register int            t;
+       char*                   s;
+       Extype_t*               v;
+       Extype_t**              p;
+
+       if (!expr)
+               return;
+       if (expr->op == CALL) {
+               sfprintf(cc->ccdisc->text, "%s(", expr->data.call.procedure->name);
+               if (expr->data.call.args)
+                       gen(cc, expr->data.call.args);
+               sfprintf(cc->ccdisc->text, ")");
+               return;
        }
-       return;
-    case PRINT:
-       sfprintf(cc->ccdisc->text, "print");
-       if (x)
-           gen(cc, x);
-       else
-           sfprintf(cc->ccdisc->text, "()");
-       return;
-    case PRINTF:
-       print(cc, expr);
-       return;
-    case RETURN:
-       sfprintf(cc->ccdisc->text, "return(");
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ");\n");
-       return;
-    case SCANF:
-       scan(cc, expr);
-       return;
-    case SPLIT:
-    case TOKENS:
-       if (expr->op == SPLIT)
-           sfprintf(cc->ccdisc->text, "split (");
-       else
-           sfprintf(cc->ccdisc->text, "tokens (");
-        gen(cc, expr->data.split.string);
-       sfprintf(cc->ccdisc->text, ", %s", expr->data.split.array->name);
-        if (expr->data.split.seps) {
-         sfprintf(cc->ccdisc->text, ",");
-          gen(cc, expr->data.split.seps);
-        }
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-    case SWITCH:
-       t = x->type;
-       sfprintf(cc->ccdisc->text, "{ %s %stmp_%d = ", extype(t), cc->id,
-                ++cc->tmp);
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ";");
-       x = expr->data.operand.right;
-       y = x->data.select.statement;
-       n = 0;
-       while ((x = x->data.select.next)) {
-           if (n)
-               sfprintf(cc->ccdisc->text, "else ");
-           if (!(p = x->data.select.constant))
+       x = expr->data.operand.left;
+       switch (expr->op)
+       {
+       case BREAK:
+               sfprintf(cc->ccdisc->text, "break;\n");
+               return;
+       case CONTINUE:
+               sfprintf(cc->ccdisc->text, "continue;\n");
+               return;
+       case CONSTANT:
+               switch (expr->type)
+               {
+               case FLOATING:
+                       sfprintf(cc->ccdisc->text, "%g", expr->data.constant.value.floating);
+                       break;
+               case STRING:
+                       sfprintf(cc->ccdisc->text, "\"%s\"", fmtesq(expr->data.constant.value.string, quote));
+                       break;
+               case UNSIGNED:
+                       sfprintf(cc->ccdisc->text, "%I*u", sizeof(expr->data.constant.value.integer), expr->data.constant.value.integer);
+                       break;
+               default:
+                       sfprintf(cc->ccdisc->text, "%I*d", sizeof(expr->data.constant.value.integer), expr->data.constant.value.integer);
+                       break;
+               }
+               return;
+       case DEC:
+               sfprintf(cc->ccdisc->text, "%s--", x->data.variable.symbol->name);
+               return;
+       case DYNAMIC:
+               sfprintf(cc->ccdisc->text, "%s", expr->data.variable.symbol->name);
+               return;
+       case EXIT:
+               sfprintf(cc->ccdisc->text, "exit(");
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ");\n");
+               return;
+       case FUNCTION:
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, "(");
+               if ((y = expr->data.operand.right)) {
+                       gen(cc, y);
+               }
+               sfprintf(cc->ccdisc->text, ")");
+               return;
+       case RAND:
+               sfprintf(cc->ccdisc->text, "rand();\n");
+               return;
+       case SRAND:
+               if (expr->binary) {
+                       sfprintf(cc->ccdisc->text, "srand(");
+                       gen(cc, x);
+                       sfprintf(cc->ccdisc->text, ");\n");
+               } else
+                       sfprintf(cc->ccdisc->text, "srand();\n");
+               return;
+       case GSUB:
+       case SUB:
+       case SUBSTR:
+               s = (expr->op == GSUB ? "gsub(" : expr->op == SUB ? "sub(" : "substr(");
+               sfprintf(cc->ccdisc->text, s);
+               gen(cc, expr->data.string.base);
+               sfprintf(cc->ccdisc->text, ", ");
+               gen(cc, expr->data.string.pat);
+               if (expr->data.string.repl) {
+                       sfprintf(cc->ccdisc->text, ", ");
+                       gen(cc, expr->data.string.repl);
+               }
+               sfprintf(cc->ccdisc->text, ")");
+               return;
+       case IN_OP:
+               gen(cc, expr->data.variable.index);
+               sfprintf(cc->ccdisc->text, " in %s", expr->data.variable.symbol->name);
+               return;
+       case IF:
+               sfprintf(cc->ccdisc->text, "if (");
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ") {\n");
+               gen(cc, expr->data.operand.right->data.operand.left);
+               if (expr->data.operand.right->data.operand.right)
+               {
+                       sfprintf(cc->ccdisc->text, "} else {\n");
+                       gen(cc, expr->data.operand.right->data.operand.right);
+               }
+               sfprintf(cc->ccdisc->text, "}\n");
+               return;
+       case FOR:
+               sfprintf(cc->ccdisc->text, "for (;");
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ");");
+               if (expr->data.operand.left)
+               {
+                       sfprintf(cc->ccdisc->text, "(");
+                       gen(cc, expr->data.operand.left);
+                       sfprintf(cc->ccdisc->text, ")");
+               }
+               sfprintf(cc->ccdisc->text, ") {");
+               if (expr->data.operand.right)
+                       gen(cc, expr->data.operand.right);
+               sfprintf(cc->ccdisc->text, "}");
+               return;
+       case ID:
+               if (cc->ccdisc->ccf)
+                       (*cc->ccdisc->ccf)(cc, expr, expr->data.variable.symbol, expr->data.variable.reference, expr->data.variable.index, cc->ccdisc);
+               else
+                       sfprintf(cc->ccdisc->text, "%s", expr->data.variable.symbol->name);
+               return;
+       case INC:
+               sfprintf(cc->ccdisc->text, "%s++", x->data.variable.symbol->name);
+               return;
+       case ITERATE:
+       case ITERATER:
+               if (expr->op == DYNAMIC)
+               {
+                       sfprintf(cc->ccdisc->text, "{ Exassoc_t* %stmp_%d;", cc->id, ++cc->tmp);
+                       sfprintf(cc->ccdisc->text, "for (%stmp_%d = (Exassoc_t*)dtfirst(%s); %stmp_%d && (%s = %stmp_%d->name); %stmp_%d = (Exassoc_t*)dtnext(%s, %stmp_%d)) {", cc->id, cc->tmp, expr->data.generate.array->data.variable.symbol->name, cc->id, cc->tmp, expr->data.generate.index->name, cc->id, cc->tmp, cc->id, cc->tmp, expr->data.generate.array->data.variable.symbol->name, cc->id, cc->tmp);
+                       gen(cc, expr->data.generate.statement);
+                       sfprintf(cc->ccdisc->text, "} }");
+               }
+               return;
+       case PRINT:
+               sfprintf(cc->ccdisc->text, "print");
+               if (x)
+                       gen(cc, x);
+               else
+                       sfprintf(cc->ccdisc->text, "()");
+               return;
+       case PRINTF:
+               print(cc, expr);
+               return;
+       case RETURN:
+               sfprintf(cc->ccdisc->text, "return(");
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ");\n");
+               return;
+       case SCANF:
+               scan(cc, expr);
+               return;
+       case SPLIT:
+       case TOKENS:
+               if (expr->op == SPLIT)
+                       sfprintf(cc->ccdisc->text, "split (");
+               else
+                       sfprintf(cc->ccdisc->text, "tokens (");
+               gen(cc, expr->data.split.string);
+               sfprintf(cc->ccdisc->text, ", %s", expr->data.split.array->name);
+               if (expr->data.split.seps) {
+                       sfprintf(cc->ccdisc->text, ",");
+                       gen(cc, expr->data.split.seps);
+               }
+               sfprintf(cc->ccdisc->text, ")");
+               return;
+       case SWITCH:
+               t = x->type;
+               sfprintf(cc->ccdisc->text, "{ %s %stmp_%d = ", extype(t), cc->id, ++cc->tmp);
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ";");
+               x = expr->data.operand.right;
                y = x->data.select.statement;
-           else {
-               m = 0;
-               while ((v = *p++)) {
-                   if (m)
-                       sfprintf(cc->ccdisc->text, "||");
-                   else {
-                       m = 1;
-                       sfprintf(cc->ccdisc->text, "if (");
-                   }
-                   if (t == STRING)
-                       sfprintf(cc->ccdisc->text,
-                                "strmatch(%stmp_%d, \"%s\")", cc->id,
-                                cc->tmp, fmtesq(v->string, quote));
-                   else {
-                       sfprintf(cc->ccdisc->text, "%stmp_%d == ", cc->id,
-                                cc->tmp);
-                       switch (t) {
-                       case INTEGER:
-                       case UNSIGNED:
-                           sfprintf(cc->ccdisc->text, "%I*u",
-                                    sizeof(v->integer), v->integer);
-                           break;
-                       default:
-                           sfprintf(cc->ccdisc->text, "%g", v->floating);
-                           break;
+               n = 0;
+               while ((x = x->data.select.next))
+               {
+                       if (n)
+                               sfprintf(cc->ccdisc->text, "else ");
+                       if (!(p = x->data.select.constant))
+                               y = x->data.select.statement;
+                       else
+                       {
+                               m = 0;
+                               while ((v = *p++))
+                               {
+                                       if (m)
+                                               sfprintf(cc->ccdisc->text, "||");
+                                       else
+                                       {
+                                               m = 1;
+                                               sfprintf(cc->ccdisc->text, "if (");
+                                       }
+                                       if (t == STRING)
+                                               sfprintf(cc->ccdisc->text, "strmatch(%stmp_%d, \"%s\")", cc->id, cc->tmp, fmtesq(v->string, quote));
+                                       else
+                                       {
+                                               sfprintf(cc->ccdisc->text, "%stmp_%d == ", cc->id, cc->tmp);
+                                               switch (t)
+                                               {
+                                               case INTEGER:
+                                               case UNSIGNED:
+                                                       sfprintf(cc->ccdisc->text, "%I*u", sizeof(v->integer), v->integer);
+                                                       break;
+                                               default:
+                                                       sfprintf(cc->ccdisc->text, "%g", v->floating);
+                                                       break;
+                                               }
+                                       }
+                               }
+                               sfprintf(cc->ccdisc->text, ") {");
+                               gen(cc, x->data.select.statement);
+                               sfprintf(cc->ccdisc->text, "}");
                        }
-                   }
                }
+               if (y)
+               {
+                       if (n)
+                               sfprintf(cc->ccdisc->text, "else ");
+                       sfprintf(cc->ccdisc->text, "{");
+                       gen(cc, y);
+                       sfprintf(cc->ccdisc->text, "}");
+               }
+               sfprintf(cc->ccdisc->text, "}");
+               return;
+       case UNSET:
+               sfprintf(cc->ccdisc->text, "unset(%s", expr->data.variable.symbol->name);
+               if (expr->data.variable.index) {
+                       sfprintf(cc->ccdisc->text, ",");
+                       gen(cc, expr->data.variable.index);
+               }
+               sfprintf(cc->ccdisc->text, ")");
+               return;
+       case WHILE:
+               sfprintf(cc->ccdisc->text, "while (");
+               gen(cc, x);
                sfprintf(cc->ccdisc->text, ") {");
-               gen(cc, x->data.select.statement);
+               if (expr->data.operand.right)
+                       gen(cc, expr->data.operand.right);
                sfprintf(cc->ccdisc->text, "}");
-           }
-       }
-       if (y) {
-           if (n)
-               sfprintf(cc->ccdisc->text, "else ");
-           sfprintf(cc->ccdisc->text, "{");
-           gen(cc, y);
-           sfprintf(cc->ccdisc->text, "}");
-       }
-       sfprintf(cc->ccdisc->text, "}");
-       return;
-    case UNSET:
-       sfprintf(cc->ccdisc->text, "unset(%s", expr->data.variable.symbol->name);
-        if (expr->data.variable.index) {
-         sfprintf(cc->ccdisc->text, ",");
-          gen(cc, expr->data.variable.index);
-        }
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-    case WHILE:
-       sfprintf(cc->ccdisc->text, "while (");
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ") {");
-       if (expr->data.operand.right)
-           gen(cc, expr->data.operand.right);
-       sfprintf(cc->ccdisc->text, "}");
-       return;
+               return;
     case '#':
-       sfprintf(cc->ccdisc->text, "# %s", 
-           expr->data.variable.symbol->name);
-       return;
-    case '=':
-       sfprintf(cc->ccdisc->text, "(%s%s=", x->data.variable.symbol->name,
-                expr->subop == '=' ? "" : exopname(expr->subop));
-       gen(cc, expr->data.operand.right);
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-    case ';':
-       for (;;) {
-           if (!(x = expr->data.operand.right))
-               switch (cc->lastop = expr->data.operand.left->op) {
-               case FOR:
-               case IF:
-               case PRINTF:
-               case PRINT:
-               case RETURN:
-               case WHILE:
-                   break;
-               default:
-                   sfprintf(cc->ccdisc->text, "_%svalue=", cc->id);
-                   break;
+               sfprintf(cc->ccdisc->text, "# %s", expr->data.variable.symbol->name);
+               return;
+       case '=':
+               sfprintf(cc->ccdisc->text, "(%s%s=", x->data.variable.symbol->name, expr->subop == '=' ? "" : exopname(expr->subop));
+               gen(cc, expr->data.operand.right);
+               sfprintf(cc->ccdisc->text, ")");
+               return;
+       case ';':
+               for (;;)
+               {
+                       if (!(x = expr->data.operand.right))
+                               switch (cc->lastop = expr->data.operand.left->op)
+                               {
+                               case FOR:
+                               case IF:
+                               case PRINTF:
+                               case PRINT:
+                               case RETURN:
+                               case WHILE:
+                                       break;
+                               default:
+                                       sfprintf(cc->ccdisc->text, "_%svalue=", cc->id);
+                                       break;
+                               }
+                       gen(cc, expr->data.operand.left);
+                       sfprintf(cc->ccdisc->text, ";\n");
+                       if (!(expr = x))
+                               break;
+                       switch (cc->lastop = expr->op)
+                       {
+                       case ';':
+                               continue;
+                       case FOR:
+                       case IF:
+                       case PRINTF:
+                       case PRINT:
+                       case RETURN:
+                       case WHILE:
+                               break;
+                       default:
+                               sfprintf(cc->ccdisc->text, "_%svalue=", cc->id);
+                               break;
+                       }
+                       gen(cc, expr);
+                       sfprintf(cc->ccdisc->text, ";\n");
+                       break;
                }
-           gen(cc, expr->data.operand.left);
-           sfprintf(cc->ccdisc->text, ";\n");
-           if (!(expr = x))
-               break;
-           switch (cc->lastop = expr->op) {
-           case ';':
-               continue;
-           case FOR:
-           case IF:
-           case PRINTF:
-           case PRINT:
-           case RETURN:
-           case WHILE:
-               break;
-           default:
-               sfprintf(cc->ccdisc->text, "_%svalue=", cc->id);
-               break;
-           }
-           gen(cc, expr);
-           sfprintf(cc->ccdisc->text, ";\n");
-           break;
-       }
-       return;
-    case ',':
-       sfprintf(cc->ccdisc->text, "(");
-       gen(cc, x);
-       while ((expr = expr->data.operand.right) && expr->op == ',') {
-           sfprintf(cc->ccdisc->text, "), (");
-           gen(cc, expr->data.operand.left);
-       }
-       if (expr) {
-           sfprintf(cc->ccdisc->text, "), (");
-           gen(cc, expr);
-       }
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-    case '?':
-       sfprintf(cc->ccdisc->text, "(");
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ") ? (");
-       gen(cc, expr->data.operand.right->data.operand.left);
-       sfprintf(cc->ccdisc->text, ") : (");
-       gen(cc, expr->data.operand.right->data.operand.right);
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-    case AND:
-       sfprintf(cc->ccdisc->text, "(");
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ") && (");
-       gen(cc, expr->data.operand.right);
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-    case OR:
-       sfprintf(cc->ccdisc->text, "(");
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ") || (");
-       gen(cc, expr->data.operand.right);
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-    case F2I:
-       sfprintf(cc->ccdisc->text, "(%s)(", extype(INTEGER));
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-    case I2F:
-       sfprintf(cc->ccdisc->text, "(%s)(", extype(FLOATING));
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-    case S2I:
-       sfprintf(cc->ccdisc->text, "strtoll(");
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ",(char**)0,0)");
-       return;
-     case X2I:
-       sfprintf(cc->ccdisc->text, "X2I(");
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-     case X2X:
-       sfprintf(cc->ccdisc->text, "X2X(");
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ")");
-       return;
-    }
-    y = expr->data.operand.right;
-    if (x->type == STRING) {
-       switch (expr->op) {
-       case S2B:
-           sfprintf(cc->ccdisc->text, "*(");
-           gen(cc, x);
-           sfprintf(cc->ccdisc->text, ")!=0");
-           return;
-       case S2F:
-           sfprintf(cc->ccdisc->text, "strtod(");
-           gen(cc, x);
-           sfprintf(cc->ccdisc->text, ",0)");
-           return;
+               return;
+       case ',':
+               sfprintf(cc->ccdisc->text, "(");
+               gen(cc, x);
+               while ((expr = expr->data.operand.right) && expr->op == ',')
+               {
+                       sfprintf(cc->ccdisc->text, "), (");
+                       gen(cc, expr->data.operand.left);
+               }
+               if (expr)
+               {
+                       sfprintf(cc->ccdisc->text, "), (");
+                       gen(cc, expr);
+               }
+               sfprintf(cc->ccdisc->text, ")");
+               return;
+       case '?':
+               sfprintf(cc->ccdisc->text, "(");
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ") ? (");
+               gen(cc, expr->data.operand.right->data.operand.left);
+               sfprintf(cc->ccdisc->text, ") : (");
+               gen(cc, expr->data.operand.right->data.operand.right);
+               sfprintf(cc->ccdisc->text, ")");
+               return;
+       case AND:
+               sfprintf(cc->ccdisc->text, "(");
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ") && (");
+               gen(cc, expr->data.operand.right);
+               sfprintf(cc->ccdisc->text, ")");
+               return;
+       case OR:
+               sfprintf(cc->ccdisc->text, "(");
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ") || (");
+               gen(cc, expr->data.operand.right);
+               sfprintf(cc->ccdisc->text, ")");
+               return;
+       case F2I:
+               sfprintf(cc->ccdisc->text, "(%s)(", extype(INTEGER));
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ")");
+               return;
+       case I2F:
+               sfprintf(cc->ccdisc->text, "(%s)(", extype(FLOATING));
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ")");
+               return;
        case S2I:
-           sfprintf(cc->ccdisc->text, "strtol(");
-           gen(cc, x);
-           sfprintf(cc->ccdisc->text, ",0,0)");
-           return;
-       case S2X:
-           sfprintf(cc->ccdisc->text,
-                    "** cannot convert string value to external **");
-           return;
-       case NE:
-           sfprintf(cc->ccdisc->text, "!");
-        /*FALLTHROUGH*/ case EQ:
-           sfprintf(cc->ccdisc->text, "strmatch(");
-           gen(cc, x);
-           sfprintf(cc->ccdisc->text, ",");
-           gen(cc, y);
-           sfprintf(cc->ccdisc->text, ")");
-           return;
-       case '+':
-       case '|':
-       case '&':
-       case '^':
-       case '%':
-       case '*':
-           sfprintf(cc->ccdisc->text, "** string bits not supported **");
-           return;
+               /* sfprintf(cc->ccdisc->text, "strto%s(", sizeof(intmax_t) > sizeof(long) ? "ll" : "l"); */
+               sfprintf(cc->ccdisc->text, "strtoll(");
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ",(char**)0,0)");
+               return;
+    case X2I:
+               sfprintf(cc->ccdisc->text, "X2I(");
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ")");
+               return;
+       case X2X:
+               sfprintf(cc->ccdisc->text, "X2X(");
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ")");
+               return;
        }
-       switch (expr->op) {
-       case '<':
-           s = "<0";
-           break;
-       case LE:
-           s = "<=0";
-           break;
-       case GE:
-           s = ">=0";
-           break;
-       case '>':
-           s = ">0";
-           break;
-       default:
-           s = "** unknown string op **";
-           break;
+       y = expr->data.operand.right;
+       if (x->type == STRING)
+       {
+               switch (expr->op)
+               {
+               case S2B:
+                       sfprintf(cc->ccdisc->text, "*(");
+                       gen(cc, x);
+                       sfprintf(cc->ccdisc->text, ")!=0");
+                       return;
+               case S2F:
+                       sfprintf(cc->ccdisc->text, "strtod(");
+                       gen(cc, x);
+                       sfprintf(cc->ccdisc->text, ",0)");
+                       return;
+               case S2I:
+                       sfprintf(cc->ccdisc->text, "strtol(");
+                       gen(cc, x);
+                       sfprintf(cc->ccdisc->text, ",0,0)");
+                       return;
+               case S2X:
+                       sfprintf(cc->ccdisc->text, "** cannot convert string value to external **");
+                       return;
+               case NE:
+                       sfprintf(cc->ccdisc->text, "!");
+                       /*FALLTHROUGH*/
+               case EQ:
+                       sfprintf(cc->ccdisc->text, "strmatch(");
+                       gen(cc, x);
+                       sfprintf(cc->ccdisc->text, ",");
+                       gen(cc, y);
+                       sfprintf(cc->ccdisc->text, ")");
+                       return;
+               case '+':
+               case '|':
+               case '&':
+               case '^':
+               case '%':
+               case '*':
+                       sfprintf(cc->ccdisc->text, "** string bits not supported **");
+                       return;
+               }
+               switch (expr->op)
+               {
+               case '<':
+                       s = "<0";
+                       break;
+               case LE:
+                       s = "<=0";
+                       break;
+               case GE:
+                       s = ">=0";
+                       break;
+               case '>':
+                       s = ">0";
+                       break;
+               default:
+                       s = "** unknown string op **";
+                       break;
+               }
+               sfprintf(cc->ccdisc->text, "strcoll(");
+               gen(cc, x);
+               sfprintf(cc->ccdisc->text, ",");
+               gen(cc, y);
+               sfprintf(cc->ccdisc->text, ")%s", s);
+               return;
        }
-       sfprintf(cc->ccdisc->text, "strcoll(");
-       gen(cc, x);
-       sfprintf(cc->ccdisc->text, ",");
-       gen(cc, y);
-       sfprintf(cc->ccdisc->text, ")%s", s);
-       return;
-    } else {
-       if (!y)
-           sfprintf(cc->ccdisc->text, "%s", exopname(expr->op));
-       sfprintf(cc->ccdisc->text, "(");
-       gen(cc, x);
-       if (y) {
-           sfprintf(cc->ccdisc->text, ")%s(", exopname(expr->op));
-           gen(cc, y);
+       else
+       {
+               if (!y)
+                       sfprintf(cc->ccdisc->text, "%s", exopname(expr->op));
+               sfprintf(cc->ccdisc->text, "(");
+               gen(cc, x);
+               if (y)
+               {
+                       sfprintf(cc->ccdisc->text, ")%s(", exopname(expr->op));
+                       gen(cc, y);
+               }
+               sfprintf(cc->ccdisc->text, ")");
        }
-       sfprintf(cc->ccdisc->text, ")");
-    }
-    return;
+       return;
 }
 
 /*
@@ -615,119 +621,123 @@ static void gen(Excc_t * cc, register Exnode_t * expr)
  */
 
 static int
-global (Dt_t * table, void *object, void *handle) {
-    register Excc_t *cc = (Excc_t *) handle;
-    register Exid_t *sym = (Exid_t *) object;
-
-    if (sym->lex == DYNAMIC)
-       sfprintf(cc->ccdisc->text, "static %s   %s;\n", extype(sym->type),
-                sym->name);
-    return 0;
+global(Dt_t* table, void* object, void* handle)
+{
+       register Excc_t*        cc = (Excc_t*)handle;
+       register Exid_t*        sym = (Exid_t*)object;
+
+       if (sym->lex == DYNAMIC)
+               sfprintf(cc->ccdisc->text, "static %s   %s;\n", extype(sym->type), sym->name);
+       return 0;
 }
 
 /*
  * open C program generator context
  */
 
-Excc_t *exccopen(Expr_t * expr, Exccdisc_t * disc)
+Excc_t*
+exccopen(Expr_t* expr, Exccdisc_t* disc)
 {
-    register Excc_t *cc;
-    char *id;
-
-    if (!(id = disc->id))
-       id = "";
-    if (!(cc = newof(0, Excc_t, 1, strlen(id) + 2)))
-       return 0;
-    cc->expr = expr;
-    cc->disc = expr->disc;
-    cc->id = (char *) (cc + 1);
-    cc->ccdisc = disc;
-    if (!(disc->flags & EX_CC_DUMP)) {
-       sfprintf(disc->text, "/* : : generated by %s : : */\n", exversion);
-       sfprintf(disc->text, "\n#include <ast.h>\n");
-       if (*id)
-           sfsprintf(cc->id, strlen(id) + 2, "%s_", id);
-       sfprintf(disc->text, "\n");
-       dtwalk(expr->symbols, global, cc);
-    }
-    return cc;
+       register Excc_t*        cc;
+       char*                   id;
+
+       if (!(id = disc->id))
+               id = "";
+       if (!(cc = newof(0, Excc_t, 1, strlen(id) + 2)))
+               return 0;
+       cc->expr = expr;
+       cc->disc = expr->disc;
+       cc->id = (char*)(cc + 1);
+       cc->ccdisc = disc;
+       if (!(disc->flags & EX_CC_DUMP))
+       {
+               sfprintf(disc->text, "/* : : generated by %s : : */\n", exversion);
+               sfprintf(disc->text, "\n#include <ast.h>\n");
+               if (*id)
+                       sfsprintf(cc->id, strlen(id) + 2, "%s_", id);
+               sfprintf(disc->text, "\n");
+               dtwalk(expr->symbols, global, cc);
+       }
+       return cc;
 }
 
 /*
  * close C program generator context
  */
 
-int exccclose(Excc_t * cc)
+int
+exccclose(Excc_t* cc)
 {
-    int r = 0;
-
-    if (!cc)
-       r = -1;
-    else {
-       if (!(cc->ccdisc->flags & EX_CC_DUMP)) {
-           if (cc->ccdisc->text)
-               sfclose(cc->ccdisc->text);
-           else
+       int     r = 0;
+
+       if (!cc)
                r = -1;
+       else
+       {
+               if (!(cc->ccdisc->flags & EX_CC_DUMP))
+               {
+                       if (cc->ccdisc->text)
+                               sfclose(cc->ccdisc->text);
+                       else
+                               r = -1;
+               }
+               free(cc);
        }
-       free(cc);
-    }
-    return r;
+       return r;
 }
 
 /*
  * generate the program for name or sym coerced to type
  */
 
-int excc(Excc_t * cc, const char *name, Exid_t * sym, int type)
+int
+excc(Excc_t* cc, const char* name, Exid_t* sym, int type)
 {
-    register char *t;
-
-    if (!cc)
+       register char*  t;
+
+       if (!cc)
+               return -1;
+       if (!sym)
+               sym = name ? (Exid_t*)dtmatch(cc->expr->symbols, name) : &cc->expr->main;
+       if (sym && sym->lex == PROCEDURE && sym->value)
+       {
+               t = extype(type);
+               sfprintf(cc->ccdisc->text, "\n%s %s%s(data) char** data; {\n%s _%svalue = 0;\n", t, cc->id, sym->name, t, cc->id);
+               gen(cc, sym->value->data.procedure.body);
+               sfprintf(cc->ccdisc->text, ";\n");
+               if (cc->lastop != RETURN)
+                       sfprintf(cc->ccdisc->text, "return _%svalue;\n", cc->id);
+               sfprintf(cc->ccdisc->text, "}\n");
+               return 0;
+       }
        return -1;
-    if (!sym)
-       sym =
-           name ? (Exid_t *) dtmatch(cc->expr->symbols,
-                                     name) : &cc->expr->main;
-    if (sym && sym->lex == PROCEDURE && sym->value) {
-       t = extype(type);
-       sfprintf(cc->ccdisc->text,
-                "\n%s %s%s(data) char** data; {\n%s _%svalue = 0;\n", t,
-                cc->id, sym->name, t, cc->id);
-       gen(cc, sym->value->data.procedure.body);
-       sfprintf(cc->ccdisc->text, ";\n");
-       if (cc->lastop != RETURN)
-           sfprintf(cc->ccdisc->text, "return _%svalue;\n", cc->id);
-       sfprintf(cc->ccdisc->text, "}\n");
-       return 0;
-    }
-    return -1;
 }
 
 /*
  * dump an expression tree on sp
  */
 
-int exdump(Expr_t * expr, Exnode_t * node, Sfio_t * sp)
+int
+exdump(Expr_t* expr, Exnode_t* node, Sfio_t* sp)
 {
-    Excc_t *cc;
-    Exccdisc_t ccdisc;
-    Exid_t *sym;
-
-    memset(&ccdisc, 0, sizeof(ccdisc));
-    ccdisc.flags = EX_CC_DUMP;
-    ccdisc.text = sp;
-    if (!(cc = exccopen(expr, &ccdisc)))
-       return -1;
-    if (node)
-       gen(cc, node);
-    else
-       for (sym = (Exid_t *) dtfirst(expr->symbols); sym;
-            sym = (Exid_t *) dtnext(expr->symbols, sym))
-           if (sym->lex == PROCEDURE && sym->value) {
-               sfprintf(sp, "\n%s:\n", sym->name);
-               gen(cc, sym->value->data.procedure.body);
-           }
-    sfprintf(sp, "\n");
-    return exccclose(cc);
+       Excc_t*         cc;
+       Exccdisc_t      ccdisc;
+       Exid_t*         sym;
+
+       memset(&ccdisc, 0, sizeof(ccdisc));
+       ccdisc.flags = EX_CC_DUMP;
+       ccdisc.text = sp;
+       if (!(cc = exccopen(expr, &ccdisc)))
+               return -1;
+       if (node)
+               gen(cc, node);
+       else
+               for (sym = (Exid_t*)dtfirst(expr->symbols); sym; sym = (Exid_t*)dtnext(expr->symbols, sym))
+                       if (sym->lex == PROCEDURE && sym->value)
+                       {
+                               sfprintf(sp, "%s:\n", sym->name);
+                               gen(cc, sym->value->data.procedure.body);
+                       }
+       sfprintf(sp, "\n");
+       return exccclose(cc);
 }
index 96dc6e1da236bc11885ca018cdde4d10b3736018..7353ac4177dfa7200479315c5a713a35ca8ebaff 100644 (file)
@@ -1,4 +1,3 @@
-/* $Id$ $Revision$ */
 /* vim:set shiftwidth=4 ts=8: */
 
 /*************************************************************************
  * end of buf returned
  */
 
-char *excontext(Expr_t * p, char *buf, int n)
+char*
+excontext(Expr_t* p, char* buf, int n)
 {
-    register char *s;
-    register char *t;
-    register char *e;
+       register char*  s;
+       register char*  t;
+       register char*  e;
 
-    s = buf;
-    if (p->linep > p->line || p->linewrap) {
-       e = buf + n - 5;
-       if (p->linewrap) {
-           t = p->linep + 1;
-           while (t < &p->line[sizeof(p->line)] && isspace(*t))
-               t++;
-           if ((n =
-                (sizeof(p->line) - (t - (p->linep + 1))) - (e - s)) > 0) {
-               if (n > &p->line[sizeof(p->line)] - t)
-                   t = &p->line[sizeof(p->line)];
-               else
-                   t += n;
-           }
-           while (t < &p->line[sizeof(p->line)])
-               *s++ = *t++;
+       s = buf;
+       if (p->linep > p->line || p->linewrap)
+       {
+               e = buf + n - 5;
+               if (p->linewrap)
+               {
+                       t = p->linep + 1;
+                       while (t < &p->line[sizeof(p->line)] && isspace(*t))
+                               t++;
+                       if ((n = (sizeof(p->line) - (t - (p->linep + 1))) - (e - s)) > 0)
+                       {
+                               if (n > &p->line[sizeof(p->line)] - t)
+                                       t = &p->line[sizeof(p->line)];
+                               else t += n;
+                       }
+                       while (t < &p->line[sizeof(p->line)])
+                               *s++ = *t++;
+               }
+               t = p->line;
+               if (p->linewrap)
+                       p->linewrap = 0;
+               else while (t < p->linep && isspace(*t))
+                       t++;
+               if ((n = (p->linep - t) - (e - s)) > 0)
+                       t += n;
+               while (t < p->linep)
+                       *s++ = *t++;
+               p->linep = p->line;
+               t = "<<< ";
+               while ((*s = *t++))
+                       s++;
        }
-       t = p->line;
-       if (p->linewrap)
-           p->linewrap = 0;
-       else
-           while (t < p->linep && isspace(*t))
-               t++;
-       if ((n = (p->linep - t) - (e - s)) > 0)
-           t += n;
-       while (t < p->linep)
-           *s++ = *t++;
-       p->linep = p->line;
-       t = "<<< ";
-       while ((*s = *t++))
-           s++;
-    }
-    *s = 0;
-    return s;
+       *s = 0;
+       return s;
 }
index c3752513c34593b372b3fbea0a7506a89783f6ce..d46d809de3cfe5d408d7efd561a7b131b8524726 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
+/* vim:set shiftwidth=4 ts=4: */
 
 /*************************************************************************
  * Copyright (c) 2011 AT&T Intellectual Property 
  * expression library readonly tables
  */
 
-static const char id[] =
-    "\n@(#)$Id$\0\n";
+static const char id[] = "\n@(#)$Id: libexpr (AT&T Research) 2011-06-30 $\0\n";
 
 #include <exlib.h>
 
-const char *exversion = id + 10;
+const char*    exversion = id + 10;
 
-Exid_t exbuiltin[] = {
+Exid_t         exbuiltin[] =
+{
 
-    /* id_string references the first entry */
+       /* id_string references the first entry */
 
-    EX_ID("string", DECLARE, STRING, STRING, 0),
+       EX_ID("string", DECLARE,        STRING,         STRING, 0),
 
-    /* order not important after this point (but sorted anyway) */
+       /* order not important after this point (but sorted anyway) */
 
-    EX_ID("break", BREAK, BREAK, 0, 0),
-    EX_ID("case", CASE, CASE, 0, 0),
-    EX_ID("char", DECLARE, CHARACTER, CHARACTER, 0),
-    EX_ID("continue", CONTINUE, CONTINUE, 0, 0),
-    EX_ID("default", DEFAULT, DEFAULT, 0, 0),
-    EX_ID("double", DECLARE, FLOATING, FLOATING, 0),
-    EX_ID("else", ELSE, ELSE, 0, 0),
-    EX_ID("exit", EXIT, EXIT, INTEGER, 0),
-    EX_ID("for", FOR, FOR, 0, 0),
-    EX_ID("forr", ITERATER, ITERATER, 0, 0),
-    EX_ID("float", DECLARE, FLOATING, FLOATING, 0),
-    EX_ID("gsub", GSUB, GSUB, STRING, 0),
-    EX_ID("if", IF, IF, 0, 0),
-    EX_ID("in", IN_OP, IN_OP, 0, 0),
-    EX_ID("int", DECLARE, INTEGER, INTEGER, 0),
-    EX_ID("long", DECLARE, INTEGER, INTEGER, 0),
-    EX_ID("print", PRINT, PRINT, INTEGER, 0),
-    EX_ID("printf", PRINTF, PRINTF, INTEGER, 0),
-    EX_ID("query", QUERY, QUERY, INTEGER, 0),
-    EX_ID("rand", RAND, RAND, FLOATING, 0),
-    EX_ID("return", RETURN, RETURN, 0, 0),
-    EX_ID("scanf", SCANF, SCANF, INTEGER, 0),
-    EX_ID("sscanf", SSCANF, SSCANF, INTEGER, 0),
-    EX_ID("split", SPLIT, SPLIT, INTEGER, 0),
-    EX_ID("sprintf", SPRINTF, SPRINTF, STRING, 0),
-    EX_ID("srand", SRAND, SRAND, INTEGER, 0),
-    EX_ID("sub", SUB, SUB, STRING, 0),
-    EX_ID("substr", SUBSTR, SUBSTR, STRING, 0),
-    EX_ID("switch", SWITCH, SWITCH, 0, 0),
-    EX_ID("tokens", TOKENS, TOKENS, INTEGER, 0),
-    EX_ID("unsigned", DECLARE, UNSIGNED, UNSIGNED, 0),
-    EX_ID("void", DECLARE, VOIDTYPE, 0, 0),
-    EX_ID("unset", UNSET, UNSET, 0, 0),
-    EX_ID("while", WHILE, WHILE, 0, 0),
-    EX_ID({0}, 0, 0, 0, 0)
+       EX_ID("break",  BREAK,          BREAK,          0,      0),
+       EX_ID("case",   CASE,           CASE,           0,      0),
+       EX_ID("char",   DECLARE,        CHARACTER,              CHARACTER,      0),
+       EX_ID("continue",CONTINUE,      CONTINUE,       0,      0),
+       EX_ID("default",        DEFAULT,        DEFAULT,        0,      0),
+       EX_ID("double", DECLARE,        FLOATING,       FLOATING,0),
+       EX_ID("else",   ELSE,           ELSE,           0,      0),
+       EX_ID("exit",   EXIT,           EXIT,           INTEGER,0),
+       EX_ID("for",    FOR,            FOR,            0,      0),
+       EX_ID("forr",   ITERATER,       ITERATER,       0,      0),
+       EX_ID("float",  DECLARE,        FLOATING,       FLOATING,0),
+       EX_ID("gsub",   GSUB,           GSUB,           STRING, 0),
+       EX_ID("if",     IF,             IF,             0,      0),
+       EX_ID("in",     IN_OP,          IN_OP,          0,      0),
+       EX_ID("int",    DECLARE,        INTEGER,        INTEGER,0),
+       EX_ID("long",   DECLARE,        INTEGER,        INTEGER,0),
+       EX_ID("print",  PRINT,          PRINT,          INTEGER,0),
+       EX_ID("printf", PRINTF,         PRINTF,         INTEGER,0),
+       EX_ID("query",  QUERY,          QUERY,          INTEGER,0),
+       EX_ID("rand",   RAND,           RAND,           FLOATING,0),
+       EX_ID("return", RETURN,         RETURN,         0,      0),
+       EX_ID("scanf",  SCANF,          SCANF,          INTEGER,0),
+       EX_ID("sscanf", SSCANF,         SSCANF,         INTEGER,0),
+       EX_ID("split",  SPLIT,          SPLIT,          INTEGER,0),
+       EX_ID("sprintf",        SPRINTF,        SPRINTF,        STRING, 0),
+       EX_ID("srand",  SRAND,          SRAND,          INTEGER,0),
+       EX_ID("static", STATIC,         STATIC,         0,      0),
+       EX_ID("sub",    SUB,            SUB,            STRING, 0),
+       EX_ID("substr", SUBSTR,         SUBSTR,         STRING, 0),
+       EX_ID("switch", SWITCH,         SWITCH,         0,      0),
+       EX_ID("tokens", TOKENS,         TOKENS,         INTEGER,0),
+       EX_ID("unset",  UNSET,          UNSET,          0,      0),
+       EX_ID("unsigned",DECLARE,       UNSIGNED,       UNSIGNED,0),
+       EX_ID("void",   DECLARE,        VOIDTYPE,       0,      0),
+       EX_ID("while",  WHILE,          WHILE,          0,      0),
+       EX_ID("while",  WHILE,          WHILE,          0,      0),
+       EX_ID({0},              0,              0,              0,      0)
 
 };
index cdfa3a800c5b087c83fce088887f2662772a44a5..235d4f9de34d011d7b7a5a9d28f45aa0b2132f90 100644 (file)
@@ -1,4 +1,3 @@
-/* $Id$ $Revision$ */
 /* vim:set shiftwidth=4 ts=8: */
 
 /*************************************************************************
  * library error handler
  */
 
-void exerror(const char *format, ...)
+void
+exerror(const char* format, ...)
 {
-    Sfio_t *sp;
+       Sfio_t* sp;
 
-    if (expr.program->disc->errorf && !expr.program->errors
-       && (sp = sfstropen())) {
-       va_list ap;
-       char *s;
-       char buf[64];
+       if (expr.program->disc->errorf && !expr.program->errors && (sp = sfstropen()))
+       {
+               va_list ap;
+               char*   s;
+               char    buf[64];
 
-       expr.program->errors = 1;
-       excontext(expr.program, buf, sizeof(buf));
-       sfputr(sp, buf, -1);
-       sfputr(sp, "\n -- ", -1);
-       va_start(ap, format);
-       sfvprintf(sp, format, ap);
-       va_end(ap);
-       s = sfstruse(sp);
-       (*expr.program->disc->errorf) (expr.program, expr.program->disc,
-                                      (expr.program->disc->
-                                       flags & EX_FATAL) ? ERROR_FATAL :
-                                      ERROR_ERROR, "%s", s);
-       sfclose(sp);
-    } else if (expr.program->disc->flags & EX_FATAL)
-       exit(1);
+               expr.program->errors = 1;
+               excontext(expr.program, buf, sizeof(buf));
+               sfputr(sp, buf, -1);
+               sfputr(sp, "\n -- ", -1);
+               va_start(ap, format);
+               sfvprintf(sp, format, ap);
+               va_end(ap);
+               if (!(s = sfstruse(sp)))
+                       s = "out of space";
+               (*expr.program->disc->errorf)(expr.program, expr.program->disc, (expr.program->disc->flags & EX_FATAL) ? 3 : 2, "%s", s);
+               sfclose(sp);
+       }
+       else if (expr.program->disc->flags & EX_FATAL)
+               exit(1);
 }
 
-void exwarn(const char *format, ...)
+void 
+exwarn(const char *format, ...)
 {
-    Sfio_t *sp;
+       Sfio_t *sp;
 
-    if (expr.program->disc->errorf && (sp = sfstropen())) {
-       va_list ap;
-       char *s;
-       char buf[64];
+       if (expr.program->disc->errorf && (sp = sfstropen())) {
+               va_list ap;
+               char *s;
+               char buf[64];
 
-       excontext(expr.program, buf, sizeof(buf));
-       sfputr(sp, buf, -1);
-       sfputr(sp, "\n -- ", -1);
-       va_start(ap, format);
-       sfvprintf(sp, format, ap);
-       va_end(ap);
-       s = sfstruse(sp);
-       (*expr.program->disc->errorf) (expr.program, expr.program->disc,
+               excontext(expr.program, buf, sizeof(buf));
+               sfputr(sp, buf, -1);
+               sfputr(sp, "\n -- ", -1);
+               va_start(ap, format);
+               sfvprintf(sp, format, ap);
+               va_end(ap);
+               s = sfstruse(sp);
+               (*expr.program->disc->errorf) (expr.program, expr.program->disc,
                                       ERROR_WARNING, "%s", s);
        sfclose(sp);
-    }
+       }
 }
index 246f10430aaaac9d57a9bfe962f88e54ab529aae..8c3cbcf7c56f0b624333f41b57480f8772669ef0 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
+/* vim:set shiftwidth=4 ts=4: */
 
 /*************************************************************************
  * Copyright (c) 2011 AT&T Intellectual Property 
 #define drand48 rand
 #endif
 
+#ifdef OLD
+#include <tm.h>
+#else
+#define TIME_LEN 80             /* max. characters to store time */
+#endif
 
-static Extype_t eval(Expr_t *, Exnode_t *, void *);
+static Extype_t        eval(Expr_t*, Exnode_t*, void*);
 
 #define TOTNAME                4
 #define MAXNAME                16
 #define FRAME          64
 
-static char *lexname(int op, int subop)
+static char*
+lexname(int op, int subop)
 {
-    register char *b;
-
-    static int n;
-    static char buf[TOTNAME][MAXNAME];
-
-    if (op > MINTOKEN && op < MAXTOKEN)
-       return (char *) exop[op - MINTOKEN];
-    if (++n >= TOTNAME)
-       n = 0;
-    b = buf[n];
-    if (op == '=') {
-       if (subop > MINTOKEN && subop < MAXTOKEN)
-           sfsprintf(b, MAXNAME, "%s=", exop[subop - MINTOKEN]);
-       else if (subop > ' ' && subop <= '~')
-           sfsprintf(b, MAXNAME, "%c=", subop);
+       register char*  b;
+
+       static int      n;
+       static char     buf[TOTNAME][MAXNAME];
+
+       if (op > MINTOKEN && op < MAXTOKEN)
+               return (char*)exop[op - MINTOKEN];
+       if (++n >= TOTNAME)
+               n = 0;
+       b = buf[n];
+       if (op == '=')
+       {
+               if (subop > MINTOKEN && subop < MAXTOKEN)
+                       sfsprintf(b, MAXNAME, "%s=", exop[subop - MINTOKEN]);
+               else if (subop > ' ' && subop <= '~')
+                       sfsprintf(b, MAXNAME, "%c=", subop);
+               else
+                       sfsprintf(b, MAXNAME, "(%d)=", subop);
+       }
+       else if (subop < 0)
+               sfsprintf(b, MAXNAME, "(EXTERNAL:%d)", op);
+       else if (op > ' ' && op <= '~')
+               sfsprintf(b, MAXNAME, "%c", op);
        else
-           sfsprintf(b, MAXNAME, "(%d)=", subop);
-    } else if (subop < 0)
-       sfsprintf(b, MAXNAME, "(EXTERNAL:%d)", op);
-    else if (op > ' ' && op <= '~')
-       sfsprintf(b, MAXNAME, "%c", op);
-    else
-       sfsprintf(b, MAXNAME, "(%d)", op);
-    return b;
+               sfsprintf(b, MAXNAME, "(%d)", op);
+       return b;
 }
 
 /* evaldyn:
@@ -80,41 +87,39 @@ static char *lexname(int op, int subop)
 static int
 evaldyn (Expr_t * ex, register Exnode_t * expr, void *env, int delete)
 {
-    Exassoc_t *b;
-    Extype_t v;
-    char buf[32];
-    Extype_t key;
-    char *keyname;
-
-    v = eval(ex, expr->data.variable.index, env);
-    if (expr->data.variable.symbol->index_type == INTEGER) {
-       if (!(b = (Exassoc_t *) dtmatch((Dt_t *) expr->data.variable.
-               symbol->local.pointer, &v))) {
-           return 0;
-       }
-    } 
-    else {
-       int type = expr->data.variable.index->type;
-       if (type != STRING) {
-               if (!BUILTIN(type)) {
-                   key = (*ex->disc->keyf) (ex, v, type, ex->disc);
+       Exassoc_t *b;
+       Extype_t v;
+       char buf[32];
+       Extype_t key;
+       char *keyname;
+
+       v = eval(ex, expr->data.variable.index, env);
+       if (expr->data.variable.symbol->index_type == INTEGER) {
+               if (!(b = (Exassoc_t *) dtmatch((Dt_t *) expr->data.variable.symbol->local.pointer, &v))) {
+                       return 0;
+               }
+       } 
+       else {
+               int type = expr->data.variable.index->type;
+               if (type != STRING) {
+                       if (!BUILTIN(type)) {
+                               key = (*ex->disc->keyf) (ex, v, type, ex->disc);
+                       } else
+                               key.integer = v.integer;
+                       sfsprintf(buf, sizeof(buf), "0x%I*x", sizeof(v.integer), key.integer);
+                       keyname = buf;
                } else
-                   key.integer = v.integer;
-               sfsprintf(buf, sizeof(buf), "0x%I*x", sizeof(v.integer),
-                         key.integer);
-               keyname = buf;
-       } else
-               keyname = v.string;
-       if (!(b = (Exassoc_t *) dtmatch((Dt_t *) expr->data.variable.
-               symbol->local.pointer, keyname))) {
-           return 0;
+                       keyname = v.string;
+               if (!(b = (Exassoc_t *) dtmatch((Dt_t *) expr->data.variable.
+                       symbol->local.pointer, keyname))) {
+                       return 0;
+               }
        }
-    }
-    if (delete) {
-       dtdelete ((Dt_t*)expr->data.variable.symbol->local.pointer, b);
-       free (b);    
-    }
-    return 1;
+       if (delete) {
+               dtdelete ((Dt_t*)expr->data.variable.symbol->local.pointer, b);
+               free (b);
+       }
+       return 1;
 }
 
 /*
@@ -123,225 +128,249 @@ evaldyn (Expr_t * ex, register Exnode_t * expr, void *env, int delete)
  */
 
 static Extype_t
-getdyn(Expr_t * ex, register Exnode_t * expr, void *env,
-       Exassoc_t ** assoc)
+getdyn(Expr_t* ex, register Exnode_t* expr, void* env, Exassoc_t** assoc)
 {
-    Exassoc_t *b;
-    Extype_t v;
-
-    if (expr->data.variable.index) {
-       char buf[32];
-       Extype_t key;
-       char *keyname;
+       Exassoc_t*      b;
+       Extype_t        v;
 
-       v = eval(ex, expr->data.variable.index, env);
-       if (expr->data.variable.symbol->index_type == INTEGER) {
-           if (!
-               (b =
-                (Exassoc_t *) dtmatch((Dt_t *) expr->data.variable.
-                                      symbol->local.pointer, &v))) {
-               if (!(b = newof(0, Exassoc_t, 1, 0)))
-                   exerror("out of space [assoc]");
-               b->key = v;
-               dtinsert((Dt_t *) expr->data.variable.symbol->local.
-                        pointer, b);
-           }
-       } else {
-           int type = expr->data.variable.index->type;
-           if (type != STRING) {
-               if (!BUILTIN(type)) {
-                   key = (*ex->disc->keyf) (ex, v, type, ex->disc);
-               } else
-                   key.integer = v.integer;
-               sfsprintf(buf, sizeof(buf), "0x%I*x", sizeof(v.integer),
-                         key.integer);
-               keyname = buf;
-           } else
-               keyname = v.string;
-           if (!
-               (b =
-                (Exassoc_t *) dtmatch((Dt_t *) expr->data.variable.
-                                      symbol->local.pointer, keyname))) {
-               if (!(b = newof(0, Exassoc_t, 1, strlen(keyname))))
-                   exerror("out of space [assoc]");
-               strcpy(b->name, keyname);
-               b->key = v;
-               dtinsert((Dt_t *) expr->data.variable.symbol->local.
-                        pointer, b);
-           }
-       }
-       *assoc = b;
-       if (b) {
-           if (expr->data.variable.symbol->type == STRING
-               && !b->value.string)
-               b->value = exzero(expr->data.variable.symbol->type);
-           return b->value;
+       if (expr->data.variable.index)
+       {
+               char    buf[9];
+               Extype_t key;
+               char *keyname;
+
+               v = eval(ex, expr->data.variable.index, env);
+               if (expr->data.variable.symbol->index_type == INTEGER) {
+                       if (!(b = (Exassoc_t *) dtmatch((Dt_t *) expr->data.variable.symbol->local.pointer, &v))) 
+                       {
+                               if (!(b = newof(0, Exassoc_t, 1, 0)))
+                                       exnospace();
+                               b->key = v;
+                               dtinsert((Dt_t *) expr->data.variable.symbol->local.  pointer, b);
+                       }
+               } else {
+                       int type = expr->data.variable.index->type;
+                       if (type != STRING) {
+                               if (!BUILTIN(type)) {
+                                       key = (*ex->disc->keyf) (ex, v, type, ex->disc);
+                               } else
+                                       key.integer = v.integer;
+                               sfsprintf(buf, sizeof(buf), "0x%I*x", sizeof(v.integer), key.integer);
+                               keyname = buf;
+                       } else
+                               keyname = v.string;
+                       if (!(b = (Exassoc_t *) dtmatch((Dt_t *) expr->data.variable.symbol->local.pointer, keyname))) 
+                       {
+                               if (!(b = newof(0, Exassoc_t, 1, strlen(keyname))))
+                                       exnospace();
+                               strcpy(b->name, keyname);
+                               b->key = v;
+                               dtinsert((Dt_t *) expr->data.variable.symbol->local.pointer, b);
+                       }
+               }
+               *assoc = b;
+               if (b)
+               {
+                       if (expr->data.variable.symbol->type == STRING && !b->value.string)
+                               b->value = exzero(expr->data.variable.symbol->type);
+                       return b->value;
+               }
+               v = exzero(expr->data.variable.symbol->type);
+               return v;
        }
-       v = exzero(expr->data.variable.symbol->type);
-       return v;
-    }
-    *assoc = 0;
-    return expr->data.variable.symbol->value->data.constant.value;
+       *assoc = 0;
+       return expr->data.variable.symbol->value->data.constant.value;
 }
 
-typedef struct {
-    Sffmt_t fmt;
-    Expr_t *expr;
-    void *env;
-    Print_t *args;
-    Extype_t value;
-    Exnode_t *actuals;
-    Sfio_t *tmp;
+typedef struct
+{
+       Sffmt_t         fmt;
+       Expr_t*         expr;
+       void*           env;
+       Print_t*        args;
+       Extype_t        value;
+       Exnode_t*       actuals;
+       Sfio_t*         tmp;
 } Fmt_t;
 
 /*
  * printf %! extension function
  */
-#define TIME_LEN 80            /* max. characters to store time */
 
-static int prformat(Sfio_t * sp, void *vp, Sffmt_t * dp)
+static int
+prformat(Sfio_t* sp, void* vp, Sffmt_t* dp)
 {
-    register Fmt_t *fmt = (Fmt_t *) dp;
-    register Exnode_t *node;
-    register char *s;
-    register char *txt;
-    int n;
-    int from;
-    int to = 0;
-    time_t tm;
+       register Fmt_t*         fmt = (Fmt_t*)dp;
+       register Exnode_t*      node;
+       register char*          s;
+       register char*          txt;
+       int                     n;
+       int                     from;
+       int                     to = 0;
+       time_t                  tm;
+#ifndef OLD
     struct tm *stm;
+#endif
+
 
-    dp->flags |= SFFMT_VALUE;
-    if (fmt->args) {
-       if ((node =
-            (dp->fmt ==
-             '*') ? fmt->args->param[dp->size] : fmt->args->arg))
-           fmt->value = exeval(fmt->expr, node, fmt->env);
+       dp->flags |= SFFMT_VALUE;
+       if (fmt->args)
+       {
+               if ((node = (dp->fmt == '*') ? fmt->args->param[dp->size] : fmt->args->arg))
+                       fmt->value = exeval(fmt->expr, node, fmt->env);
+               else
+                       fmt->value.integer = 0;
+               to = fmt->args->arg->type;
+       }
+       else if (!(fmt->actuals = fmt->actuals->data.operand.right))
+               exerror("printf: not enough arguments");
        else
-           fmt->value.integer = 0;
-       to = fmt->args->arg->type;
-    } else if (!(fmt->actuals = fmt->actuals->data.operand.right))
-       exerror("printf: not enough arguments");
-    else {
-       node = fmt->actuals->data.operand.left;
-       from = node->type;
-       switch (dp->fmt) {
-       case 'f':
-       case 'g':
-           to = FLOATING;
-           break;
-       case 's':
-           to = STRING;
-           break;
-       default:
-           switch (from) {
-           case INTEGER:
-           case UNSIGNED:
-               to = from;
+       {
+               node = fmt->actuals->data.operand.left;
+               from = node->type;
+               switch (dp->fmt)
+               {
+               case 'f':
+               case 'g':
+                       to = FLOATING;
+                       break;
+               case 's':
+                       to = STRING;
+                       break;
+               default:
+                       switch (from)
+                       {
+                       case INTEGER:
+                       case UNSIGNED:
+                               to = from;
+                               break;
+                       default:
+                               to = INTEGER;
+                               break;
+                       }
+                       break;
+               }
+               if (to == from)
+                       fmt->value = exeval(fmt->expr, node, fmt->env);
+               else
+               {
+                       node = excast(fmt->expr, node, to, NiL, 0);
+                       fmt->value = exeval(fmt->expr, node, fmt->env);
+                       node->data.operand.left = 0;
+                       exfree(fmt->expr, node);
+                       if (to == STRING)
+                       {
+                               if (fmt->value.string)
+                               {
+                                       n = strlen(fmt->value.string);
+                                       if ((s = fmtbuf(n + 1)))
+                                               memcpy(s, fmt->value.string, n + 1);
+                                       vmfree(fmt->expr->vm, fmt->value.string);
+                                       fmt->value.string = s;
+                               }
+                               if (!fmt->value.string)
+                                       fmt->value.string = "";
+                       }
+               }
+       }
+       switch (to)
+       {
+       case STRING:
+               *((char**)vp) = fmt->value.string;
+               fmt->fmt.size = -1;
+               break;
+       case FLOATING:
+               *((double*)vp) = fmt->value.floating;
+               fmt->fmt.size = sizeof(double);
                break;
-           default:
-               to = INTEGER;
+       default:
+               *((Sflong_t*)vp) = fmt->value.integer;
+               dp->size = sizeof(Sflong_t);
                break;
-           }
-           break;
        }
-       if (to == from)
-           fmt->value = exeval(fmt->expr, node, fmt->env);
-       else {
-           node = excast(fmt->expr, node, to, NiL, 0);
-           fmt->value = exeval(fmt->expr, node, fmt->env);
-           node->data.operand.left = 0;
-           exfree(fmt->expr, node);
-           if (to == STRING) {
-               if (fmt->value.string) {
-                   n = strlen(fmt->value.string);
-                   if ((s = fmtbuf(n + 1)))
-                       memcpy(s, fmt->value.string, n + 1);
-                   vmfree(fmt->expr->vm, fmt->value.string);
-                   fmt->value.string = s;
+       if (dp->n_str > 0)
+       {
+               if (!fmt->tmp && !(fmt->tmp = sfstropen()))
+                       txt = exnospace();
+               else
+               {
+                       sfprintf(fmt->tmp, "%.*s", dp->n_str, dp->t_str);
+                       txt = exstash(fmt->tmp, NiL);
                }
-               if (!fmt->value.string)
-                   fmt->value.string = "";
-           }
        }
-    }
-    switch (to) {
-    case STRING:
-       *((char **) vp) = fmt->value.string;
-       fmt->fmt.size = -1;
-       break;
-    case FLOATING:
-       *((double *) vp) = fmt->value.floating;
-       fmt->fmt.size = sizeof(double);
-       break;
-    default:
-       *((Sflong_t *) vp) = fmt->value.integer;
-       dp->size = sizeof(Sflong_t);
-       break;
-    }
-    if (dp->n_str > 0) {
-       if (!fmt->tmp)
-           fmt->tmp = sfstropen();
-       sfprintf(fmt->tmp, "%.*s", (int) (dp->n_str), dp->t_str);
-       txt = sfstruse(fmt->tmp);
-    } else
-       txt = 0;
-    switch (dp->fmt) {
-    case 'q':
-    case 'Q':
-       s = *((char **) vp);
-       *((char **) vp) = fmtquote(s, "$'", "'", strlen(s), 0);
-       dp->fmt = 's';
-       dp->size = -1;
-       break;
-    case 'S':
-       dp->flags &= ~SFFMT_LONG;
-       s = *((char **) vp);
-       if (txt) {
-           if (streq(txt, "identifier")) {
-               if (*s && !isalpha(*s))
-                   *s++ = '_';
-               for (; *s; s++)
-                   if (!isalnum(*s))
-                       *s = '_';
-           } else if (streq(txt, "invert")) {
-               for (; *s; s++)
-                   if (isupper(*s))
-                       *s = tolower(*s);
-                   else if (islower(*s))
-                       *s = toupper(*s);
-           } else if (streq(txt, "lower")) {
-               for (; *s; s++)
-                   if (isupper(*s))
-                       *s = tolower(*s);
-           } else if (streq(txt, "upper")) {
-               for (; *s; s++)
-                   if (islower(*s))
-                       *s = toupper(*s);
-           } else if (streq(txt, "variable")) {
-               for (; *s; s++)
-                   if (!isalnum(*s) && *s != '_')
-                       *s = '.';
-           }
+       else
+               txt = 0;
+       switch (dp->fmt)
+       {
+       case 'q':
+       case 'Q':
+               s = *((char**)vp);
+               *((char**)vp) = fmtquote(s, "$'", "'", strlen(s), 0);
+               dp->fmt = 's';
+               dp->size = -1;
+               break;
+       case 'S':
+               dp->flags &= ~SFFMT_LONG;
+               s = *((char**)vp);
+               if (txt)
+               {
+                       if (streq(txt, "identifier"))
+                       {
+                               if (*s && !isalpha(*s))
+                                       *s++ = '_';
+                               for (; *s; s++)
+                                       if (!isalnum(*s))
+                                               *s = '_';
+                       }
+                       else if (streq(txt, "invert"))
+                       {
+                               for (; *s; s++)
+                                       if (isupper(*s))
+                                               *s = tolower(*s);
+                                       else if (islower(*s))
+                                               *s = toupper(*s);
+                       }
+                       else if (streq(txt, "lower"))
+                       {
+                               for (; *s; s++)
+                                       if (isupper(*s))
+                                               *s = tolower(*s);
+                       }
+                       else if (streq(txt, "upper"))
+                       {
+                               for (; *s; s++)
+                                       if (islower(*s))
+                                               *s = toupper(*s);
+                       }
+                       else if (streq(txt, "variable"))
+                       {
+                               for (; *s; s++)
+                                       if (!isalnum(*s) && *s != '_')
+                                               *s = '.';
+                       }
+               }
+               dp->fmt = 's';
+               dp->size = -1;
+               break;
+       case 't':
+       case 'T':
+               if ((tm = *((Sflong_t*)vp)) == -1)
+                       tm = time(NiL);
+#ifndef OLD
+        if (!txt)
+            txt = "%?%K";
+        s = fmtbuf(TIME_LEN);
+        stm = localtime(&tm);
+        strftime(s, TIME_LEN, txt, stm);
+        *((char **) vp) = s;
+#else
+               *((char**)vp) = fmttime(txt ? txt : "%?%K", tm);
+#endif
+               dp->fmt = 's';
+               dp->size = -1;
+               break;
        }
-       dp->fmt = 's';
-       dp->size = -1;
-       break;
-    case 't':
-    case 'T':
-       if ((tm = *((Sflong_t *) vp)) == -1)
-           tm = time(0);
-       if (!txt)
-           txt = "%?%K";
-       s = fmtbuf(TIME_LEN);
-       stm = localtime(&tm);
-       strftime(s, TIME_LEN, txt, stm);
-       *((char **) vp) = s;
-       dp->fmt = 's';
-       dp->size = -1;
-       break;
-    }
-    return 0;
+       return 0;
 }
 
 /*
@@ -368,257 +397,252 @@ prints(Expr_t * ex, register Exnode_t * expr, void *env, Sfio_t * sp)
  * do printf
  */
 
-static int print(Expr_t * ex, Exnode_t * expr, void *env, Sfio_t * sp)
+static int
+print(Expr_t* ex, Exnode_t* expr, void* env, Sfio_t* sp)
 {
-    register Print_t *x;
-    Extype_t v;
-    Fmt_t fmt;
-
-    if (!sp) {
-       v = eval(ex, expr->data.print.descriptor, env);
-       if (v.integer < 0 || v.integer >= elementsof(ex->file)
-           || (!((sp = ex->file[v.integer]))
-               &&
-               !((sp = ex->file[v.integer] =
-                  sfnew(NiL, NiL, SF_UNBOUND, v.integer,
-                        SF_READ | SF_WRITE))))) {
-           exerror("printf: %d: invalid descriptor", v.integer);
-           return -1;
+       register Print_t*       x;
+       Extype_t                v;
+       Fmt_t                   fmt;
+
+       if (!sp)
+       {
+               v = eval(ex, expr->data.print.descriptor, env);
+               if (v.integer < 0 || v.integer >= elementsof(ex->file) || (!(sp = ex->file[v.integer]) && !(sp = ex->file[v.integer] = sfnew(NiL, NiL, SF_UNBOUND, v.integer, SF_READ|SF_WRITE))))
+               {
+                       exerror("printf: %d: invalid descriptor", v.integer);
+                       return -1;
+               }
        }
-    }
-    memset(&fmt, 0, sizeof(fmt));
-    fmt.fmt.version = SFIO_VERSION;
-    fmt.fmt.extf = prformat;
-    fmt.expr = ex;
-    fmt.env = env;
-    x = expr->data.print.args;
-    if (x->format)
-       do {
-           if (x->arg) {
-               fmt.fmt.form = x->format;
-               fmt.args = x;
+       memset(&fmt, 0, sizeof(fmt));
+       fmt.fmt.version = SFIO_VERSION;
+       fmt.fmt.extf = prformat;
+       fmt.expr = ex;
+       fmt.env = env;
+       x = expr->data.print.args;
+       if (x->format)
+               do
+               {
+                       if (x->arg)
+                       {
+                               fmt.fmt.form = x->format;
+                               fmt.args = x;
+                               sfprintf(sp, "%!", &fmt);
+                       }
+                       else
+                               sfputr(sp, x->format, -1);
+               } while ((x = x->next));
+       else
+       {
+               v = eval(ex, x->arg->data.operand.left, env);
+               fmt.fmt.form = v.string;
+               fmt.actuals = x->arg;
                sfprintf(sp, "%!", &fmt);
-           } else
-               sfputr(sp, x->format, -1);
-       } while ((x = x->next));
-    else {
-       v = eval(ex, x->arg->data.operand.left, env);
-       fmt.fmt.form = v.string;
-       fmt.actuals = x->arg;
-       sfprintf(sp, "%!", &fmt);
-       if (fmt.actuals->data.operand.right)
-           exerror("(s)printf: \"%s\": too many arguments", fmt.fmt.form);
-    }
-    if (fmt.tmp)
-       sfstrclose(fmt.tmp);
-    return 0;
+               if (fmt.actuals->data.operand.right)
+                       exerror("(s)printf: \"%s\": too many arguments", fmt.fmt.form);
+       }
+       if (fmt.tmp)
+               sfstrclose(fmt.tmp);
+       return 0;
 }
 
 /*
  * scanf %! extension function
  */
 
-static int scformat(Sfio_t * sp, void *vp, Sffmt_t * dp)
+static int
+scformat(Sfio_t* sp, void* vp, Sffmt_t* dp)
 {
-    register Fmt_t *fmt = (Fmt_t *) dp;
-    register Exnode_t *node;
+       register Fmt_t*         fmt = (Fmt_t*)dp;
+       register Exnode_t*      node;
 
-    if (!fmt->actuals) {
-       exerror("scanf: not enough arguments");
-       return -1;
-    }
-    node = fmt->actuals->data.operand.left;
-    switch (dp->fmt) {
-    case 'f':
-    case 'g':
-       if (node->type != FLOATING) {
-           exerror
-               ("scanf: %s: floating variable address argument expected",
-                node->data.variable.symbol->name);
-           return -1;
-       }
-       fmt->fmt.size = sizeof(double);
-       *((void **) vp) =
-           &node->data.variable.symbol->value->data.constant.value;
-       break;
-    case 's':
-       if (node->type != STRING) {
-           exerror("scanf: %s: string variable address argument expected",
-                   node->data.variable.symbol->name);
-           return -1;
-       }
-       if (node->data.variable.symbol->value->data.constant.value.
-           string == expr.nullstring)
-           node->data.variable.symbol->value->data.constant.value.string =
-               0;
-       fmt->fmt.size = 1024;
-       *((void **) vp) =
-           node->data.variable.symbol->value->data.constant.value.string =
-           vmnewof(fmt->expr->vm,
-                   node->data.variable.symbol->value->data.constant.value.
-                   string, char, fmt->fmt.size, 0);
-       break;
-    case 'c':
-       if (node->type != CHARACTER) {
-           exerror("scanf: %s: char variable address argument expected",
-                   node->data.variable.symbol->name);
-           return -1;
+       if (!fmt->actuals)
+       {
+               exerror("scanf: not enough arguments");
+               return -1;
        }
-       fmt->fmt.size = sizeof(Sflong_t);
-       *((void **) vp) =
-           &node->data.variable.symbol->value->data.constant.value;
-       break;
-    default:
-       if (node->type != INTEGER && node->type != UNSIGNED) {
-           exerror
-               ("scanf: %s: integer variable address argument expected",
-                node->data.variable.symbol->name);
-           return -1;
+       node = fmt->actuals->data.operand.left;
+       switch (dp->fmt)
+       {
+       case 'f':
+       case 'g':
+               if (node->type != FLOATING)
+               {
+                       exerror("scanf: %s: floating variable address argument expected", node->data.variable.symbol->name);
+                       return -1;
+               }
+               fmt->fmt.size = sizeof(double);
+               *((void**)vp) = &node->data.variable.symbol->value->data.constant.value;
+               break;
+       case 's':
+               if (node->type != STRING)
+               {
+                       exerror("scanf: %s: string variable address argument expected", node->data.variable.symbol->name);
+                       return -1;
+               }
+               if (node->data.variable.symbol->value->data.constant.value.string == expr.nullstring)
+                       node->data.variable.symbol->value->data.constant.value.string = 0;
+               fmt->fmt.size = 1024;
+               *((void**)vp) = node->data.variable.symbol->value->data.constant.value.string = vmnewof(fmt->expr->vm, node->data.variable.symbol->value->data.constant.value.string, char, fmt->fmt.size, 0);
+               break;
+       case 'c':
+               if (node->type != CHARACTER) {
+                       exerror("scanf: %s: char variable address argument expected", node->data.variable.symbol->name);
+                       return -1;
+               }
+               fmt->fmt.size = sizeof(Sflong_t);
+               *((void **) vp) = &node->data.variable.symbol->value->data.constant.value;
+               break;
+       default:
+               if (node->type != INTEGER && node->type != UNSIGNED)
+               {
+                       exerror("scanf: %s: integer variable address argument expected", node->data.variable.symbol->name);
+                       return -1;
+               }
+               dp->size = sizeof(Sflong_t);
+               *((void**)vp) = &node->data.variable.symbol->value->data.constant.value;
+               break;
        }
-       dp->size = sizeof(Sflong_t);
-       *((void **) vp) =
-           &node->data.variable.symbol->value->data.constant.value;
-       break;
-    }
-    fmt->actuals = fmt->actuals->data.operand.right;
-    dp->flags |= SFFMT_VALUE;
-    return 0;
+       fmt->actuals = fmt->actuals->data.operand.right;
+       dp->flags |= SFFMT_VALUE;
+       return 0;
 }
 
 /*
  * do scanf
  */
 
-static int scan(Expr_t * ex, Exnode_t * expr, void *env, Sfio_t * sp)
+static int
+scan(Expr_t* ex, Exnode_t* expr, void* env, Sfio_t* sp)
 {
-    Extype_t v;
-    Extype_t u;
-    Fmt_t fmt;
-    int n;
-
-    if (!sp) {
-       if (expr->data.scan.descriptor) {
-           v = eval(ex, expr->data.scan.descriptor, env);
-           if (expr->data.scan.descriptor->type == STRING)
-               goto get;
-       } else
-           v.integer = 0;
-       if ((v.integer < 0) ||
-           (v.integer >= elementsof(ex->file)) ||
-           (!(sp = ex->file[v.integer]) &&
-            !(sp = ex->file[v.integer] =
-              sfnew(NiL, NiL, SF_UNBOUND, v.integer,
-                    SF_READ | SF_WRITE)))) {
-           exerror("scanf: %d: invalid descriptor", v.integer);
-           return 0;
+       Extype_t                v;
+       Extype_t                u;
+       Fmt_t                   fmt;
+       int                     n;
+
+       if (!sp)
+       {
+               if (expr->data.scan.descriptor)
+               {
+                       v = eval(ex, expr->data.scan.descriptor, env);
+                       if (expr->data.scan.descriptor->type == STRING)
+                               goto get;
+               }
+               else
+                       v.integer = 0;
+               if ((v.integer < 0) || (v.integer >= elementsof(ex->file)) || (!(sp = ex->file[v.integer]) && !(sp = ex->file[v.integer] = sfnew(NiL, NiL, SF_UNBOUND, v.integer, SF_READ|SF_WRITE))))
+               {
+                       exerror("scanf: %d: invalid descriptor", v.integer);
+                       return 0;
+               }
        }
-    }
-  get:
-    memset(&fmt, 0, sizeof(fmt));
-    fmt.fmt.version = SFIO_VERSION;
-    fmt.fmt.extf = scformat;
-    fmt.expr = ex;
-    fmt.env = env;
-    u = eval(ex, expr->data.scan.format, env);
-    fmt.fmt.form = u.string;
-    fmt.actuals = expr->data.scan.args;
-    n = sp ? sfscanf(sp, "%!", &fmt) : sfsscanf(v.string, "%!", &fmt);
-    if (fmt.tmp)
-       sfstrclose(fmt.tmp);
-    if (fmt.actuals && !*fmt.fmt.form)
-       exerror("scanf: %s: too many arguments",
-               fmt.actuals->data.operand.left->data.variable.symbol->
-               name);
-    return n;
+ get:
+       memset(&fmt, 0, sizeof(fmt));
+       fmt.fmt.version = SFIO_VERSION;
+       fmt.fmt.extf = scformat;
+       fmt.expr = ex;
+       fmt.env = env;
+       u = eval(ex, expr->data.scan.format, env);
+       fmt.fmt.form = u.string;
+       fmt.actuals = expr->data.scan.args;
+       n = sp ? sfscanf(sp, "%!", &fmt) : sfsscanf(v.string, "%!", &fmt);
+       if (fmt.tmp) sfstrclose(fmt.tmp);
+       if (fmt.actuals && !*fmt.fmt.form)
+               exerror("scanf: %s: too many arguments", fmt.actuals->data.operand.left->data.variable.symbol->name);
+       return n;
 }
 
 /*
  * string add
  */
 
-static char *str_add(Expr_t * ex, register char *l, register char *r)
+static char*
+str_add(Expr_t* ex, register char* l, register char* r)
 {
-    sfprintf(ex->tmp, "%s%s", l, r);
-    return vmstrdup(ex->vc, sfstruse(ex->tmp));
+       sfprintf(ex->tmp, "%s%s", l, r);
+       return exstash(ex->tmp, ex->ve);
 }
 
 /*
  * string ior
  */
 
-static char *str_ior(Expr_t * ex, register char *l, register char *r)
+static char*
+str_ior(Expr_t* ex, register char* l, register char* r)
 {
-    register int c;
-    register char *s = l;
-
-    while ((c = *s++))
-       if (!strchr(s, c))
-           sfputc(ex->tmp, c);
-    while ((c = *r++))
-       if (!strchr(l, c) && !strchr(r, c))
-           sfputc(ex->tmp, c);
-    return vmstrdup(ex->vc, sfstruse(ex->tmp));
+       register int    c;
+       register char*  s = l;
+
+       while ((c = *s++))
+               if (!strchr(s, c))
+                       sfputc(ex->tmp, c);
+       while ((c = *r++))
+               if (!strchr(l, c) && !strchr(r, c))
+                       sfputc(ex->tmp, c);
+       return exstash(ex->tmp, ex->ve);
 }
 
 /*
  * string and
  */
 
-static char *str_and(Expr_t * ex, register char *l, register char *r)
+static char*
+str_and(Expr_t* ex, register char* l, register char* r)
 {
-    register int c;
+       register int    c;
 
-    while ((c = *l++))
-       if (strchr(r, c) && !strchr(l, c))
-           sfputc(ex->tmp, c);
-    return vmstrdup(ex->vc, sfstruse(ex->tmp));
+       while ((c = *l++))
+               if (strchr(r, c) && !strchr(l, c))
+                       sfputc(ex->tmp, c);
+       return exstash(ex->tmp, ex->ve);
 }
 
 /*
  * string xor
  */
 
-static char *str_xor(Expr_t * ex, register char *l, register char *r)
+static char*
+str_xor(Expr_t* ex, register char* l, register char* r)
 {
-    register int c;
-    register char *s = l;
-
-    while ((c = *s++))
-       if (!strchr(r, c) && !strchr(s, c))
-           sfputc(ex->tmp, c);
-    while ((c = *r++))
-       if (!strchr(l, c) && !strchr(r, c))
-           sfputc(ex->tmp, c);
-    return vmstrdup(ex->vc, sfstruse(ex->tmp));
+       register int    c;
+       register char*  s = l;
+
+       while ((c = *s++))
+               if (!strchr(r, c) && !strchr(s, c))
+                       sfputc(ex->tmp, c);
+       while ((c = *r++))
+               if (!strchr(l, c) && !strchr(r, c))
+                       sfputc(ex->tmp, c);
+       return exstash(ex->tmp, ex->ve);
 }
 
 /*
  * string mod
  */
 
-static char *str_mod(Expr_t * ex, register char *l, register char *r)
+static char*
+str_mod(Expr_t* ex, register char* l, register char* r)
 {
-    register int c;
+       register int    c;
 
-    while ((c = *l++))
-       if (!strchr(r, c) && !strchr(l, c))
-           sfputc(ex->tmp, c);
-    return vmstrdup(ex->vc, sfstruse(ex->tmp));
+       while ((c = *l++))
+               if (!strchr(r, c) && !strchr(l, c))
+                       sfputc(ex->tmp, c);
+       return exstash(ex->tmp, ex->ve);
 }
 
 /*
  * string mpy
  */
 
-
-static char *str_mpy(Expr_t * ex, register char *l, register char *r)
+static char*
+str_mpy(Expr_t* ex, register char* l, register char* r)
 {
-    register int lc;
-    register int rc;
+       register int    lc;
+       register int    rc;
 
-    while ((lc = *l++) && (rc = *r++))
-       sfputc(ex->tmp, lc == rc ? lc : ' ');
-    return vmstrdup(ex->vc, sfstruse(ex->tmp));
+       while ((lc = *l++) && (rc = *r++))
+               sfputc(ex->tmp, lc == rc ? lc : ' ');
+       return exstash(ex->tmp, ex->ve);
 }
 
 /* replace:
@@ -628,23 +652,23 @@ static char *str_mpy(Expr_t * ex, register char *l, register char *r)
 static void
 replace(Sfio_t * s, char *base, register char *repl, int ng, int *sub)
 {
-    char c;
-    int idx, offset;
+       char c;
+       int idx, offset;
 
-    while ((c = *repl++)) {
+       while ((c = *repl++)) {
        if (c == '\\') {
            if ((c = *repl) && isdigit(c)) {
-               idx = c - '0';
-               if (idx < ng) {
-                   offset = sub[2 * idx];
-                   sfwrite(s, base + offset, sub[2 * idx + 1] - offset);
-               }
-               repl++;
+                       idx = c - '0';
+                       if (idx < ng) {
+                       offset = sub[2 * idx];
+                       sfwrite(s, base + offset, sub[2 * idx + 1] - offset);
+                       }
+                       repl++;
            } else
-               sfputc(s, '\\');
+                       sfputc(s, '\\');
        } else
            sfputc(s, c);
-    }
+       }
 }
 
 #define MCNT(s) (sizeof(s)/(2*sizeof(int)))
@@ -652,15 +676,15 @@ replace(Sfio_t * s, char *base, register char *repl, int ng, int *sub)
 static void
 addItem (Dt_t* arr, Extype_t v, char* tok)
 {
-    Exassoc_t* b;
+       Exassoc_t* b;
 
-    if (!(b = (Exassoc_t *) dtmatch(arr, &v))) {
-       if (!(b = newof(0, Exassoc_t, 1, 0)))
-           exerror("out of space [assoc]");
-       b->key = v;
-       dtinsert(arr, b);
-    }
-    b->value.string = tok;
+       if (!(b = (Exassoc_t *) dtmatch(arr, &v))) {
+               if (!(b = newof(0, Exassoc_t, 1, 0)))
+               exerror("out of space [assoc]");
+               b->key = v;
+               dtinsert(arr, b);
+       }
+       b->value.string = tok;
 }
 
 /* exsplit:
@@ -670,45 +694,45 @@ addItem (Dt_t* arr, Extype_t v, char* tok)
 Extype_t
 exsplit(Expr_t * ex, register Exnode_t * expr, void *env)
 {
-    Extype_t v;
-    char *str;
-    char *seps;
-    char *tok;
-    size_t sz;
-    Sfio_t* fp = ex->tmp;
-    Dt_t* arr = (Dt_t*)expr->data.split.array->local.pointer;
-    int i;
+       Extype_t v;
+       char *str;
+       char *seps;
+       char *tok;
+       size_t sz;
+       Sfio_t* fp = ex->tmp;
+       Dt_t* arr = (Dt_t*)expr->data.split.array->local.pointer;
+       int i;
+
+       str = (eval(ex, expr->data.split.string, env)).string;
+       if (expr->data.split.seps)
+               seps = (eval(ex, expr->data.split.seps, env)).string;
+       else
+               seps = " \t\n";
 
-    str = (eval(ex, expr->data.split.string, env)).string;
-    if (expr->data.split.seps)
-       seps = (eval(ex, expr->data.split.seps, env)).string;
-    else
-       seps = " \t\n";
-
-    v.integer = 0;
-    while (*str) {
-       sz = strspn (str, seps);
-       for (i = 0; i < sz; i++) {
-           addItem (arr, v, "");
-           v.integer++;
-       }
-       str += sz;
-       if (*str == '\0') {
-           if (v.integer == sz) {  /* only separators */
-               addItem (arr, v, "");
+       v.integer = 0;
+       while (*str) {
+               sz = strspn (str, seps);
+               for (i = 0; i < sz; i++) {
+               addItem (arr, v, "");
+               v.integer++;
+               }
+               str += sz;
+               if (*str == '\0') {
+               if (v.integer == sz) {  /* only separators */
+                               addItem (arr, v, "");
+                               v.integer++;
+               }
+               break;
+               }
+               sz = strcspn (str, seps);
+               sfwrite (fp, str, sz);
+               tok = exstrdup(ex, sfstruse(fp));
+               addItem (arr, v, tok);
                v.integer++;
-           }
-           break;
+               str += sz;
        }
-       sz = strcspn (str, seps);
-       sfwrite (fp, str, sz);
-       tok = exstrdup(ex, sfstruse(fp));
-       addItem (arr, v, tok);
-       v.integer++;
-       str += sz;
-    }
 
-    return v;
+       return v;
 }
 
 /* extoken:
@@ -718,37 +742,37 @@ exsplit(Expr_t * ex, register Exnode_t * expr, void *env)
 Extype_t
 extokens(Expr_t * ex, register Exnode_t * expr, void *env)
 {
-    Extype_t v;
-    char *str;
-    char *seps;
-    char *tok;
-    size_t sz;
-    Sfio_t* fp = ex->tmp;
-    Dt_t* arr = (Dt_t*)expr->data.split.array->local.pointer;
-
-    str = (eval(ex, expr->data.split.string, env)).string;
-    if (expr->data.split.seps)
-       seps = (eval(ex, expr->data.split.seps, env)).string;
-    else
-       seps = " \t\n";
-
-    v.integer = 0;
-    while (*str) {
-       sz = strspn (str, seps);
-       str += sz;
-       if (*str == '\0')
-           break;
-
-       sz = strcspn (str, seps);
-       assert (sz);
-       sfwrite (fp, str, sz);
-       tok = exstrdup(ex, sfstruse(fp));
-       addItem (arr, v, tok);
-       v.integer++;
-       str += sz;
-    }
+       Extype_t v;
+       char *str;
+       char *seps;
+       char *tok;
+       size_t sz;
+       Sfio_t* fp = ex->tmp;
+       Dt_t* arr = (Dt_t*)expr->data.split.array->local.pointer;
+
+       str = (eval(ex, expr->data.split.string, env)).string;
+       if (expr->data.split.seps)
+               seps = (eval(ex, expr->data.split.seps, env)).string;
+       else
+               seps = " \t\n";
 
-    return v;
+       v.integer = 0;
+       while (*str) {
+               sz = strspn (str, seps);
+               str += sz;
+               if (*str == '\0')
+               break;
+
+               sz = strcspn (str, seps);
+               assert (sz);
+               sfwrite (fp, str, sz);
+               tok = exstrdup(ex, sfstruse(fp));
+               addItem (arr, v, tok);
+               v.integer++;
+               str += sz;
+       }
+
+       return v;
 }
 
 /* exsub:
@@ -757,70 +781,70 @@ extokens(Expr_t * ex, register Exnode_t * expr, void *env)
 Extype_t
 exsub(Expr_t * ex, register Exnode_t * expr, void *env, int global)
 {
-    char *str;
-    char *pat;
-    char *repl;
-    char *p;
-    char *s;
-    Extype_t v;
-    int sub[20];
-    int flags = STR_MAXIMAL;
-    int ng;
-
-    str = (eval(ex, expr->data.string.base, env)).string;
-    pat = (eval(ex, expr->data.string.pat, env)).string;
-    if (expr->data.string.repl)
-       repl = (eval(ex, expr->data.string.repl, env)).string;
-    else
-       repl = 0;
-
-    if (!global) {
-       if (*pat == '^') {
-           pat++;
-           flags |= STR_LEFT;
+       char *str;
+       char *pat;
+       char *repl;
+       char *p;
+       char *s;
+       Extype_t v;
+       int sub[20];
+       int flags = STR_MAXIMAL;
+       int ng;
+
+       str = (eval(ex, expr->data.string.base, env)).string;
+       pat = (eval(ex, expr->data.string.pat, env)).string;
+       if (expr->data.string.repl)
+               repl = (eval(ex, expr->data.string.repl, env)).string;
+       else
+               repl = 0;
+
+       if (!global) {
+               if (*pat == '^') {
+                   pat++;
+                   flags |= STR_LEFT;
+               }
+               p = pat;
+               while (*p)
+                   p++;
+               if (p > pat)
+                   p--;
+               if (*p == '$') {
+                   if ((p > pat) && (*(p - 1) == '\\')) {
+                               *p-- = '\0';
+                               *p = '$';
+               } else {
+                               flags |= STR_RIGHT;
+                               *p = '\0';
+               }
+               }
        }
-       p = pat;
-       while (*p)
-           p++;
-       if (p > pat)
-           p--;
-       if (*p == '$') {
-           if ((p > pat) && (*(p - 1) == '\\')) {
-               *p-- = '\0';
-               *p = '$';
-           } else {
-               flags |= STR_RIGHT;
-               *p = '\0';
-           }
+       if (*pat == '\0') {
+               v.string = vmstrdup(ex->ve, str);
+               return v;
        }
-    }
-    if (*pat == '\0') {
-       v.string = vmstrdup(ex->vc, str);
-       return v;
-    }
 
-    ng = strgrpmatch(str, pat, sub, MCNT(sub), flags);
-    if (ng == 0) {
-       v.string = vmstrdup(ex->vc, str);
-       return v;
-    }
-    sfwrite(ex->tmp, str, sub[0]);
-    if (repl)
-       replace(ex->tmp, str, repl, ng, sub);
-
-    s = str + sub[1];
-    if (global) {
-       while ((ng = strgrpmatch(s, pat, sub, MCNT(sub), flags))) {
-           sfwrite(ex->tmp, s, sub[0]);
-           if (repl)
-               replace(ex->tmp, s, repl, ng, sub);
-           s = s + sub[1];
+       ng = strgrpmatch(str, pat, sub, MCNT(sub), flags);
+       if (ng == 0) {
+               v.string = vmstrdup(ex->ve, str);
+               return v;
+       }
+       sfwrite(ex->tmp, str, sub[0]);
+       if (repl)
+               replace(ex->tmp, str, repl, ng, sub);
+
+       s = str + sub[1];
+       if (global) {
+               while ((ng = strgrpmatch(s, pat, sub, MCNT(sub), flags))) {
+                sfwrite(ex->tmp, s, sub[0]);
+                if (repl)
+                       replace(ex->tmp, s, repl, ng, sub);
+                s = s + sub[1];
+               }
        }
-    }
 
-    sfputr(ex->tmp, s, -1);
-    v.string = vmstrdup(ex->vc, sfstruse(ex->tmp));
-    return v;
+       sfputr(ex->tmp, s, -1);
+       v.string = exstash(ex->tmp,ex->ve);
+       return v;
 }
 
 /* exsubstr:
@@ -828,33 +852,31 @@ exsub(Expr_t * ex, register Exnode_t * expr, void *env, int global)
  */
 static Extype_t exsubstr(Expr_t * ex, register Exnode_t * expr, void *env)
 {
-    Extype_t s;
-    Extype_t i;
-    Extype_t l;
-    Extype_t v;
-    int len;
-
-    s = eval(ex, expr->data.string.base, env);
-    len = strlen(s.string);
-    i = eval(ex, expr->data.string.pat, env);
-    if ((i.integer < 0) || (len < i.integer))
-       exerror("illegal start index in substr(%s,%d)",
-               s.string, i.integer);
-    if (expr->data.string.repl) {
-       l = eval(ex, expr->data.string.repl, env);
-       if ((l.integer < 0) || (len - i.integer < l.integer))
-           exerror("illegal length in substr(%s,%d,%d)",
-                   s.string, i.integer, l.integer);
-    } else
-       l.integer = len - i.integer;
+       Extype_t s;
+       Extype_t i;
+       Extype_t l;
+       Extype_t v;
+       int len;
+
+       s = eval(ex, expr->data.string.base, env);
+       len = strlen(s.string);
+       i = eval(ex, expr->data.string.pat, env);
+       if ((i.integer < 0) || (len < i.integer))
+               exerror("illegal start index in substr(%s,%d)", s.string, i.integer);
+       if (expr->data.string.repl) {
+               l = eval(ex, expr->data.string.repl, env);
+               if ((l.integer < 0) || (len - i.integer < l.integer))
+           exerror("illegal length in substr(%s,%d,%d)", s.string, i.integer, l.integer);
+       } else
+               l.integer = len - i.integer;
 
-    v.string = vmalloc(ex->vc, l.integer + 1);
-    if (expr->data.string.repl) {
-       strncpy(v.string, s.string + i.integer, l.integer);
-       v.string[l.integer] = '\0';
-    } else
-       strcpy(v.string, s.string + i.integer);
-    return v;
+       v.string = vmalloc(ex->ve, l.integer + 1);
+       if (expr->data.string.repl) {
+               strncpy(v.string, s.string + i.integer, l.integer);
+               v.string[l.integer] = '\0';
+       } else
+               strcpy(v.string, s.string + i.integer);
+       return v;
 }
 
 /* xConvert:
@@ -864,17 +886,15 @@ static void
 xConvert(Expr_t * ex, Exnode_t * expr, int type, Extype_t v,
         Exnode_t * tmp)
 {
-    *tmp = *expr->data.operand.left;
-    tmp->data.constant.value = v;
-    if ((*ex->disc->convertf) (ex, tmp, type,
-                              expr->data.operand.right ? expr->data.
-                              operand.right->data.variable.
-                              symbol : (Exid_t *) 0, 0, ex->disc))
-       exerror("%s: cannot convert %s value to %s",
-               expr->data.operand.left->data.variable.symbol->name,
-               extypename(ex, expr->data.operand.left->type),
-               extypename(ex, type));
-    tmp->type = type;
+       *tmp = *expr->data.operand.left;
+       tmp->data.constant.value = v;
+       if ((*ex->disc->convertf) (ex, tmp, type, expr->data.operand.right ? expr->data.
+               operand.right->data.variable.symbol : (Exid_t *) 0, 0, ex->disc)) {
+               exerror("%s: cannot convert %s value to %s",
+                       expr->data.operand.left->data.variable.symbol->name,
+                       extypename(ex, expr->data.operand.left->type), extypename(ex, type));
+       }
+       tmp->type = type;
 }
 
 /* xPrint:
@@ -883,13 +903,13 @@ xConvert(Expr_t * ex, Exnode_t * expr, int type, Extype_t v,
 static void
 xPrint(Expr_t * ex, Exnode_t * expr, Extype_t v, Exnode_t * tmp)
 {
-    *tmp = *expr->data.operand.left;
-    tmp->data.constant.value = v;
-    if ((*ex->disc->stringof) (ex, tmp, 0, ex->disc))
+       *tmp = *expr->data.operand.left;
+       tmp->data.constant.value = v;
+       if ((*ex->disc->stringof) (ex, tmp, 0, ex->disc))
        exerror("%s: no string representation of %s value",
                expr->data.operand.left->data.variable.symbol->name,
                extypename(ex, expr->data.operand.left->type));
-    tmp->type = STRING;
+       tmp->type = STRING;
 }
 
 /*
@@ -897,1068 +917,976 @@ xPrint(Expr_t * ex, Exnode_t * expr, Extype_t v, Exnode_t * tmp)
  */
 static long seed;
 
-static Extype_t eval(Expr_t * ex, register Exnode_t * expr, void *env)
+static Extype_t
+eval(Expr_t* ex, register Exnode_t* expr, void* env)
 {
-    register Exnode_t *x;
-    register Exnode_t *a;
-    register Extype_t **t;
-    register int n;
-    Extype_t v;
-    Extype_t r;
-    Extype_t i;
-    char *e;
-    Exnode_t tmp;
-    Exnode_t rtmp;
-    Exnode_t *rp;
-    Exassoc_t *assoc;
-    Extype_t args[FRAME];
-    Extype_t save[FRAME];
-
-    if (!expr || ex->loopcount) {
-       v.integer = 1;
-       return v;
-    }
-    x = expr->data.operand.left;
-    switch (expr->op) {
-    case BREAK:
-    case CONTINUE:
-       v = eval(ex, x, env);
-       ex->loopcount = v.integer;
-       ex->loopop = expr->op;
-       return v;
-    case CONSTANT:
-       return expr->data.constant.value;
-    case DEC:
-       n = -1;
-      add:
-       if (x->op == DYNAMIC)
-           r = getdyn(ex, x, env, &assoc);
-       else {
-           if (x->data.variable.index)
-               i = eval(ex, x->data.variable.index, env);
-           else
-               i.integer = EX_SCALAR;
+       register Exnode_t*      x;
+       register Exnode_t*      a;
+       register Extype_t**     t;
+       register int            n;
+       Extype_t                v;
+       Extype_t                r;
+       Extype_t                i;
+       char*                   e;
+       Exnode_t                tmp;
+       Exnode_t                rtmp;
+       Exnode_t*               rp;
+       Exassoc_t*              assoc;
+       Extype_t                args[FRAME+1];
+       Extype_t                save[FRAME];
+
+       if (!expr || ex->loopcount)
+       {
+               v.integer = 1;
+               return v;
+       }
+       x = expr->data.operand.left;
+       switch (expr->op)
+       {
+       case BREAK:
+       case CONTINUE:
+               v = eval(ex, x, env);
+               ex->loopcount = v.integer;
+               ex->loopop = expr->op;
+               return v;
+       case CONSTANT:
+               return expr->data.constant.value;
+       case DEC:
+               n = -1;
+       add:
+               if (x->op == DYNAMIC)
+                       r = getdyn(ex, x, env, &assoc);
+               else
+               {
+                       if (x->data.variable.index)
+                               i = eval(ex, x->data.variable.index, env);
+                       else
+                               i.integer = EX_SCALAR;
 #ifndef OLD
-           if (x->data.variable.dyna) {
-               Extype_t locv;
-               locv = getdyn(ex, x->data.variable.dyna, env, &assoc);
-               x->data.variable.dyna->data.variable.dyna->data.constant.
-                   value = locv;
-           }
+                       if (x->data.variable.dyna) {
+                               Extype_t locv;
+                               locv = getdyn(ex, x->data.variable.dyna, env, &assoc);
+                               x->data.variable.dyna->data.variable.dyna->data.constant.value = locv;
+                       }
 #endif
-           r = (*ex->disc->getf) (ex, x, x->data.variable.symbol,
-                                  x->data.variable.reference, env,
-                                  (int) i.integer, ex->disc);
-       }
-       v = r;
-       switch (x->type) {
-       case FLOATING:
-           v.floating += n;
-           break;
-       case INTEGER:
-       case UNSIGNED:
-           v.integer += n;
-           break;
-       default:
-           goto huh;
-       }
-      set:
-       if (x->op == DYNAMIC) {
-           if (x->type == STRING) {
-               v.string = vmstrdup(ex->vm, v.string);
-               if ((e =
-                    assoc ? assoc->value.string : x->data.variable.
-                    symbol->value->data.constant.value.string))
-                   vmfree(ex->vm, e);
-           }
-           if (assoc)
-               assoc->value = v;
-           else
-               x->data.variable.symbol->value->data.constant.value = v;
-       } else {
-           if (x->data.variable.index)
-               i = eval(ex, x->data.variable.index, env);
-           else
-               i.integer = EX_SCALAR;
+                       r = (*ex->disc->getf)(ex, x, x->data.variable.symbol, x->data.variable.reference, env, (int)i.integer, ex->disc);
+               }
+               v = r;
+               switch (x->type)
+               {
+               case FLOATING:
+                       v.floating += n;
+                       break;
+               case INTEGER:
+               case UNSIGNED:
+                       v.integer += n;
+                       break;
+               default:
+                       goto huh;
+               }
+       set:
+               if (x->op == DYNAMIC)
+               {
+                       if (x->type == STRING)
+                       {
+                               v.string = vmstrdup(ex->vm, v.string);
+                               if ((e = assoc ? assoc->value.string : x->data.variable.symbol->value->data.constant.value.string))
+                                       vmfree(ex->vm, e);
+                       }
+                       if (assoc)
+                               assoc->value = v;
+                       else
+                               x->data.variable.symbol->value->data.constant.value = v;
+               }
+               else
+               {
+                       if (x->data.variable.index)
+                               i = eval(ex, x->data.variable.index, env);
+                       else
+                               i.integer = EX_SCALAR;
 #ifndef OLD
-           if (x->data.variable.dyna) {
-               Extype_t locv;
-               locv = getdyn(ex, x->data.variable.dyna, env, &assoc);
-               x->data.variable.dyna->data.variable.dyna->data.constant.
-                   value = locv;
-           }
+                       if (x->data.variable.dyna) {
+                               Extype_t locv;
+                               locv = getdyn(ex, x->data.variable.dyna, env, &assoc);
+                               x->data.variable.dyna->data.variable.dyna->data.constant.value = locv;
+                       }
 #endif
-           if ((*ex->disc->setf) (ex, x, x->data.variable.symbol,
-                                  x->data.variable.reference, env,
-                                  (int) i.integer, v, ex->disc) < 0)
-               exerror("%s: cannot set value",
-                       x->data.variable.symbol->name);
-       }
-       if (expr->subop == PRE)
-           r = v;
-       return r;
-    case DYNAMIC:
-       return getdyn(ex, expr, env, &assoc);
-    case SPLIT:
-       return exsplit(ex, expr, env);
-    case TOKENS:
-       return extokens(ex, expr, env);
-    case GSUB:
-       return exsub(ex, expr, env, 1);
-    case SUB:
-       return exsub(ex, expr, env, 0);
-    case SUBSTR:
-       return exsubstr(ex, expr, env);
-    case SRAND:
-       v.integer = seed;
-       if (expr->binary) {
-           seed = eval(ex, x, env).integer;
-       } else
-           seed = time(0);
-       srand48(seed);
-       return v;
-    case RAND:
-       v.floating = drand48();
-       return v;
-    case EXIT:
-       v = eval(ex, x, env);
-       if (ex->disc->exitf) 
-           (*ex->disc->exitf) (ex, env, (int)v.integer);
-       else
-           exit((int) v.integer);
-        /*NOTREACHED*/ v.integer = -1;
-       return v;
-    case IF:
-       v = eval(ex, x, env);
-       if (v.integer)
-           eval(ex, expr->data.operand.right->data.operand.left, env);
-       else
-           eval(ex, expr->data.operand.right->data.operand.right, env);
-       v.integer = 1;
-       return v;
-    case FOR:
-    case WHILE:
-       expr = expr->data.operand.right;
-       for (;;) {
-           r = eval(ex, x, env);
-           if (!r.integer) {
+                       if ((*ex->disc->setf)(ex, x, x->data.variable.symbol, x->data.variable.reference, env, (int)i.integer, v, ex->disc) < 0)
+                               exerror("%s: cannot set value", x->data.variable.symbol->name);
+               }
+               if (expr->subop == PRE)
+                       r = v;
+               return r;
+       case DYNAMIC:
+               return getdyn(ex, expr, env, &assoc);
+       case SPLIT:
+               return exsplit(ex, expr, env);
+       case TOKENS:
+               return extokens(ex, expr, env);
+       case GSUB:
+               return exsub(ex, expr, env, 1);
+       case SUB:
+               return exsub(ex, expr, env, 0);
+       case SUBSTR:
+               return exsubstr(ex, expr, env);
+       case SRAND:
+               v.integer = seed;
+               if (expr->binary) {
+                       seed = eval(ex, x, env).integer;
+               } else
+                       seed = time(0);
+               srand48(seed);
+               return v;
+       case RAND:
+               v.floating = drand48();
+               return v;
+       case EXIT:
+               v = eval(ex, x, env);
+               if (ex->disc->exitf)
+                       (*ex->disc->exitf) (ex, env, (int)v.integer);
+               else
+                       exit((int)v.integer);
+               /*NOTREACHED*/
+               v.integer = -1;
+               return v;
+       case IF:
+               v = eval(ex, x, env);
+               if (v.integer)
+                       eval(ex, expr->data.operand.right->data.operand.left, env);
+               else
+                       eval(ex, expr->data.operand.right->data.operand.right, env);
                v.integer = 1;
                return v;
-           }
-           if (expr->data.operand.right) {
-               eval(ex, expr->data.operand.right, env);
-               if (ex->loopcount > 0
-                   && (--ex->loopcount > 0 || ex->loopop != CONTINUE)) {
-                   v.integer = 0;
-                   return v;
+       case FOR:
+       case WHILE:
+               expr = expr->data.operand.right;
+               for (;;)
+               {
+                       r = eval(ex, x, env);
+                       if (!r.integer)
+                       {
+                               v.integer = 1;
+                               return v;
+                       }
+                       if (expr->data.operand.right)
+                       {
+                               eval(ex, expr->data.operand.right, env);
+                               if (ex->loopcount > 0 && (--ex->loopcount > 0 || ex->loopop != CONTINUE))
+                               {
+                                       v.integer = 0;
+                                       return v;
+                               }
+                       }
+                       if (expr->data.operand.left)
+                               eval(ex, expr->data.operand.left, env);
                }
-           }
-           if (expr->data.operand.left)
-               eval(ex, expr->data.operand.left, env);
-       }
-     /*NOTREACHED*/ case SWITCH:
-       v = eval(ex, x, env);
-       i.integer = x->type;
-       r.integer = 0;
-       x = expr->data.operand.right;
-       a = x->data.select.statement;
-       n = 0;
-       while ((x = x->data.select.next)) {
-           if (!(t = x->data.select.constant))
-               n = 1;
-           else
-               for (; *t; t++) {
-                   switch ((int) i.integer) {
-                   case INTEGER:
-                   case UNSIGNED:
-                       if ((*t)->integer == v.integer)
-                           break;
-                       continue;
-                   case STRING:
-                       if ((ex->disc->version >= 19981111L
-                            && ex->disc->matchf) ? (*ex->disc->
-                                                    matchf) (ex, x,
-                                                             (*t)->string,
-                                                             expr->data.
-                                                             operand.left,
-                                                             v.string,
-                                                             env,
-                                                             ex->
-                                                             disc) :
-                           strmatch((*t)->string, v.string))
-                           break;
-                       continue;
-                   case FLOATING:
-                       if ((*t)->floating == v.floating)
-                           break;
-                       continue;
-                   }
-                   n = 1;
-                   break;
+               /*NOTREACHED*/
+       case SWITCH:
+               v = eval(ex, x, env);
+               i.integer = x->type;
+               r.integer = 0;
+               x = expr->data.operand.right;
+               a = x->data.select.statement;
+               n = 0;
+               while ((x = x->data.select.next))
+               {
+                       if (!(t = x->data.select.constant))
+                               n = 1;
+                       else
+                               for (; *t; t++)
+                               {
+                                       switch ((int)i.integer)
+                                       {
+                                       case INTEGER:
+                                       case UNSIGNED:
+                                               if ((*t)->integer == v.integer)
+                                                       break;
+                                               continue;
+                                       case STRING:
+                                               if ((ex->disc->version >= 19981111L && ex->disc->matchf) ? (*ex->disc->matchf)(ex, x, (*t)->string, expr->data.operand.left, v.string, env, ex->disc) : strmatch((*t)->string, v.string))
+                                                       break;
+                                               continue;
+                                       case FLOATING:
+                                               if ((*t)->floating == v.floating)
+                                                       break;
+                                               continue;
+                                       }
+                                       n = 1;
+                                       break;
+                               }
+                       if (n)
+                       {
+                               if (!x->data.select.statement)
+                               {
+                                       r.integer = 1;
+                                       break;
+                               }
+                               r = eval(ex, x->data.select.statement, env);
+                               if (ex->loopcount > 0)
+                               {
+                                       ex->loopcount--;
+                                       break;
+                               }
+                       }
                }
-           if (n) {
-               if (!x->data.select.statement) {
-                   r.integer = 1;
-                   break;
+               if (!n && a)
+               {
+                       r = eval(ex, a, env);
+                       if (ex->loopcount > 0)
+                               ex->loopcount--;
                }
-               r = eval(ex, x->data.select.statement, env);
-               if (ex->loopcount > 0) {
-                   ex->loopcount--;
-                   break;
+               return r;
+       case ITERATE:
+               v.integer = 0;
+               if (expr->data.generate.array->op == DYNAMIC)
+               {
+                       n = expr->data.generate.index->type == STRING;
+                       for (assoc = (Exassoc_t*)dtfirst((Dt_t*)expr->data.generate.array->data.variable.symbol->local.pointer); assoc; assoc = (Exassoc_t*)dtnext((Dt_t*)expr->data.generate.array->data.variable.symbol->local.pointer, assoc))
+                       {
+                               v.integer++;
+                               if (n)
+                                       expr->data.generate.index->value->data.constant.value.string = assoc->name;
+                               else
+                                       expr->data.generate.index->value->data.constant.value = assoc->key;
+                               eval(ex, expr->data.generate.statement, env);
+                               if (ex->loopcount > 0 && (--ex->loopcount > 0 || ex->loopop != CONTINUE))
+                               {
+                                       v.integer = 0;
+                                       break;
+                               }
+                       }
                }
-           }
-       }
-       if (!n && a) {
-           r = eval(ex, a, env);
-           if (ex->loopcount > 0)
-               ex->loopcount--;
-       }
-       return r;
-    case ITERATE:
-       v.integer = 0;
-       if (expr->data.generate.array->op == DYNAMIC) {
-           n = expr->data.generate.index->type == STRING;
-           for (assoc =
-                (Exassoc_t *) dtfirst((Dt_t *) expr->data.generate.array->
-                                      data.variable.symbol->local.
-                                      pointer); assoc;
-                assoc =
-                (Exassoc_t *) dtnext((Dt_t *) expr->data.generate.array->
-                                     data.variable.symbol->local.pointer,
-                                     assoc)) {
-               v.integer++;
-               if (n)
-                   expr->data.generate.index->value->data.constant.value.
-                       string = assoc->name;
                else
-                   expr->data.generate.index->value->data.constant.value =
-                       assoc->key;
-               eval(ex, expr->data.generate.statement, env);
-               if (ex->loopcount > 0
-                   && (--ex->loopcount > 0 || ex->loopop != CONTINUE)) {
-                   v.integer = 0;
-                   break;
-               }
-           }
-       } else {
-           r = (*ex->disc->getf) (ex, expr,
-                                  expr->data.generate.array->data.
-                                  variable.symbol,
-                                  expr->data.generate.array->data.
-                                  variable.reference, env, 0, ex->disc);
-           for (v.integer = 0; v.integer < r.integer; v.integer++) {
-               expr->data.generate.index->value->data.constant.value.
-                   integer = v.integer;
-               eval(ex, expr->data.generate.statement, env);
-               if (ex->loopcount > 0
-                   && (--ex->loopcount > 0 || ex->loopop != CONTINUE)) {
-                   v.integer = 0;
-                   break;
+               {
+                       r = (*ex->disc->getf)(ex, expr, expr->data.generate.array->data.variable.symbol, expr->data.generate.array->data.variable.reference, env, 0, ex->disc);
+                       for (v.integer = 0; v.integer < r.integer; v.integer++)
+                       {
+                               expr->data.generate.index->value->data.constant.value.integer = v.integer;
+                               eval(ex, expr->data.generate.statement, env);
+                               if (ex->loopcount > 0 && (--ex->loopcount > 0 || ex->loopop != CONTINUE))
+                               {
+                                       v.integer = 0;
+                                       break;
+                               }
+                       }
                }
-           }
-       }
-       return v;
+               return v;
     case ITERATER:
-       v.integer = 0;
-       if (expr->data.generate.array->op == DYNAMIC) {
-           n = expr->data.generate.index->type == STRING;
-           for (assoc =
-                (Exassoc_t *) dtlast((Dt_t *) expr->data.generate.array->
-                                      data.variable.symbol->local.
-                                      pointer); assoc;
-                assoc =
-                (Exassoc_t *) dtprev((Dt_t *) expr->data.generate.array->
-                                     data.variable.symbol->local.pointer,
-                                     assoc)) {
-               v.integer++;
-               if (n)
-                   expr->data.generate.index->value->data.constant.value.
-                       string = assoc->name;
-               else
-                   expr->data.generate.index->value->data.constant.value =
-                       assoc->key;
-               eval(ex, expr->data.generate.statement, env);
-               if (ex->loopcount > 0
-                   && (--ex->loopcount > 0 || ex->loopop != CONTINUE)) {
-                   v.integer = 0;
-                   break;
+               v.integer = 0;
+               if (expr->data.generate.array->op == DYNAMIC) {
+                       n = expr->data.generate.index->type == STRING;
+                       for (assoc = (Exassoc_t *) dtlast((Dt_t *) expr->data.generate.array->
+                                                  data.variable.symbol->local.
+                                                  pointer); assoc;
+                               assoc = (Exassoc_t *) dtprev((Dt_t *) expr->data.generate.array->
+                                                 data.variable.symbol->local.pointer,
+                                                 assoc)) {
+                               v.integer++;
+                               if (n)
+                                       expr->data.generate.index->value->data.constant.value.string = assoc->name;
+                               else
+                                       expr->data.generate.index->value->data.constant.value = assoc->key;
+                               eval(ex, expr->data.generate.statement, env);
+                               if (ex->loopcount > 0 && (--ex->loopcount > 0 || ex->loopop != CONTINUE)) {
+                                       v.integer = 0;
+                                       break;
+                               }
+                       }
+               } else {
+                       r = (*ex->disc->getf) (ex, expr, expr->data.generate.array->data.
+                                  variable.symbol, expr->data.generate.array->data.  variable.reference, env, 0, ex->disc);
+                       for (v.integer = r.integer-1; 0 <= v.integer; v.integer--) {
+                               expr->data.generate.index->value->data.constant.value.integer = v.integer;
+                               eval(ex, expr->data.generate.statement, env);
+                               if (ex->loopcount > 0 && (--ex->loopcount > 0 || ex->loopop != CONTINUE)) {
+                                       v.integer = 0;
+                                       break;
+                               }
+                       }
                }
-           }
-       } else {
-           r = (*ex->disc->getf) (ex, expr,
-                                  expr->data.generate.array->data.
-                                  variable.symbol,
-                                  expr->data.generate.array->data.
-                                  variable.reference, env, 0, ex->disc);
-           for (v.integer = r.integer-1; 0 <= v.integer; v.integer--) {
-               expr->data.generate.index->value->data.constant.value.
-                   integer = v.integer;
-               eval(ex, expr->data.generate.statement, env);
-               if (ex->loopcount > 0
-                   && (--ex->loopcount > 0 || ex->loopop != CONTINUE)) {
-                   v.integer = 0;
-                   break;
+               return v;
+       case '#':
+               v.integer = dtsize ((Dt_t*)expr->data.variable.symbol->local.pointer);
+               return v;
+       case IN_OP:
+               v.integer = evaldyn (ex, expr, env, 0);
+               return v;
+       case UNSET:
+               if (expr->data.variable.index) {
+                       v.integer = evaldyn (ex, expr, env, 1);
                }
-           }
-       }
-       return v;
-    case '#':
-       v.integer = dtsize ((Dt_t*)expr->data.variable.symbol->local.pointer);
-       return v;
-    case IN_OP:
-       v.integer = evaldyn (ex, expr, env, 0);
-       return v;
-    case UNSET:
-       if (expr->data.variable.index) {
-           v.integer = evaldyn (ex, expr, env, 1);
-       }
-       else {
-           dtclear ((Dt_t*)expr->data.variable.symbol->local.pointer);
-           v.integer = 0;
-       }
-       return v;
-    case CALL:
-       x = expr->data.call.args;
-       for (n = 0, a =
-            expr->data.call.procedure->value->data.procedure.args; a && x;
-            a = a->data.operand.right) {
-           if (n < elementsof(args)) {
-               save[n] =
-                   a->data.operand.left->data.variable.symbol->value->
-                   data.constant.value;
-               args[n++] = eval(ex, x->data.operand.left, env);
-           } else
-               a->data.operand.left->data.variable.symbol->value->data.
-                   constant.value = eval(ex, x->data.operand.left, env);
-           x = x->data.operand.right;
-       }
-       for (n = 0, a =
-            expr->data.call.procedure->value->data.procedure.args;
-            a && n < elementsof(save); a = a->data.operand.right)
-           a->data.operand.left->data.variable.symbol->value->data.
-               constant.value = args[n++];
-       if (x)
-           exerror("too many actual args");
-       else if (a)
-           exerror("not enough actual args");
-       v = exeval(ex,
-                  expr->data.call.procedure->value->data.procedure.body,
-                  env);
-       for (n = 0, a =
-            expr->data.call.procedure->value->data.procedure.args;
-            a && n < elementsof(save); a = a->data.operand.right)
-           a->data.operand.left->data.variable.symbol->value->data.
-               constant.value = save[n++];
-       return v;
-    case ARRAY:
-       n = 0;
-       for (x = expr->data.operand.right; x && n < elementsof(args);
-            x = x->data.operand.right)
-           args[n++] = eval(ex, x->data.operand.left, env);
-       return (*ex->disc->getf) (ex, expr->data.operand.left,
-                                 expr->data.operand.left->data.variable.
-                                 symbol,
-                                 expr->data.operand.left->data.variable.
-                                 reference, args, EX_ARRAY, ex->disc);
-    case FUNCTION:
-       n = 0;
-       for (x = expr->data.operand.right; x && n < elementsof(args);
-            x = x->data.operand.right)
-           args[n++] = eval(ex, x->data.operand.left, env);
-       return (*ex->disc->getf) (ex, expr->data.operand.left,
-                                 expr->data.operand.left->data.variable.
-                                 symbol,
-                                 expr->data.operand.left->data.variable.
-                                 reference, args, EX_CALL, ex->disc);
-    case ID:
-       if (expr->data.variable.index)
-           i = eval(ex, expr->data.variable.index, env);
-       else
-           i.integer = EX_SCALAR;
+               else {
+                       dtclear ((Dt_t*)expr->data.variable.symbol->local.pointer);
+                       v.integer = 0;
+               }
+               return v;
+       case CALL:
+               x = expr->data.call.args;
+               for (n = 0, a = expr->data.call.procedure->value->data.procedure.args; a && x; a = a->data.operand.right)
+               {
+                       if (n < elementsof(args))
+                       {
+                               save[n] = a->data.operand.left->data.variable.symbol->value->data.constant.value;
+                               args[n++] = eval(ex, x->data.operand.left, env);
+                       }
+                       else
+                               a->data.operand.left->data.variable.symbol->value->data.constant.value = eval(ex, x->data.operand.left, env);
+                       x = x->data.operand.right;
+               }
+               for (n = 0, a = expr->data.call.procedure->value->data.procedure.args; a && n < elementsof(save); a = a->data.operand.right)
+                       a->data.operand.left->data.variable.symbol->value->data.constant.value = args[n++];
+               if (x)
+                       exerror("too many actual args");
+               else if (a)
+                       exerror("not enough actual args");
+               v = exeval(ex, expr->data.call.procedure->value->data.procedure.body, env);
+               for (n = 0, a = expr->data.call.procedure->value->data.procedure.args; a && n < elementsof(save); a = a->data.operand.right)
+                       a->data.operand.left->data.variable.symbol->value->data.constant.value = save[n++];
+               return v;
+       case ARRAY:
+               n = 0;
+               for (x = expr->data.operand.right; x && n < elementsof(args); x = x->data.operand.right)
+                       args[n++] = eval(ex, x->data.operand.left, env);
+               return (*ex->disc->getf) (ex, expr->data.operand.left, expr->data.operand.left->data.variable.symbol,
+                       expr->data.operand.left->data.variable.reference, args, EX_ARRAY, ex->disc);
+       case FUNCTION:
+               n = 0;
+               args[n++].string = (char*)env;
+               for (x = expr->data.operand.right; x && n < elementsof(args); x = x->data.operand.right)
+                       args[n++] = eval(ex, x->data.operand.left, env);
+               return (*ex->disc->getf)(ex, expr->data.operand.left, expr->data.operand.left->data.variable.symbol, expr->data.operand.left->data.variable.reference, args+1, EX_CALL, ex->disc);
+       case ID:
+               if (expr->data.variable.index)
+                       i = eval(ex, expr->data.variable.index, env);
+               else
+                       i.integer = EX_SCALAR;
 #ifndef OLD
-       if (expr->data.variable.dyna) {
-           Extype_t locv;
-           locv = getdyn(ex, expr->data.variable.dyna, env, &assoc);
-           expr->data.variable.dyna->data.variable.dyna->data.constant.
-               value = locv;
-       }
+               if (expr->data.variable.dyna) {
+                       Extype_t locv;
+                       locv = getdyn(ex, expr->data.variable.dyna, env, &assoc);
+                       expr->data.variable.dyna->data.variable.dyna->data.constant.  value = locv;
+               }
 #endif
-       return (*ex->disc->getf) (ex, expr, expr->data.variable.symbol,
-                                 expr->data.variable.reference, env,
-                                 (int) i.integer, ex->disc);
-    case INC:
-       n = 1;
-       goto add;
-    case PRINT:
-       v.integer = prints(ex, expr, env, sfstdout);
-       return v;
-    case PRINTF:
-       v.integer = print(ex, expr, env, NiL);
-       return v;
+               return (*ex->disc->getf)(ex, expr, expr->data.variable.symbol, expr->data.variable.reference, env, (int)i.integer, ex->disc);
+       case INC:
+               n = 1;
+               goto add;
+       case PRINT:
+               v.integer = prints(ex, expr, env, sfstdout);
+               return v;
+       case PRINTF:
+               v.integer = print(ex, expr, env, NiL);
+               return v;
 #ifdef UNUSED
-    case QUERY:
-       print(ex, expr, env, sfstderr);
-       v.integer = !astquery(2, "");
-       return v;
+       case QUERY:
+               print(ex, expr, env, sfstderr);
+               v.integer = !astquery(2, "");
+               return v;
 #endif
-    case RETURN:
-       ex->loopret = eval(ex, x, env);
-       ex->loopcount = 32767;
-       ex->loopop = expr->op;
-       return ex->loopret;
-    case SCANF:
-    case SSCANF:
-       v.integer = scan(ex, expr, env, NiL);
-       return v;
-    case SPRINTF:
-       print(ex, expr, env, ex->tmp);
-       v.string = vmstrdup(ex->ve, sfstruse(ex->tmp));
-       return v;
-    case '=':
-       v = eval(ex, expr->data.operand.right, env);
-       if (expr->subop != '=') {
-           r = v;
-           if (x->op == DYNAMIC)
-               v = getdyn(ex, x, env, &assoc);
-           else {
-               if (x->data.variable.index)
-                   v = eval(ex, x->data.variable.index, env);
-               else
-                   v.integer = EX_SCALAR;
+       case RETURN:
+               ex->loopret = eval(ex, x, env);
+               ex->loopcount = 32767;
+               ex->loopop = expr->op;
+               return ex->loopret;
+       case SCANF:
+       case SSCANF:
+               v.integer = scan(ex, expr, env, NiL);
+               return v;
+       case SPRINTF:
+               print(ex, expr, env, ex->tmp);
+               v.string = exstash(ex->tmp, ex->ve);
+               return v;
+       case '=':
+               v = eval(ex, expr->data.operand.right, env);
+               if (expr->subop != '=')
+               {
+                       r = v;
+                       if (x->op == DYNAMIC)
+                               v = getdyn(ex, x, env, &assoc);
+                       else
+                       {
+                               if (x->data.variable.index)
+                                       v = eval(ex, x->data.variable.index, env);
+                               else
+                                       v.integer = EX_SCALAR;
 #ifndef OLD
-               if (x->data.variable.dyna) {
-                   Extype_t locv;
-                   locv = getdyn(ex, x->data.variable.dyna, env, &assoc);
-                   x->data.variable.dyna->data.variable.dyna->data.
-                       constant.value = locv;
-               }
+                               if (x->data.variable.dyna) {
+                                       Extype_t locv;
+                                       locv = getdyn(ex, x->data.variable.dyna, env, &assoc);
+                                       x->data.variable.dyna->data.variable.dyna->data.  constant.value = locv;
+                               }
 #endif
-               v = (*ex->disc->getf) (ex, x, x->data.variable.symbol,
-                                      x->data.variable.reference, env,
-                                      (int) v.integer, ex->disc);
-           }
-           switch (x->type) {
-           case FLOATING:
-               switch (expr->subop) {
-               case '+':
-                   v.floating += r.floating;
-                   break;
+                               v = (*ex->disc->getf)(ex, x, x->data.variable.symbol, x->data.variable.reference, env, (int)v.integer, ex->disc);
+                       }
+                       switch (x->type)
+                       {
+                       case FLOATING:
+                               switch (expr->subop)
+                               {
+                               case '+':
+                                       v.floating += r.floating;
+                                       break;
+                               case '-':
+                                       v.floating -= r.floating;
+                                       break;
+                               case '*':
+                                       v.floating *= r.floating;
+                                       break;
+                               case '/':
+                                       if (r.floating == 0.0)
+                                               exerror("floating divide by 0");
+                                       else
+                                               v.floating /= r.floating;
+                                       break;
+                               case '%':
+                                       if ((r.integer = r.floating) == 0)
+                                               exerror("floating 0 modulus");
+                                       else
+                                               v.floating = ((Sflong_t)v.floating) % r.integer;
+                                       break;
+                               case '&':
+                                       v.floating = ((Sflong_t)v.floating) & ((Sflong_t)r.floating);
+                                       break;
+                               case '|':
+                                       v.floating = ((Sflong_t)v.floating) | ((Sflong_t)r.floating);
+                                       break;
+                               case '^':
+                                       v.floating = ((Sflong_t)v.floating) ^ ((Sflong_t)r.floating);
+                                       break;
+                               case LS:
+                                       v.floating = ((Sflong_t)v.floating) << ((Sflong_t)r.floating);
+                                       break;
+                               case RS:
+#if _WIN32
+                                       v.floating = (Sflong_t)(((Sfulong_t)v.floating) >> ((Sflong_t)r.floating));
+#else
+                                       v.floating = ((Sfulong_t)v.floating) >> ((Sflong_t)r.floating);
+#endif
+                                       break;
+                               default:
+                                       goto huh;
+                               }
+                               break;
+                       case INTEGER:
+                       case UNSIGNED:
+                               switch (expr->subop)
+                               {
+                               case '+':
+                                       v.integer += r.integer;
+                                       break;
+                               case '-':
+                                       v.integer -= r.integer;
+                                       break;
+                               case '*':
+                                       v.integer *= r.integer;
+                                       break;
+                               case '/':
+                                       if (r.integer == 0)
+                                               exerror("integer divide by 0");
+                                       else
+                                               v.integer /= r.integer;
+                                       break;
+                               case '%':
+                                       if (r.integer == 0)
+                                               exerror("integer 0 modulus");
+                                       else
+                                               v.integer %= r.integer;
+                                       break;
+                               case '&':
+                                       v.integer &= r.integer;
+                                       break;
+                               case '|':
+                                       v.integer |= r.integer;
+                                       break;
+                               case '^':
+                                       v.integer ^= r.integer;
+                                       break;
+                               case LS:
+                                       v.integer <<= r.integer;
+                                       break;
+                               case RS:
+                                       v.integer = (Sfulong_t)v.integer >> r.integer;
+                                       break;
+                               default:
+                                       goto huh;
+                               }
+                               break;
+                       case STRING:
+                               switch (expr->subop)
+                               {
+                               case '+':
+                                       v.string = str_add(ex, v.string, r.string);
+                                       break;
+                               case '|':
+                                       v.string = str_ior(ex, v.string, r.string);
+                                       break;
+                               case '&':
+                                       v.string = str_and(ex, v.string, r.string);
+                                       break;
+                               case '^':
+                                       v.string = str_xor(ex, v.string, r.string);
+                                       break;
+                               case '%':
+                                       v.string = str_mod(ex, v.string, r.string);
+                                       break;
+                               case '*':
+                                       v.string = str_mpy(ex, v.string, r.string);
+                                       break;
+                               default:
+                                       goto huh;
+                               }
+                               break;
+                       default:
+                               goto huh;
+                       }
+               }
+               else if (x->op == DYNAMIC)
+                       getdyn(ex, x, env, &assoc);
+               else
+                       assoc = 0;
+               r = v;
+               goto set;
+       case ';':
+       case ',':
+               v = eval(ex, x, env);
+               while ((expr = expr->data.operand.right) && (expr->op == ';' || expr->op == ','))
+               {
+                       v = eval(ex, expr->data.operand.left, env);
+                       if (ex->loopcount)
+                               return v;
+               }
+               return expr ? eval(ex, expr, env) : v;
+       case '?':
+               v = eval(ex, x, env);
+               return v.integer ? eval(ex, expr->data.operand.right->data.operand.left, env) : eval(ex, expr->data.operand.right->data.operand.right, env);
+       case AND:
+               v = eval(ex, x, env);
+               return v.integer ? eval(ex, expr->data.operand.right, env) : v;
+       case OR:
+               v = eval(ex, x, env);
+               return v.integer ? v : eval(ex, expr->data.operand.right, env);
+       }
+       v = eval(ex, x, env);
+       if ((x = expr->data.operand.right)) {
+               r = eval(ex, x, env);
+               if (!BUILTIN(x->type) && expr->binary) {
+                       tmp = *expr->data.operand.left;
+                       tmp.data.constant.value = v;
+                       rtmp = *x;
+                       rtmp.data.constant.value = r;
+                       if (!(*ex->disc->binaryf) (ex, &tmp, expr, &rtmp, 0, ex->disc)) return tmp.data.constant.value;
+               }
+       }
+       switch (expr->data.operand.left->type)
+       {
+       case FLOATING:
+               switch (expr->op)
+               {
+               case F2I:
+                       v.integer = v.floating;
+                       return v;
+               case F2S:
+                       tmp = *expr->data.operand.left;
+                       tmp.data.constant.value = v;
+                       if (expr->data.operand.left->op != DYNAMIC && expr->data.operand.left->op != ID)
+                       {
+                               sfprintf(ex->tmp, "%g", v.floating);
+                               tmp.data.constant.value.string = exstash(ex->tmp, ex->ve);
+                       }
+                       else if ((*ex->disc->convertf)(ex, &tmp, STRING, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc)) {
+                               sfprintf(ex->tmp, "%g", v.floating);
+                               tmp.data.constant.value.string = exstash(ex->tmp, ex->ve);
+                       }
+                       tmp.type = STRING;
+                       return tmp.data.constant.value;
+               case F2X:
+                       tmp = *expr->data.operand.left;
+                       tmp.data.constant.value = v;
+                       if ((*ex->disc->convertf)(ex, &tmp, expr->type, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
+                               exerror("%s: cannot convert floating value to external", tmp.data.variable.symbol->name);
+                       tmp.type = expr->type;
+                       return tmp.data.constant.value;
+               case '!':
+                       v.floating = !((Sflong_t)v.floating);
+                       return v;
+               case '~':
+                       v.floating = ~((Sflong_t)v.floating);
+                       return v;
                case '-':
-                   v.floating -= r.floating;
-                   break;
-               case '*':
-                   v.floating *= r.floating;
-                   break;
-               case '/':
-                   if (r.floating == 0.0)
-                       exerror("floating divide by 0");
-                   else
-                       v.floating /= r.floating;
-                   break;
-               case '%':
-                   if ((r.integer = r.floating) == 0)
-                       exerror("floating 0 modulus");
-                   else
-                       v.floating = ((Sflong_t) v.floating) % r.integer;
-                   break;
+                       if (x)
+                               v.floating -= r.floating;
+                       else
+                               v.floating = -v.floating;
+                       return v;
+               case '+':
+                       v.floating += r.floating;
+                       return v;
                case '&':
-                   v.floating =
-                       ((Sflong_t) v.floating) & ((Sflong_t) r.floating);
-                   break;
+                       v.floating = (Sflong_t)v.floating & (Sflong_t)r.floating;
+                       return v;
                case '|':
-                   v.floating =
-                       ((Sflong_t) v.floating) | ((Sflong_t) r.floating);
-                   break;
+                       v.floating = (Sflong_t)v.floating | (Sflong_t)r.floating;
+                       return v;
                case '^':
-                   v.floating =
-                       ((Sflong_t) v.floating) ^ ((Sflong_t) r.floating);
-                   break;
+                       v.floating = (Sflong_t)v.floating ^ (Sflong_t)r.floating;
+                       return v;
+               case '*':
+                       v.floating *= r.floating;
+                       return v;
+               case '/':
+                       if (r.floating == 0.0)
+                               exerror("floating divide by 0");
+                       else
+                               v.floating /= r.floating;
+                       return v;
+               case '%':
+                       if ((r.integer = r.floating) == 0)
+                               exerror("floating 0 modulus");
+                       else
+                               v.floating = (Sflong_t)v.floating % r.integer;
+                       return v;
+               case '<':
+                       v.integer = v.floating < r.floating;
+                       return v;
+               case LE:
+                       v.integer = v.floating <= r.floating;
+                       return v;
+               case EQ:
+                       v.integer = v.floating == r.floating;
+                       return v;
+               case NE:
+                       v.integer = v.floating != r.floating;
+                       return v;
+               case GE:
+                       v.integer = v.floating >= r.floating;
+                       return v;
+               case '>':
+                       v.integer = v.floating > r.floating;
+                       return v;
                case LS:
 /* IBM compilers can't deal with these shift operators on long long.
- *                                     v.floating = ((Sflong_t)v.floating) << ((Sflong_t)r.floating);
+ *                                      v.floating = ((Sflong_t)v.floating) << ((Sflong_t)r.floating);
  */
-                   {
-                       Sflong_t op1, op2;
-                       op1 = ((Sflong_t) v.floating);
-                       op2 = ((Sflong_t) r.floating);
-                       v.floating = (double) (op1 << op2);
-                   }
-                   break;
+                       {
+                               Sflong_t op1, op2;
+                               op1 = ((Sflong_t) v.floating);
+                               op2 = ((Sflong_t) r.floating);
+                               v.floating = (double) (op1 << op2);
+                       }
+                       return v;
                case RS:
 #if _WIN32
-                   v.floating =
-                       (Sflong_t) (((Sfulong_t) v.
-                                    floating) >> ((Sflong_t) r.floating));
+                       v.floating = (Sflong_t) (((Sfulong_t) v.floating) >> ((Sflong_t) r.floating));
 #else
 /* IBM compilers can't deal with these shift operators on long long.
- *                                     v.floating = ((Sfulong_t)v.floating) >> ((Sflong_t)r.floating);
+ *                                      v.floating = ((Sfulong_t)v.floating) >> ((Sflong_t)r.floating);
  */
-                   {
-                       Sflong_t op1, op2;
-                       op1 = ((Sfulong_t) v.floating);
-                       op2 = ((Sflong_t) r.floating);
-                       v.floating = (double) (op1 >> op2);
-                   }
+                       {
+                               Sflong_t op1, op2;
+                               op1 = ((Sfulong_t) v.floating);
+                               op2 = ((Sflong_t) r.floating);
+                               v.floating = (double) (op1 >> op2);
+                       }
 #endif
-                   break;
-               default:
-                   goto huh;
+
+                       return v;
                }
                break;
-           case INTEGER:
-           case UNSIGNED:
-               switch (expr->subop) {
-               case '+':
-                   v.integer += r.integer;
-                   break;
+       default:
+               switch (expr->op)
+               {
+               case X2F:
+                       xConvert(ex, expr, FLOATING, v, &tmp);
+                       return tmp.data.constant.value;
+               case X2I:
+                       xConvert(ex, expr, INTEGER, v, &tmp);
+                       return tmp.data.constant.value;
+               case X2S:
+                       xConvert(ex, expr, STRING, v, &tmp);
+                       return tmp.data.constant.value;
+               case X2X:
+                       xConvert(ex, expr, expr->type, v, &tmp);
+                       return tmp.data.constant.value;
+               case XPRINT:
+                       xPrint(ex, expr, v, &tmp);
+                       return tmp.data.constant.value;
+               default:
+                       tmp = *expr->data.operand.left;
+                       tmp.data.constant.value = v;
+                       if (x) {
+                               rtmp = *x;
+                               rtmp.data.constant.value = r;
+                               rp = &rtmp;
+                       } else
+                               rp = 0;
+                       if (!(*ex->disc->binaryf) (ex, &tmp, expr, rp, 0, ex->disc))
+                               return tmp.data.constant.value;
+               }
+               goto integer;
+       case UNSIGNED:
+               switch (expr->op)
+               {
+               case '<':
+                       v.integer = (Sfulong_t)v.integer < (Sfulong_t)r.integer;
+                       return v;
+               case LE:
+                       v.integer = (Sfulong_t)v.integer <= (Sfulong_t)r.integer;
+                       return v;
+               case GE:
+                       v.integer = (Sfulong_t)v.integer >= (Sfulong_t)r.integer;
+                       return v;
+               case '>':
+                       v.integer = (Sfulong_t)v.integer > (Sfulong_t)r.integer;
+                       return v;
+               }
+               /*FALLTHROUGH*/
+       case INTEGER:
+       integer:
+               switch (expr->op)
+               {
+               case I2F:
+#if _WIN32
+                       v.floating = v.integer;
+#else
+                       if (expr->type == UNSIGNED)
+                               v.floating = (Sfulong_t)v.integer;
+                       else
+                               v.floating = v.integer;
+#endif
+                       return v;
+               case I2S:
+                       tmp = *expr->data.operand.left;
+                       tmp.data.constant.value = v;
+                       if (expr->data.operand.left->op != DYNAMIC && expr->data.operand.left->op != ID)
+                       {
+                               if (expr->data.operand.left->type == UNSIGNED)
+                                       sfprintf(ex->tmp, "%I*u", sizeof(v.integer), v.integer);
+                               else
+                                       sfprintf(ex->tmp, "%I*d", sizeof(v.integer), v.integer);
+                               tmp.data.constant.value.string = exstash(ex->tmp, ex->ve);
+                       }
+                       else if ((*ex->disc->convertf)(ex, &tmp, STRING, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc)) {
+                               if (expr->data.operand.left->type == UNSIGNED)
+                                       sfprintf(ex->tmp, "%I*u", sizeof(v.integer), v.integer);
+                               else
+                                       sfprintf(ex->tmp, "%I*d", sizeof(v.integer), v.integer);
+                               tmp.data.constant.value.string =  exstash(ex->tmp, ex->ve);
+                       }
+                       tmp.type = STRING;
+                       return tmp.data.constant.value;
+               case I2X:
+                       tmp = *expr->data.operand.left;
+                       tmp.data.constant.value = v;
+                       if ((*ex->disc->convertf)(ex, &tmp, expr->type, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
+                               exerror("%s: cannot convert integer value to external", tmp.data.variable.symbol->name);
+                       tmp.type = expr->type;
+                       return tmp.data.constant.value;
+               case '!':
+                       v.integer = !v.integer;
+                       return v;
+               case '~':
+                       v.integer = ~v.integer;
+                       return v;
                case '-':
-                   v.integer -= r.integer;
-                   break;
-               case '*':
-                   v.integer *= r.integer;
-                   break;
-               case '/':
-                   if (r.integer == 0)
-                       exerror("integer divide by 0");
-                   else
-                       v.integer /= r.integer;
-                   break;
-               case '%':
-                   if (r.integer == 0)
-                       exerror("integer 0 modulus");
-                   else
-                       v.integer %= r.integer;
-                   break;
+                       if (x)
+                               v.integer -= r.integer;
+                       else
+                               v.integer = -v.integer;
+                       return v;
+               case '+':
+                       v.integer += r.integer;
+                       return v;
                case '&':
-                   v.integer &= r.integer;
-                   break;
+                       v.integer &= r.integer;
+                       return v;
                case '|':
-                   v.integer |= r.integer;
-                   break;
+                       v.integer |= r.integer;
+                       return v;
                case '^':
-                   v.integer ^= r.integer;
-                   break;
+                       v.integer ^= r.integer;
+                       return v;
+               case '*':
+                       v.integer *= r.integer;
+                       return v;
+               case '/':
+                       if (r.integer == 0)
+                               exerror("integer divide by 0");
+                       else
+                               v.integer /= r.integer;
+                       return v;
+               case '%':
+                       if (r.integer == 0)
+                               exerror("integer 0 modulus");
+                       else
+                               v.integer %= r.integer;
+                       return v;
+               case EQ:
+                       v.integer = v.integer == r.integer;
+                       return v;
+               case NE:
+                       v.integer = v.integer != r.integer;
+                       return v;
                case LS:
-                   v.integer <<= r.integer;
-                   break;
+/* IBM compilers can't deal with these shift operators on long long.
+ *                      v.floating = (Sflong_t)v.floating << (Sflong_t)r.floating;
+ */
+                       {
+                               Sflong_t op1, op2;
+                               op1 = ((Sflong_t) v.floating);
+                               op2 = ((Sflong_t) r.floating);
+                               v.floating = (double) (op1 << op2);
+                       }
+                       return v;
                case RS:
-                   v.integer = (Sfulong_t) v.integer >> r.integer;
-                   break;
-               default:
-                   goto huh;
+/* IBM compilers can't deal with these shift operators on long long.
+ *                      v.integer = ((Sfulong_t)v.floating) >> (Sflong_t)r.floating;
+ */
+                       {
+                               Sfulong_t op1;
+                               Sflong_t op2;
+                               op1 = ((Sfulong_t) v.floating);
+                               op2 = ((Sflong_t) r.floating);
+                               v.integer = (op1 >> op2);
+                       }
+                       return v;
+               case '<':
+                       v.integer = v.integer < r.integer;
+                       return v;
+               case LE:
+                       v.integer = v.integer <= r.integer;
+                       return v;
+               case GE:
+                       v.integer = v.integer >= r.integer;
+                       return v;
+               case '>':
+                       v.integer = v.integer > r.integer;
+                       return v;
                }
                break;
-           case STRING:
-               switch (expr->subop) {
+       case STRING:
+               switch (expr->op)
+               {
+               case S2B:
+                       v.integer = *v.string != 0;
+                       return v;
+               case S2F:
+                       tmp = *expr->data.operand.left;
+                       tmp.data.constant.value = v;
+                       if ((*ex->disc->convertf)(ex, &tmp, FLOATING, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
+                       {
+                               tmp.data.constant.value.floating = strtod(v.string, &e);
+                               if (*e)
+                                       tmp.data.constant.value.floating = *v.string != 0;
+                       }
+                       tmp.type = FLOATING;
+                       return tmp.data.constant.value;
+               case S2I:
+                       tmp = *expr->data.operand.left;
+                       tmp.data.constant.value = v;
+                       if ((*ex->disc->convertf)(ex, &tmp, INTEGER, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
+                       {
+                               if (v.string) {
+                                       tmp.data.constant.value.integer = strToL(v.string, &e);
+                    if (*e)
+                        tmp.data.constant.value.integer = *v.string != 0;
+                               }
+                               else
+                                       tmp.data.constant.value.integer = 0;
+                       }
+                       tmp.type = INTEGER;
+                       return tmp.data.constant.value;
+               case S2X:
+                       tmp = *expr->data.operand.left;
+                       tmp.data.constant.value = v;
+                       if ((*ex->disc->convertf)(ex, &tmp, expr->type, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
+                               exerror("%s: cannot convert string value to external", tmp.data.variable.symbol->name);
+                       tmp.type = expr->type;
+                       return tmp.data.constant.value;
+               case EQ:
+               case NE:
+                       v.integer = ((v.string && r.string) ? ((ex->disc->version >= 19981111L && ex->disc->matchf) ? (*ex->disc->matchf)(ex, expr->data.operand.left, v.string, expr->data.operand.right, r.string, env, ex->disc) : strmatch(v.string, r.string)) : (v.string == r.string)) == (expr->op == EQ);
+                       return v;
                case '+':
-                   v.string = str_add(ex, v.string, r.string);
-                   break;
+                       v.string = str_add(ex, v.string, r.string);
+                       return v;
                case '|':
-                   v.string = str_ior(ex, v.string, r.string);
-                   break;
+                       v.string = str_ior(ex, v.string, r.string);
+                       return v;
                case '&':
-                   v.string = str_and(ex, v.string, r.string);
-                   break;
+                       v.string = str_and(ex, v.string, r.string);
+                       return v;
                case '^':
-                   v.string = str_xor(ex, v.string, r.string);
-                   break;
+                       v.string = str_xor(ex, v.string, r.string);
+                       return v;
                case '%':
-                   v.string = str_mod(ex, v.string, r.string);
-                   break;
+                       v.string = str_mod(ex, v.string, r.string);
+                       return v;
                case '*':
-                   v.string = str_mpy(ex, v.string, r.string);
-                   break;
-               default:
-                   goto huh;
+                       v.string = str_mpy(ex, v.string, r.string);
+                       return v;
                }
-               break;
-           default:
-               goto huh;
-           }
-       } else if (x->op == DYNAMIC)
-           getdyn(ex, x, env, &assoc);
-       else
-           assoc = 0;
-       r = v;
-       goto set;
-    case ';':
-    case ',':
-       v = eval(ex, x, env);
-       while ((expr = expr->data.operand.right)
-              && (expr->op == ';' || expr->op == ',')) {
-           v = eval(ex, expr->data.operand.left, env);
-           if (ex->loopcount)
-               return v;
-       }
-       return expr ? eval(ex, expr, env) : v;
-    case '?':
-       v = eval(ex, x, env);
-       return v.integer ? eval(ex,
-                               expr->data.operand.right->data.operand.
-                               left, env) : eval(ex,
-                                                 expr->data.operand.
-                                                 right->data.operand.
-                                                 right, env);
-    case AND:
-       v = eval(ex, x, env);
-       return v.integer ? eval(ex, expr->data.operand.right, env) : v;
-    case OR:
-       v = eval(ex, x, env);
-       return v.integer ? v : eval(ex, expr->data.operand.right, env);
-    }
-    v = eval(ex, x, env);
-    if ((x = expr->data.operand.right)) {
-       r = eval(ex, x, env);
-       if (!BUILTIN(x->type) && expr->binary) {
-           tmp = *expr->data.operand.left;
-           tmp.data.constant.value = v;
-           rtmp = *x;
-           rtmp.data.constant.value = r;
-           if (!(*ex->disc->binaryf) (ex, &tmp, expr, &rtmp, 0, ex->disc))
-               return tmp.data.constant.value;
-       }
-    }
-    switch (expr->data.operand.left->type) {
-    case FLOATING:
-       switch (expr->op) {
-       case F2I:
-           v.integer = v.floating;
-           return v;
-       case F2S:
-           tmp = *expr->data.operand.left;
-           tmp.data.constant.value = v;
-           if (expr->data.operand.left->op != DYNAMIC
-               && expr->data.operand.left->op != ID) {
-               sfprintf(ex->tmp, "%g", v.floating);
-               tmp.data.constant.value.string =
-                   vmstrdup(ex->ve, sfstruse(ex->tmp));
-           } else
-               if ((*ex->disc->convertf) (ex, &tmp, STRING,
-                                          expr->data.operand.
-                                          right ? expr->data.operand.
-                                          right->data.variable.
-                                          symbol : (Exid_t *) 0, 0,
-                                          ex->disc)) {
-               sfprintf(ex->tmp, "%g", v.floating);
-               tmp.data.constant.value.string =
-                   vmstrdup(ex->ve, sfstruse(ex->tmp));
-           }
-           tmp.type = STRING;
-           return tmp.data.constant.value;
-       case F2X:
-           tmp = *expr->data.operand.left;
-           tmp.data.constant.value = v;
-           if ((*ex->disc->convertf) (ex, &tmp, expr->type,
-                                      expr->data.operand.right ? expr->
-                                      data.operand.right->data.variable.
-                                      symbol : (Exid_t *) 0, 0, ex->disc))
-               exerror("%s: cannot convert floating value to external",
-                       tmp.data.variable.symbol->name);
-           tmp.type = expr->type;
-           return tmp.data.constant.value;
-       case '!':
-           v.floating = !((Sflong_t) v.floating);
-           return v;
-       case '~':
-           v.floating = ~((Sflong_t) v.floating);
-           return v;
-       case '-':
-           if (x)
-               v.floating -= r.floating;
-           else
-               v.floating = -v.floating;
-           return v;
-       case '+':
-           v.floating += r.floating;
-           return v;
-       case '&':
-           v.floating = (Sflong_t) v.floating & (Sflong_t) r.floating;
-           return v;
-       case '|':
-           v.floating = (Sflong_t) v.floating | (Sflong_t) r.floating;
-           return v;
-       case '^':
-           v.floating = (Sflong_t) v.floating ^ (Sflong_t) r.floating;
-           return v;
-       case '*':
-           v.floating *= r.floating;
-           return v;
-       case '/':
-           if (r.floating == 0.0)
-               exerror("floating divide by 0");
-           else
-               v.floating /= r.floating;
-           return v;
-       case '%':
-           if ((r.integer = r.floating) == 0)
-               exerror("floating 0 modulus");
-           else
-               v.floating = (Sflong_t) v.floating % r.integer;
-           return v;
-       case '<':
-           v.integer = v.floating < r.floating;
-           return v;
-       case LE:
-           v.integer = v.floating <= r.floating;
-           return v;
-       case EQ:
-           v.integer = v.floating == r.floating;
-           return v;
-       case NE:
-           v.integer = v.floating != r.floating;
-           return v;
-       case GE:
-           v.integer = v.floating >= r.floating;
-           return v;
-       case '>':
-           v.integer = v.floating > r.floating;
-           return v;
-       case LS:
-/* IBM compilers can't deal with these shift operators on long long.
- *                     v.floating = (Sflong_t)v.floating << (Sflong_t)r.floating;
- */
-           {
-               Sflong_t op1, op2;
-               op1 = ((Sflong_t) v.floating);
-               op2 = ((Sflong_t) r.floating);
-               v.floating = (double) (op1 << op2);
-           }
-           return v;
-       case RS:
-/* IBM compilers can't deal with these shift operators on long long.
- *                     v.integer = ((Sfulong_t)v.floating) >> (Sflong_t)r.floating;
- */
-           {
-               Sfulong_t op1;
-               Sflong_t op2;
-               op1 = ((Sfulong_t) v.floating);
-               op2 = ((Sflong_t) r.floating);
-               v.integer = (op1 >> op2);
-           }
-           return v;
-       }
-       break;
-    default:
-       switch (expr->op) {
-       case X2F:
-           xConvert(ex, expr, FLOATING, v, &tmp);
-           return tmp.data.constant.value;
-       case X2I:
-           xConvert(ex, expr, INTEGER, v, &tmp);
-           return tmp.data.constant.value;
-       case X2S:
-           xConvert(ex, expr, STRING, v, &tmp);
-           return tmp.data.constant.value;
-       case X2X:
-           xConvert(ex, expr, expr->type, v, &tmp);
-           return tmp.data.constant.value;
-       case XPRINT:
-           xPrint(ex, expr, v, &tmp);
-           return tmp.data.constant.value;
-       default:
-           tmp = *expr->data.operand.left;
-           tmp.data.constant.value = v;
-           if (x) {
-               rtmp = *x;
-               rtmp.data.constant.value = r;
-               rp = &rtmp;
-           } else
-               rp = 0;
-           if (!(*ex->disc->binaryf) (ex, &tmp, expr, rp, 0, ex->disc))
-               return tmp.data.constant.value;
-       }
-       goto integer;
-    case UNSIGNED:
-       switch (expr->op) {
-       case '<':
-           v.integer = (Sfulong_t) v.integer < (Sfulong_t) r.integer;
-           return v;
-       case LE:
-           v.integer = (Sfulong_t) v.integer <= (Sfulong_t) r.integer;
-           return v;
-       case GE:
-           v.integer = (Sfulong_t) v.integer >= (Sfulong_t) r.integer;
-           return v;
-       case '>':
-           v.integer = (Sfulong_t) v.integer > (Sfulong_t) r.integer;
-           return v;
-       }
-     /*FALLTHROUGH*/ case INTEGER:
-      integer:
-       switch (expr->op) {
-       case I2F:
-#if _WIN32
-           v.floating = v.integer;
-#else
-           if (expr->type == UNSIGNED) 
-               v.floating = (Sfulong_t) v.integer;
-           else
-               v.floating = v.integer;
-#endif
-           return v;
-       case I2S:
-           tmp = *expr->data.operand.left;
-           tmp.data.constant.value = v;
-           if (expr->data.operand.left->op != DYNAMIC
-               && expr->data.operand.left->op != ID) {
-               if (expr->data.operand.left->type == UNSIGNED)
-                   sfprintf(ex->tmp, "%I*u", sizeof(v.integer),
-                            v.integer);
-               else
-                   sfprintf(ex->tmp, "%I*d", sizeof(v.integer),
-                            v.integer);
-               tmp.data.constant.value.string =
-                   vmstrdup(ex->ve, sfstruse(ex->tmp));
-           } else
-               if ((*ex->disc->convertf) (ex, &tmp, STRING,
-                                          expr->data.operand.
-                                          right ? expr->data.operand.
-                                          right->data.variable.
-                                          symbol : (Exid_t *) 0, 0,
-                                          ex->disc)) {
-               if (expr->data.operand.left->type == UNSIGNED)
-                   sfprintf(ex->tmp, "%I*u", sizeof(v.integer),
-                            v.integer);
-               else
-                   sfprintf(ex->tmp, "%I*d", sizeof(v.integer),
-                            v.integer);
-               tmp.data.constant.value.string =
-                   vmstrdup(ex->ve, sfstruse(ex->tmp));
-           }
-           tmp.type = STRING;
-           return tmp.data.constant.value;
-       case I2X:
-           tmp = *expr->data.operand.left;
-           tmp.data.constant.value = v;
-           if ((*ex->disc->convertf) (ex, &tmp, expr->type,
-                                      expr->data.operand.right ? expr->
-                                      data.operand.right->data.variable.
-                                      symbol : (Exid_t *) 0, 0, ex->disc))
-               exerror("%s: cannot convert integer value to external",
-                       tmp.data.variable.symbol->name);
-           tmp.type = expr->type;
-           return tmp.data.constant.value;
-       case '!':
-           v.integer = !v.integer;
-           return v;
-       case '~':
-           v.integer = ~v.integer;
-           return v;
-       case '-':
-           if (x)
-               v.integer -= r.integer;
-           else
-               v.integer = -v.integer;
-           return v;
-       case '+':
-           v.integer += r.integer;
-           return v;
-       case '&':
-           v.integer &= r.integer;
-           return v;
-       case '|':
-           v.integer |= r.integer;
-           return v;
-       case '^':
-           v.integer ^= r.integer;
-           return v;
-       case '*':
-           v.integer *= r.integer;
-           return v;
-       case '/':
-           if (r.integer == 0)
-               exerror("integer divide by 0");
-           else
-               v.integer /= r.integer;
-           return v;
-       case '%':
-           if (r.integer == 0)
-               exerror("integer 0 modulus");
-           else
-               v.integer %= r.integer;
-           return v;
-       case EQ:
-           v.integer = v.integer == r.integer;
-           return v;
-       case NE:
-           v.integer = v.integer != r.integer;
-           return v;
-       case LS:
-           v.integer = v.integer << r.integer;
-           return v;
-       case RS:
-           v.integer = ((Sfulong_t) v.integer) >> r.integer;
-           return v;
-       case '<':
-           v.integer = v.integer < r.integer;
-           return v;
-       case LE:
-           v.integer = v.integer <= r.integer;
-           return v;
-       case GE:
-           v.integer = v.integer >= r.integer;
-           return v;
-       case '>':
-           v.integer = v.integer > r.integer;
-           return v;
-       }
-       break;
-    case STRING:
-       switch (expr->op) {
-       case S2B:
-           v.integer = *v.string != 0;
-           return v;
-       case S2F:
-           tmp = *expr->data.operand.left;
-           tmp.data.constant.value = v;
-           if ((*ex->disc->convertf) (ex, &tmp, FLOATING,
-                                      expr->data.operand.right ? expr->
-                                      data.operand.right->data.variable.
-                                      symbol : (Exid_t *) 0, 0,
-                                      ex->disc)) {
-               tmp.data.constant.value.floating = strtod(v.string, &e);
-               if (*e)
-                   tmp.data.constant.value.floating = *v.string != 0;
-           }
-           tmp.type = FLOATING;
-           return tmp.data.constant.value;
-       case S2I:
-           tmp = *expr->data.operand.left;
-           tmp.data.constant.value = v;
-           if ((*ex->disc->convertf) (ex, &tmp, INTEGER,
-                                      expr->data.operand.right ? expr->
-                                      data.operand.right->data.variable.
-                                      symbol : (Exid_t *) 0, 0,
-                                      ex->disc)) {
-               if (v.string) {
-                   tmp.data.constant.value.integer = strToL(v.string, &e);
-                   if (*e)
-                       tmp.data.constant.value.integer = *v.string != 0;
+               v.integer = strcoll(v.string, r.string);
+               switch (expr->op)
+               {
+               case '<':
+                       v.integer = v.integer < 0;
+                       return v;
+               case LE:
+                       v.integer = v.integer <= 0;
+                       return v;
+               case GE:
+                       v.integer = v.integer >= 0;
+                       return v;
+               case '>':
+                       v.integer = v.integer > 0;
+                       return v;
                }
-               else
-                   tmp.data.constant.value.integer = 0;
-           }
-           tmp.type = INTEGER;
-           return tmp.data.constant.value;
-       case S2X:
-           tmp = *expr->data.operand.left;
-           tmp.data.constant.value = v;
-           if ((*ex->disc->convertf) (ex, &tmp, expr->type,
-                                      expr->data.operand.right ? expr->
-                                      data.operand.right->data.variable.
-                                      symbol : (Exid_t *) 0, 0, ex->disc))
-               exerror("%s: cannot convert string value to external",
-                       tmp.data.variable.symbol->name);
-           tmp.type = expr->type;
-           return tmp.data.constant.value;
-       case EQ:
-       case NE:
-           v.integer =
-               ((v.string
-                 && r.string) ? ((ex->disc->version >= 19981111L
-                                  && ex->disc->matchf) ? (*ex->disc->
-                                                          matchf) (ex,
-                                                                   expr->
-                                                                   data.
-                                                                   operand.
-                                                                   left,
-                                                                   v.
-                                                                   string,
-                                                                   expr->
-                                                                   data.
-                                                                   operand.
-                                                                   right,
-                                                                   r.
-                                                                   string,
-                                                                   env,
-                                                                   ex->
-                                                                   disc) :
-                                 strmatch(v.string,
-                                          r.string)) : (v.string ==
-                                                        r.string)) ==
-               (expr->op == EQ);
-           return v;
-       case '+':
-           v.string = str_add(ex, v.string, r.string);
-           return v;
-       case '|':
-           v.string = str_ior(ex, v.string, r.string);
-           return v;
-       case '&':
-           v.string = str_and(ex, v.string, r.string);
-           return v;
-       case '^':
-           v.string = str_xor(ex, v.string, r.string);
-           return v;
-       case '%':
-           v.string = str_mod(ex, v.string, r.string);
-           return v;
-       case '*':
-           v.string = str_mpy(ex, v.string, r.string);
-           return v;
-       }
-       v.integer = strcoll(v.string, r.string);
-       switch (expr->op) {
-       case '<':
-           v.integer = v.integer < 0;
-           return v;
-       case LE:
-           v.integer = v.integer <= 0;
-           return v;
-       case GE:
-           v.integer = v.integer >= 0;
-           return v;
-       case '>':
-           v.integer = v.integer > 0;
-           return v;
+               goto huh;
        }
-       goto huh;
-    }
-  huh:
-    if (expr->binary)
-       exerror("operator %s %s %s not implemented",
-               lexname(expr->data.operand.left->type, -1),
-               lexname(expr->op, expr->subop),
-               expr->data.operand.right ? lexname(expr->data.operand.
-                                                  right->type,
-                                                  -1) : "UNARY");
-    else
-       exerror("operator %s %s not implemented",
-               lexname(expr->op, expr->subop),
-               lexname(expr->data.operand.left->type, -1));
-    return exzero(expr->type);
+ huh:
+       if (expr->binary)
+               exerror("operator %s %s %s not implemented", lexname(expr->data.operand.left->type, -1), lexname(expr->op, expr->subop), expr->data.operand.right ? lexname(expr->data.operand.right->type, -1) : "UNARY");
+       else
+               exerror("operator %s %s not implemented", lexname(expr->op, expr->subop), lexname(expr->data.operand.left->type, -1));
+       return exzero(expr->type);
 }
 
 /*
  * evaluate expression expr
  */
 
-Extype_t exeval(Expr_t * ex, Exnode_t * expr, void *env)
+Extype_t
+exeval(Expr_t* ex, Exnode_t* expr, void* env)
 {
-    Extype_t v;
-
-    vmclear(ex->ve);
-    if (expr->compiled.integer) {
-       switch (expr->type) {
-       case FLOATING:
-           v.floating = (*expr->compiled.floating) (ex->disc->data);
-           break;
-       case STRING:
-           v.string = (*expr->compiled.string) (ex->disc->data);
-           break;
-       default:
-           v.integer = (*expr->compiled.integer) (ex->disc->data);
-           break;
+       Extype_t        v;
+
+       vmclear(ex->ve);
+       if (expr->compiled.integer)
+       {
+               switch (expr->type)
+               {
+               case FLOATING:
+                       v.floating = (*expr->compiled.floating)(ex->disc->data);
+                       break;
+               case STRING:
+                       v.string = (*expr->compiled.string)(ex->disc->data);
+                       break;
+               default:
+                       v.integer = (*expr->compiled.integer)(ex->disc->data);
+                       break;
+               }
        }
-    } else {
-       v = eval(ex, expr, env);
-       if (ex->loopcount > 0) {
-           ex->loopcount = 0;
-           if (ex->loopop == RETURN)
-               return ex->loopret;
+       else
+       {
+               v = eval(ex, expr, env);
+               if (ex->loopcount > 0)
+               {
+                       ex->loopcount = 0;
+                       if (ex->loopop == RETURN)
+                               return ex->loopret;
+               }
        }
-    }
-    return v;
+       return v;
 }
 
 /* strToL:
@@ -1993,7 +1921,7 @@ Sflong_t strToL(char *s, char **p)
  */
 char *exstring(Expr_t * ex, char *s)
 {
-    return vmstrdup(ex->vc, s);
+    return vmstrdup(ex->ve, s);
 }
 
 /* exstralloc:
@@ -2012,3 +1940,4 @@ int exstrfree(Expr_t * ex, void *p)
 {
     return vmfree(ex->ve, p);
 }
+
index 5faf2a1c325d952508d1a13f86a00b5d537e9f8c..ae7abd57e78523504306b2d0b035ee8f5e477a3b 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
+/* vim:set shiftwidth=4 ts=4: */
 
 /*************************************************************************
  * Copyright (c) 2011 AT&T Intellectual Property 
  * return the expression for name or sym coerced to type
  */
 
-Exnode_t *exexpr(Expr_t * ex, const char *name, Exid_t * sym, int type)
+Exnode_t*
+exexpr(Expr_t* ex, const char* name, Exid_t* sym, int type)
 {
-    if (ex) {
-       if (!sym)
-           sym = name ? (Exid_t *) dtmatch(ex->symbols, name) : &ex->main;
-       if (sym && sym->lex == PROCEDURE && sym->value) {
-           if (type != DELETE_T)
-               return excast(ex, sym->value->data.procedure.body, type,
-                             NiL, 0);
-           exfreenode(ex, sym->value);
-           sym->lex = NAME;
-           sym->value = 0;
+       if (ex)
+       {
+               if (!sym)
+                       sym = name ? (Exid_t*)dtmatch(ex->symbols, name) : &ex->main;
+               if (sym && sym->lex == PROCEDURE && sym->value)
+               {
+                       if (type != DELETE_T)
+                               return excast(ex, sym->value->data.procedure.body, type, NiL, 0);
+                       exfreenode(ex, sym->value);
+                       sym->lex = NAME;
+                       sym->value = 0;
+               }
        }
-    }
-    return 0;
+       return 0;
 }
index 018e19e05840177737d720dd3518ef4f239f2d93..9de314082444cf4d1573ac5bc3e002953a741a44 100644 (file)
@@ -1,5 +1,5 @@
 /* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
+/* vim:set shiftwidth=4 ts=4: */
 
 /*************************************************************************
  * Copyright (c) 2011 AT&T Intellectual Property 
@@ -23,7 +23,7 @@ extern "C" {
  * sometimes free stuff can cost a lot
  */
 
-#if defined(MINTOKEN) && !defined(_EXGRAM_H)
+#if !defined(_EXGRAM_H) && ( defined(MINTOKEN) || defined(YYTOKENTYPE) )
 #define _EXGRAM_H
 
 #if !defined(_EXPARSE_H)
@@ -38,26 +38,27 @@ extern "C" {
 #define ALLOCATE(p,x)  (x*)exalloc(p,sizeof(x))
 #define QUALIFY(r,s)   ((r)&&(expr.program->disc->flags&EX_QUALIFY)?qualify(r,s):(s))
 
-    static int a2t[] = { 0, FLOATING, INTEGER, STRING };
-    static Switch_t swstate;
+static int             a2t[] = { 0, FLOATING, INTEGER, STRING };
+static Switch_t                swstate;
 
-    Exstate_t expr;
+Exstate_t              expr;
 
-    static int
-     T(int t) {
+static int T(int t) 
+{
        if (expr.program->disc->types)
            return expr.program->disc->types[t & TMASK];
        else
            return a2t[t & TMASK];
-    }
+}
 
 /*
  * allocate and initialize a new expression node in the current program
  */
 
-    Exnode_t *exnewnode(Expr_t * p, int op, int binary, int type,
-                       Exnode_t * left, Exnode_t * right) {
-       register Exnode_t *x;
+Exnode_t*
+exnewnode(Expr_t* p, int op, int binary, int type, Exnode_t* left, Exnode_t* right)
+{
+       register Exnode_t*      x;
 
        x = ALLOCATE(p, Exnode_t);
        x->op = op;
@@ -68,111 +69,117 @@ extern "C" {
        x->data.operand.left = left;
        x->data.operand.right = right;
        return x;
-    }
+}
 
 /*
  * free node x and its children
  */
 
-    void
-     exfreenode(Expr_t * p, register Exnode_t * x) {
-       register Print_t *pr;
-       register Exref_t *r;
-       Print_t *pn;
-       Exref_t *rn;
-       int i;
-
-       switch (x->op) {
+void
+exfreenode(Expr_t* p, register Exnode_t* x)
+{
+       register Print_t*       pr;
+       register Exref_t*       r;
+       Print_t*                pn;
+       Exref_t*                rn;
+       int                     i;
+
+       switch (x->op)
+       {
        case CALL:
-           if (x->data.call.args)
-               exfreenode(p, x->data.call.args);
-           break;
+               if (x->data.call.args)
+                       exfreenode(p, x->data.call.args);
+               break;
        case CONSTANT:
-           break;
+               break;
        case DEFAULT:
-           if (x->data.select.next)
-               exfreenode(p, x->data.select.next);
-           break;
+               if (x->data.select.next)
+                       exfreenode(p, x->data.select.next);
+               break;
        case DYNAMIC:
-           if (x->data.variable.index)
-               exfreenode(p, x->data.variable.index);
-           if (x->data.variable.symbol->local.pointer) {
-               dtclose((Dt_t *) x->data.variable.symbol->local.pointer);
-               x->data.variable.symbol->local.pointer = 0;
-           }
-           break;
+               if (x->data.variable.index)
+                       exfreenode(p, x->data.variable.index);
+               if (x->data.variable.symbol->local.pointer)
+               {
+                       dtclose((Dt_t*)x->data.variable.symbol->local.pointer);
+                       x->data.variable.symbol->local.pointer = 0;
+               }
+               break;
        case '#':
-           if (x->data.variable.symbol->local.pointer) {
-               dtclose((Dt_t *) x->data.variable.symbol->local.pointer);
-               x->data.variable.symbol->local.pointer = 0;
-           }
-           break;
-       case IN_OP:
+               if (x->data.variable.symbol->local.pointer) {
+                       dtclose((Dt_t *) x->data.variable.symbol->local.pointer);
+                       x->data.variable.symbol->local.pointer = 0;
+               }
+               break;
+//     case IN_OP:
        case UNSET:
-           if (x->data.variable.index)
-               exfreenode(p, x->data.variable.index);
-           if (x->data.variable.symbol->local.pointer) {
-               dtclose((Dt_t *) x->data.variable.symbol->local.pointer);
-               x->data.variable.symbol->local.pointer = 0;
-           }
-           break;
+               if (x->data.variable.index)
+                       exfreenode(p, x->data.variable.index);
+               if (x->data.variable.symbol->local.pointer) {
+                       dtclose((Dt_t *) x->data.variable.symbol->local.pointer);
+                       x->data.variable.symbol->local.pointer = 0;
+               }
+               break;
        case ITERATE:
        case ITERATER:
-           if (x->data.generate.statement)
-               exfreenode(p, x->data.generate.statement);
-           break;
+               if (x->data.generate.statement)
+                       exfreenode(p, x->data.generate.statement);
+               break;
        case ID:
-           rn = x->data.variable.reference;
-           while ((r = rn)) {
-               rn = r->next;
-               vmfree(p->vm, r);
-           }
-           if (x->data.variable.index)
-           break;
+               rn = x->data.variable.reference;
+               while ((r = rn))
+               {
+                       rn = r->next;
+                       vmfree(p->vm, r);
+               }
+               if (x->data.variable.index)
+                       exfreenode(p, x->data.variable.index);
+               break;
        case GSUB:
        case SUB:
        case SUBSTR:
-           exfreenode(p, x->data.string.base);
-           exfreenode(p, x->data.string.pat);
-           if (x->data.string.repl)
-               exfreenode(p, x->data.string.repl);
-           break;
+               exfreenode(p, x->data.string.base);
+               exfreenode(p, x->data.string.pat);
+               if (x->data.string.repl)
+                       exfreenode(p, x->data.string.repl);
+               break;
        case TOKENS:
        case SPLIT:
-           if (x->data.split.seps)
-               exfreenode(p, x->data.split.seps);
-           exfreenode(p, x->data.split.string);
-           if (x->data.split.array->local.pointer) {
-               dtclose((Dt_t *) x->data.split.array->local.pointer);
-               x->data.split.array->local.pointer = 0;
-           }
-           break;
+               if (x->data.split.seps)
+                       exfreenode(p, x->data.split.seps);
+               exfreenode(p, x->data.split.string);
+               if (x->data.split.array->local.pointer) {
+                       dtclose((Dt_t *) x->data.split.array->local.pointer);
+                       x->data.split.array->local.pointer = 0;
+               }
+               break;
        case PRINT:
-           exfreenode(p, x->data.operand.left);
-           break;
+               exfreenode(p, x->data.operand.left);
+               break;
        case PRINTF:
        case SPRINTF:
-           if (x->data.print.descriptor)
-               exfreenode(p, x->data.print.descriptor);
-           pn = x->data.print.args;
-           while ((pr = pn)) {
-               for (i = 0; i < elementsof(pr->param) && pr->param[i]; i++)
-                   exfreenode(p, pr->param[i]);
-               if (pr->arg)
-                   exfreenode(p, pr->arg);
-               pn = pr->next;
-               vmfree(p->vm, pr);
-           }
-           break;
+               if (x->data.print.descriptor)
+                       exfreenode(p, x->data.print.descriptor);
+               pn = x->data.print.args;
+               while ((pr = pn))
+               {
+                       for (i = 0; i < elementsof(pr->param) && pr->param[i]; i++)
+                               exfreenode(p, pr->param[i]);
+                       if (pr->arg)
+                               exfreenode(p, pr->arg);
+                       pn = pr->next;
+                       vmfree(p->vm, pr);
+               }
+               break;
        default:
-           if (x->data.operand.left)
-               exfreenode(p, x->data.operand.left);
-           if (x->data.operand.right)
-               exfreenode(p, x->data.operand.right);
-           break;
+               if (x->data.operand.left)
+                       exfreenode(p, x->data.operand.left);
+               if (x->data.operand.right)
+                       exfreenode(p, x->data.operand.right);
+               break;
        }
        vmfree(p->vm, x);
-    }
+}
 
 /* extract:
  * Given an argument list, extract first argument,
@@ -180,7 +187,7 @@ extern "C" {
  * return first argument.
  * Return 0 on failure.
  */
-    static Exnode_t *extract(Expr_t * p, Exnode_t ** argp, int type) {
+static Exnode_t *extract(Expr_t * p, Exnode_t ** argp, int type) {
        Exnode_t *args = *argp;
        Exnode_t *left;
 
@@ -191,13 +198,13 @@ extern "C" {
        args->data.operand.left = args->data.operand.right = 0;
        exfreenode(p, args);
        return left;
-    }
+}
 
 /* exnewsplit:
  * Generate split/tokens node.
  * Fifth argument is optional.
  */
-    static Exnode_t *exnewsplit(Expr_t * p, int op, Exid_t* dyn, Exnode_t * s, Exnode_t* seps) {
+static Exnode_t *exnewsplit(Expr_t * p, int op, Exid_t* dyn, Exnode_t * s, Exnode_t* seps) {
        Exnode_t *ss = 0;
 
        if (dyn->local.pointer == 0)
@@ -219,13 +226,13 @@ extern "C" {
        ss->data.split.string = s;
        ss->data.split.seps = seps;
        return ss;
-    }
+}
 
 /* exnewsub:
  * Generate sub node.
  * Third argument is optional.
  */
-    static Exnode_t *exnewsub(Expr_t * p, Exnode_t * args, int op) {
+static Exnode_t *exnewsub(Expr_t * p, Exnode_t * args, int op) {
        Exnode_t *base;
        Exnode_t *pat;
        Exnode_t *repl;
@@ -250,12 +257,12 @@ extern "C" {
        ss->data.string.pat = pat;
        ss->data.string.repl = repl;
        return ss;
-    }
+}
 
 /* exnewsubstr:
  * Generate substr node.
  */
-    static Exnode_t *exnewsubstr(Expr_t * p, Exnode_t * args) {
+static Exnode_t *exnewsubstr(Expr_t * p, Exnode_t * args) {
        Exnode_t *base;
        Exnode_t *pat;
        Exnode_t *repl;
@@ -280,13 +287,13 @@ extern "C" {
        ss->data.string.pat = pat;
        ss->data.string.repl = repl;
        return ss;
-    }
+}
 
 /* exstringOf:
  * Cast x to type STRING
  * Assume x->type != STRING
  */
-    static Exnode_t *exstringOf(Expr_t * p, register Exnode_t * x) {
+static Exnode_t *exstringOf(Expr_t * p, register Exnode_t * x) {
        int type = x->type;
        int cvt = 0;
 
@@ -337,12 +344,12 @@ extern "C" {
            }
        x->type = STRING;
        return x;
-    }
+}
 
 /* exprint:
  * Generate argument list of strings.
  */
-    static Exnode_t *exprint(Expr_t * p, Exid_t * ex, Exnode_t * args) {
+static Exnode_t *exprint(Expr_t * p, Exid_t * ex, Exnode_t * args) {
        Exnode_t *arg = args;
        Exnode_t *pr;
 
@@ -354,7 +361,7 @@ extern "C" {
        }
        pr = exnewnode(p, ex->index, 1, ex->type, args, NiL);
        return pr;
-    }
+}
 
 /* makeVar:
  *
@@ -364,7 +371,7 @@ extern "C" {
  * and the prefix gets stored in refs. (This format is used to simplify
  * the yacc parser.)
  */
-    static Exnode_t *makeVar(Expr_t * prog, Exid_t * s, Exnode_t * idx,
+static Exnode_t *makeVar(Expr_t * prog, Exid_t * s, Exnode_t * idx,
                             Exnode_t * dyna, Exref_t * refs) {
        Exnode_t *nn;
        int kind;
@@ -400,24 +407,26 @@ extern "C" {
                                         NiL, EX_SCALAR, prog->disc);
 
        return nn;
-    }
+}
 
 /*
  * cast x to type
  */
 
-    static char *typename[] = {
+static char*   typename[] =
+{
        "external", "integer", "unsigned", "char", "float", "string"
-    };
-
-    static int typecast[6][6] = {
-       {X2X, X2I, X2I, X2I, X2F, X2S},
-       {I2X, 0, 0, 0, I2F, I2S},
-       {I2X, 0, 0, 0, I2F, I2S},
-       {I2X, 0, 0, 0, I2F, I2S},
-       {F2X, F2I, F2I, F2I, 0, F2S},
-       {S2X, S2I, S2I, S2I, S2F, 0}
-    };
+};
+
+static int     typecast[6][6] =
+{
+       {X2X,   X2I,    X2I,    X2I,    X2F,    X2S},
+       {I2X,   0,      0,      0,      I2F,    I2S},
+       {I2X,   0,      0,      0,      I2F,    I2S},
+       {I2X,   0,      0,      0,      I2F,    I2S},
+       {F2X,   F2I,    F2I,    F2I,    0,      F2S},
+       {S2X,   S2I,    S2I,    S2I,    S2F,    0},
+};
 
 #define TYPEINDEX(t)   (((t)>=INTEGER&&(t)<=STRING)?((t)-INTEGER+1):0)
 #define TYPENAME(t)    typename[TYPEINDEX(t)]
@@ -425,64 +434,64 @@ extern "C" {
 
 #define EXTERNAL(t)    ((t)>=F2X)
 
-    char *extypename(Expr_t * p, int type) {
+char *extypename(Expr_t * p, int type) {
        if (BUILTIN(type))
            return TYPENAME(type);
        return (p->disc->typename) (p, type);
-    }
+}
 
 /* exnoncast:
  * Return first non-cast node.
  */
-    Exnode_t *exnoncast(register Exnode_t * x) {
+Exnode_t *exnoncast(register Exnode_t * x) {
        while (x && (x->op >= F2I) && (x->op <= X2X))
            x = x->data.operand.left;
        return x;
-    }
-
-    Exnode_t *excast(Expr_t * p, register Exnode_t * x, register int type,
-                    register Exnode_t * xref, int arg) {
-       register int t2t;
-       char *s;
-       char *e;
+}
 
-       if (x && x->type != type && type && type != VOIDTYPE) {
-           if (!x->type) {
-               x->type = type;
-               return x;
-           }
-           if (!(t2t = TYPECAST(x->type, type)))
-               return x;
-           if (EXTERNAL(t2t) && !p->disc->convertf)
-               exerror("cannot convert %s to %s", extypename(p, x->type),
-                       extypename(p, type));
-           if (x->op != CONSTANT) {
-               Exid_t *sym = (xref ? xref->data.variable.symbol : NiL);
-               if (EXTERNAL(t2t)) {
-                   int a = (arg ? arg : 1);
-                   if ((*p->disc->convertf) (p, x, type, sym, a,
-                                             p->disc) < 0) {
-                       if (xref) {
-                           if ((sym->lex == FUNCTION) && arg)
-                               exerror
-                                   ("%s: cannot use value of type %s as argument %d in function %s",
-                                    sym->name, extypename(p, x->type),
-                                    arg, sym->name);
-                           else
-                               exerror("%s: cannot convert %s to %s",
-                                       xref->data.variable.symbol->name,
-                                       extypename(p, x->type),
-                                       extypename(p, type));
-                       } else {
-                           exerror("cannot convert %s to %s",
-                                   extypename(p, x->type), extypename(p,
-                                                                      type));
+Exnode_t*
+excast(Expr_t* p, register Exnode_t* x, register int type, register Exnode_t* xref, int arg)
+{
+       register int    t2t;
+       char*           s;
+       char*           e;
+
+       if (x && x->type != type && type && type != VOIDTYPE)
+       {
+               if (!x->type)
+               {
+                       x->type = type;
+                       return x;
+               }
+               if (!(t2t = TYPECAST(x->type, type)))
+                       return x;
+               if (EXTERNAL(t2t) && !p->disc->convertf)
+                       exerror("cannot convert %s to %s", extypename(p, x->type), extypename(p, type));
+               if (x->op != CONSTANT) {
+                       Exid_t *sym = (xref ? xref->data.variable.symbol : NiL);
+                       if (EXTERNAL(t2t)) {
+                               int a = (arg ? arg : 1);
+                       if ((*p->disc->convertf) (p, x, type, sym, a, p->disc) < 0) {
+                                       if (xref) {
+                                               if ((sym->lex == FUNCTION) && arg)
+                                                       exerror ("%s: cannot use value of type %s as argument %d in function %s",
+                                                       sym->name, extypename(p, x->type),
+                                                       arg, sym->name);
+                                               else
+                                                       exerror("%s: cannot convert %s to %s",
+                                                       xref->data.variable.symbol->name,
+                                                       extypename(p, x->type),
+                                                       extypename(p, type));
+                                       } else {
+                                       exerror("cannot convert %s to %s",
+                                                       extypename(p, x->type), extypename(p, type));
+                                       }
+                               }
                        }
-                   }
+                       x = exnewnode(p, t2t, 0, type, x, xref);
                }
-               x = exnewnode(p, t2t, 0, type, x, xref);
-           } else
-               switch (t2t) {
+               else switch (t2t)
+               {
                case F2X:
                case I2X:
                case S2X:
@@ -490,99 +499,164 @@ extern "C" {
                case X2I:
                case X2S:
                case X2X:
-                   if (xref && xref->op == ID) {
-                       if ((*p->disc->convertf) (p, x, type,
-                                                 xref->data.variable.
-                                                 symbol, 0, p->disc) < 0)
-                           exerror("%s: cannot cast constant %s to %s",
-                                   xref->data.variable.symbol->name,
-                                   extypename(p, x->type), extypename(p,
-                                                                      type));
-                   } else
-                       if ((*p->disc->convertf) (p, x, type, NiL, 0,
-                                                 p->disc) < 0)
-                       exerror("cannot cast constant %s to %s",
-                               extypename(p, x->type), extypename(p,
-                                                                  type));
-                   break;
+                       if (xref && xref->op == ID)
+                       {
+                               if ((*p->disc->convertf)(p, x, type, xref->data.variable.symbol, arg, p->disc) < 0)
+                                       exerror("%s: cannot cast constant %s to %s", xref->data.variable.symbol->name, extypename(p, x->type), extypename(p, type));
+                       }
+                       else if ((*p->disc->convertf)(p, x, type, NiL, arg, p->disc) < 0)
+                               exerror("cannot cast constant %s to %s", extypename(p, x->type), extypename(p, type));
+                       break;
                case F2I:
-                   x->data.constant.value.integer =
-                       x->data.constant.value.floating;
-                   break;
+                       x->data.constant.value.integer = x->data.constant.value.floating;
+                       break;
                case F2S:
-                   sfprintf(p->tmp, "%g",
-                            x->data.constant.value.floating);
-                   x->data.constant.value.string =
-                       vmstrdup(p->vm, sfstruse(p->tmp));
-                   break;
+                       sfprintf(p->tmp, "%g", x->data.constant.value.floating);
+                       x->data.constant.value.string = exstash(p->tmp, p->vm);
+                       break;
                case I2F:
-                   x->data.constant.value.floating =
-                       x->data.constant.value.integer;
-                   break;
+                       x->data.constant.value.floating = x->data.constant.value.integer;
+                       break;
                case I2S:
-                   sfprintf(p->tmp, "%I*d",
-                            sizeof(x->data.constant.value.integer),
-                            x->data.constant.value.integer);
-                   x->data.constant.value.string =
-                       vmstrdup(p->vm, sfstruse(p->tmp));
-                   break;
+                       sfprintf(p->tmp, "%I*d", sizeof(x->data.constant.value.integer), x->data.constant.value.integer);
+                       x->data.constant.value.string = exstash(p->tmp, p->vm);
+                       break;
                case S2F:
-                   s = x->data.constant.value.string;
-                   x->data.constant.value.floating = strtod (s, &e);
-                   if (*e)
-                       x->data.constant.value.floating = (*s != 0);
-                   break;
+                       s =  x->data.constant.value.string;
+                       x->data.constant.value.integer = strtod(s, &e);
+                       if (*e)
+                               x->data.constant.value.floating = (*s != 0);
+                       break;
                case S2I:
-                   s = x->data.constant.value.string;
-                   x->data.constant.value.integer = strToL(s, &e);
-                   if (*e)
-                       x->data.constant.value.integer = (*s != 0);
-                   break;
+                       s = x->data.constant.value.string;
+                       x->data.constant.value.integer = strToL(s, &e);
+                       if (*e)
+                               x->data.constant.value.integer = (*s != 0);
+                       break;
                default:
-                   exerror("internal error: %d: unknown cast op", t2t);
-                   break;
+                       exerror("internal error: %d: unknown cast op", t2t);
+                       break;
                }
-           x->type = type;
+               x->type = type;
        }
        return x;
-    }
+}
+
+#if 0
+
+/*
+ * convert value v from type from to type to
+ * string data placed in buf
+ */
+
+Extype_t
+exconvert(Expr_t* p, Extype_t v, int from, int to, char* buf, size_t size)
+{
+       register int    t2t;
+       int             n;
+       Exnode_t        tmp;
+
+       if (from && (t2t = TYPECAST(from, to)))
+       {
+               if (EXTERNAL(t2t) && !p->disc->convertf)
+                       exerror("cannot cast %s to %s", TYPENAME(from), TYPENAME(to));
+               switch (t2t)
+               {
+               case F2X:
+               case I2X:
+               case S2X:
+               case X2F:
+               case X2I:
+               case X2S:
+                       tmp.type = from;
+                       tmp.name = "*INTERNAL*";
+                       tmp.data.constant.value = v;
+                       if ((*p->disc->convertf)(p, &tmp, to, NiL, -1, p->disc) < 0)
+                               exerror("cannot convert %s to %s", TYPENAME(from), TYPENAME(to));
+                       if (t2t == X2S)
+                       {
+                               n = strlen(tmp.data.constant.value.string);
+                               if (n >= size)
+                                       n = size - 1;
+                               memcpy(buf, tmp.data.constant.value.string, n);
+                               buf[n] = 0;
+                               vmfree(p->vm, tmp.data.constant.value.string);
+                               tmp.data.constant.value.string = buf;
+                       }
+                       return tmp.data.constant.value;
+               case F2I:
+                       v.integer = (type == UNSIGNED) ? (Sfulong_t)v.floating : v.floating;
+                       break;
+               case F2S:
+                       sfsprintf(buf, size, "%g", v.floating);
+                       v.string = buf;
+                       break;
+               case I2F:
+                       v.floating = (from == UNSIGNED) ? (Sfulong_t)v.integer : v.integer;
+                       break;
+               case I2S:
+                       sfsprintf(buf, size, "%I*d", sizeof(v.integer), v.integer);
+                       v.string = buf;
+                       break;
+               case S2F:
+                       v.floating = *v.string != 0;
+                       break;
+               case S2I:
+                       v.integer = *v.string != 0;
+                       break;
+               default:
+                       exerror("internal error: %d: unknown conversion op", t2t);
+                       break;
+               }
+       }
+       return v;
+}
+
+#endif
 
 /*
  * force ref . sym qualification
  */
 
-    static Exid_t *qualify(register Exref_t * ref, register Exid_t * sym) {
-       register Exid_t *x;
-       char *s;
+static Exid_t*
+qualify(register Exref_t* ref, register Exid_t* sym)
+{
+       register Exid_t*        x;
+       char*                   s;
 
        while (ref->next)
-           ref = ref->next;
+               ref = ref->next;
        sfprintf(expr.program->tmp, "%s.%s", ref->symbol->name, sym->name);
-       s = sfstruse(expr.program->tmp);
-       if (!(x = (Exid_t *) dtmatch(expr.program->symbols, s))) {
-           if ((x = newof(0, Exid_t, 1, strlen(s) - EX_NAMELEN + 1))) {
-               memcpy(x, sym, sizeof(Exid_t) - EX_NAMELEN);
-               strcpy(x->name, s);
-               dtinsert(expr.program->symbols, x);
-           } else {
-               exerror("out of space [qualify]");
-               x = sym;
-           }
+       s = exstash(expr.program->tmp, NiL);
+       if (!(x = (Exid_t*)dtmatch(expr.program->symbols, s)))
+       {
+               if ((x = newof(0, Exid_t, 1, strlen(s) - EX_NAMELEN + 1)))
+               {
+                       memcpy(x, sym, sizeof(Exid_t) - EX_NAMELEN);
+                       strcpy(x->name, s);
+                       dtinsert(expr.program->symbols, x);
+               }
+               else
+               {
+                       exnospace();
+                       x = sym;
+               }
        }
        return x;
-    }
+}
 
 /*
  * check function call arg types and count
  * return function identifier node
  */
 
-    Exnode_t *call(Exref_t * ref, register Exid_t * fun,
-                  register Exnode_t * args) {
-       register int t;
-       register int type;
-       Exnode_t *x;
-       int num;
+static Exnode_t*
+call(Exref_t* ref, register Exid_t* fun, register Exnode_t* args)
+{
+       register int    t;
+       register int    type;
+       Exnode_t*       x;
+       int             num;
 
        x = exnewnode(expr.program, ID, 0, 0, NiL, NiL);
        t = fun->type;
@@ -590,425 +664,430 @@ extern "C" {
        x->data.variable.reference = ref;
        num = 0;
        N(t);
-       while ((type = T(t))) {
-           if (!args) {
-               exerror("%s: not enough args", fun->name);
-               return args;
-           }
-           num++;
-           if (type != args->data.operand.left->type)
-               args->data.operand.left =
-                   excast(expr.program, args->data.operand.left, type, NiL,
-                          num);
-           args = args->data.operand.right;
-           N(t);
+       while ((type = T(t)))
+       {
+               if (!args)
+               {
+                       exerror("%s: not enough args", fun->name);
+                       return args;
+               }
+               num++;
+               if (type != args->data.operand.left->type)
+                       args->data.operand.left = excast(expr.program, args->data.operand.left, type, NiL, num);
+               args = args->data.operand.right;
+               N(t);
        }
        if (args)
-           exerror("%s: too many args", fun->name);
+               exerror("%s: too many args", fun->name);
        return x;
-    }
+}
 
 /*
  * precompile a printf/scanf call
  */
 
-    static Print_t *preprint(register Exnode_t * args) {
-       register Print_t *x;
-       register char *s;
-       register int c;
-       int t;
-       int i;
-       int n;
-       char *e;
-       char *f;
-       Print_t *p = 0;
-       Print_t *q;
+static Print_t*
+preprint(register Exnode_t* args)
+{
+       register Print_t*       x;
+       register char*          s;
+       register int            c;
+       int                     t;
+       int                     i;
+       int                     n;
+       char*                   e;
+       char*                   f;
+       Print_t*                p = 0;
+       Print_t*                q;
 
        if (!args || args->data.operand.left->type != STRING)
-           exerror("format string argument expected");
-       if (args->data.operand.left->op != CONSTANT) {
-           x = ALLOCATE(expr.program, Print_t);
-           memzero(x, sizeof(*x));
-           x->arg = args;
-           return x;
+               exerror("format string argument expected");
+       if (args->data.operand.left->op != CONSTANT)
+       {
+               x = ALLOCATE(expr.program, Print_t);
+               memzero(x, sizeof(*x));
+               x->arg = args;
+               return x;
        }
        f = args->data.operand.left->data.constant.value.string;
        args = args->data.operand.right;
-       for (s = f; *s; s++) {
-           sfputc(expr.program->tmp, *s);
-           if (*s == '%') {
-               if (!*++s)
-                   exerror("%s: trailing %% in format", f);
-               if (*s != '%')
-                   break;
-               if (args)
-                   sfputc(expr.program->tmp, '%');
-           }
+       for (s = f; *s; s++)
+       {
+               sfputc(expr.program->tmp, *s);
+               if (*s == '%')
+               {
+                       if (!*++s)
+                               exerror("%s: trailing %% in format", f);
+                       if (*s != '%')
+                               break;
+                       if (args)
+                               sfputc(expr.program->tmp, '%');
+               }
        }
        x = 0;
-       for (;;) {
-           q = ALLOCATE(expr.program, Print_t);
-           if (x)
-               x->next = q;
-           else
-               p = q;
-           x = q;
-           memzero(x, sizeof(*x));
-           if (*s) {
-               i = 0;
-               t = INTEGER;
-               for (;;) {
-                   switch (c = *s++) {
-                   case 0:
-                       exerror("unterminated %%... in format");
-                       goto done;
-                   case '*':
-                       if (i >= elementsof(x->param)) {
-                           *s = 0;
-                           exerror("format %s has too many * arguments",
-                                   f);
-                           goto done;
-                       }
-                       if (!args) {
-                           *s = 0;
-                           exerror("format %s * argument expected", f);
-                           goto done;
+       for (;;)
+       {
+               q = ALLOCATE(expr.program, Print_t);
+               if (x)
+                       x->next = q;
+               else
+                       p = q;
+               x = q;
+               memzero(x, sizeof(*x));
+               if (*s)
+               {
+                       i = 0;
+                       t = INTEGER;
+                       for (;;)
+                       {
+                               switch (c = *s++)
+                               {
+                               case 0:
+                                       exerror("unterminated %%... in format");
+                                       goto done;
+                               case '*':
+                                       if (i >= elementsof(x->param))
+                                       {
+                                               *s = 0;
+                                               exerror("format %s has too many * arguments", f);
+                                               goto done;
+                                       }
+                                       if (!args)
+                                       {
+                                               *s = 0;
+                                               exerror("format %s * argument expected", f);
+                                               goto done;
+                                       }
+                                       x->param[i++] = args->data.operand.left;
+                                       args = args->data.operand.right;
+                                       break;
+                               case '(':
+                                       n = 1;
+                                       for (;;)
+                                       {
+                                               sfputc(expr.program->tmp, c);
+                                               switch (c = *s++)
+                                               {
+                                               case 0:
+                                                       s--;
+                                                       break;
+                                               case '(':
+                                                       n++;
+                                                       continue;
+                                               case ')':
+                                                       if (--n <= 0)
+                                                               break;
+                                                       continue;
+                                               default:
+                                                       continue;
+                                               }
+                                               break;
+                                       }
+                                       break;
+                               case 'c':
+                               case 'd':
+                                       goto specified;
+                               case 'e':
+                               case 'f':
+                               case 'g':
+                                       t = FLOATING;
+                                       goto specified;
+                               case 'h':
+                                       exerror("short formats not supported");
+                                       goto done;
+                               case 'l':
+                                       t = INTEGER;
+                                       break;
+                               case 'o':
+                               case 'u':
+                               case 'x':
+                               case 'T':
+                                       t = UNSIGNED;
+                                       goto specified;
+                               case 's':
+                               case 'S':
+                                       t = STRING;
+                                       goto specified;
+                               default:
+                                       if (isalpha(c))
+                                               goto specified;
+                                       break;
+                               }
+                               sfputc(expr.program->tmp, c);
                        }
-                       x->param[i++] = args->data.operand.left;
-                       args = args->data.operand.right;
-                       break;
-                   case '(':
-                       n = 1;
-                       for (;;) {
-                           sfputc(expr.program->tmp, c);
-                           switch (c = *s++) {
-                           case 0:
-                               s--;
-                               break;
-                           case '(':
-                               n++;
-                               continue;
-                           case ')':
-                               if (--n <= 0)
-                                   break;
-                               continue;
-                           default:
-                               continue;
-                           }
-                           break;
+               specified:
+                       sfputc(expr.program->tmp, c);
+                       for (e = s; *s; s++)
+                       {
+                               if (*s == '%')
+                               {
+                                       if (!*++s)
+                                       {
+                                               *e = 0;
+                                               exerror("%s: trailing %% in format", f);
+                                               goto done;
+                                       }
+                                       if (*s != '%')
+                                       {
+                                               s--;
+                                               break;
+                                       }
+                               }
+                               sfputc(expr.program->tmp, *s);
                        }
-                       break;
-                   case 'c':
-                   case 'd':
-                       goto specified;
-                   case 'e':
-                   case 'f':
-                   case 'g':
-                       t = FLOATING;
-                       goto specified;
-                   case 'h':
-                       exerror("short formats not supported");
-                       goto done;
-                   case 'l':
-                       t = INTEGER;
-                       break;
-                   case 'o':
-                   case 'u':
-                   case 'x':
-                   case 'T':
-                       t = UNSIGNED;
-                       goto specified;
-                   case 's':
-                   case 'S':
-                       t = STRING;
-                       goto specified;
-                   default:
-                       if (isalpha(c))
-                           goto specified;
-                       break;
-                   }
-                   sfputc(expr.program->tmp, c);
-               }
-             specified:
-               sfputc(expr.program->tmp, c);
-               for (e = s; *s; s++) {
-                   if (*s == '%') {
-                       if (!*++s) {
-                           *e = 0;
-                           exerror("%s: trailing %% in format", f);
-                           goto done;
+                       if (!args)
+                       {
+                               *e = 0;
+                               exerror("%s format argument expected", f);
+                               goto done;
                        }
-                       if (*s != '%') {
-                           s--;
-                           break;
+                       x->arg = args->data.operand.left;
+                       switch (t)
+                       {
+                       case FLOATING:
+                               if (x->arg->type != FLOATING)
+                                       x->arg = exnewnode(expr.program, x->arg->type == STRING ? S2F : INTEGRAL(x->arg->type) ? I2F : X2F, 0, FLOATING, x->arg, x->arg->op == ID ? x->arg : (Exnode_t*)0);
+                               break;
+                       case INTEGER:
+                       case UNSIGNED:
+                               if (!INTEGRAL(x->arg->type))
+                                       x->arg = exnewnode(expr.program, x->arg->type == STRING ? S2I : x->arg->type == FLOATING ? F2I : X2I, 0, INTEGER, x->arg, x->arg->op == ID ? x->arg : (Exnode_t*)0);
+                               x->arg->type = t;
+                               break;
+                       case STRING:
+                               if (x->arg->type != STRING)
+                               {
+                                       if (x->arg->op == CONSTANT && x->arg->data.constant.reference && expr.program->disc->convertf)
+                                       {
+                                               if ((*expr.program->disc->convertf)(expr.program, x->arg, STRING, x->arg->data.constant.reference, 0, expr.program->disc) < 0)
+                                                       exerror("cannot convert string format argument");
+                                               else x->arg->data.constant.value.string = vmstrdup(expr.program->vm, x->arg->data.constant.value.string);
+                                       }
+                                       else if (!expr.program->disc->convertf || (x->arg->op != ID && x->arg->op != DYNAMIC && x->arg->op != F2X && x->arg->op != I2X && x->arg->op != S2X))
+                                               exerror("string format argument expected");
+                                       else
+                                               x->arg = exnewnode(expr.program, x->arg->type == FLOATING ? F2S : INTEGRAL(x->arg->type) ? I2S : X2S, 0, STRING, x->arg, x->arg->op == ID ? x->arg : (Exnode_t*)0);
+                               }
+                               break;
                        }
-                   }
-                   sfputc(expr.program->tmp, *s);
-               }
-               if (!args) {
-                   *e = 0;
-                   exerror("%s format argument expected", f);
-                   goto done;
-               }
-               x->arg = args->data.operand.left;
-               switch (t) {
-               case FLOATING:
-                   if (x->arg->type != FLOATING)
-                       x->arg =
-                           exnewnode(expr.program,
-                                     x->arg->type ==
-                                     STRING ? S2F : INTEGRAL(x->arg->
-                                                             type) ? I2F :
-                                     X2F, 0, FLOATING, x->arg,
-                                     x->arg->op ==
-                                     ID ? x->arg : (Exnode_t *) 0);
-                   break;
-               case INTEGER:
-               case UNSIGNED:
-                   if (!INTEGRAL(x->arg->type))
-                       x->arg =
-                           exnewnode(expr.program,
-                                     x->arg->type ==
-                                     STRING ? S2I : x->arg->type ==
-                                     FLOATING ? F2I : X2I, 0, INTEGER,
-                                     x->arg,
-                                     x->arg->op ==
-                                     ID ? x->arg : (Exnode_t *) 0);
-                   x->arg->type = t;
-                   break;
-               case STRING:
-                   if (x->arg->type != STRING) {
-                       if (x->arg->op == CONSTANT
-                           && x->arg->data.constant.reference
-                           && expr.program->disc->convertf) {
-                           if ((*expr.program->disc->convertf) (expr.
-                                                                program,
-                                                                x->arg,
-                                                                STRING,
-                                                                x->arg->
-                                                                data.
-                                                                constant.
-                                                                reference,
-                                                                0,
-                                                                expr.
-                                                                program->
-                                                                disc) < 0)
-                               exerror
-                                   ("cannot convert string format argument");
-                           else
-                               x->arg->data.constant.value.string =
-                                   vmstrdup(expr.program->vm,
-                                            x->arg->data.constant.value.
-                                            string);
-                       } else if (!expr.program->disc->convertf
-                                  || (x->arg->op != ID
-                                      && x->arg->op != DYNAMIC
-                                      && x->arg->op != F2X
-                                      && x->arg->op != I2X
-                                      && x->arg->op != S2X))
-                           exerror("string format argument expected");
-                       else
-                           x->arg =
-                               exnewnode(expr.program,
-                                         x->arg->type ==
-                                         FLOATING ? F2S : INTEGRAL(x->
-                                                                   arg->
-                                                                   type) ?
-                                         I2S : X2S, 0, STRING, x->arg,
-                                         x->arg->op ==
-                                         ID ? x->arg : (Exnode_t *) 0);
-                   }
-                   break;
+                       args = args->data.operand.right;
                }
-               args = args->data.operand.right;
-           }
-           x->format =
-               vmstrdup(expr.program->vm, sfstruse(expr.program->tmp));
-           if (!*s)
-               break;
-           f = s;
+               x->format = exstash(expr.program->tmp, expr.program->vm);
+               if (!*s)
+                       break;
+               f = s;
        }
        if (args)
-           exerror("too many format arguments");
     done:
-       sfstrset(expr.program->tmp, 0);
+               exerror("too many format arguments");
+ done:
+       sfstrseek(expr.program->tmp, 0, SEEK_SET);
        return p;
-    }
+}
 
 /*
  * push a new input stream and program
  */
 
-    int
-     expush(Expr_t * p, const char *name, int line, const char *sp,
-           Sfio_t * fp) {
-       register Exinput_t *in;
-       register char *s;
-       char buf[PATH_MAX];
+int
+expush(Expr_t* p, const char* name, int line, const char* sp, Sfio_t* fp)
+{
+       register Exinput_t*     in;
+       register char*          s;
+       char                    buf[PATH_MAX];
 
-       if (!(in = newof(0, Exinput_t, 1, 0))) {
-           exerror("out of space [push]");
-           return -1;
+       if (!(in = newof(0, Exinput_t, 1, 0)))
+       {
+               exnospace();
+               return -1;
        }
        if (!p->input)
-           p->input = &expr.null;
-       if (!(in->bp = in->sp = (char *) sp)) {
-           if ((in->fp = fp))
-               in->close = 0;
-           else if (name) {
-               if (!
-                   (s =
-                    pathfind(name, p->disc->lib, p->disc->type, buf,
-                             sizeof(buf)))
-                   || !(in->fp = sfopen(NiL, s, "r"))) {
-                   exerror("%s: file not found", name);
-                   in->bp = in->sp = "";
-               } else {
-                   name = (const char *) vmstrdup(p->vm, s);
-                   in->close = 1;
+               p->input = &expr.null;
+       if (!(in->bp = in->sp = (char*)sp))
+       {
+               if ((in->fp = fp))
+                       in->close = 0;
+               else if (name)
+               {
+                       if (!(s = pathfind(name, p->disc->lib, p->disc->type, buf, sizeof(buf))) || !(in->fp = sfopen(NiL, s, "r")))
+                       {
+                               exerror("%s: file not found", name);
+                               in->bp = in->sp = "";
+                       }
+                       else
+                       {
+                               name = (const char*)vmstrdup(p->vm, s);
+                               in->close = 1;
+                       }
                }
-           }
-       } else
-           in->fp = 0;
-       if (!(in->next = p->input)->next) {
-           p->errors = 0;
-           if (!(p->disc->flags & EX_INTERACTIVE)) {
-               if (line >= 0)
-                   error_info.line = line;
-           } else if (!error_info.line)
-               error_info.line = 1;
-       } else if (line >= 0)
-           error_info.line = line;
+       }
+       else in->fp = 0;
+       if (!(in->next = p->input)->next)
+       {
+               p->errors = 0;
+               if (!(p->disc->flags & EX_INTERACTIVE))
+               {
+                       if (line >= 0)
+                               error_info.line = line;
+               }
+               else if (!error_info.line)
+                       error_info.line = 1;
+       }
+       else if (line >= 0)
+               error_info.line = line;
        setcontext(p);
        p->eof = 0;
        p->input = in;
        in->file = error_info.file;
        if (line >= 0)
-           error_info.file = (char *) name;
+               error_info.file = (char*)name;
        in->line = error_info.line;
        in->nesting = 0;
        in->unit = !name && !line;
        p->program = expr.program;
        expr.program = p;
        return 0;
-    }
+}
 
 /*
  * pop the current input stream
  */
 
-    int
-     expop(register Expr_t * p) {
-       register int c;
-       register Exinput_t *in;
+int
+expop(register Expr_t* p)
+{
+       register int            c;
+       register Exinput_t*     in;
 
        if (!(in = p->input) || !in->next || in->unit)
-           return -1;
+               return -1;
        if (in->nesting)
-           exerror("unbalanced quote or nesting construct");
+               exerror("unbalanced quote or nesting construct");
        error_info.file = in->file;
        if (in->next->next)
-           error_info.line = in->line;
-       else {
-           if (p->errors && in->fp && p->linep != p->line)
-               while ((c = sfgetc(in->fp)) != EOF)
-                   if (c == '\n') {
-                       error_info.line++;
-                       break;
-                   }
-           if (!(p->disc->flags & EX_INTERACTIVE))
                error_info.line = in->line;
+       else
+       {
+               if (p->errors && in->fp && p->linep != p->line)
+                       while ((c = sfgetc(in->fp)) != EOF)
+                               if (c == '\n')
+                               {
+                                       error_info.line++;
+                                       break;
+                               }
+               if (!(p->disc->flags & EX_INTERACTIVE))
+                       error_info.line = in->line;
        }
        if (in->fp && in->close)
-           sfclose(in->fp);
+               sfclose(in->fp);
        if (in->pushback)
-           free(in->pushback);
+               free(in->pushback);
        p->input = in->next;
        free(in);
        setcontext(p);
        if (p->program)
-           expr.program = p->program;
+               expr.program = p->program;
        return 0;
-    }
+}
 
 /*
  * clear global state of stale pointers
  */
 
-    void
-     exinit(void) {
+void exinit(void) {
        memset (&expr, 0, sizeof(Exstate_t));
-    }
+}
+
 /*
  * compile the expression in [sf]p
  */
 
-    int
-     excomp(register Expr_t * p, const char *name, int line,
-           const char *sp, Sfio_t * fp) {
-       int eof;
+int
+excomp(register Expr_t* p, const char* name, int line, const char* sp, Sfio_t* fp)
+{
+       Exid_t* v;
+       int     eof;
 
        p->more = 0;
        eof = p->eof;
-       if (!sp && !fp) {
-           if (!p->input)
+       if (!sp && !fp)
+       {
+               if (!p->input)
+                       return -1;
+       }
+       else if (expush(p, name, line, sp, fp))
                return -1;
-       } else if (expush(p, name, line, sp, fp))
-           return -1;
        else
-           p->input->unit = line >= 0;
+               p->input->unit = line >= 0;
        exparse();
        p->input->unit = 0;
        expop(p);
        p->eof = eof;
+       if (expr.statics)
+       {
+               for (v = (Exid_t*)dtfirst(p->symbols); v; v = (Exid_t*)dtnext(p->symbols, v))
+                       if (v->isstatic)
+                       {
+                               dtdelete(p->symbols, v);
+                               if (!--expr.statics)
+                                       break;
+                       }
+               expr.statics = 0;
+       }
        return 0;
-    }
+}
 
 /*
  * free the program p
  */
 
-    void
-     exclose(register Expr_t * p, int all) {
-       register int i;
-       register Exinput_t *in;
-
-       if (p) {
-           if (all) {
-               for (i = 3; i < elementsof(p->file); i++)
-                   if (p->file[i])
-                       sfclose(p->file[i]);
-               if (p->vm)
-                   vmclose(p->vm);
-               if (p->ve)
-                   vmclose(p->ve);
-               if (p->symbols)
-                   dtclose(p->symbols);
-               if (p->tmp)
-                   sfclose(p->tmp);
-               while ((in = p->input)) {
-                   if (in->pushback)
-                       free(in->pushback);
-                   if (in->fp && in->close)
-                       sfclose(in->fp);
-                   if ((p->input = in->next))
-                       free(in);
+void
+exclose(register Expr_t* p, int all)
+{
+       register int            i;
+       register Exinput_t*     in;
+
+       if (p)
+       {
+               if (all)
+               {
+                       for (i = 3; i < elementsof(p->file); i++)
+                               if (p->file[i])
+                                       sfclose(p->file[i]);
+                       if (p->vm)
+                               vmclose(p->vm);
+                       if (p->ve)
+                               vmclose(p->ve);
+                       if (p->symbols)
+                               dtclose(p->symbols);
+                       if (p->tmp)
+                               sfclose(p->tmp);
+                       while ((in = p->input))
+                       {
+                               if (in->pushback)
+                                       free(in->pushback);
+                               if (in->fp && in->close)
+                                       sfclose(in->fp);
+                               if ((p->input = in->next))
+                                       free(in);
+                       }
+                       free(p);
+               }
+               else
+               {
+                       vmclear(p->ve);
+                       p->main.value = 0;
                }
-               free(p);
-           } else {
-               vmclear(p->ve);
-               p->main.value = 0;
-           }
        }
-    }
+}
 
 /* checkBinary:
  * See if application wants to allow the given expression
  * combination. l and r give the operands; the operator
  * is given by ex. r may be NULL.
  */
-    static void
-     checkBinary(Expr_t * p, Exnode_t * l, Exnode_t * ex, Exnode_t * r) {
+static void
+checkBinary(Expr_t * p, Exnode_t * l, Exnode_t * ex, Exnode_t * r) 
+{
        if ((*p->disc->binaryf) (p, l, ex, r, 1, p->disc) < 0) {
            if (r)
                exerror
@@ -1020,15 +1099,15 @@ extern "C" {
                    ("cannot apply operator %s to expression of type %s",
                     exopname(ex->op), extypename(p, l->type));
        }
-    }
+}
 
 /* checkName:
  * We allow parser to accept any name in a declaration, in
  * order to check that the name is undeclared and give a better
  * error message if it isn't.
  */
-    static void
-     checkName(Exid_t * id) {
+static void checkName(Exid_t * id) 
+{
        switch (id->lex) {
        case DYNAMIC:
            exerror("Variable \"%s\" already declared", id->name);
@@ -1046,22 +1125,24 @@ extern "C" {
                  "Unexpected token \"%s\" as name in dcl_item", id->name);
            break;
        }
-    }
+}
 
-    static int
-     cmpKey(Dt_t * d, Extype_t * key1, Extype_t * key2, Dtdisc_t * disc) {
+static int
+cmpKey(Dt_t * d, Extype_t * key1, Extype_t * key2, Dtdisc_t * disc) 
+{
        if (key1->integer < key2->integer)
            return -1;
        else if (key1->integer > key2->integer)
            return 1;
        else
            return 0;
-    }
+}
 
-    int
-     exisAssign(Exnode_t * n) {
+int
+exisAssign(Exnode_t * n) 
+{
        return ((n->op == '=') && (n->subop == '='));
-    }
+}
 
 #endif
 
index c3e98808ed9d1c8a13bb058e91f26248dd074045..1cb2092e7ae9774bb59419cb69f8ef156cd8c21e 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
+/* vim:set shiftwidth=4 ts=4: */
 
 /*************************************************************************
  * Copyright (c) 2011 AT&T Intellectual Property 
 #define TOTNAME                3
 #define MAXNAME                16
 
-char *exlexname(int op, int subop)
+char*
+exlexname(int op, int subop)
 {
-    register char *b;
+       register char*  b;
 
-    static int n;
-    static char buf[TOTNAME][MAXNAME];
+       static int      n;
+       static char     buf[TOTNAME][MAXNAME];
 
-    if (op > MINTOKEN && op < MAXTOKEN)
-       return (char *) exop[op - MINTOKEN];
-    if (++n > TOTNAME)
-       n = 0;
-    b = buf[n];
-    if (op == '=') {
-       if (subop > MINTOKEN && subop < MAXTOKEN)
-           sfsprintf(b, MAXNAME, "%s=", exop[subop - MINTOKEN]);
-       else if (subop > ' ' && subop <= '~')
-           sfsprintf(b, MAXNAME, "%c=", subop);
-       else
-           sfsprintf(b, MAXNAME, "(%d)=", subop);
-    } else if (op > ' ' && op <= '~')
-       sfsprintf(b, MAXNAME, "%c", op);
-    else
-       sfsprintf(b, MAXNAME, "(%d)", op);
-    return b;
+       if (op > MINTOKEN && op < MAXTOKEN)
+               return (char*)exop[op - MINTOKEN];
+       if (++n > TOTNAME)
+               n = 0;
+       b = buf[n];
+       if (op == '=')
+       {
+               if (subop > MINTOKEN && subop < MAXTOKEN)
+                       sfsprintf(b, MAXNAME, "%s=", exop[subop - MINTOKEN]);
+               else if (subop > ' ' && subop <= '~')
+                       sfsprintf(b, MAXNAME, "%c=", subop);
+               else sfsprintf(b, MAXNAME, "(%d)=", subop);
+       }
+       else if (op > ' ' && op <= '~')
+               sfsprintf(b, MAXNAME, "%c", op);
+       else sfsprintf(b, MAXNAME, "(%d)", op);
+       return b;
 }
index 953f113d53bcaa93fe05a1a4e20755346a592928..6fe96e5b8c2a98bd7510259b42d9489ae3af2d42 100644 (file)
@@ -28,27 +28,36 @@ extern "C" {
 #include <align.h>
 #include <ast.h>
 
-    typedef struct Exinput_s { /* input stack                    */
-       struct Exinput_s *next; /* next in stack                */
-       int close;              /* close fp on pop              */
-       char *file;             /* previous file                */
-       Sfio_t *fp;             /* expression file pointer      */
-       int line;               /* previous line                */
-       int nesting;            /* expression nesting level     */
-       int peek;               /* 1 char peek                  */
-       int unit;               /* first frame in parse unit    */
-       char *pushback;         /* pushback buffer              */
-       char *bp;               /* expression string base       */
-       char *pp;               /* pushback pointer             */
-       char *sp;               /* expression string pointer    */
-    } Exinput_t;
-
-    typedef struct Print_s {   /* compiled printf arg node       */
-       struct Print_s *next;   /* next arg                     */
-       char *format;           /* printf format for arg        */
-       struct Exnode_s *param[3];      /* 0:width 1:precision 2:base   */
-       struct Exnode_s *arg;   /* arg to format                */
-    } Print_t;
+#define sfstrseek(f,p,m) \
+    ( \
+        (((p) < 0 || (p) > (f)->size) ? (char*)0 : \
+         (char*)((f)->next = (f)->data+(p)) ) \
+    )
+
+
+typedef struct Exinput_s               /* input stack                  */
+{
+       struct Exinput_s*next;          /* next in stack                */
+       int             close;          /* close fp on pop              */
+       char*           file;           /* previous file                */
+       Sfio_t*         fp;             /* expression file pointer      */
+       int             line;           /* previous line                */
+       int             nesting;        /* expression nesting level     */
+       int             peek;           /* 1 char peek                  */
+       int             unit;           /* first frame in parse unit    */
+       char*           pushback;       /* pushback buffer              */
+       char*           bp;             /* expression string base       */
+       char*           pp;             /* pushback pointer             */
+       char*           sp;             /* expression string pointer    */
+} Exinput_t;
+
+typedef struct Print_s                 /* compiled printf arg node     */
+{
+       struct Print_s* next;           /* next arg                     */
+       char*           format;         /* printf format for arg        */
+       struct Exnode_s*param[3];       /* 0:width 1:precision 2:base   */
+       struct Exnode_s*arg;            /* arg to format                */
+} Print_t;
 
 #define _EX_DATA_PRIVATE_ \
        Exnode_t*       next;           /* free list link               */ \
@@ -69,7 +78,7 @@ extern "C" {
        Exid_t*         array;          /* array                        */ \
        Exnode_t*       string;         /* string                       */ \
        Exnode_t*       seps;           /* optional separators          */ \
-       }               split;          /* string split */ \
+       }               split;          /* string split                 */ \
        struct                                                             \
        {                                                                  \
        Exnode_t*       descriptor;     /* Expr_t.file index            */ \
@@ -93,15 +102,14 @@ extern "C" {
        Exnode_t*       descriptor;     /* Expr_t.file index            */ \
        Exnode_t*       format;         /* format arg                   */ \
        Exnode_t*       args;           /* actual args                  */ \
-       }               scan;   /* printf                       */
+       }               scan;           /* printf                       */
 
 #define _EX_NODE_PRIVATE_ \
        Exshort_t       subop;          /* operator qualifier           */ \
-       Exshort_t       pad_2;  /* padding                      */
+       Exshort_t       pad_2;          /* padding                      */
 
 #define _EX_PROG_PRIVATE_ \
        Vmalloc_t*      ve;             /* eval tmp region              */ \
-       Vmalloc_t*      vc;             /* str_* region         */ \
        Dt_t*           frame;          /* frame symbol table           */ \
        Dtdisc_t        symdisc;        /* Expr_t.symbols discipline    */ \
        Exdisc_t*       disc;           /* user discipline              */ \
@@ -118,7 +126,7 @@ extern "C" {
        int             linewrap;       /* linep wrapped around line[]  */ \
        int             loopcount;      /* break|continue|return count  */ \
        int             loopop;         /* break|continue|return op     */ \
-       int             nesting;        /* exstatement() nesting        */
+       int             nesting;        /* exstatement() nesting        */
 
 #include <expr.h>
 #include <ctype.h>
@@ -132,44 +140,50 @@ extern "C" {
 #define putcontext(p,c)        (((p)->linep>=&(p)->line[sizeof((p)->line)]?(p)->linep=(p)->line,(p)->linewrap=1:0),*(p)->linep++=(c))
 #define setcontext(p)  ((p)->linep=(p)->line,(p)->linewrap=0)
 
-    typedef struct Switch_s {  /* switch parse state             */
-       struct Switch_s *prev;  /* previous switch state        */
-       Exnode_t *firstcase;    /* first case block             */
-       Exnode_t *lastcase;     /* last case block              */
-       Exnode_t *defcase;      /* default case block           */
-       Extype_t **base;        /* label base pointer           */
-       Extype_t **cur;         /* current label pointer        */
-       Extype_t **last;        /* last label pointer           */
-       int def;                /* default label hit            */
-       int type;               /* switch test type             */
-    } Switch_t;
-
-    typedef struct {           /* associative array bucket       */
-       Dtlink_t link;          /* table link                   */
-       Extype_t key;           /* key                                  */
-       Extype_t value;         /* value                                */
-       char name[1];           /* key name                             */
-    } Exassoc_t;
-
-    typedef struct {           /* ex global state                */
-       Exid_t *id;             /* current declaration id       */
-       int declare;            /* current declaration type     */
-       Exref_t *lastref;       /* last in . reference list     */
-       int nolabel;            /* <id>':' not a label          */
-       Exinput_t null;         /* null input                   */
-       Expr_t *program;        /* current program              */
-       Exnode_t *procedure;    /* current procedure            */
-       Exref_t *refs;          /* . reference list             */
-       Switch_t *swstate;      /* switch parse state           */
-       char nullstring[1];     /* ""               */
-    } Exstate_t;
-
-    extern Exid_t exbuiltin[];
-    extern const char *exversion;
-    extern Exstate_t expr;
-
-    extern int exparse(void);  /* yacc should do this          */
-    extern Sflong_t strToL(char *, char **);
+typedef struct Switch_s                        /* switch parse state           */
+{
+       struct Switch_s*prev;           /* previous switch state        */
+       Exnode_t*       firstcase;      /* first case block             */
+       Exnode_t*       lastcase;       /* last case block              */
+       Exnode_t*       defcase;        /* default case block           */
+       Extype_t**      base;           /* label base pointer           */
+       Extype_t**      cur;            /* current label pointer        */
+       Extype_t**      last;           /* last label pointer           */
+       int             def;            /* default label hit            */
+       int             type;           /* switch test type             */
+} Switch_t;
+
+typedef struct Exassoc_s               /* associative array bucket     */
+{
+       Dtlink_t        link;           /* table link                   */
+       Extype_t        key;            /* key                          */
+       Extype_t        value;          /* value                        */
+       char            name[1];        /* index name                   */
+} Exassoc_t;
+
+typedef struct Exstate_s               /* ex global state              */
+{
+       Exid_t*         id;             /* current declaration id       */
+       int             declare;        /* current declaration type     */
+       Exref_t*        lastref;        /* last in . reference list     */
+       int             nolabel;        /* <id>':' not a label          */
+       Exinput_t       null;           /* null input                   */
+       Expr_t*         program;        /* current program              */
+       Exnode_t*       procedure;      /* current procedure            */
+       Exref_t*        refs;           /* . reference list             */
+       int             assigned;       /* declaration assignment       */
+       int             instatic;       /* static declaration           */
+       int             statics;        /* static used                  */
+       Switch_t*       swstate;        /* switch parse state           */
+       char            nullstring[1];  /* ""                           */
+} Exstate_t;
+
+extern Exid_t          exbuiltin[];
+extern const char*     exversion;
+extern Exstate_t       expr;
+
+extern int             exparse(void);  /* yacc should do this          */
+extern Sflong_t                strToL(char *, char **);
 
 #endif
 
index bf62276ec857874a13bfaed083320ecfb6674349..5fdbccd0ccac9c58e4bd849a1f6268a19c2b3b73 100644 (file)
  * allocate a new expression program environment
  */
 
-Expr_t *exopen(register Exdisc_t * disc)
+Expr_t*
+exopen(register Exdisc_t* disc)
 {
-    register Expr_t *program;
-    register Exid_t *sym;
-    int debug;
+       register Expr_t*        program;
+       register Exid_t*        sym;
+       int                     debug;
 
-    if (!(program = newof(0, Expr_t, 1, 0)))
-       return 0;
-    program->symdisc.key = offsetof(Exid_t, name);
-    debug = getenv("VMDEBUG") != 0;
-    if (!(program->symbols = dtopen(&program->symdisc, Dtset)) ||
-       !(program->tmp = sfstropen()) ||
-       !(program->vm =
-         (debug ? vmopen(Vmdcsbrk, Vmdebug, VM_DBCHECK | VM_DBABORT) :
-          vmopen(Vmdcheap, Vmbest, 0)))
-       || !(program->ve =
-            (debug ? vmopen(Vmdcsbrk, Vmdebug, VM_DBCHECK | VM_DBABORT) :
-             vmopen(Vmdcheap, Vmbest, 0)))) {
-       exclose(program, 1);
-       return 0;
-    }
-    program->vc = program->ve;
-    program->id = "libexpr:expr";
-    program->disc = disc;
-    setcontext(program);
-    program->file[0] = sfstdin;
-    program->file[1] = sfstdout;
-    program->file[2] = sfstderr;
-    strcpy(program->main.name, "main");
-    program->main.lex = PROCEDURE;
-    program->main.index = PROCEDURE;
-    dtinsert(program->symbols, &program->main);
-    if (!(disc->flags & EX_PURE))
-       for (sym = exbuiltin; *sym->name; sym++)
-           dtinsert(program->symbols, sym);
-    if ((sym = disc->symbols))
-       for (; *sym->name; sym++)
-           dtinsert(program->symbols, sym);
-    return program;
+       if (!(program = newof(0, Expr_t, 1, 0)))
+               return 0;
+       program->symdisc.key = offsetof(Exid_t, name);
+       debug = getenv("VMDEBUG") != 0;
+       if (!(program->symbols = dtopen(&program->symdisc, Dtset)) ||
+           !(program->tmp = sfstropen()) ||
+           !(program->vm = (debug ? vmopen(Vmdcsbrk, Vmdebug, VM_DBCHECK|VM_DBABORT) : vmopen(Vmdcheap, Vmbest, 0))) ||
+           !(program->ve = (debug ? vmopen(Vmdcsbrk, Vmdebug, VM_DBCHECK|VM_DBABORT) : vmopen(Vmdcheap, Vmbest, 0))))
+       {
+               exclose(program, 1);
+               return 0;
+       }
+       program->id = "libexpr:expr";
+       program->disc = disc;
+       setcontext(program);
+       program->file[0] = sfstdin;
+       program->file[1] = sfstdout;
+       program->file[2] = sfstderr;
+       strcpy(program->main.name, "main");
+       program->main.lex = PROCEDURE;
+       program->main.index = PROCEDURE;
+       dtinsert(program->symbols, &program->main);
+       if (!(disc->flags & EX_PURE))
+               for (sym = exbuiltin; *sym->name; sym++)
+                       dtinsert(program->symbols, sym);
+       if ((sym = disc->symbols))
+               for (; *sym->name; sym++)
+                       dtinsert(program->symbols, sym);
+       return program;
 }
index 14a5814089250024b53b69e6af21e0c8ae70ae65..4421f6748bd056c22581af653245aea716c8c3b0 100644 (file)
@@ -1,5 +1,5 @@
 /* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
+/* vim:set shiftwidth=4 ts=4: */
 
 /*************************************************************************
  * Copyright (c) 2011 AT&T Intellectual Property 
 
 %{
 
-
 /*
  * Glenn Fowler
  * AT&T Research
  *
  * expression library grammar and compiler
- *
- * NOTE: procedure arguments not implemented yet
  */
 
 #ifdef WIN32
 
 %token MINTOKEN
 
+%token CHARACTER
 %token INTEGER
 %token UNSIGNED
-%token CHARACTER
 %token FLOATING
 %token STRING
 %token VOIDTYPE
+%token STATIC
 
-%token  ADDRESS
+%token ADDRESS
 %token ARRAY
 %token BREAK
 %token CALL
 %binary        <op>    EQ      NE
 %binary        <op>    '<'     '>'     LE      GE
 %left  <op>    LS      RS
-%left  <op>    '+'     '-'     IN_OP
+%left  <op>    '+'     '-'     IN_OP
 %left  <op>    '*'     '/'     '%'
 %right <op>    '!'     '~'     '#'     UNARY
 %right <op>    INC     DEC
-%right <op>    CAST    
+%right <op>    CAST
 %left  <op>    '('
 
 %type <expr>           statement       statement_list  arg_list
 %type <id>             CONSTANT        ARRAY           FUNCTION        DECLARE
 %type <id>             EXIT            PRINT           PRINTF          QUERY
 %type <id>             RAND            SRAND
-%type <id>             SPRINTF         GSUB            SUB
+%type <id>             SPRINTF         PROCEDURE       name            dcl_name
+%type <id>             GSUB            SUB             SUBSTR
 %type <id>             SPLIT           TOKENS          splitop
-%type <id>             SUBSTR          PROCEDURE       name            dcl_name
 %type <id>             IF              WHILE           FOR             ITERATER
 %type <id>             BREAK           CONTINUE        print           member
 %type <id>             RETURN          DYNAMIC         SWITCH          UNSET
 %type <id>             SCANF           SSCANF          scan
 %type <floating>       FLOATING
 %type <integer>                INTEGER         UNSIGNED        array
+%type <integer>                static
 %type <string>         STRING
 
 %token MAXTOKEN
@@ -206,11 +205,14 @@ action            :       LABEL ':' {
                                expr.procedure = $1->value = exnewnode(expr.program, PROCEDURE, 1, $1->type, NiL, NiL);
                                expr.procedure->type = INTEGER;
                                if (!(disc = newof(0, Dtdisc_t, 1, 0)))
-                                       exerror("out of space [frame discipline]");
+                                       exnospace();
                                disc->key = offsetof(Exid_t, name);
-                               if (!(expr.procedure->data.procedure.frame = dtopen(disc, Dtset)) || !dtview(expr.procedure->data.procedure.frame, expr.program->symbols))
-                                       exerror("out of space [frame table]");
-                               expr.program->symbols = expr.program->frame = expr.procedure->data.procedure.frame;
+                               if (expr.assigned && !streq($1->name, "begin"))
+                               {
+                                       if (!(expr.procedure->data.procedure.frame = dtopen(disc, Dtset)) || !dtview(expr.procedure->data.procedure.frame, expr.program->symbols))
+                                               exnospace();
+                                       expr.program->symbols = expr.program->frame = expr.procedure->data.procedure.frame;
+                               }
                        } statement_list
                {
                        expr.procedure = 0;
@@ -218,6 +220,7 @@ action              :       LABEL ':' {
                        {
                                expr.program->symbols = expr.program->frame->view;
                                dtview(expr.program->frame, NiL);
+                               expr.program->frame = 0;
                        }
                        if ($4 && $4->op == S2B)
                        {
@@ -247,7 +250,16 @@ statement_list     :       /* empty */
                                exfreenode(expr.program, $1);
                                $$ = $2;
                        }
-                       else $$ = exnewnode(expr.program, ';', 1, $2->type, $1, $2);
+                       else if ($1->op == ';')
+                       {
+                               $$ = $1;
+                               $1->data.operand.last = $1->data.operand.last->data.operand.right = exnewnode(expr.program, ';', 1, $2->type, $2, NiL);
+                       }
+                       else
+                       {
+                               $$ = exnewnode(expr.program, ';', 1, $1->type, $1, NiL);
+                               $$->data.operand.last = $$->data.operand.right = exnewnode(expr.program, ';', 1, $2->type, $2, NiL);
+                       }
                }
                ;
 
@@ -259,9 +271,10 @@ statement  :       '{' statement_list '}'
                {
                        $$ = ($1 && $1->type == STRING) ? exnewnode(expr.program, S2B, 1, INTEGER, $1, NiL) : $1;
                }
-               |       DECLARE {expr.declare=$1->type;} dcl_list ';'
+               |       static {expr.instatic=$1;} DECLARE {expr.declare=$3->type;} dcl_list ';'
                {
-                       $$ = $3;
+                       $$ = $5;
+                       expr.declare = 0;
                }
                |       IF '(' expr ')' statement else_opt
                {
@@ -353,6 +366,7 @@ statement   :       '{' statement_list '}'
                                free(sw->base);
                        if (sw != &swstate)
                                free(sw);
+                       expr.declare = 0;
                }
                |       BREAK expr_opt ';'
                {
@@ -391,12 +405,13 @@ switch_list       :       /* empty */
                        {
                                if (!(sw = newof(0, Switch_t, 1, 0)))
                                {
-                                       exerror("out of space [switch]");
+                                       exnospace();
                                        sw = &swstate;
                                }
                                sw->prev = expr.swstate;
                        }
-                       else sw = &swstate;
+                       else
+                               sw = &swstate;
                        expr.swstate = sw;
                        sw->type = expr.declare;
                        sw->firstcase = 0;
@@ -406,7 +421,7 @@ switch_list :       /* empty */
                        n = 8;
                        if (!(sw->base = newof(0, Extype_t*, n, 0)))
                        {
-                               exerror("out of space [case]");
+                               exnospace();
                                n = 0;
                        }
                        sw->cur = sw->base;
@@ -425,7 +440,8 @@ switch_item :       case_list statement_list
                        {
                                if (sw->lastcase)
                                        sw->lastcase->data.select.next = $$;
-                               else sw->firstcase = $$;
+                               else
+                                       sw->firstcase = $$;
                                sw->lastcase = $$;
                                n = sw->cur - sw->base;
                                sw->cur = sw->base;
@@ -433,13 +449,15 @@ switch_item       :       case_list statement_list
                                memcpy($$->data.select.constant, sw->base, n * sizeof(Extype_t*));
                                $$->data.select.constant[n] = 0;
                        }
-                       else $$->data.select.constant = 0;
+                       else
+                               $$->data.select.constant = 0;
                        if (sw->def)
                        {
                                sw->def = 0;
                                if (sw->defcase)
                                        exerror("duplicate default in switch");
-                               else sw->defcase = $2;
+                               else
+                                       sw->defcase = $2;
                        }
                }
                ;
@@ -475,6 +493,16 @@ case_item  :       CASE constant ':'
                }
                ;
 
+static :       /* empty */
+               {
+                       $$ = 0;
+               }
+               |       STATIC
+               {
+                       $$ = 1;
+               }
+               ;
+
 dcl_list       :       dcl_item
                |       dcl_list ',' dcl_item
                {
@@ -486,7 +514,8 @@ dcl_list    :       dcl_item
 dcl_item       :       dcl_name {checkName ($1); expr.id=$1;} array initialize
                {
                        $$ = 0;
-                       $1->type = expr.declare;
+                       if (!$1->type || expr.declare)
+                               $1->type = expr.declare;
                        if ($4 && $4->op == PROCEDURE)
                        {
                                $1->lex = PROCEDURE;
@@ -502,15 +531,14 @@ dcl_item  :       dcl_name {checkName ($1); expr.id=$1;} array initialize
                                        Dtdisc_t*       disc;
 
                                        if (!(disc = newof(0, Dtdisc_t, 1, 0)))
-                                               exerror("out of space [associative array]");
+                                               exnospace();
                                        if ($3 == INTEGER) {
                                                disc->key = offsetof(Exassoc_t, key);
                                                disc->size = sizeof(Extype_t);
                                                disc->comparf = (Dtcompar_f)cmpKey;
                                        }
-                                       else {
+                                       else
                                                disc->key = offsetof(Exassoc_t, name);
-                                       }
                                        if (!($1->local.pointer = (char*)dtopen(disc, Dtoset)))
                                                exerror("%s: cannot initialize associative array", $1->name);
                                        $1->index_type = $3; /* -1 indicates no typechecking */
@@ -525,6 +553,11 @@ dcl_item   :       dcl_name {checkName ($1); expr.id=$1;} array initialize
                                        $4->data.operand.left = exnewnode(expr.program, DYNAMIC, 0, $1->type, NiL, NiL);
                                        $4->data.operand.left->data.variable.symbol = $1;
                                        $$ = $4;
+                                       if (!expr.program->frame && !expr.program->errors)
+                                       {
+                                               expr.assigned++;
+                                               exeval(expr.program, $$, NiL);
+                                       }
                                }
                                else if (!$3)
                                        $1->value->data.value = exzero($1->type);
@@ -532,7 +565,7 @@ dcl_item    :       dcl_name {checkName ($1); expr.id=$1;} array initialize
                }
                ;
 
-dcl_name               :       NAME
+dcl_name       :       NAME
                |       DYNAMIC
                |       ID
                |       FUNCTION
@@ -581,9 +614,11 @@ expr               :       '(' expr ')'
                        {
                                if (!$3->type)
                                        $1->type = $3->type = rel ? STRING : INTEGER;
-                               else $1->type = $3->type;
+                               else
+                                       $1->type = $3->type;
                        }
-                       else if (!$3->type) $3->type = $1->type;
+                       else if (!$3->type)
+                               $3->type = $1->type;
                        if ($1->type != $3->type)
                        {
                                if ($1->type == STRING)
@@ -600,9 +635,7 @@ expr                :       '(' expr ')'
                        $$ = exnewnode(expr.program, $2, 1, rel, $1, $3);
                        if (!expr.program->errors && $1->op == CONSTANT && $3->op == CONSTANT)
                        {
-                               expr.program->vc = expr.program->vm;
                                $$->data.constant.value = exeval(expr.program, $$, NiL);
-                               expr.program->vc = expr.program->ve;
                                $$->binary = 0;
                                $$->op = CONSTANT;
                                exfreenode(expr.program, $1);
@@ -696,7 +729,8 @@ expr                :       '(' expr ')'
                                exfreenode(expr.program, $1);
                                $$ = $3;
                        }
-                       else $$ = exnewnode(expr.program, ',', 1, $3->type, $1, $3);
+                       else
+                               $$ = exnewnode(expr.program, ',', 1, $3->type, $1, $3);
                }
                |       expr '?' {expr.nolabel=1;} expr ':' {expr.nolabel=0;} expr
                {
@@ -704,7 +738,8 @@ expr                :       '(' expr ')'
                        {
                                if (!$7->type)
                                        $4->type = $7->type = INTEGER;
-                               else $4->type = $7->type;
+                               else
+                                       $4->type = $7->type;
                        }
                        else if (!$7->type)
                                $7->type = $4->type;
@@ -735,7 +770,8 @@ expr                :       '(' expr ')'
                                }
                                exfreenode(expr.program, $1);
                        }
-                       else $$ = exnewnode(expr.program, '?', 1, $4->type, $1, exnewnode(expr.program, ':', 1, $4->type, $4, $7));
+                       else
+                               $$ = exnewnode(expr.program, '?', 1, $4->type, $1, exnewnode(expr.program, ':', 1, $4->type, $4, $7));
                }
                |       '!' expr
                {
@@ -787,6 +823,10 @@ expr               :       '(' expr ')'
                |       FUNCTION '(' args ')'
                {
                        $$ = exnewnode(expr.program, FUNCTION, 1, T($1->type), call(0, $1, $3), $3);
+                       if (!expr.program->disc->getf)
+                               exerror("%s: function references not supported", $$->data.operand.left->data.variable.symbol->name);
+                       else if (expr.program->disc->reff)
+                               (*expr.program->disc->reff)(expr.program, $$->data.operand.left, $$->data.operand.left->data.variable.symbol, 0, NiL, EX_CALL, expr.program->disc);
                }
                |       GSUB '(' args ')'
                {
@@ -845,20 +885,21 @@ expr              :       '(' expr ')'
                                $$->data.print.descriptor = $3->data.operand.left;
                                $3 = $3->data.operand.right;
                        }
-                       else switch ($1->index)
-                       {
-                       case QUERY:
-                               $$->data.print.descriptor = exnewnode(expr.program, CONSTANT, 0, INTEGER, NiL, NiL);
-                               $$->data.print.descriptor->data.constant.value.integer = 2;
-                               break;
-                       case PRINTF:
-                               $$->data.print.descriptor = exnewnode(expr.program, CONSTANT, 0, INTEGER, NiL, NiL);
-                               $$->data.print.descriptor->data.constant.value.integer = 1;
-                               break;
-                       case SPRINTF:
-                               $$->data.print.descriptor = 0;
-                               break;
-                       }
+                       else 
+                               switch ($1->index)
+                               {
+                               case QUERY:
+                                       $$->data.print.descriptor = exnewnode(expr.program, CONSTANT, 0, INTEGER, NiL, NiL);
+                                       $$->data.print.descriptor->data.constant.value.integer = 2;
+                                       break;
+                               case PRINTF:
+                                       $$->data.print.descriptor = exnewnode(expr.program, CONSTANT, 0, INTEGER, NiL, NiL);
+                                       $$->data.print.descriptor->data.constant.value.integer = 1;
+                                       break;
+                               case SPRINTF:
+                                       $$->data.print.descriptor = 0;
+                                       break;
+                               }
                        $$->data.print.args = preprint($3);
                }
                |       scan '(' args ')'
@@ -871,29 +912,30 @@ expr              :       '(' expr ')'
                                $$->data.scan.descriptor = $3->data.operand.left;
                                $3 = $3->data.operand.right;
                        }
-                       else switch ($1->index)
-                       {
-                       case SCANF:
-                               $$->data.scan.descriptor = 0;
-                               break;
-                       case SSCANF:
-                               if ($3 && $3->data.operand.left->type == STRING)
+                       else 
+                               switch ($1->index)
                                {
-                                       $$->data.scan.descriptor = $3->data.operand.left;
-                                       $3 = $3->data.operand.right;
+                               case SCANF:
+                                       $$->data.scan.descriptor = 0;
+                                       break;
+                               case SSCANF:
+                                       if ($3 && $3->data.operand.left->type == STRING)
+                                       {
+                                               $$->data.scan.descriptor = $3->data.operand.left;
+                                               $3 = $3->data.operand.right;
+                                       }
+                                       else
+                                               exerror("%s: string argument expected", $1->name);
+                                       break;
                                }
-                               else
-                                       exerror("%s: string argument expected", $1->name);
-                               break;
-                       }
                        if (!$3 || !$3->data.operand.left || $3->data.operand.left->type != STRING)
                                exerror("%s: format argument expected", $1->name);
                        $$->data.scan.format = $3->data.operand.left;
                        for (x = $$->data.scan.args = $3->data.operand.right; x; x = x->data.operand.right)
                        {
-                if (x->data.operand.left->op != ADDRESS)
-                    exerror("%s: address argument expected", $1->name);
-                x->data.operand.left = x->data.operand.left->data.operand.left;
+                               if (x->data.operand.left->op != ADDRESS)
+                                       exerror("%s: address argument expected", $1->name);
+                               x->data.operand.left = x->data.operand.left->data.operand.left;
                        }
                }
                |       variable assign
@@ -966,7 +1008,8 @@ constant   :       CONSTANT
                        $$ = exnewnode(expr.program, CONSTANT, 0, $1->type, NiL, NiL);
                        if (!expr.program->disc->reff)
                                exerror("%s: identifier references not supported", $1->name);
-                       else $$->data.constant.value = (*expr.program->disc->reff)(expr.program, $$, $1, NiL, NiL, EX_SCALAR, expr.program->disc);
+                       else
+                               $$->data.constant.value = (*expr.program->disc->reff)(expr.program, $$, $1, NiL, NiL, EX_SCALAR, expr.program->disc);
                }
                |       FLOATING
                {
@@ -1005,23 +1048,23 @@ variable        :       ID members
                }
                |       DYNAMIC index members
                {
-            Exnode_t*   n;
+                       Exnode_t*   n;
 
-            n = exnewnode(expr.program, DYNAMIC, 0, $1->type, NiL, NiL);
-            n->data.variable.symbol = $1;
-            n->data.variable.reference = 0;
-            if (((n->data.variable.index = $2) == 0) != ($1->local.pointer == 0))
-              exerror("%s: is%s an array", $1->name, $1->local.pointer ? "" : " not");
+                       n = exnewnode(expr.program, DYNAMIC, 0, $1->type, NiL, NiL);
+                       n->data.variable.symbol = $1;
+                       n->data.variable.reference = 0;
+                       if (((n->data.variable.index = $2) == 0) != ($1->local.pointer == 0))
+                               exerror("%s: is%s an array", $1->name, $1->local.pointer ? "" : " not");
                        if ($1->local.pointer && ($1->index_type > 0)) {
                                if ($2->type != $1->index_type)
-                       exerror("%s: indices must have type %s, not %s", 
+                                       exerror("%s: indices must have type %s, not %s", 
                                                $1->name, extypename(expr.program, $1->index_type),extypename(expr.program, $2->type));
                        }
                        if ($3) {
-              n->data.variable.dyna =exnewnode(expr.program, 0, 0, 0, NiL, NiL);
-              $$ = makeVar(expr.program, $1, $2, n, $3);
-            }
-            else $$ = n;
+                               n->data.variable.dyna =exnewnode(expr.program, 0, 0, 0, NiL, NiL);
+                               $$ = makeVar(expr.program, $1, $2, n, $3);
+                       }
+                       else $$ = n;
                }
                |       NAME
                {
@@ -1125,6 +1168,7 @@ formal_item       :       DECLARE {expr.declare=$1->type;} name
                        $3->type = $1->type;
                        $3->value = exnewnode(expr.program, 0, 0, 0, NiL, NiL);
                        expr.procedure->data.procedure.arity++;
+                       expr.declare = 0;
                }
                ;
 
@@ -1145,7 +1189,7 @@ members   :       /* empty */
                        $$ = expr.refs;
                }
                |       '.' ID member
-        {
+               {
                        Exref_t*        r;
                        Exref_t*        l;
 
@@ -1160,7 +1204,7 @@ members   :       /* empty */
                        expr.refs = l;
                        expr.lastref = r;
                        $$ = expr.refs;
-        }
+               }
                ;
 
 member :       '.' ID
@@ -1172,7 +1216,6 @@ member    :       '.' ID
                        $$ = $2;
                }
                ;
-
 assign         :       /* empty */
                {
                        $$ = 0;
@@ -1189,19 +1232,24 @@ initialize      :       assign
                                register Dtdisc_t*      disc;
 
                                if (expr.procedure)
-                                       exerror("no nested function definitions");
+                                       exerror("%s: nested function definitions not supported", expr.id->name);
                                expr.procedure = exnewnode(expr.program, PROCEDURE, 1, expr.declare, NiL, NiL);
                                if (!(disc = newof(0, Dtdisc_t, 1, 0)))
-                                       exerror("out of space [frame discipline]");
+                                       exnospace();
                                disc->key = offsetof(Exid_t, name);
-                               if (!(expr.procedure->data.procedure.frame = dtopen(disc, Dtset)) || !dtview(expr.procedure->data.procedure.frame, expr.program->symbols))
-                                       exerror("out of space [frame table]");
-                               expr.program->symbols = expr.program->frame = expr.procedure->data.procedure.frame;
-                               expr.program->formals = 1;
+                               if (!streq(expr.id->name, "begin"))
+                               {
+                                       if (!(expr.procedure->data.procedure.frame = dtopen(disc, Dtset)) || !dtview(expr.procedure->data.procedure.frame, expr.program->symbols))
+                                               exnospace();
+                                       expr.program->symbols = expr.program->frame = expr.procedure->data.procedure.frame;
+                                       expr.program->formals = 1;
+                               }
+                               expr.declare = 0;
                        } formals {
-                               expr.program->formals = 0;
                                expr.id->lex = PROCEDURE;
-                               expr.id->type = expr.declare;
+                               expr.id->type = expr.procedure->type;
+                               expr.program->formals = 0;
+                               expr.declare = 0;
                        } ')' '{' statement_list '}'
                {
                        $$ = expr.procedure;
@@ -1210,6 +1258,7 @@ initialize        :       assign
                        {
                                expr.program->symbols = expr.program->frame->view;
                                dtview(expr.program->frame, NiL);
+                               expr.program->frame = 0;
                        }
                        $$->data.operand.left = $3;
                        $$->data.operand.right = excast(expr.program, $7, $$->type, NiL, 0);
index 7fe5ffdb6a7d01d52566f7451950f51d35adcf59..35b24a75a01ce74dd41101ef8b351318b5597ed2 100644 (file)
@@ -27,23 +27,34 @@ extern "C" {
 
 #include <ast.h>
 
-#undef RS                      /* hp.pa <signal.h> grabs this!! */
+#undef RS      /* hp.pa <signal.h> grabs this!! */
 
-#ifndef __CYGWIN__
 #if _BLD_expr && defined(__EXPORT__)
 #define extern         __EXPORT__
 #endif
 #if !_BLD_expr && defined(__IMPORT__)
 #define extern         extern __IMPORT__
 #endif
+
+/*
+ * bison -pPREFIX misses YYSTYPE
+ */
+
+#if defined(YYSTYPE) || defined(YYBISON)
+#define EXSTYPE                YYSTYPE
+#else
+#include <exparse.h>
+#if defined(YYSTYPE) || defined(yystype)
+#define EXSTYPE                YYSTYPE
+#endif
 #endif
 
 #include "exparse.h"
 
 #undef extern
 
-#include "cdt.h"
-#include "vmalloc.h"
+#include <cdt.h>
+#include <vmalloc.h>
 
 #define EX_VERSION     20000101L
 
@@ -51,31 +62,31 @@ extern "C" {
  * flags
  */
 
-#define EX_CHARSTRING  (1<<0)  /* '...' same as "..."          */
-#define EX_CONSTANT    (1<<1)  /* compile to constant expr     */
-#define EX_FATAL       (1<<2)  /* errors are fatal             */
-#define EX_INTERACTIVE (1<<3)  /* interactive input            */
-#define EX_PURE                (1<<4)  /* no default symbols/keywords  */
-#define EX_QUALIFY     (1<<5)  /* '.' refs qualified in id tab */
-#define EX_RETAIN      (1<<6)  /* retain expressions on redef  */
-#define EX_SIZED       (1<<7)  /* strings are sized buffers    */
-#define EX_STRICT      (1<<8)  /* don't override null label    */
-#define EX_UNDECLARED  (1<<9)  /* allow undeclared identifiers */
+#define EX_CHARSTRING  (1<<0)          /* '...' same as "..."          */
+#define EX_CONSTANT    (1<<1)          /* compile to constant expr     */
+#define EX_FATAL       (1<<2)          /* errors are fatal             */
+#define EX_INTERACTIVE (1<<3)          /* interactive input            */
+#define EX_PURE                (1<<4)          /* no default symbols/keywords  */
+#define EX_QUALIFY     (1<<5)          /* '.' refs qualified in id tab */
+#define EX_RETAIN      (1<<6)          /* retain expressions on redef  */
+#define EX_SIZED       (1<<7)          /* strings are sized buffers    */
+#define EX_STRICT      (1<<8)          /* don't override null label    */
+#define EX_UNDECLARED  (1<<9)          /* allow undeclared identifiers */
 
-#define EX_ARRAY       (-3)    /* getval() array elt   */
-#define EX_CALL                (-2)    /* getval() function call elt   */
-#define EX_SCALAR      (-1)    /* getval() scalar elt          */
+#define EX_ARRAY       (-3)            /* getval() array elt   */
+#define EX_CALL                (-2)            /* getval() function call elt   */
+#define EX_SCALAR      (-1)            /* getval() scalar elt          */
 
-#define EX_NAMELEN     32      /* default Exid_t.name length   */
+#define EX_NAMELEN     32              /* default Exid_t.name length   */
 
 #define EX_INTARRAY  1         /* integer-index array */
 
 /* previously known as EXID, but EXID is also defined by bison in y.tab.h */
-#define EX_ID(n,l,i,t,f)       {{0},(l),(i),(t),0,(f),0,{0},n}
+#define EX_ID(n,l,i,t,f)       {{0},(l),(i),(t),0,(f),0,{0},0,n}
 
-#define DELETE_T               BREAK   /* exexpr() delete `type'       */
+#define DELETE_T               MINTOKEN                /* exexpr() delete `type'       */
 
-#define INTEGRAL(t)    ((t)>=INTEGER&&(t)<=CHARACTER)
+#define INTEGRAL(t)    ((t)>=CHARACTER&&(t)<=UNSIGNED)
 #define BUILTIN(t)  ((t) > MINTOKEN)
 
 /* function type mechanism
@@ -88,12 +99,12 @@ extern "C" {
  * arg 0 is the return value type
  */
 
-#define F              01      /* FLOATING                     */
-#define I              02      /* INTEGER                      */
-#define S              03      /* STRING                       */
+#define F              01              /* FLOATING                     */
+#define I              02              /* INTEGER                      */
+#define S              03              /* STRING                       */
 
-#define TBITS       4
-#define TMASK       ((1<<TBITS)-1)
+#define TBITS          4
+#define TMASK          ((1<<TBITS)-1)
 #define A(n,t)         ((t)<<((n)*TBITS))      /* function arg n is type t     */
 #define N(t)           ((t)>>=TBITS)   /* shift for next arg           */
 
@@ -103,216 +114,220 @@ extern "C" {
 #define exstrdup(p,s)          vmstrdup((p)->vm,s)
 
 #if LONG_MAX > INT_MAX
-    typedef int Exshort_t;
+typedef int Exshort_t;
 #else
-    typedef short Exshort_t;
+typedef short Exshort_t;
 #endif
 
-    typedef EXSTYPE Extype_t;
-
-    union Exdata_u;
-    typedef union Exdata_u Exdata_t;
-    struct Exdisc_s;
-    typedef struct Exdisc_s Exdisc_t;
-    struct Exnode_s;
-    typedef struct Exnode_s Exnode_t;
-    struct Expr_s;
-    typedef struct Expr_s Expr_t;
-    struct Exref_s;
-    typedef struct Exref_s Exref_t;
-
-    typedef int (*Exerror_f) (Expr_t *, Exdisc_t *, int, const char *,
-                             ...);
-    typedef void (*Exexit_f) (Expr_t *, Exdisc_t *, int);
-
-    typedef struct {           /* user defined member type       */
-       Sflong_t number;
-       char *pointer;
-    } Exlocal_t;
-
-    typedef struct Exid_s {    /* id symbol table info           */
-       Dtlink_t link;          /* symbol table link            */
-       long lex;               /* lex class                    */
-       long index;             /* user defined index           */
-       long type;              /* symbol and arg types         */
-       long index_type;        /* index type for arrays        */
-       long flags;             /* user defined flags           */
-       Exnode_t *value;        /* value                        */
-       Exlocal_t local;        /* user defined local stuff     */
-       char name[EX_NAMELEN];  /* symbol name                 */
-    } Exid_t;
-
-    struct Exref_s {           /* . reference list               */
-       Exref_t *next;          /* next in list                 */
-       Exid_t *symbol;         /* reference id symbol          */
-       Exnode_t *index;        /* optional reference index     */
-    };
-
-    typedef struct {           /* sized buffer                   */
-       unsigned long size;     /* buffer size                  */
-       char *data;             /* buffer data                  */
-    } Exbuf_t;
-
-    union Exdata_u {
-
-       struct {
-           Extype_t value;     /* constant value               */
-           Exid_t *reference;  /* conversion reference symbol  */
-       } constant;             /* variable reference           */
-
-       struct {
-           Exnode_t *left;     /* left operand                 */
-           Exnode_t *right;    /* right operand                */
-       } operand;              /* operands                     */
-
-       struct {
-           Exnode_t *statement;        /* case label statement(s)      */
-           Exnode_t *next;     /* next case item               */
-           Extype_t **constant;        /* case label constant array    */
-       } select;               /* case item                    */
-
-       struct {
-           Exid_t *symbol;     /* id symbol table entry        */
-           Exref_t *reference; /* . reference list             */
-           Exnode_t *index;    /* array index expression       */
-           Exnode_t *dyna;     /* dynamic expression   */
-       } variable;             /* variable reference           */
+typedef EXSTYPE Extype_t;
+
+union Exdata_u; typedef union Exdata_u Exdata_t;
+struct Exdisc_s; typedef struct Exdisc_s Exdisc_t;
+struct Exnode_s; typedef struct Exnode_s Exnode_t;
+struct Expr_s; typedef struct Expr_s Expr_t;
+struct Exref_s; typedef struct Exref_s Exref_t;
+
+typedef int (*Exerror_f) (Expr_t *, Exdisc_t *, int, const char *, ...);
+typedef void (*Exexit_f) (Expr_t *, Exdisc_t *, int);
+
+typedef struct Exlocal_s               /* user defined member type     */
+{
+       Sflong_t        number;
+       char*           pointer;
+} Exlocal_t;
+
+typedef struct Exid_s                  /* id symbol table info         */
+{
+       Dtlink_t        link;           /* symbol table link            */
+       long            lex;            /* lex class                    */
+       long            index;          /* user defined index           */
+       long            type;           /* symbol and arg types         */
+       long            index_type;     /* index type for arrays        */
+       long            flags;          /* user defined flags           */
+       Exnode_t*       value;          /* value                        */
+       Exlocal_t       local;          /* user defined local stuff     */
+       long            isstatic;       /* static                       */
+       char            name[EX_NAMELEN];/* symbol name                 */
+} Exid_t;
+
+struct Exref_s                         /* . reference list             */
+{
+       Exref_t*        next;           /* next in list                 */
+       Exid_t*         symbol;         /* reference id symbol          */
+       Exnode_t*       index;          /* optional reference index     */
+};
+
+typedef struct Exbuf_s                 /* sized buffer                 */
+{
+       unsigned long   size;           /* buffer size                  */
+       char*           data;           /* buffer data                  */
+} Exbuf_t;
+
+union Exdata_u
+{
+
+       struct
+       {
+       Extype_t        value;          /* constant value               */
+       Exid_t*         reference;      /* conversion reference symbol  */
+       }               constant;       /* variable reference           */
+
+       struct
+       {
+       Exnode_t*       left;           /* left operand                 */
+       Exnode_t*       right;          /* right operand                */
+       Exnode_t*       last;           /* for cons                     */
+       }               operand;        /* operands                     */
+
+       struct
+       {
+       Exnode_t*       statement;      /* case label statement(s)      */
+       Exnode_t*       next;           /* next case item               */
+       Extype_t**      constant;       /* case label constant array    */
+       }               select;         /* case item                    */
+
+       struct
+       {
+       Exid_t*         symbol;         /* id symbol table entry        */
+       Exref_t*        reference;      /* . reference list             */
+       Exnode_t*       index;          /* array index expression       */
+       Exnode_t*       dyna;           /* dynamic expression           */
+       }               variable;       /* variable reference           */
 
 #ifdef _EX_DATA_PRIVATE_
-        _EX_DATA_PRIVATE_
+       _EX_DATA_PRIVATE_
 #endif
-    };
-
-    struct Exnode_s {          /* expression tree node           */
-       Exshort_t type;         /* value type                   */
-       Exshort_t op;           /* operator                     */
-       Exshort_t binary;       /* data.operand.{left,right} ok */
-       Exshort_t pad_1;        /* padding to help cc           */
-       Exlocal_t local;        /* user defined local stuff     */
-       union {
-           double (*floating) (char **);       /* FLOATING return value        */
-            Sflong_t(*integer) (char **);      /* INTEGER|UNSIGNED return value */
-           char *(*string) (char **);  /* STRING return value          */
-       } compiled;             /* compiled function pointer    */
-       Exdata_t data;          /* node data                    */
+
+};
+
+struct Exnode_s                                /* expression tree node         */
+{
+       Exshort_t       type;           /* value type                   */
+       Exshort_t       op;             /* operator                     */
+       Exshort_t       binary;         /* data.operand.{left,right} ok */
+       Exshort_t       pad_1;          /* padding to help cc           */
+       Exlocal_t       local;          /* user defined local stuff     */
+       union
+       {
+       double  (*floating)(char**);    /* FLOATING return value        */
+       Sflong_t(*integer)(char**);     /* INTEGER|UNSIGNED return value*/
+       char*   (*string)(char**);      /* STRING return value          */
+       }               compiled;       /* compiled function pointer    */
+       Exdata_t        data;           /* node data                    */
 
 #ifdef _EX_NODE_PRIVATE_
-        _EX_NODE_PRIVATE_
+       _EX_NODE_PRIVATE_
 #endif
-    };
-
-    struct Exdisc_s {          /* discipline                     */
-       unsigned long version;  /* EX_VERSION                   */
-       unsigned long flags;    /* EX_* flags                   */
-       Exid_t *symbols;        /* static symbols               */
-       char **data;            /* compiled function arg data   */
-       char *lib;              /* pathfind() lib               */
-       char *type;             /* pathfind() type              */
-       int (*castf) (Expr_t *, Exnode_t *, const char *, int, Exid_t *,
-                     int, Exdisc_t *);
-       /* unknown cast function        */
-       int (*convertf) (Expr_t *, Exnode_t *, int, Exid_t *, int,
-                        Exdisc_t *);
-       /* type conversion function     */
-       int (*binaryf) (Expr_t *, Exnode_t *, Exnode_t *, Exnode_t *, int,
-                       Exdisc_t *);
-       /* binary operator function     */
-       char *(*typename) (Expr_t *, int);
-       /* application type names       */
-       int (*stringof) (Expr_t *, Exnode_t *, int, Exdisc_t *);
-       /* value to string conversion   */
-        Extype_t(*keyf) (Expr_t *, Extype_t, int, Exdisc_t *);
-       /* dictionary key for external type objects     */
-       Exerror_f errorf;       /* error function               */
-        Extype_t(*getf) (Expr_t *, Exnode_t *, Exid_t *, Exref_t *,
-                         void *, int, Exdisc_t *);
-       /* get value function           */
-        Extype_t(*reff) (Expr_t *, Exnode_t *, Exid_t *, Exref_t *,
-                         char *, int, Exdisc_t *);
-       /* reference value function     */
-       int (*setf) (Expr_t *, Exnode_t *, Exid_t *, Exref_t *, void *,
-                    int, Extype_t, Exdisc_t *);
-       /* set value function           */
-       int (*matchf) (Expr_t *, Exnode_t *, const char *, Exnode_t *,
-                      const char *, void *, Exdisc_t *);
+
+};
+
+struct Exdisc_s                                /* discipline                   */
+{
+       unsigned long   version;        /* EX_VERSION                   */
+       unsigned long   flags;          /* EX_* flags                   */
+       Exid_t*         symbols;        /* static symbols               */
+       char**          data;           /* compiled function arg data   */
+       char*           lib;            /* pathfind() lib               */
+       char*           type;           /* pathfind() type              */
+       int             (*castf)(Expr_t*, Exnode_t*, const char*, int, Exid_t*, int, Exdisc_t*);
+                                       /* unknown cast function        */
+       int             (*convertf)(Expr_t*, Exnode_t*, int, Exid_t*, int, Exdisc_t*);
+                                       /* type conversion function     */
+       int             (*binaryf) (Expr_t *, Exnode_t *, Exnode_t *, Exnode_t *, int, Exdisc_t *);
+                                       /* binary operator function     */
+       char*           (*typename) (Expr_t *, int);
+                                       /* application type names       */
+       int             (*stringof) (Expr_t *, Exnode_t *, int, Exdisc_t *);
+                                       /* value to string conversion   */
+       Extype_t        (*keyf) (Expr_t *, Extype_t, int, Exdisc_t *);
+                                       /* dictionary key for external type objects     */
+       Exerror_f       errorf;         /* error function               */
+       Extype_t        (*getf)(Expr_t*, Exnode_t*, Exid_t*, Exref_t*, void*, int, Exdisc_t*);
+                                       /* get value function           */
+       Extype_t        (*reff)(Expr_t*, Exnode_t*, Exid_t*, Exref_t*, char*, int, Exdisc_t*);
+                                       /* reference value function     */
+       int             (*setf)(Expr_t*, Exnode_t*, Exid_t*, Exref_t*, void*, int, Extype_t, Exdisc_t*);
+                                       /* set value function           */
+       int             (*matchf)(Expr_t*, Exnode_t*, const char*, Exnode_t*, const char*, void*, Exdisc_t*);
        /* exit function           */
-       Exexit_f exitf;
-       int *types;
-       void *user;
-    };
-
-    struct Expr_s {            /* ex program state               */
-       const char *id;         /* library id                   */
-       Dt_t *symbols;          /* symbol table                 */
-       const char *more;       /* more after %% (sp or != 0)   */
-       Sfio_t *file[10];       /* io streams                   */
-       Vmalloc_t *vm;          /* program store                */
+       Exexit_f        exitf;
+       int*            types;
+       void*           user;
+};
+
+struct Expr_s                          /* ex program state             */
+{
+       const char*     id;             /* library id                   */
+       Dt_t*           symbols;        /* symbol table                 */
+       const char*     more;           /* more after %% (sp or != 0)   */
+       Sfio_t*         file[10];       /* io streams                   */
+       Vmalloc_t*      vm;             /* program store                */
 
 #ifdef _EX_PROG_PRIVATE_
-        _EX_PROG_PRIVATE_
+       _EX_PROG_PRIVATE_
 #endif
-    };
-
-    struct Excc_s;
-    typedef struct Excc_s Excc_t;
-    struct Exccdisc_s;
-    typedef struct Exccdisc_s Exccdisc_t;
-
-    struct Exccdisc_s {                /* excc() discipline              */
-       Sfio_t *text;           /* text output stream           */
-       char *id;               /* symbol prefix                */
-       unsigned long flags;    /* EXCC_* flags                 */
-       int (*ccf) (Excc_t *, Exnode_t *, Exid_t *, Exref_t *, Exnode_t *,
-                   Exccdisc_t *);
-       /* program generator function   */
-    };
-
-    struct Excc_s {            /* excc() state                   */
-       Expr_t *expr;           /* exopen() state               */
-       Exdisc_t *disc;         /* exopen() discipline          */
+
+};
+
+struct Excc_s; typedef struct Excc_s Excc_t;
+struct Exccdisc_s; typedef struct Exccdisc_s Exccdisc_t;
+
+struct Exccdisc_s                      /* excc() discipline            */
+{
+       Sfio_t*         text;           /* text output stream           */
+       char*           id;             /* symbol prefix                */
+       unsigned long   flags;          /* EXCC_* flags                 */
+       int             (*ccf)(Excc_t*, Exnode_t*, Exid_t*, Exref_t*, Exnode_t*, Exccdisc_t*);
+                                       /* program generator function   */
+};
+
+struct Excc_s                          /* excc() state                 */
+{
+       Expr_t*         expr;           /* exopen() state               */
+       Exdisc_t*       disc;           /* exopen() discipline          */
 
 #ifdef _EX_CC_PRIVATE_
-        _EX_CC_PRIVATE_
+       _EX_CC_PRIVATE_
 #endif
-    };
 
-#ifndef __CYGWIN__
+};
+
 #if _BLD_expr && defined(__EXPORT__)
 #define extern         __EXPORT__
-#endif
 #endif
 
-    extern Exnode_t *excast(Expr_t *, Exnode_t *, int, Exnode_t *, int);
-    extern Exnode_t *exnoncast(Exnode_t *);
-    extern int excc(Excc_t *, const char *, Exid_t *, int);
-    extern int exccclose(Excc_t *);
-    extern Excc_t *exccopen(Expr_t *, Exccdisc_t *);
-    extern void exclose(Expr_t *, int);
-    extern int excomp(Expr_t *, const char *, int, const char *, Sfio_t *);
-    extern char *excontext(Expr_t *, char *, int);
-    extern int exdump(Expr_t *, Exnode_t *, Sfio_t *);
-    extern void exerror(const char *, ...);
-    extern void exwarn(const char *, ...);
-    extern Extype_t exeval(Expr_t *, Exnode_t *, void *);
-    extern Exnode_t *exexpr(Expr_t *, const char *, Exid_t *, int);
-    extern void exfreenode(Expr_t *, Exnode_t *);
-    extern Exnode_t *exnewnode(Expr_t *, int, int, int, Exnode_t *,
-                              Exnode_t *);
-    extern Expr_t *exopen(Exdisc_t *);
-    extern int expop(Expr_t *);
-    extern int expush(Expr_t *, const char *, int, const char *, Sfio_t *);
-    extern int exrewind(Expr_t *);
-    extern void exstatement(Expr_t *);
-    extern int extoken_fn(Expr_t *);
-    extern char *exstring(Expr_t *, char *);
-    extern void *exstralloc(Expr_t *, void *, size_t);
-    extern int exstrfree(Expr_t *, void *);
-    extern char *extype(int);
-    extern Extype_t exzero(int);
-    extern char *exopname(int);
-    extern void exinit(void);
-    extern char *extypename(Expr_t * p, int);
-    extern int exisAssign(Exnode_t *);
+extern Exnode_t*       excast(Expr_t*, Exnode_t*, int, Exnode_t*, int);
+extern Exnode_t*       exnoncast(Exnode_t *);
+extern int             excc(Excc_t*, const char*, Exid_t*, int);
+extern int             exccclose(Excc_t*);
+extern Excc_t*         exccopen(Expr_t*, Exccdisc_t*);
+extern void            exclose(Expr_t*, int);
+extern int             excomp(Expr_t*, const char*, int, const char*, Sfio_t*);
+extern char*           excontext(Expr_t*, char*, int);
+extern int             exdump(Expr_t*, Exnode_t*, Sfio_t*);
+extern void            exerror(const char*, ...);
+extern void            exwarn(const char *, ...);
+extern Extype_t                exeval(Expr_t*, Exnode_t*, void*);
+extern Exnode_t*       exexpr(Expr_t*, const char*, Exid_t*, int);
+extern void            exfreenode(Expr_t*, Exnode_t*);
+extern Exnode_t*       exnewnode(Expr_t*, int, int, int, Exnode_t*, Exnode_t*);
+extern char*           exnospace(void);
+extern Expr_t*         exopen(Exdisc_t*);
+extern int             expop(Expr_t*);
+extern int             expush(Expr_t*, const char*, int, const char*, Sfio_t*);
+extern int             exrewind(Expr_t*);
+extern char*           exstash(Sfio_t*, Vmalloc_t*);
+extern void            exstatement(Expr_t*);
+extern int             extoken_fn(Expr_t*);
+extern char*           exstring(Expr_t *, char *);
+extern void*           exstralloc(Expr_t *, void *, size_t);
+extern int             exstrfree(Expr_t *, void *);
+extern char*           extype(int);
+extern Extype_t                exzero(int);
+extern char*   exopname(int);
+extern void            exinit(void);
+extern char*   extypename(Expr_t * p, int);
+extern int             exisAssign(Exnode_t *);
 
 #undef extern
 
index e71356d70551d940a3f1f1a91ba3d8ba2109d8a7..326d4c7674a951dd11a0f386d957b802b277b453 100644 (file)
 #include "exlib.h"
 #include <string.h>
 
-int exrewind(Expr_t * ex)
+int
+exrewind(Expr_t* ex)
 {
-    register int n;
+       register int    n;
 
-    if (ex->linewrap) {
-       exerror("too much pushback");
-       return -1;
-    }
-    if (!ex->input->pushback
-       && !(ex->input->pushback = oldof(0, char, sizeof(ex->line), 3))) {
-       exerror("out of space [rewind]");
-       return -1;
-    }
-    if ((n = ex->linep - ex->line))
-       memcpy(ex->input->pushback, ex->line, n);
-    if (ex->input->peek) {
-       ex->input->pushback[n++] = ex->input->peek;
-       ex->input->peek = 0;
-    }
-    ex->input->pushback[n++] = ' ';
-    ex->input->pushback[n] = 0;
-    ex->input->pp = ex->input->pushback;
-    ex->input->nesting = ex->nesting;
-    setcontext(ex);
-    return 0;
+       if (ex->linewrap)
+       {
+               exerror("too much pushback");
+               return -1;
+       }
+       if (!ex->input->pushback && !(ex->input->pushback = oldof(0, char, sizeof(ex->line), 3)))
+       {
+               exnospace();
+               return -1;
+       }
+       if ((n = ex->linep - ex->line))
+               memcpy(ex->input->pushback, ex->line, n);
+       if (ex->input->peek)
+       {
+               ex->input->pushback[n++] = ex->input->peek;
+               ex->input->peek = 0;
+       }
+       ex->input->pushback[n++] = ' ';
+       ex->input->pushback[n] = 0;
+       ex->input->pp = ex->input->pushback;
+       ex->input->nesting = ex->nesting;
+       setcontext(ex);
+       return 0;
 }
 
-void exstatement(Expr_t * ex)
+void
+exstatement(Expr_t* ex)
 {
-    ex->nesting = ex->input->nesting;
-    setcontext(ex);
+       ex->nesting = ex->input->nesting;
+       setcontext(ex);
 }
index e86ffcc2645acb324af6badfe3e5856ff0bc46dc..c0bf271b3d6d61ebf5575dc5d43037a4f0ae49a6 100644 (file)
@@ -1,5 +1,5 @@
 /* $Id$ $Revision$ */
-/* vim:set shiftwidth=4 ts=8: */
+/* vim:set shiftwidth=4 ts=4: */
 
 /*************************************************************************
  * Copyright (c) 2011 AT&T Intellectual Property 
 #define TRACE_lex      -10
 #endif
 
-
-#define TRACE_lex      -10
 #if TRACE_lex
 
-int traceLex;
 /*
  * trace c for op
  */
 
-static void trace(Expr_t * ex, int lev, char *op, int c)
+static void
+trace(Expr_t* ex, int lev, char* op, int c)
 {
-    char *s = 0;
-    char *t;
-    char buf[16];
-    void *x = 0;
-
-    if (!traceLex)
-       return;
-    t = "";
-    switch (c) {
-    case 0:
-       s = " EOF";
-       break;
-    case '=':
-       s = t = buf;
-       *t++ = ' ';
-       if (!lev && exlval.op != c)
-           *t++ = exlval.op;
-       *t++ = c;
-       *t = 0;
-       break;
-    case AND:
-       s = " AND ";
-       t = "&&";
-       break;
-    case DEC:
-       s = " DEC ";
-       t = "--";
-       break;
-    case FUNCTION:
-       s = " FUNCTION ";
-       t = exlval.id->name;
-       break;
-    case DECLARE:
-       s = " DECLARE ";
-       t = exlval.id->name;
-       break;
-    case PROCEDURE:
-       s = " PROCEDURE ";
-       t = exlval.id->name;
-       break;
-    case DYNAMIC:
-       s = " DYNAMIC ";
-       t = exlval.id->name;
-       x = (void *) (exlval.id);
-       break;
-    case EQ:
-       s = " EQ ";
-       t = "==";
-       break;
-    case FLOATING:
-       s = " FLOATING ";
-       sfsprintf(t = buf, sizeof(buf), "%f", exlval.floating);
-       break;
-    case GE:
-       s = " GE ";
-       t = ">=";
-       break;
-    case ID:
-       s = " ID ";
-       t = exlval.id->name;
-       break;
-    case INC:
-       s = "INC ";
-       t = "++";
-       break;
-    case INTEGER:
-       s = " INTEGER ";
-       sfsprintf(t =
-                 buf, sizeof(buf), "%I*d", sizeof(exlval.integer),
-                 exlval.integer);
-       break;
-    case LABEL:
-       s = " LABEL ";
-       t = exlval.id->name;
-       break;
-    case LE:
-       s = " LE ";
-       t = "<=";
-       break;
-    case LS:
-       s = " LS ";
-       t = "<<";
-       break;
-    case NAME:
-       s = " NAME ";
-       t = exlval.id->name;
-       x = (void *) (exlval.id);
-       break;
-    case NE:
-       s = " NE ";
-       t = "!=";
-       break;
-    case OR:
-       s = " OR ";
-       t = "||";
-       break;
-    case RS:
-       s = " RS ";
-       t = ">>";
-       break;
-    case STRING:
-       s = " STRING ";
-       t = fmtesc(exlval.string);
-       break;
-    case UNSIGNED:
-       s = " UNSIGNED ";
-       sfsprintf(t =
-                 buf, sizeof(buf), "%I*u", sizeof(exlval.integer),
-                 exlval.integer);
-       break;
-    case BREAK:
-       s = " break";
-       break;
-    case CASE:
-       s = " case";
-       break;
-    case CONTINUE:
-       s = " continue";
-       break;
-    case DEFAULT:
-       s = " default";
-       break;
-    case ELSE:
-       s = " else";
-       break;
-    case EXIT:
-       s = " exit";
-       break;
-    case FOR:
-       s = " for";
-       break;
-    case ITERATER:
-       s = " forr";
-       break;
-    case GSUB:
-       s = " gsub";
-       break;
-    case IF:
-       s = " if";
-       break;
-    case IN_OP:
-       s = " in";
-       break;
-    case PRAGMA:
-       s = " pragma";
-       break;
-    case PRINT:
-       s = " print";
-       break;
-    case PRINTF:
-       s = " printf";
-       break;
-    case QUERY:
-       s = " query";
-       break;
-    case RAND:
-       s = " rand";
-       break;
-    case RETURN:
-       s = " return";
-       break;
-    case SPLIT:
-       s = " split";
-       break;
-    case SPRINTF:
-       s = " sprintf";
-       break;
-    case SRAND:
-       s = " srand";
-       break;
-    case SUB:
-       s = " sub";
-       break;
-    case SUBSTR:
-       s = " substr";
-       break;
-    case SWITCH:
-       s = " switch";
-       break;
-    case TOKENS:
-       s = " tokens";
-       break;
-    case UNSET:
-       s = " unset";
-       break;
-    case WHILE:
-       s = " while";
-       break;
-    default:
-       if (c < 0177) {
-           s = buf;
-           *s++ = c;
-           *s = 0;
-           t = fmtesc(buf);
-           s = " ";
+       char*   s = 0;
+       char*   t;
+       char    buf[16];
+       void*   x = 0;
+
+       t = "";
+       switch (c)
+       {
+       case 0:
+               s = " EOF";
+               break;
+       case '=':
+               s = t = buf;
+               *t++ = ' ';
+               if (!lev && exlval.op != c)
+                       *t++ = exlval.op;
+               *t++ = c;
+               *t = 0;
+               break;
+       case AND:
+               s = " AND ";
+               t = "&&";
+               break;
+       case DEC:
+               s = " DEC ";
+               t = "--";
+               break;
+       case DECLARE:
+               s = " DECLARE ";
+               t = exlval.id->name;
+               break;
+       case DYNAMIC:
+               s = " DYNAMIC ";
+               t = exlval.id->name;
+               x = (void *) (exlval.id);
+               break;
+       case EQ:
+               s = " EQ ";
+               t = "==";
+               break;
+       case FLOATING:
+               s = " FLOATING ";
+               sfsprintf(t = buf, sizeof(buf), "%f", exlval.floating);
+               break;
+       case GE:
+               s = " GE ";
+               t = ">=";
+               break;
+       case ID:
+               s = " ID ";
+               t = exlval.id->name;
+               break;
+       case INC:
+               s = "INC ";
+               t = "++";
+               break;
+       case INTEGER:
+               s = " INTEGER ";
+               sfsprintf(t = buf, sizeof(buf), "%I*d", sizeof(exlval.integer), exlval.integer);
+               break;
+       case LABEL:
+               s = " LABEL ";
+               t = exlval.id->name;
+               break;
+       case LE:
+               s = " LE ";
+               t = "<=";
+               break;
+       case LS:
+               s = " LS ";
+               t = "<<";
+               break;
+       case NAME:
+               s = " NAME ";
+               t = exlval.id->name;
+               x = (void *) (exlval.id);
+               break;
+       case NE:
+               s = " NE ";
+               t = "!=";
+               break;
+       case OR:
+               s = " OR ";
+               t = "||";
+               break;
+       case RS:
+               s = " RS ";
+               t = ">>";
+               break;
+       case STRING:
+               s = " STRING ";
+               t = fmtesc(exlval.string);
+               break;
+       case UNSIGNED:
+               s = " UNSIGNED ";
+               sfsprintf(t = buf, sizeof(buf), "%I*u", sizeof(exlval.integer), exlval.integer);
+               break;
+       case BREAK:
+               s = " break";
+               break;
+       case CASE:
+               s = " case";
+               break;
+       case CONTINUE:
+               s = " continue";
+               break;
+       case DEFAULT:
+               s = " default";
+               break;
+       case ELSE:
+               s = " else";
+               break;
+       case EXIT:
+               s = " exit";
+               break;
+       case FOR:
+               s = " for";
+               break;
+       case ITERATER:
+               s = " forf";
+               break;
+       case GSUB:
+               s = " gsub";
+               break;
+       case IF:
+               s = " if";
+               break;
+       case IN_OP:
+               s = " in";
+               break;
+       case PRAGMA:
+               s = " pragma";
+               break;
+       case PRINT:
+               s = " print";
+               break;
+       case PRINTF:
+               s = " printf";
+               break;
+       case QUERY:
+               s = " query";
+               break;
+       case RAND:
+               s = " rand";
+               break;
+       case RETURN:
+               s = " return";
+               break;
+       case SPLIT:
+               s = " split";
+               break;
+       case SPRINTF:
+               s = " sprintf";
+               break;
+       case SRAND:
+               s = " srand";
+               break;
+       case SUB:
+               s = " sub";
+               break;
+       case SUBSTR:
+               s = " substr";
+               break;
+       case SWITCH:
+               s = " switch";
+               break;
+       case TOKENS:
+               s = " tokens";
+               break;
+       case UNSET:
+               s = " unset";
+               break;
+       case WHILE:
+               s = " while";
+               break;
+       default:
+               if (c < 0177)
+               {
+                       s = buf;
+                       *s++ = c;
+                       *s = 0;
+                       t = fmtesc(buf);
+                       s = " ";
+               }
+               break;
        }
-       break;
-    }
-    if (x)
-       error(TRACE_lex + lev, "%s: [%d] %04d%s%s (%x)",
-             op, ex->input->nesting, c, s, t, x);
-    else
-       error(TRACE_lex + lev, "%s: [%d] %04d%s%s",
-             op, ex->input->nesting, c, s, t);
+       if (x)
+               error(TRACE_lex + lev, "%s: [%d] %04d%s%s (%x)", op, ex->input->nesting, c, s, t, x);
+
+       else
+               error(TRACE_lex + lev, "%s: [%d] %04d%s%s", op, ex->input->nesting, c, s, t);
 }
 
 /*
- * trace wrapper for extoken_fn()
+ * trace wrapper for extoken()
  */
 
+extern int     _extoken_fn_(Expr_t*);
 
-int _extoken_fn_(register Expr_t * ex);
-
-int extoken_fn(Expr_t * ex)
+int
+extoken_fn(Expr_t* ex)
 {
-    int c;
+       int     c;
 
 #define extoken_fn     _extoken_fn_
 
-    c = extoken_fn(ex);
-    trace(ex, 0, "exlex", c);
-    return c;
+       c = extoken_fn(ex);
+       trace(ex, 0, "exlex", c);
+       return c;
 }
 
 #else
@@ -270,575 +255,633 @@ int extoken_fn(Expr_t * ex)
 
 #endif
 
-#ifdef OLD
-
-#define BUMP(l) if (l) l++; else l = 2
-
-#else
-
-#define BUMP(l) l++
-
-#endif
 /*
  * get the next expression char
  */
 
-static int lex(register Expr_t * ex)
+static int
+lex(register Expr_t* ex)
 {
-    register int c;
-
-    for (;;) {
-       if ((c = ex->input->peek))
-           ex->input->peek = 0;
-       else if (ex->input->pp) {
-           if (!(c = *ex->input->pp++)) {
-               ex->input->pp = 0;
-               continue;
-           }
-       } else if (ex->input->sp) {
-           if (!(c = *ex->input->sp++)) {
-               if (!expop(ex))
-                   continue;
-               else
-                   trace(ex, -1, "expop sp FAIL", 0);
-               ex->input->sp--;
-           }
-       } else if (ex->input->fp) {
-           if ((c = sfgetc(ex->input->fp)) == EOF) {
-               if (!expop(ex))
-                   continue;
-               else
-                   trace(ex, -1, "expop fp FAIL", 0);
-               c = 0;
-           } else if ((ex->disc->flags & EX_INTERACTIVE) && c == '\n'
-                      && ex->input->next && !ex->input->next->next
-                      && ex->input->nesting <= 0) {
-               error_info.line++;
-               expop(ex);
-               trace(ex, -1, "expop sp FORCE", 0);
-               c = 0;
-           }
-       } else
-           c = 0;
-       if (c == '\n')
-           setcontext(ex);
-       else if (c)
-           putcontext(ex, c);
-       /* trace(ex, -3, "ex--lex", c); */
-       return c;
-    }
+       register int    c;
+
+       for (;;)
+       {
+               if ((c = ex->input->peek))
+                       ex->input->peek = 0;
+               else if (ex->input->pp)
+               {
+                       if (!(c = *ex->input->pp++))
+                       {
+                               ex->input->pp = 0;
+                               continue;
+                       }
+               }
+               else if (ex->input->sp)
+               {
+                       if (!(c = *ex->input->sp++))
+                       {
+                               if (!expop(ex))
+                                       continue;
+                               else trace(ex, -1, "expop sp FAIL", 0);
+                               ex->input->sp--;
+                       }
+               }
+               else if (ex->input->fp)
+               {
+                       if ((c = sfgetc(ex->input->fp)) == EOF)
+                       {
+                               if (!expop(ex))
+                                       continue;
+                               else trace(ex, -1, "expop fp FAIL", 0);
+                               c = 0;
+                       }
+                       else if ((ex->disc->flags & EX_INTERACTIVE) && c == '\n' && ex->input->next && !ex->input->next->next && ex->input->nesting <= 0)
+                       {
+                               error_info.line++;
+                               expop(ex);
+                               trace(ex, -1, "expop sp FORCE", 0);
+                               c = 0;
+                       }
+               }
+               else c = 0;
+               if (c == '\n')
+                       setcontext(ex);
+               else if (c)
+                       putcontext(ex, c);
+               trace(ex, -3, "ex--lex", c);
+               return c;
+       }
 }
 
 /*
  * get the next expression token
  */
 
-int extoken_fn(register Expr_t * ex)
+int
+extoken_fn(register Expr_t* ex)
 {
-    register int c;
-    register char *s;
-    register int q;
-    char *e;
-
-    if (ex->eof || ex->errors)
-       return 0;
-  again:
-    for (;;)
-       switch (c = lex(ex)) {
-       case 0:
-           goto eof;
-       case '/':
-           switch (q = lex(ex)) {
-           case '*':
-               for (;;)
-                   switch (lex(ex)) {
-                   case '\n':
-                       BUMP(error_info.line);
-                       continue;
-                   case '*':
-                       switch (lex(ex)) {
-                       case 0:
-                           goto eof;
-                       case '\n':
-                           BUMP(error_info.line);
-                           break;
+       register int    c;
+       register char*  s;
+       register int    q;
+       int             b;
+       char*           e;
+       Dt_t*           v;
+
+       if (ex->eof || ex->errors)
+               return 0;
+ again:
+       for (;;)
+               switch (c = lex(ex))
+               {
+               case 0:
+                       goto eof;
+               case '/':
+                       switch (q = lex(ex))
+                       {
                        case '*':
-                           exunlex(ex, '*');
-                           break;
+                               for (;;) switch (lex(ex))
+                               {
+                               case '\n':
+                                       if (error_info.line)
+                                               error_info.line++;
+                                       else error_info.line = 2;
+                                       continue;
+                               case '*':
+                                       switch (lex(ex))
+                                       {
+                                       case 0:
+                                               goto eof;
+                                       case '\n':
+                                               if (error_info.line)
+                                                       error_info.line++;
+                                               else error_info.line = 2;
+                                               break;
+                                       case '*':
+                                               exunlex(ex, '*');
+                                               break;
+                                       case '/':
+                                               goto again;
+                                       }
+                                       break;
+                               }
+                               break;
                        case '/':
-                           goto again;
+                               while ((c = lex(ex)) != '\n')
+                                       if (!c)
+                                               goto eof;
+                               break;
+                       default:
+                               goto opeq;
                        }
+                       /*FALLTHROUGH*/
+               case '\n':
+                       if (error_info.line)
+                               error_info.line++;
+                       else error_info.line = 2;
+                       /*FALLTHROUGH*/
+               case ' ':
+               case '\t':
                        break;
-                   }
-               break;
-           case '/':
-               while ((c = lex(ex)) != '\n')
-                   if (!c)
-                       goto eof;
-               break;
-           default:
-               goto opeq;
-           }
-        /*FALLTHROUGH*/ case '\n':
-           BUMP(error_info.line);
-        /*FALLTHROUGH*/ case ' ':
-       case '\t':
-           break;
-       case '(':
-       case '{':
-       case '[':
-           ex->input->nesting++;
-           return exlval.op = c;
-       case ')':
-       case '}':
-       case ']':
-           ex->input->nesting--;
-           return exlval.op = c;
-       case '+':
-       case '-':
-           if ((q = lex(ex)) == c)
-               return exlval.op = c == '+' ? INC : DEC;
-           goto opeq;
-       case '*':
-       case '%':
-       case '^':
-           q = lex(ex);
-         opeq:
-           exlval.op = c;
-           if (q == '=')
-               c = '=';
-           else if (q == '%' && c == '%') {
-               if (ex->input->fp)
-                   ex->more = (const char *) ex->input->fp;
-               else
-                   ex->more = ex->input->sp;
-               goto eof;
-           } else
-               exunlex(ex, q);
-           return c;
-       case '&':
-       case '|':
-           if ((q = lex(ex)) == '=') {
-               exlval.op = c;
-               return '=';
-           }
-           if (q == c)
-               c = c == '&' ? AND : OR;
-           else
-               exunlex(ex, q);
-           return exlval.op = c;
-       case '<':
-       case '>':
-           if ((q = lex(ex)) == c) {
-               exlval.op = c = c == '<' ? LS : RS;
-               if ((q = lex(ex)) == '=')
-                   c = '=';
-               else
-                   exunlex(ex, q);
-               return c;
-           }
-           goto relational;
-       case '=':
-       case '!':
-           q = lex(ex);
-         relational:
-           if (q == '=')
-               switch (c) {
+               case '(':
+               case '{':
+               case '[':
+                       ex->input->nesting++;
+                       return exlval.op = c;
+               case ')':
+               case '}':
+               case ']':
+                       ex->input->nesting--;
+                       return exlval.op = c;
+               case '+':
+               case '-':
+                       if ((q = lex(ex)) == c)
+                               return exlval.op = c == '+' ? INC : DEC;
+                       goto opeq;
+               case '*':
+               case '%':
+               case '^':
+                       q = lex(ex);
+               opeq:
+                       exlval.op = c;
+                       if (q == '=')
+                               c = '=';
+                       else if (q == '%' && c == '%')
+                       {
+                               if (ex->input->fp)
+                                       ex->more = (const char*)ex->input->fp;
+                               else ex->more = ex->input->sp;
+                               goto eof;
+                       }
+                       else exunlex(ex, q);
+                       return c;
+               case '&':
+               case '|':
+                       if ((q = lex(ex)) == '=')
+                       {
+                               exlval.op = c;
+                               return '=';
+                       }
+                       if (q == c)
+                               c = c == '&' ? AND : OR;
+                       else exunlex(ex, q);
+                       return exlval.op = c;
                case '<':
-                   c = LE;
-                   break;
                case '>':
-                   c = GE;
-                   break;
+                       if ((q = lex(ex)) == c)
+                       {
+                               exlval.op = c = c == '<' ? LS : RS;
+                               if ((q = lex(ex)) == '=')
+                                       c = '=';
+                               else exunlex(ex, q);
+                               return c;
+                       }
+                       goto relational;
                case '=':
-                   c = EQ;
-                   break;
                case '!':
-                   c = NE;
-                   break;
-           } else
-               exunlex(ex, q);
-           return exlval.op = c;
-       case '#':
-           if (!ex->linewrap && !(ex->disc->flags & EX_PURE)) {
-               s = ex->linep - 1;
-               while (s > ex->line && isspace(*(s - 1)))
-                   s--;
-               if (s == ex->line) {
-                   switch (extoken_fn(ex)) {
-                   case DYNAMIC:
-                   case ID:
-                   case NAME:
-                       s = exlval.id->name;
-                       break;
-                   default:
-                       s = "";
-                       break;
-                   }
-                   if (streq(s, "include")) {
-                       if (extoken_fn(ex) != STRING)
-                           exerror("#%s: string argument expected", s);
-                       else if (!expush(ex, exlval.string, 1, NiL, NiL)) {
-                           setcontext(ex);
-                           goto again;
+                       q = lex(ex);
+               relational:
+                       if (q == '=') switch (c)
+                       {
+                       case '<':
+                               c = LE;
+                               break;
+                       case '>':
+                               c = GE;
+                               break;
+                       case '=':
+                               c = EQ;
+                               break;
+                       case '!':
+                               c = NE;
+                               break;
                        }
-                   } else
-                       exerror("unknown directive");
-               }
-           }
-           return exlval.op = c;
-       case '\'':
-       case '"':
-           q = c;
-           sfstrset(ex->tmp, 0);
-           ex->input->nesting++;
-           while ((c = lex(ex)) != q) {
-               if (c == '\\') {
-                   sfputc(ex->tmp, c);
-                   c = lex(ex);
-               }
-               if (!c) {
-                   exerror("unterminated %c string", q);
-                   goto eof;
-               }
-               if (c == '\n') {
-                   BUMP(error_info.line);
-               }
-               sfputc(ex->tmp, c);
-           }
-           ex->input->nesting--;
-           s = sfstruse(ex->tmp);
-           if (q == '"' || (ex->disc->flags & EX_CHARSTRING)) {
-               if (!(exlval.string = vmstrdup(ex->vm, s)))
-                   goto eof;
-               stresc(exlval.string);
-               return STRING;
-           }
-           exlval.integer = chrtoi(s);
-           return INTEGER;
-       case '.':
-           if (isdigit(c = lex(ex))) {
-               sfstrset(ex->tmp, 0);
-               sfputc(ex->tmp, '0');
-               sfputc(ex->tmp, '.');
-               goto floating;
-           }
-           exunlex(ex, c);
-           return exlval.op = '.';
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-           sfstrset(ex->tmp, 0);
-           sfputc(ex->tmp, c);
-           q = INTEGER;
-           if ((c = lex(ex)) == 'x' || c == 'X') {
-               sfputc(ex->tmp, c);
-               for (;;) {
-                   switch (c = lex(ex)) {
-                   case '0':
-                   case '1':
-                   case '2':
-                   case '3':
-                   case '4':
-                   case '5':
-                   case '6':
-                   case '7':
-                   case '8':
-                   case '9':
-                   case 'a':
-                   case 'b':
-                   case 'c':
-                   case 'd':
-                   case 'e':
-                   case 'f':
-                   case 'A':
-                   case 'B':
-                   case 'C':
-                   case 'D':
-                   case 'E':
-                   case 'F':
-                       sfputc(ex->tmp, c);
-                       continue;
-                   }
-                   break;
-               }
-           } else {
-               while (isdigit(c)) {
-                   sfputc(ex->tmp, c);
-                   c = lex(ex);
-               }
-               if (c == '#') {
-                   sfputc(ex->tmp, c);
-                   /* s = sfstruse(ex->tmp); */
-                   /* b = strtol(s, NiL, 10); */
-                   do {
-                       sfputc(ex->tmp, c);
-                   } while (isalnum(c = lex(ex)));
-               } else {
-                   if (c == '.') {
-                     floating:
-                       q = FLOATING;
-                       sfputc(ex->tmp, c);
-                       while (isdigit(c = lex(ex)))
-                           sfputc(ex->tmp, c);
-                   }
-                   if (c == 'e' || c == 'E') {
-                       q = FLOATING;
+                       else exunlex(ex, q);
+                       return exlval.op = c;
+               case '#':
+                       if (!ex->linewrap && !(ex->disc->flags & EX_PURE))
+                       {
+                               s = ex->linep - 1;
+                               while (s > ex->line && isspace(*(s - 1)))
+                                       s--;
+                               if (s == ex->line)
+                               {
+                                       switch (extoken_fn(ex))
+                                       {
+                                       case DYNAMIC:
+                                       case ID:
+                                       case NAME:
+                                               s = exlval.id->name;
+                                               break;
+                                       default:
+                                               s = "";
+                                               break;
+                                       }
+                                       if (streq(s, "include"))
+                                       {
+                                               if (extoken_fn(ex) != STRING)
+                                                       exerror("#%s: string argument expected", s);
+                                               else if (!expush(ex, exlval.string, 1, NiL, NiL))
+                                               {
+                                                       setcontext(ex);
+                                                       goto again;
+                                               }
+                                       }
+                                       else exerror("unknown directive");
+                               }
+                       }
+                       return exlval.op = c;
+               case '\'':
+               case '"':
+                       q = c;
+                       sfstrseek(ex->tmp, 0, SEEK_SET);
+                       ex->input->nesting++;
+                       while ((c = lex(ex)) != q)
+                       {
+                               if (c == '\\')
+                               {
+                                       sfputc(ex->tmp, c);
+                                       c = lex(ex);
+                               }
+                               if (!c)
+                               {
+                                       exerror("unterminated %c string", q);
+                                       goto eof;
+                               }
+                               if (c == '\n')
+                               {
+                                       if (error_info.line)
+                                               error_info.line++;
+                                       else error_info.line = 2;
+                               }
+                               sfputc(ex->tmp, c);
+                       }
+                       ex->input->nesting--;
+                       s = exstash(ex->tmp, NiL);
+                       if (q == '"' || (ex->disc->flags & EX_CHARSTRING))
+                       {
+                               if (!(exlval.string = vmstrdup(ex->vm, s)))
+                                       goto eof;
+                               stresc(exlval.string);
+                               return STRING;
+                       }
+                       exlval.integer = chrtoi(s);
+                       return INTEGER;
+               case '.':
+                       if (isdigit(c = lex(ex)))
+                       {
+                               sfstrseek(ex->tmp, 0, SEEK_SET);
+                               sfputc(ex->tmp, '0');
+                               sfputc(ex->tmp, '.');
+                               goto floating;
+                       }
+                       exunlex(ex, c);
+                       return exlval.op = '.';
+               case '0': case '1': case '2': case '3': case '4':
+               case '5': case '6': case '7': case '8': case '9':
+                       sfstrseek(ex->tmp, 0, SEEK_SET);
                        sfputc(ex->tmp, c);
-                       if ((c = lex(ex)) == '-' || c == '+') {
-                           sfputc(ex->tmp, c);
-                           c = lex(ex);
+                       q = INTEGER;
+                       b = 0;
+                       if ((c = lex(ex)) == 'x' || c == 'X')
+                       {
+                               b = 16;
+                               sfputc(ex->tmp, c);
+                               for (;;)
+                               {
+                                       switch (c = lex(ex))
+                                       {
+                                       case '0': case '1': case '2': case '3': case '4':
+                                       case '5': case '6': case '7': case '8': case '9':
+                                       case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 
+                                       case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 
+                                               sfputc(ex->tmp, c);
+                                               continue;
+                                       }
+                                       break;
+                               }
                        }
-                       while (isdigit(c)) {
-                           sfputc(ex->tmp, c);
-                           c = lex(ex);
+                       else
+                       {
+                               while (isdigit(c))
+                               {
+                                       sfputc(ex->tmp, c);
+                                       c = lex(ex);
+                               }
+                               if (c == '#')
+                               {
+                                       sfputc(ex->tmp, c);
+                                       /* s = exstash(ex->tmp, NiL); */
+                                       /* b = strtol(s, NiL, 10); */
+                                       do
+                                       {
+                                               sfputc(ex->tmp, c);
+                                       } while (isalnum(c = lex(ex)));
+                               }
+                               else
+                               {
+                                       if (c == '.')
+                                       {
+                                       floating:
+                                               q = FLOATING;
+                                               sfputc(ex->tmp, c);
+                                               while (isdigit(c = lex(ex)))
+                                                       sfputc(ex->tmp, c);
+                                       }
+                                       if (c == 'e' || c == 'E')
+                                       {
+                                               q = FLOATING;
+                                               sfputc(ex->tmp, c);
+                                               if ((c = lex(ex)) == '-' || c == '+')
+                                               {
+                                                       sfputc(ex->tmp, c);
+                                                       c = lex(ex);
+                                               }
+                                               while (isdigit(c))
+                                               {
+                                                       sfputc(ex->tmp, c);
+                                                       c = lex(ex);
+                                               }
+                                       }
+                               }
                        }
-                   }
-               }
-           }
-           s = sfstruse(ex->tmp);
-           if (q == FLOATING)
-               exlval.floating = strtod(s, &e);
-           else {
-               if (c == 'u' || c == 'U') {
-                   q = UNSIGNED;
-                   c = lex(ex);
-                   exlval.integer = strToL(s, &e);
-               } else
-                   exlval.integer = strToL(s, &e);
-               if (*e) {
-                   *--e = 1;
-                   exlval.integer *= strton(e, &e, NiL, 0);
-               }
-           }
-           exunlex(ex, c);
-           if (*e || isalpha(c) || c == '_' || c == '$') {
-               exerror("%s: invalid numeric constant", s);
-               goto eof;
-           }
-           return q;
-       default:
-           if (isalpha(c) || c == '_' || c == '$') {
-               sfstrset(ex->tmp, 0);
-               sfputc(ex->tmp, c);
-               while (isalnum(c = lex(ex)) || c == '_' || c == '$')
-                   sfputc(ex->tmp, c);
-               exunlex(ex, c);
-               s = sfstruse(ex->tmp);
-               if (!(exlval.id = (Exid_t *) dtmatch(ex->symbols, s))) {
-                   if (!
-                       (exlval.id =
-                        newof(0, Exid_t, 1,
-                              strlen(s) - EX_NAMELEN + 1))) {
-                       exerror("out of space");
-                       goto eof;
-                   }
-                   strcpy(exlval.id->name, s);
-                   exlval.id->lex = NAME;
-                   dtinsert((ex->formals
-                             || !ex->symbols->view) ? ex->symbols : ex->
-                            symbols->view, exlval.id);
-               }
-
-               /*
-                * lexical analyzer state controlled by the grammar
-                */
-
-               switch (exlval.id->lex) {
-               case DECLARE:
-                   if (exlval.id->index == CHARACTER) {
-                       /*
-                        * `char*' === `string'
-                        * the * must immediately follow char
-                        */
-
-                       if (c == '*') {
-                           lex(ex);
-                           exlval.id = id_string;
+                       s = exstash(ex->tmp, NiL);
+                       if (q == FLOATING)
+                               exlval.floating = strtod(s, &e);
+                       else
+                       {
+                               if (c == 'u' || c == 'U')
+                               {
+                                       q = UNSIGNED;
+                                       c = lex(ex);
+                                       exlval.integer = strtoull(s, &e, b);
+                               }
+                               else
+                                       exlval.integer = strtoll(s, &e, b);
+                               if (*e)
+                               {
+                                       *--e = 1;
+                                       exlval.integer *= strton(e, &e, NiL, 0);
+                               }
                        }
-                   }
-                   break;
-               case NAME:
-                   /*
-                    * action labels are disambiguated from ?:
-                    * through the expr.nolabel grammar hook
-                    * the : must immediately follow labels
-                    */
-
-                   if (c == ':' && !expr.nolabel)
-                       return LABEL;
-                   break;
-               case PRAGMA:
-                   /*
-                    * user specific statement stripped and
-                    * passed as string
-                    */
-
-                   {
-                       int b;
-                       int n;
-                       int pc = 0;
-                       int po;
-                       int t;
-
-                       /*UNDENT... */
-                       sfstrset(ex->tmp, 0);
-                       b = 1;
-                       n = 0;
-                       po = 0;
-                       t = 0;
-                       for (c = t = lex(ex);; c = lex(ex)) {
-                           switch (c) {
-                           case 0:
+                       exunlex(ex, c);
+                       if (*e || isalpha(c) || c == '_' || c == '$')
+                       {
+                               exerror("%s: invalid numeric constant", s);
                                goto eof;
-                           case '/':
-                               switch (q = lex(ex)) {
-                               case '*':
-                                   for (;;) {
-                                       switch (lex(ex)) {
-                                       case '\n':
-                                           BUMP(error_info.line);
-                                           continue;
-                                       case '*':
-                                           switch (lex(ex)) {
-                                           case 0:
+                       }
+                       return q;
+               default:
+                       if (isalpha(c) || c == '_' || c == '$')
+                       {
+                               sfstrseek(ex->tmp, 0, SEEK_SET);
+                               sfputc(ex->tmp, c);
+                               while (isalnum(c = lex(ex)) || c == '_' || c == '$')
+                                       sfputc(ex->tmp, c);
+                               exunlex(ex, c);
+                               s = exstash(ex->tmp, NiL);
+                               v = expr.declare ? dtview(ex->symbols, NiL) : (Dt_t*)0;
+                               exlval.id = (Exid_t*)dtmatch(ex->symbols, s);
+                               if (v)
+                                       dtview(ex->symbols, v);
+                               if (!exlval.id)
+                               {
+                                       if (!(exlval.id = newof(0, Exid_t, 1, strlen(s) - EX_NAMELEN + 1)))
+                                       {
+                                               exnospace();
                                                goto eof;
-                                           case '\n':
-                                               BUMP(error_info.line);
-                                               continue;
-                                           case '*':
-                                               exunlex(ex, '*');
-                                               continue;
-                                           case '/':
+                                       }
+                                       strcpy(exlval.id->name, s);
+                                       exlval.id->lex = NAME;
+                                       expr.statics += exlval.id->isstatic = expr.instatic;
+
+                                       /*
+                                        * LABELs are in the parent scope!
+                                        */
+
+                                       if (c == ':' && !expr.nolabel && ex->frame && ex->frame->view)
+                                               dtinsert(ex->frame->view, exlval.id);
+                                       else
+                                               dtinsert(ex->symbols, exlval.id);
+                               }
+
+                               /*
+                                * lexical analyzer state controlled by the grammar
+                                */
+
+                               switch (exlval.id->lex)
+                               {
+                               case DECLARE:
+                                       if (exlval.id->index == CHARACTER)
+                                       {
+                                               /*
+                                                * `char*' === `string'
+                                                * the * must immediately follow char
+                                                */
+
+                                               if (c == '*')
+                                               {
+                                                       lex(ex);
+                                                       exlval.id = id_string;
+                                               }
+                                       }
+                                       break;
+                               case NAME:
+                                       /*
+                                        * action labels are disambiguated from ?:
+                                        * through the expr.nolabel grammar hook
+                                        * the : must immediately follow labels
+                                        */
+
+                                       if (c == ':' && !expr.nolabel)
+                                               return LABEL;
+                                       break;
+                               case PRAGMA:
+                                       /*
+                                        * user specific statement stripped and
+                                        * passed as string
+                                        */
+
+                                       {
+                                               int     b;
+                                               int     n;
+                                               int     pc;
+                                               int     po;
+                                               int     t;
+
+                                               /*UNDENT...*/
+               sfstrseek(ex->tmp, 0, SEEK_SET);
+               b = 1;
+               n = 0;
+               po = 0;
+               t = 0;
+               for (c = t = lex(ex);; c = lex(ex))
+               {
+                       switch (c)
+                       {
+                       case 0:
+                               goto eof;
+                       case '/':
+                               switch (q = lex(ex))
+                               {
+                               case '*':
+                                       for (;;)
+                                       {
+                                               switch (lex(ex))
+                                               {
+                                               case '\n':
+                                                       if (error_info.line)
+                                                               error_info.line++;
+                                                       else error_info.line = 2;
+                                                       continue;
+                                               case '*':
+                                                       switch (lex(ex))
+                                                       {
+                                                       case 0:
+                                                               goto eof;
+                                                       case '\n':
+                                                               if (error_info.line)
+                                                                       error_info.line++;
+                                                               else error_info.line = 2;
+                                                               continue;
+                                                       case '*':
+                                                               exunlex(ex, '*');
+                                                               continue;
+                                                       case '/':
+                                                               break;
+                                                       default:
+                                                               continue;
+                                                       }
+                                                       break;
+                                               }
+                                               if (!b++)
+                                                       goto eof;
+                                               sfputc(ex->tmp, ' ');
                                                break;
-                                           default:
-                                               continue;
-                                           }
-                                           break;
                                        }
-                                       if (!b++)
-                                           goto eof;
-                                       sfputc(ex->tmp, ' ');
                                        break;
-                                   }
-                                   break;
                                case '/':
-                                   while ((c = lex(ex)) != '\n')
-                                       if (!c)
-                                           goto eof;
-                                   BUMP(error_info.line);
-                                   b = 1;
-                                   sfputc(ex->tmp, '\n');
-                                   break;
+                                       while ((c = lex(ex)) != '\n')
+                                               if (!c)
+                                                       goto eof;
+                                       if (error_info.line)
+                                               error_info.line++;
+                                       else error_info.line = 2;
+                                       b = 1;
+                                       sfputc(ex->tmp, '\n');
+                                       break;
                                default:
-                                   b = 0;
-                                   sfputc(ex->tmp, c);
-                                   sfputc(ex->tmp, q);
-                                   break;
+                                       b = 0;
+                                       sfputc(ex->tmp, c);
+                                       sfputc(ex->tmp, q);
+                                       break;
                                }
                                continue;
-                           case '\n':
-                               BUMP(error_info.line);
+                       case '\n':
+                               if (error_info.line)
+                                       error_info.line++;
+                               else error_info.line = 2;
                                b = 1;
                                sfputc(ex->tmp, '\n');
                                continue;
-                           case ' ':
-                           case '\t':
+                       case ' ':
+                       case '\t':
                                if (!b++)
-                                   goto eof;
+                                       goto eof;
                                sfputc(ex->tmp, ' ');
                                continue;
-                           case '(':
-                           case '{':
-                           case '[':
+                       case '(':
+                       case '{':
+                       case '[':
                                b = 0;
-                               if (!po) {
-                                   switch (po = c) {
-                                   case '(':
-                                       pc = ')';
-                                       break;
-                                   case '{':
-                                       pc = '}';
-                                       break;
-                                   case '[':
-                                       pc = ']';
-                                       break;
-                                   }
-                                   n++;
-                               } else if (c == po)
-                                   n++;
+                               if (!po)
+                               {
+                                       switch (po = c)
+                                       {
+                                       case '(':
+                                               pc = ')';
+                                               break;
+                                       case '{':
+                                               pc = '}';
+                                               break;
+                                       case '[':
+                                               pc = ']';
+                                               break;
+                                       }
+                                       n++;
+                               }
+                               else if (c == po)
+                                       n++;
                                sfputc(ex->tmp, c);
                                continue;
-                           case ')':
-                           case '}':
-                           case ']':
+                       case ')':
+                       case '}':
+                       case ']':
                                b = 0;
-                               if (!po) {
-                                   exunlex(ex, c);
-                                   break;
+                               if (!po)
+                               {
+                                       exunlex(ex, c);
+                                       break;
                                }
                                sfputc(ex->tmp, c);
-                               if (c == pc && --n <= 0) {
-                                   if (t == po)
-                                       break;
-                                   po = 0;
+                               if (c == pc && --n <= 0)
+                               {
+                                       if (t == po)
+                                               break;
+                                       po = 0;
                                }
                                continue;
-                           case ';':
+                       case ';':
                                b = 0;
                                if (!n)
-                                   break;
+                                       break;
                                sfputc(ex->tmp, c);
                                continue;
-                           case '\'':
-                           case '"':
+                       case '\'':
+                       case '"':
                                b = 0;
                                sfputc(ex->tmp, c);
                                ex->input->nesting++;
                                q = c;
-                               while ((c = lex(ex)) != q) {
-                                   if (c == '\\') {
+                               while ((c = lex(ex)) != q)
+                               {
+                                       if (c == '\\')
+                                       {
+                                               sfputc(ex->tmp, c);
+                                               c = lex(ex);
+                                       }
+                                       if (!c)
+                                       {
+                                               exerror("unterminated %c string", q);
+                                               goto eof;
+                                       }
+                                       if (c == '\n')
+                                       {
+                                               if (error_info.line)
+                                                       error_info.line++;
+                                               else error_info.line = 2;
+                                       }
                                        sfputc(ex->tmp, c);
-                                       c = lex(ex);
-                                   }
-                                   if (!c) {
-                                       exerror("unterminated %c string",
-                                               q);
-                                       goto eof;
-                                   }
-                                   if (c == '\n') {
-                                       BUMP(error_info.line);
-                                   }
-                                   sfputc(ex->tmp, c);
                                }
                                ex->input->nesting--;
                                continue;
-                           default:
+                       default:
                                b = 0;
                                sfputc(ex->tmp, c);
                                continue;
-                           }
-                           break;
                        }
-                       (*ex->disc->reff) (ex, NiL, exlval.id, NiL,
-                                          sfstruse(ex->tmp), 0, ex->disc);
+                       break;
+               }
+               (*ex->disc->reff)(ex, NiL, exlval.id, NiL, exstash(ex->tmp, NiL), 0, ex->disc);
 
-                       /*..INDENT */
-                   }
-                   goto again;
+                                               /*..INDENT*/
+                                       }
+                                       goto again;
+                               }
+                               return exlval.id->lex;
+                       }
+                       return exlval.op = c;
                }
-               return exlval.id->lex;
-           }
-           return exlval.op = c;
-       }
-  eof:
-    ex->eof = 1;
-    return exlval.op = ';';
+ eof:
+       ex->eof = 1;
+       return exlval.op = ';';
 }
index f751ed63924048a7b2c98c33f10eb41d3dacfa3f..5e8f6a6513db6fc86eff4aca4f148817925423e7 100644 (file)
  * return C type name for type
  */
 
-char *extype(int type)
+char*
+extype(int type)
 {
-    switch (type) {
-    case FLOATING:
-       return "double";
-    case STRING:
-       return "char*";
-    case UNSIGNED:
-       return xstr(unsigned _ast_intmax_t);
-    }
-    return xstr(_ast_intmax_t);
+       switch (type)
+       {
+       case FLOATING:
+               return "double";
+       case STRING:
+               return "char*";
+       case UNSIGNED:
+               return xstr(uintmax_t);
+       }
+       return xstr(intmax_t);
 }
index 1aff9085e9fc999f48b6ff537cfce0a051a2e78a..9024565d0c8f2f33224e103a33b730c4eb8fa087 100644 (file)
  * return 0 value for type
  */
 
-Extype_t exzero(int type)
+Extype_t
+exzero(int type)
 {
-    Extype_t v;
+       Extype_t        v;
 
-    switch (type) {
-    case FLOATING:
-       v.floating = 0.0;
-       break;
-    case INTEGER:
-    case UNSIGNED:
-       v.integer = 0;
-       break;
-    case STRING:
-       v.string = expr.nullstring;
-       break;
-    default:
-       v.integer = 0;
-       break;
-    }
-    return v;
+       switch (type)
+       {
+       case FLOATING:
+               v.floating = 0.0;
+               break;
+       case INTEGER:
+       case UNSIGNED:
+               v.integer = 0;
+               break;
+       case STRING:
+               v.string = expr.nullstring;
+               break;
+       }
+       return v;
 }