xref: /original-bsd/usr.bin/window/parser5.c (revision fd1dcdc9)
1 #ifndef lint
2 static char sccsid[] = "@(#)parser5.c	3.6 05/23/84";
3 #endif
4 
5 #include "parser.h"
6 #include "var.h"
7 
8 /*
9  * unary $ + - ! ~
10  */
11 p_expr11(v, flag)
12 register struct value *v;
13 char flag;
14 {
15 	int op;
16 	char *opname;
17 
18 	switch (token) {
19 	case T_DOLLAR:
20 		opname = "$";
21 		break;
22 	case T_PLUS:
23 		opname = "unary +";
24 		break;
25 	case T_MINUS:
26 		opname = "unary -";
27 		break;
28 	case T_NOT:
29 		opname = "!";
30 		break;
31 	case T_COMP:
32 		opname = "~";
33 		break;
34 	default:
35 		return p_expr12(v, flag);
36 	}
37 	op = token;
38 	(void) s_gettok();
39 	if (p_expr11(v, flag) < 0)
40 		return -1;
41 	switch (v->v_type) {
42 	case V_NUM:
43 		break;
44 	case V_STR:
45 		switch (op) {
46 		case T_MINUS:
47 		case T_NOT:
48 		case T_COMP:
49 			p_error("Numeric value required for %s.", opname);
50 			str_free(v->v_str);
51 			v->v_type = V_ERR;
52 			return 0;
53 		}
54 		break;
55 	case V_ERR:
56 		return 0;
57 	}
58 	switch (op) {
59 	case T_DOLLAR: {
60 		struct var *r;
61 		if (v->v_type == V_NUM) {
62 			v->v_num--;
63 			if (cx.x_type != X_BUF || cx.x_arg == 0 ||
64 			    v->v_num < 0 || v->v_num >= cx.x_narg) {
65 				p_error("%d: No such argument.", v->v_num);
66 				v->v_type = V_ERR;
67 				return 0;
68 			}
69 			if (flag)
70 				*v = cx.x_arg[v->v_num];
71 		} else {
72 			if ((r = var_lookup(v->v_str)) == 0) {
73 				p_error("%s: Undefined variable.", v->v_str);
74 				str_free(v->v_str);
75 				v->v_type = V_ERR;
76 				return 0;
77 			}
78 			str_free(v->v_str);
79 			if (flag)
80 				*v = r->r_val;
81 		}
82 		if (v->v_type == V_STR
83 		    && (v->v_str = str_cpy(v->v_str)) == 0) {
84 			p_memerror();
85 			return -1;
86 		}
87 		break;
88 		}
89 	case T_MINUS:
90 		v->v_num = - v->v_num;
91 		break;
92 	case T_NOT:
93 		v->v_num = ! v->v_num;
94 		break;
95 	case T_COMP:
96 		v->v_num = ~ v->v_num;
97 		break;
98 	}
99 	return 0;
100 }
101 
102 /*
103  * string, number, ( expr )
104  * Plus function calls.
105  * Also we map % into string.
106  *
107  * Always return v_type == V_ERR when flag == 0.
108  */
109 p_expr12(v, flag)
110 register struct value *v;
111 char flag;
112 {
113 	v->v_type = V_ERR;
114 	switch (token) {
115 	case T_MOD:
116 		if (flag) {
117 			v->v_type = V_STR;
118 			v->v_str = str_cpy("%");
119 		}
120 		(void) s_gettok();
121 		break;
122 	case T_NUM:
123 		if (flag) {
124 			v->v_type = V_NUM;
125 			v->v_num = token_num;
126 		}
127 		(void) s_gettok();
128 		break;
129 	case T_STR:
130 		if (flag) {
131 			v->v_type = V_STR;
132 			v->v_str = token_str;
133 		} else
134 			str_free(token_str);
135 		(void) s_gettok();
136 		break;
137 	case T_LP:
138 		(void) s_gettok();
139 		if (p_expr(v, flag) < 0) {
140 			p_synerror();
141 			return -1;
142 		}
143 		if (token != T_RP) {
144 			p_synerror();
145 			val_free(*v);
146 			return -1;
147 		}
148 		(void) s_gettok();
149 		break;
150 	default:
151 		return -1;
152 	}
153 	while (token == T_LP) {
154 		char *cmd;
155 
156 		(void) s_gettok();
157 		if (p_convstr(v) < 0)
158 			return -1;
159 		cmd = v->v_type == V_STR ? v->v_str : 0;
160 		if (p_function(cmd, v, flag) < 0) {
161 			if (cmd)
162 				str_free(cmd);
163 			return -1;
164 		}
165 		if (cmd)
166 			str_free(cmd);
167 		if (token != T_RP) {
168 			p_synerror();
169 			val_free(*v);
170 			return -1;
171 		}
172 		(void) s_gettok();
173 	}
174 	return 0;
175 }
176