| Commit | Line | Data |
|---|---|---|
| 2c872e05 | 1 | /* @(#)parser2.c 8.1 (Berkeley) 6/6/93 */ |
| abecab39 SW |
2 | /* $NetBSD: parser2.c,v 1.11 2009/04/14 08:50:06 lukem Exp $ */ |
| 3 | ||
| 984263bc MD |
4 | /* |
| 5 | * Copyright (c) 1983, 1993 | |
| 6 | * The Regents of the University of California. All rights reserved. | |
| 7 | * | |
| 8 | * This code is derived from software contributed to Berkeley by | |
| 9 | * Edward Wang at The University of California, Berkeley. | |
| 10 | * | |
| 11 | * Redistribution and use in source and binary forms, with or without | |
| 12 | * modification, are permitted provided that the following conditions | |
| 13 | * are met: | |
| 14 | * 1. Redistributions of source code must retain the above copyright | |
| 15 | * notice, this list of conditions and the following disclaimer. | |
| 16 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 17 | * notice, this list of conditions and the following disclaimer in the | |
| 18 | * documentation and/or other materials provided with the distribution. | |
| abecab39 | 19 | * 3. Neither the name of the University nor the names of its contributors |
| 984263bc MD |
20 | * may be used to endorse or promote products derived from this software |
| 21 | * without specific prior written permission. | |
| 22 | * | |
| 23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
| 24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
| 27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 33 | * SUCH DAMAGE. | |
| 34 | */ | |
| 35 | ||
| abecab39 SW |
36 | #define EXTERN |
| 37 | #include "ww.h" | |
| 38 | #include "defs.h" | |
| 39 | #include "alias.h" | |
| 40 | #undef EXTERN | |
| 984263bc MD |
41 | #include "parser.h" |
| 42 | #include "var.h" | |
| 43 | #include "lcmd.h" | |
| 984263bc MD |
44 | |
| 45 | /* | |
| 46 | * name == 0 means we don't have a function name but | |
| 47 | * want to parse the arguments anyway. flag == 0 in this case. | |
| 48 | */ | |
| abecab39 SW |
49 | int |
| 50 | p_function(const char *name, struct value *v, int flag) | |
| 984263bc MD |
51 | { |
| 52 | struct value t; | |
| abecab39 SW |
53 | struct lcmd_tab *c = 0; |
| 54 | struct alias *a = 0; | |
| 55 | struct lcmd_arg *ap; /* this arg */ | |
| 984263bc | 56 | struct lcmd_arg *lp = 0; /* list arg */ |
| abecab39 | 57 | int i; |
| 984263bc | 58 | struct value av[LCMD_NARG + 1]; |
| abecab39 | 59 | struct value *vp; |
| 984263bc | 60 | |
| abecab39 SW |
61 | if (name != 0) { |
| 62 | if ((c = lcmd_lookup(name))) | |
| 984263bc | 63 | name = c->lc_name; |
| abecab39 | 64 | else if ((a = alias_lookup(name))) |
| 984263bc MD |
65 | name = a->a_name; |
| 66 | else { | |
| 67 | p_error("%s: No such command or alias.", name); | |
| 68 | flag = 0; | |
| 69 | } | |
| abecab39 | 70 | } |
| 984263bc MD |
71 | for (vp = av; vp < &av[LCMD_NARG + 1]; vp++) |
| 72 | vp->v_type = V_ERR; | |
| 73 | ||
| 74 | if (token == T_LP) | |
| 75 | (void) s_gettok(); | |
| 76 | i = 0; | |
| 77 | for (;;) { | |
| 78 | ap = 0; | |
| 79 | vp = 0; | |
| 80 | if (token == T_COMMA) /* null argument */ | |
| 81 | t.v_type = V_ERR; | |
| 82 | else { | |
| 83 | if (p_expr0(&t, flag) < 0) | |
| 84 | break; | |
| 85 | if (t.v_type == V_ERR) | |
| 86 | flag = 0; | |
| 87 | } | |
| 88 | if (token != T_ASSIGN) { | |
| 89 | if (i >= LCMD_NARG || | |
| abecab39 SW |
90 | (c != 0 && (ap = lp) == 0 && |
| 91 | (ap = c->lc_arg + i)->arg_name == 0)) { | |
| 984263bc MD |
92 | p_error("%s: Too many arguments.", name); |
| 93 | flag = 0; | |
| 94 | } else | |
| 95 | vp = &av[i++]; | |
| 96 | } else { | |
| 97 | char *tmp; | |
| 98 | if (p_convstr(&t) < 0) | |
| 99 | goto abort; | |
| 100 | tmp = t.v_type == V_STR ? t.v_str : 0; | |
| 101 | (void) s_gettok(); | |
| 102 | if (p_expr(&t, flag) < 0) { | |
| 103 | if (tmp) | |
| 104 | str_free(tmp); | |
| 105 | p_synerror(); | |
| 106 | goto abort; | |
| 107 | } | |
| 108 | if (t.v_type == V_ERR) | |
| 109 | flag = 0; | |
| 110 | if (tmp) { | |
| 111 | if (c == 0) { | |
| 112 | /* an aliase */ | |
| 113 | p_error("%s: Bad alias syntax.", name); | |
| 114 | flag = 0; | |
| 115 | } else { | |
| 116 | for (ap = c->lc_arg, vp = av; | |
| 117 | ap != 0 && ap->arg_name != 0 && | |
| 118 | (*ap->arg_name == '\0' || | |
| 119 | !str_match(tmp, ap->arg_name, | |
| 120 | ap->arg_minlen)); | |
| 121 | ap++, vp++) | |
| 122 | ; | |
| 123 | if (ap == 0 || ap->arg_name == 0) { | |
| 124 | p_error("%s: Unknown argument \"%s\".", | |
| 125 | name, tmp); | |
| 126 | flag = 0; | |
| 127 | ap = 0; | |
| 128 | vp = 0; | |
| 129 | } | |
| 130 | } | |
| 131 | str_free(tmp); | |
| 132 | } | |
| 133 | } | |
| 134 | if (ap != 0) { | |
| 135 | if (ap->arg_flags & ARG_LIST) { | |
| 136 | i = vp - av + 1; | |
| 137 | lp = ap; | |
| 138 | } | |
| abecab39 | 139 | if (vp && vp->v_type != V_ERR) { |
| 984263bc MD |
140 | if (*ap->arg_name) |
| 141 | p_error("%s: Argument %d (%s) duplicated.", | |
| abecab39 | 142 | name, (int)(vp - av + 1), |
| 984263bc MD |
143 | ap->arg_name); |
| 144 | else | |
| 145 | p_error("%s: Argument %d duplicated.", | |
| abecab39 | 146 | name, (int)(vp - av + 1)); |
| 984263bc MD |
147 | flag = 0; |
| 148 | vp = 0; | |
| 149 | } else if (t.v_type == V_ERR) { | |
| 150 | /* do nothing */ | |
| abecab39 SW |
151 | } else if (((ap->arg_flags&ARG_TYPE) == ARG_NUM && |
| 152 | t.v_type != V_NUM) || | |
| 153 | ((ap->arg_flags&ARG_TYPE) == ARG_STR && | |
| 154 | t.v_type != V_STR)) { | |
| 984263bc MD |
155 | if (*ap->arg_name) |
| 156 | p_error("%s: Argument %d (%s) type mismatch.", | |
| abecab39 | 157 | name, (int)(vp - av + 1), |
| 984263bc MD |
158 | ap->arg_name); |
| 159 | else | |
| 160 | p_error("%s: Argument %d type mismatch.", | |
| abecab39 | 161 | name, (int)(vp - av + 1)); |
| 984263bc MD |
162 | flag = 0; |
| 163 | vp = 0; | |
| 164 | } | |
| 165 | } | |
| 166 | if (vp != 0) | |
| 167 | *vp = t; | |
| 168 | else | |
| 169 | val_free(t); | |
| 170 | if (token == T_COMMA) | |
| 171 | (void) s_gettok(); | |
| 172 | } | |
| 173 | ||
| 174 | if (p_erred()) | |
| 175 | flag = 0; | |
| 176 | if (token == T_RP) | |
| 177 | (void) s_gettok(); | |
| 178 | else if (token != T_EOL && token != T_EOF) | |
| 179 | flag = 0; /* look for legal follow set */ | |
| 180 | v->v_type = V_ERR; | |
| abecab39 | 181 | if (flag) { |
| 984263bc MD |
182 | if (c != 0) |
| 183 | (*c->lc_func)(v, av); | |
| abecab39 | 184 | else { |
| 984263bc MD |
185 | if (a->a_flags & A_INUSE) |
| 186 | p_error("%s: Recursive alias.", a->a_name); | |
| 187 | else { | |
| 188 | a->a_flags |= A_INUSE; | |
| 189 | if (dolongcmd(a->a_buf, av, i) < 0) | |
| 190 | p_memerror(); | |
| 191 | a->a_flags &= ~A_INUSE; | |
| 192 | } | |
| abecab39 SW |
193 | } |
| 194 | } | |
| 984263bc MD |
195 | if (p_abort()) { |
| 196 | val_free(*v); | |
| 197 | v->v_type = V_ERR; | |
| 198 | goto abort; | |
| 199 | } | |
| 200 | for (vp = av; vp < &av[LCMD_NARG]; vp++) | |
| 201 | val_free(*vp); | |
| 202 | return 0; | |
| 203 | abort: | |
| 204 | for (vp = av; vp < &av[LCMD_NARG]; vp++) | |
| 205 | val_free(*vp); | |
| 206 | return -1; | |
| 207 | } | |
| 208 | ||
| abecab39 SW |
209 | int |
| 210 | p_assign(const char *name, struct value *v, int flag) | |
| 984263bc MD |
211 | { |
| 212 | (void) s_gettok(); | |
| 213 | ||
| 214 | if (p_expr(v, flag) < 0) { | |
| 215 | p_synerror(); | |
| 216 | return -1; | |
| 217 | } | |
| 218 | switch (v->v_type) { | |
| 219 | case V_STR: | |
| 220 | case V_NUM: | |
| abecab39 | 221 | if (name && flag && var_set(name, v) == 0) { |
| 984263bc MD |
222 | p_memerror(); |
| 223 | val_free(*v); | |
| 224 | return -1; | |
| 225 | } | |
| 226 | break; | |
| 227 | } | |
| 228 | return 0; | |
| 229 | } |