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