xref: /original-bsd/usr.bin/window/parser2.c (revision 100ae74e)
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