must free token_str if not used.
[unix-history] / usr / src / usr.bin / window / parser1.c
index 133179e..0600c53 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)parser1.c   3.1 83/11/22";
+static char *sccsid = "@(#)parser1.c   3.8 84/01/11";
 #endif
 
 #include <stdio.h>
 #endif
 
 #include <stdio.h>
@@ -11,9 +11,10 @@ static       char *sccsid = "@(#)parser1.c   3.1 83/11/22";
 #include "var.h"
 
 #define p_erred()      (cx.x_erred)
 #include "var.h"
 
 #define p_erred()      (cx.x_erred)
+#define p_synerred()   (cx.x_synerred)
 #define p_clearerr()   (cx.x_erred = cx.x_synerred = 0)
 #define p_abort()      (cx.x_abort)
 #define p_clearerr()   (cx.x_erred = cx.x_synerred = 0)
 #define p_abort()      (cx.x_abort)
-#define p_varfree(v)   if ((v).v_type == V_STR) str_free((v).v_str)
+#define p_valfree(v)   if ((v).v_type == V_STR) str_free((v).v_str)
 
 p_start()
 {
 
 p_start()
 {
@@ -40,11 +41,8 @@ p_start()
 p_statementlist(flag)
 char flag;
 {
 p_statementlist(flag)
 char flag;
 {
-       for (;;) {
-               if (p_statement(flag) < 0)
-                       return -1;
-               p_clearerr();
-       }
+       for (; p_statement(flag) >= 0; p_clearerr())
+               ;
 }
 
 p_statement(flag)
 }
 
 p_statement(flag)
@@ -139,7 +137,7 @@ char flag;
        switch (token) {
        case T_MOD:
                t.v_type = V_STR;
        switch (token) {
        case T_MOD:
                t.v_type = V_STR;
-               t.v_str = "%";
+               t.v_str = str_cpy("%");
                (void) s_gettok();
                break;
        case T_NUM:
                (void) s_gettok();
                break;
        case T_NUM:
@@ -159,7 +157,7 @@ char flag;
 #ifdef DEBUG
                        error("command: expression.");
 #endif
 #ifdef DEBUG
                        error("command: expression.");
 #endif
-                       p_varfree(t);
+                       p_valfree(t);
                        return 0;
                }
        }
                        return 0;
                }
        }
@@ -194,7 +192,7 @@ char flag;
                }
        }
        str_free(cmd);
                }
        }
        str_free(cmd);
-       p_varfree(t);
+       p_valfree(t);
        if (token == T_EOL)
                (void) s_gettok();
        else if (token != T_EOF) {
        if (token == T_EOL)
                (void) s_gettok();
        else if (token != T_EOF) {
@@ -232,15 +230,25 @@ register struct value *v;
        for (i = 0;;) {
                ap = 0;
                if (p_expr0(&t, flag) < 0)
        for (i = 0;;) {
                ap = 0;
                if (p_expr0(&t, flag) < 0)
-                       break;
+                       if (!p_synerred() && token == T_MUL) {
+                               if (c->lc_arg[i].arg_name == 0)
+                                       p_error("%s: Too many arguments.",
+                                               c->lc_name);
+                               else
+                                       i++;
+                               (void) s_gettok();
+                               continue;
+                       } else
+                               break;
                if (t.v_type == V_ERR)
                        flag = 0;
                if (token != T_ASSIGN) {
                        if (c != 0) {
                                ap = &c->lc_arg[i];
                                if (ap->arg_name == 0) {
                if (t.v_type == V_ERR)
                        flag = 0;
                if (token != T_ASSIGN) {
                        if (c != 0) {
                                ap = &c->lc_arg[i];
                                if (ap->arg_name == 0) {
-                                       p_error("Too many arguments.");
-                                       p_varfree(t);
+                                       p_error("%s: Too many arguments.",
+                                               c->lc_name);
+                                       p_valfree(t);
                                        ap = 0;
                                        flag = 0;
                                } else
                                        ap = 0;
                                        flag = 0;
                                } else
@@ -277,8 +285,9 @@ register struct value *v;
                                                        ap->arg_minlen))
                                                break;
                                if (ap->arg_name == 0) {
                                                        ap->arg_minlen))
                                                break;
                                if (ap->arg_name == 0) {
-                                       p_error("%s: Unknown argument.", tmp);
-                                       p_varfree(t);
+                                       p_error("%s: Unknown argument \"%s\".",
+                                               c->lc_name, tmp);
+                                       p_valfree(t);
                                        flag = 0;
                                        ap = 0;
                                }
                                        flag = 0;
                                        ap = 0;
                                }
@@ -286,10 +295,20 @@ register struct value *v;
                        }
                }
                if (ap != 0) {
                        }
                }
                if (ap != 0) {
-                       if (ap->arg_type == ARG_NUM && t.v_type != V_NUM
+                       if (ap->arg_val.v_type != V_ERR) {
+                               p_error("%s: Argument %d (%s) duplicated.",
+                                       c->lc_name, ap - c->lc_arg + 1,
+                                       ap->arg_name);
+                               p_valfree(t);
+                               flag = 0;
+                       } else if (t.v_type == V_ERR) {
+                               /* do nothing */
+                       } else if (ap->arg_type == ARG_NUM && t.v_type != V_NUM
                            || ap->arg_type == ARG_STR && t.v_type != V_STR) {
                            || ap->arg_type == ARG_STR && t.v_type != V_STR) {
-                               p_error("%s: Argument type mismatch.", t.v_str);
-                               p_varfree(t);
+                               p_error("%s: Argument %d (%s) type mismatch.",
+                                       c->lc_name, ap - c->lc_arg + 1,
+                                       ap->arg_name);
+                               p_valfree(t);
                                flag = 0;
                        } else
                                ap->arg_val = t;
                                flag = 0;
                        } else
                                ap->arg_val = t;
@@ -298,16 +317,21 @@ register struct value *v;
                        (void) s_gettok();
        }
 
                        (void) s_gettok();
        }
 
+       if (p_erred())
+               flag = 0;
+       if (token != T_RP && token != T_EOL && token != T_EOF)
+               flag = 0;               /* look ahead a bit */
+       v->v_type = V_ERR;
        if (flag)
                (*c->lc_func)(v);
        if (c != 0)
                for (ap = c->lc_arg; ap->arg_name != 0; ap++)
        if (flag)
                (*c->lc_func)(v);
        if (c != 0)
                for (ap = c->lc_arg; ap->arg_name != 0; ap++)
-                       p_varfree(ap->arg_val);
+                       p_valfree(ap->arg_val);
        return 0;
 abort:
        if (c != 0)
                for (ap = c->lc_arg; ap->arg_name != 0; ap++)
        return 0;
 abort:
        if (c != 0)
                for (ap = c->lc_arg; ap->arg_name != 0; ap++)
-                       p_varfree(ap->arg_val);
+                       p_valfree(ap->arg_val);
        return -1;
 }
 
        return -1;
 }
 
@@ -327,7 +351,7 @@ char flag;
        case V_NUM:
                if (flag && var_set(name, v) == 0) {
                        p_memerror();
        case V_NUM:
                if (flag && var_set(name, v) == 0) {
                        p_memerror();
-                       p_varfree(*v);
+                       p_valfree(*v);
                        return -1;
                }
                break;
                        return -1;
                }
                break;
@@ -390,6 +414,7 @@ p_expr0(v, flag)
 register struct value *v;
 char flag;
 {
 register struct value *v;
 char flag;
 {
+       struct value t;
        char true;
 
        if (p_expr1(v, flag) < 0)
        char true;
 
        if (p_expr1(v, flag) < 0)
@@ -409,14 +434,16 @@ char flag;
                break;
        }
        (void) s_gettok();
                break;
        }
        (void) s_gettok();
-       if (p_expr1(v, flag && true) < 0)
+       v->v_type = V_ERR;
+       if ((flag && true ? p_expr1(v, 1) : p_expr1(&t, 0)) < 0)
                return -1;
        if (token != T_COLON) {
                return -1;
        if (token != T_COLON) {
+               p_valfree(*v);
                p_synerror();
                return -1;
        }
        (void) s_gettok();
                p_synerror();
                return -1;
        }
        (void) s_gettok();
-       return p_expr1(v, flag && !true);
+       return flag && !true ? p_expr1(v, 1) : p_expr1(&t, 0);
 }
 
 /*
 }
 
 /*
@@ -504,6 +531,7 @@ char flag;
 {
        struct value t;
        int op;
 {
        struct value t;
        int op;
+       char *opname;
 
        if (level == 10) {
                if (p_expr11(v, flag) < 0)
 
        if (level == 10) {
                if (p_expr11(v, flag) < 0)
@@ -517,43 +545,70 @@ char flag;
                case 3:
                        if (token != T_OR)
                                return 0;
                case 3:
                        if (token != T_OR)
                                return 0;
+                       opname = "|";
                        break;
                case 4:
                        if (token != T_XOR)
                                return 0;
                        break;
                case 4:
                        if (token != T_XOR)
                                return 0;
+                       opname = "^";
                        break;
                case 5:
                        if (token != T_AND)
                                return 0;
                        break;
                case 5:
                        if (token != T_AND)
                                return 0;
+                       opname = "&";
                        break;
                case 6:
                        break;
                case 6:
-                       if (token != T_EQ && token != T_NE)
+                       if (token == T_EQ)
+                               opname = "==";
+                       else if (token == T_NE)
+                               opname = "!=";
+                       else
                                return 0;
                        break;
                case 7:
                        switch (token) {
                        case T_LT:
                                return 0;
                        break;
                case 7:
                        switch (token) {
                        case T_LT:
+                               opname = "<";
+                               break;
                        case T_LE:
                        case T_LE:
+                               opname = "<=";
+                               break;
                        case T_GT:
                        case T_GT:
+                               opname = ">";
+                               break;
                        case T_GE:
                        case T_GE:
+                               opname = ">=";
                                break;
                        default:
                                return 0;
                        }
                        break;
                case 8:
                                break;
                        default:
                                return 0;
                        }
                        break;
                case 8:
-                       if (token != T_LS && token != T_RS)
+                       if (token == T_LS)
+                               opname = "<<";
+                       else if (token == T_RS)
+                               opname = ">>";
+                       else
                                return 0;
                        break;
                case 9:
                                return 0;
                        break;
                case 9:
-                       if (token != T_PLUS && token != T_MINUS)
+                       if (token == T_PLUS)
+                               opname = "+";
+                       else if (token == T_MINUS)
+                               opname = "-";
+                       else
                                return 0;
                        break;
                case 10:
                        switch (token) {
                        case T_MUL:
                                return 0;
                        break;
                case 10:
                        switch (token) {
                        case T_MUL:
+                               opname = "*";
+                               break;
                        case T_DIV:
                        case T_DIV:
+                               opname = "/";
+                               break;
                        case T_MOD:
                        case T_MOD:
+                               opname = "%";
                                break;
                        default:
                                return 0;
                                break;
                        default:
                                return 0;
@@ -566,26 +621,25 @@ char flag;
                op = token;
                (void) s_gettok();
                if (level == 10) {
                op = token;
                (void) s_gettok();
                if (level == 10) {
-                       if (p_expr11(&t, flag) < 0)
+                       if (p_expr11(&t, flag) < 0) {
+                               p_synerror();
+                               p_valfree(*v);
                                return -1;
                                return -1;
+                       }
                } else {
                } else {
-                       if (p_expr3_10(level + 1, &t, flag) < 0)
+                       if (p_expr3_10(level + 1, &t, flag) < 0) {
+                               p_synerror();
+                               p_valfree(*v);
                                return -1;
                                return -1;
+                       }
                }
                }
-               if (t.v_type == V_ERR) {
-                       flag = 0;
-                       v->v_type = V_ERR;
-               }
-
-               if (!flag)
-                       return 0;
 
 
-               if (t.v_type != v->v_type) {
+               if (t.v_type == V_ERR)
+                       flag = 0;
+               else if (t.v_type != v->v_type) {
                        p_error("Type mismatch.");
                        p_error("Type mismatch.");
-                       v->v_type = V_ERR;
-                       return 0;
-               }
-               switch (op) {
+                       flag = 0;
+               } else switch (op) {
                case T_EQ:
                case T_NE:
                case T_LT:
                case T_EQ:
                case T_NE:
                case T_LT:
@@ -604,13 +658,19 @@ char flag;
                        break;
                default:
                        if (v->v_type == V_STR) {
                        break;
                default:
                        if (v->v_type == V_STR) {
-                               p_error("Numeric value required.");
-                               str_free(v->v_str);
-                               str_free(t.v_str);
-                               v->v_type = V_ERR;
-                               return 0;
+                               p_error("Numeric value required for %s.",
+                                       opname);
+                               flag = 0;
                        }
                }
                        }
                }
+
+               if (!flag) {
+                       p_valfree(*v);
+                       p_valfree(t);
+                       v->v_type = V_ERR;
+                       continue;
+               }
+
                switch (op) {
                case T_OR:
                        v->v_num |= t.v_num;
                switch (op) {
                case T_OR:
                        v->v_num |= t.v_num;
@@ -673,13 +733,23 @@ register struct value *v;
 char flag;
 {
        int op;
 char flag;
 {
        int op;
+       char *opname;
 
        switch (token) {
        case T_DOLLAR:
 
        switch (token) {
        case T_DOLLAR:
+               opname = "$";
+               break;
        case T_PLUS:
        case T_PLUS:
+               opname = "unary +";
+               break;
        case T_MINUS:
        case T_MINUS:
+               opname = "unary -";
+               break;
        case T_NOT:
        case T_NOT:
+               opname = "!";
+               break;
        case T_COMP:
        case T_COMP:
+               opname = "~";
                break;
        default:
                return p_expr12(v, flag);
                break;
        default:
                return p_expr12(v, flag);
@@ -700,7 +770,7 @@ char flag;
                case T_MINUS:
                case T_NOT:
                case T_COMP:
                case T_MINUS:
                case T_NOT:
                case T_COMP:
-                       p_error("Numeric value required.");
+                       p_error("Numeric value required for %s.", opname);
                        str_free(v->v_str);
                        v->v_type = V_ERR;
                        return 0;
                        str_free(v->v_str);
                        v->v_type = V_ERR;
                        return 0;
@@ -744,7 +814,8 @@ char flag;
 
 /*
  * string, number, ( expr )
 
 /*
  * string, number, ( expr )
- * plus function calls.
+ * Plus function calls.
+ * Also we map % into string.
  *
  * Always return v_type == V_ERR when flag == 0.
  */
  *
  * Always return v_type == V_ERR when flag == 0.
  */
@@ -757,6 +828,16 @@ char flag;
        error("expr12: %d.", flag);
 #endif
        switch (token) {
        error("expr12: %d.", flag);
 #endif
        switch (token) {
+       case T_MOD:
+#ifdef DEBUG
+               error("expr12: %.");
+#endif
+               if (flag) {
+                       v->v_type = V_STR;
+                       v->v_str = str_cpy("%");
+               }
+               (void) s_gettok();
+               break;
        case T_NUM:
 #ifdef DEBUG
                error("expr12: NUM %d.", token_num);
        case T_NUM:
 #ifdef DEBUG
                error("expr12: NUM %d.", token_num);
@@ -785,7 +866,7 @@ char flag;
                }
                if (token != T_RP) {
                        p_synerror();
                }
                if (token != T_RP) {
                        p_synerror();
-                       p_varfree(*v);
+                       p_valfree(*v);
                        return -1;
                }
                (void) s_gettok();
                        return -1;
                }
                (void) s_gettok();
@@ -825,7 +906,7 @@ char flag;
                str_free(cmd);
                if (token != T_RP) {
                        p_synerror();
                str_free(cmd);
                if (token != T_RP) {
                        p_synerror();
-                       p_varfree(*v);
+                       p_valfree(*v);
                        return -1;
                }
                (void) s_gettok();
                        return -1;
                }
                (void) s_gettok();