1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Edward Wang at The University of California, Berkeley. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)parser2.c 8.1 (Berkeley) 06/06/93"; 13 #endif /* not lint */ 14 15 #include "parser.h" 16 #include "var.h" 17 #include "lcmd.h" 18 #include "alias.h" 19 20 /* 21 * name == 0 means we don't have a function name but 22 * want to parse the arguments anyway. flag == 0 in this case. 23 */ 24 p_function(name, v, flag) 25 char *name; 26 register struct value *v; 27 { 28 struct value t; 29 register struct lcmd_tab *c = 0; 30 register struct alias *a = 0; 31 register struct lcmd_arg *ap; /* this arg */ 32 struct lcmd_arg *lp = 0; /* list arg */ 33 register i; 34 struct value av[LCMD_NARG + 1]; 35 register struct value *vp; 36 37 if (name != 0) 38 if (c = lcmd_lookup(name)) 39 name = c->lc_name; 40 else if (a = alias_lookup(name)) 41 name = a->a_name; 42 else { 43 p_error("%s: No such command or alias.", name); 44 flag = 0; 45 } 46 47 for (vp = av; vp < &av[LCMD_NARG + 1]; vp++) 48 vp->v_type = V_ERR; 49 50 if (token == T_LP) 51 (void) s_gettok(); 52 i = 0; 53 for (;;) { 54 ap = 0; 55 vp = 0; 56 if (token == T_COMMA) /* null argument */ 57 t.v_type = V_ERR; 58 else { 59 if (p_expr0(&t, flag) < 0) 60 break; 61 if (t.v_type == V_ERR) 62 flag = 0; 63 } 64 if (token != T_ASSIGN) { 65 if (i >= LCMD_NARG || 66 c != 0 && (ap = lp) == 0 && 67 (ap = c->lc_arg + i)->arg_name == 0) { 68 p_error("%s: Too many arguments.", name); 69 flag = 0; 70 } else 71 vp = &av[i++]; 72 } else { 73 char *tmp; 74 if (p_convstr(&t) < 0) 75 goto abort; 76 tmp = t.v_type == V_STR ? t.v_str : 0; 77 (void) s_gettok(); 78 if (p_expr(&t, flag) < 0) { 79 if (tmp) 80 str_free(tmp); 81 p_synerror(); 82 goto abort; 83 } 84 if (t.v_type == V_ERR) 85 flag = 0; 86 if (tmp) { 87 if (c == 0) { 88 /* an aliase */ 89 p_error("%s: Bad alias syntax.", name); 90 flag = 0; 91 } else { 92 for (ap = c->lc_arg, vp = av; 93 ap != 0 && ap->arg_name != 0 && 94 (*ap->arg_name == '\0' || 95 !str_match(tmp, ap->arg_name, 96 ap->arg_minlen)); 97 ap++, vp++) 98 ; 99 if (ap == 0 || ap->arg_name == 0) { 100 p_error("%s: Unknown argument \"%s\".", 101 name, tmp); 102 flag = 0; 103 ap = 0; 104 vp = 0; 105 } 106 } 107 str_free(tmp); 108 } 109 } 110 if (ap != 0) { 111 if (ap->arg_flags & ARG_LIST) { 112 i = vp - av + 1; 113 lp = ap; 114 } 115 if (vp->v_type != V_ERR) { 116 if (*ap->arg_name) 117 p_error("%s: Argument %d (%s) duplicated.", 118 name, vp - av + 1, 119 ap->arg_name); 120 else 121 p_error("%s: Argument %d duplicated.", 122 name, vp - av + 1); 123 flag = 0; 124 vp = 0; 125 } else if (t.v_type == V_ERR) { 126 /* do nothing */ 127 } else if ((ap->arg_flags&ARG_TYPE) == ARG_NUM && 128 t.v_type != V_NUM || 129 (ap->arg_flags&ARG_TYPE) == ARG_STR && 130 t.v_type != V_STR) { 131 if (*ap->arg_name) 132 p_error("%s: Argument %d (%s) type mismatch.", 133 name, vp - av + 1, 134 ap->arg_name); 135 else 136 p_error("%s: Argument %d type mismatch.", 137 name, vp - av + 1); 138 flag = 0; 139 vp = 0; 140 } 141 } 142 if (vp != 0) 143 *vp = t; 144 else 145 val_free(t); 146 if (token == T_COMMA) 147 (void) s_gettok(); 148 } 149 150 if (p_erred()) 151 flag = 0; 152 if (token == T_RP) 153 (void) s_gettok(); 154 else if (token != T_EOL && token != T_EOF) 155 flag = 0; /* look for legal follow set */ 156 v->v_type = V_ERR; 157 if (flag) 158 if (c != 0) 159 (*c->lc_func)(v, av); 160 else 161 if (a->a_flags & A_INUSE) 162 p_error("%s: Recursive alias.", a->a_name); 163 else { 164 a->a_flags |= A_INUSE; 165 if (dolongcmd(a->a_buf, av, i) < 0) 166 p_memerror(); 167 a->a_flags &= ~A_INUSE; 168 } 169 if (p_abort()) { 170 val_free(*v); 171 v->v_type = V_ERR; 172 goto abort; 173 } 174 for (vp = av; vp < &av[LCMD_NARG]; vp++) 175 val_free(*vp); 176 return 0; 177 abort: 178 for (vp = av; vp < &av[LCMD_NARG]; vp++) 179 val_free(*vp); 180 return -1; 181 } 182 183 p_assign(name, v, flag) 184 char *name; 185 struct value *v; 186 char flag; 187 { 188 (void) s_gettok(); 189 190 if (p_expr(v, flag) < 0) { 191 p_synerror(); 192 return -1; 193 } 194 switch (v->v_type) { 195 case V_STR: 196 case V_NUM: 197 if (flag && var_set(name, v) == 0) { 198 p_memerror(); 199 val_free(*v); 200 return -1; 201 } 202 break; 203 } 204 return 0; 205 } 206