1c2717aaeSedward /*
2*b72553aeSbostic * Copyright (c) 1983, 1993
3*b72553aeSbostic * The Regents of the University of California. All rights reserved.
4bac0d407Sbostic *
58e751acfSbostic * This code is derived from software contributed to Berkeley by
68e751acfSbostic * Edward Wang at The University of California, Berkeley.
78e751acfSbostic *
8122a1d9eSbostic * %sccs.include.redist.c%
9c2717aaeSedward */
10c2717aaeSedward
11bac0d407Sbostic #ifndef lint
12*b72553aeSbostic static char sccsid[] = "@(#)parser2.c 8.1 (Berkeley) 06/06/93";
13bac0d407Sbostic #endif /* not lint */
14bac0d407Sbostic
15fff12678Sedward #include "parser.h"
1610d0ed1cSedward #include "var.h"
1710d0ed1cSedward #include "lcmd.h"
18b163fd54Sedward #include "alias.h"
19fff12678Sedward
20fff12678Sedward /*
21fff12678Sedward * name == 0 means we don't have a function name but
22fff12678Sedward * want to parse the arguments anyway. flag == 0 in this case.
23fff12678Sedward */
p_function(name,v,flag)24fff12678Sedward p_function(name, v, flag)
25fff12678Sedward char *name;
26fff12678Sedward register struct value *v;
27fff12678Sedward {
28fff12678Sedward struct value t;
29b163fd54Sedward register struct lcmd_tab *c = 0;
30b163fd54Sedward register struct alias *a = 0;
31adcadf3cSedward register struct lcmd_arg *ap; /* this arg */
32adcadf3cSedward struct lcmd_arg *lp = 0; /* list arg */
33fff12678Sedward register i;
349faa66aeSedward struct value av[LCMD_NARG + 1];
35c42e298aSedward register struct value *vp;
36fff12678Sedward
37b163fd54Sedward if (name != 0)
38b163fd54Sedward if (c = lcmd_lookup(name))
39b163fd54Sedward name = c->lc_name;
40b163fd54Sedward else if (a = alias_lookup(name))
41b163fd54Sedward name = a->a_name;
42b163fd54Sedward else {
43b163fd54Sedward p_error("%s: No such command or alias.", name);
44fff12678Sedward flag = 0;
45fff12678Sedward }
46fff12678Sedward
479faa66aeSedward for (vp = av; vp < &av[LCMD_NARG + 1]; vp++)
48c42e298aSedward vp->v_type = V_ERR;
49fff12678Sedward
5092cbc4a8Sedward if (token == T_LP)
5192cbc4a8Sedward (void) s_gettok();
5292cbc4a8Sedward i = 0;
5392cbc4a8Sedward for (;;) {
54adcadf3cSedward ap = 0;
55adcadf3cSedward vp = 0;
5692cbc4a8Sedward if (token == T_COMMA) /* null argument */
5792cbc4a8Sedward t.v_type = V_ERR;
5892cbc4a8Sedward else {
5992cbc4a8Sedward if (p_expr0(&t, flag) < 0)
6092cbc4a8Sedward break;
6192cbc4a8Sedward if (t.v_type == V_ERR)
6292cbc4a8Sedward flag = 0;
6392cbc4a8Sedward }
64fff12678Sedward if (token != T_ASSIGN) {
65adcadf3cSedward if (i >= LCMD_NARG ||
66adcadf3cSedward c != 0 && (ap = lp) == 0 &&
67adcadf3cSedward (ap = c->lc_arg + i)->arg_name == 0) {
68b163fd54Sedward p_error("%s: Too many arguments.", name);
69fff12678Sedward flag = 0;
70fff12678Sedward } else
719faa66aeSedward vp = &av[i++];
72fff12678Sedward } else {
73fff12678Sedward char *tmp;
749faa66aeSedward if (p_convstr(&t) < 0)
75fff12678Sedward goto abort;
76b163fd54Sedward tmp = t.v_type == V_STR ? t.v_str : 0;
77fff12678Sedward (void) s_gettok();
78fff12678Sedward if (p_expr(&t, flag) < 0) {
79fff12678Sedward if (tmp)
80fff12678Sedward str_free(tmp);
81fff12678Sedward p_synerror();
82fff12678Sedward goto abort;
83fff12678Sedward }
84fff12678Sedward if (t.v_type == V_ERR)
85fff12678Sedward flag = 0;
86fff12678Sedward if (tmp) {
87b163fd54Sedward if (c == 0) {
88b163fd54Sedward /* an aliase */
89b163fd54Sedward p_error("%s: Bad alias syntax.", name);
90b163fd54Sedward flag = 0;
91b163fd54Sedward } else {
92c42e298aSedward for (ap = c->lc_arg, vp = av;
93b163fd54Sedward ap != 0 && ap->arg_name != 0 &&
94adcadf3cSedward (*ap->arg_name == '\0' ||
95b163fd54Sedward !str_match(tmp, ap->arg_name,
96adcadf3cSedward ap->arg_minlen));
97b163fd54Sedward ap++, vp++)
98b163fd54Sedward ;
999faa66aeSedward if (ap == 0 || ap->arg_name == 0) {
100fff12678Sedward p_error("%s: Unknown argument \"%s\".",
101b163fd54Sedward name, tmp);
102fff12678Sedward flag = 0;
103fff12678Sedward ap = 0;
1049faa66aeSedward vp = 0;
105fff12678Sedward }
106b163fd54Sedward }
107fff12678Sedward str_free(tmp);
108fff12678Sedward }
109fff12678Sedward }
110fff12678Sedward if (ap != 0) {
111adcadf3cSedward if (ap->arg_flags & ARG_LIST) {
112adcadf3cSedward i = vp - av + 1;
113adcadf3cSedward lp = ap;
114adcadf3cSedward }
115c42e298aSedward if (vp->v_type != V_ERR) {
116adcadf3cSedward if (*ap->arg_name)
117fff12678Sedward p_error("%s: Argument %d (%s) duplicated.",
118adcadf3cSedward name, vp - av + 1,
119fff12678Sedward ap->arg_name);
120adcadf3cSedward else
121adcadf3cSedward p_error("%s: Argument %d duplicated.",
122adcadf3cSedward name, vp - av + 1);
123fff12678Sedward flag = 0;
1249faa66aeSedward vp = 0;
125fff12678Sedward } else if (t.v_type == V_ERR) {
126fff12678Sedward /* do nothing */
127adcadf3cSedward } else if ((ap->arg_flags&ARG_TYPE) == ARG_NUM &&
128adcadf3cSedward t.v_type != V_NUM ||
129adcadf3cSedward (ap->arg_flags&ARG_TYPE) == ARG_STR &&
130adcadf3cSedward t.v_type != V_STR) {
131adcadf3cSedward if (*ap->arg_name)
132fff12678Sedward p_error("%s: Argument %d (%s) type mismatch.",
133adcadf3cSedward name, vp - av + 1,
134fff12678Sedward ap->arg_name);
135adcadf3cSedward else
136adcadf3cSedward p_error("%s: Argument %d type mismatch.",
137adcadf3cSedward name, vp - av + 1);
138fff12678Sedward flag = 0;
1399faa66aeSedward vp = 0;
140fff12678Sedward }
1419faa66aeSedward }
1429faa66aeSedward if (vp != 0)
1439faa66aeSedward *vp = t;
1449faa66aeSedward else
1459faa66aeSedward val_free(t);
146fff12678Sedward if (token == T_COMMA)
147fff12678Sedward (void) s_gettok();
148fff12678Sedward }
149fff12678Sedward
150fff12678Sedward if (p_erred())
151fff12678Sedward flag = 0;
15292cbc4a8Sedward if (token == T_RP)
15392cbc4a8Sedward (void) s_gettok();
15492cbc4a8Sedward else if (token != T_EOL && token != T_EOF)
1559faa66aeSedward flag = 0; /* look for legal follow set */
156fff12678Sedward v->v_type = V_ERR;
157fff12678Sedward if (flag)
158fff12678Sedward if (c != 0)
159b163fd54Sedward (*c->lc_func)(v, av);
160b163fd54Sedward else
161801312e7Sedward if (a->a_flags & A_INUSE)
162801312e7Sedward p_error("%s: Recursive alias.", a->a_name);
163801312e7Sedward else {
164801312e7Sedward a->a_flags |= A_INUSE;
165b163fd54Sedward if (dolongcmd(a->a_buf, av, i) < 0)
166b163fd54Sedward p_memerror();
167801312e7Sedward a->a_flags &= ~A_INUSE;
168801312e7Sedward }
169b163fd54Sedward if (p_abort()) {
170b163fd54Sedward val_free(*v);
171b163fd54Sedward v->v_type = V_ERR;
172b163fd54Sedward goto abort;
173b163fd54Sedward }
174c42e298aSedward for (vp = av; vp < &av[LCMD_NARG]; vp++)
175c42e298aSedward val_free(*vp);
176fff12678Sedward return 0;
177fff12678Sedward abort:
178c42e298aSedward for (vp = av; vp < &av[LCMD_NARG]; vp++)
179c42e298aSedward val_free(*vp);
180fff12678Sedward return -1;
181fff12678Sedward }
182fff12678Sedward
p_assign(name,v,flag)183fff12678Sedward p_assign(name, v, flag)
184fff12678Sedward char *name;
185fff12678Sedward struct value *v;
186fff12678Sedward char flag;
187fff12678Sedward {
188fff12678Sedward (void) s_gettok();
189fff12678Sedward
190fff12678Sedward if (p_expr(v, flag) < 0) {
191fff12678Sedward p_synerror();
192fff12678Sedward return -1;
193fff12678Sedward }
194fff12678Sedward switch (v->v_type) {
195fff12678Sedward case V_STR:
196fff12678Sedward case V_NUM:
197fff12678Sedward if (flag && var_set(name, v) == 0) {
198fff12678Sedward p_memerror();
199fff12678Sedward val_free(*v);
200fff12678Sedward return -1;
201fff12678Sedward }
202fff12678Sedward break;
203fff12678Sedward }
204fff12678Sedward return 0;
205fff12678Sedward }
206