xref: /original-bsd/usr.bin/window/parser5.c (revision 2301fdfb)
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 the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)parser5.c	3.11 (Berkeley) 06/29/88";
20 #endif /* not lint */
21 
22 #include "parser.h"
23 #include "var.h"
24 
25 /*
26  * unary $ $? + - ! ~
27  */
28 p_expr11(v, flag)
29 register struct value *v;
30 char flag;
31 {
32 	int op;
33 	char *opname;
34 
35 	switch (token) {
36 	case T_DOLLAR:
37 		opname = "$";
38 		break;
39 	case T_DQ:
40 		opname = "$?";
41 		break;
42 	case T_PLUS:
43 		opname = "unary +";
44 		break;
45 	case T_MINUS:
46 		opname = "unary -";
47 		break;
48 	case T_NOT:
49 		opname = "!";
50 		break;
51 	case T_COMP:
52 		opname = "~";
53 		break;
54 	default:
55 		return p_expr12(v, flag);
56 	}
57 	op = token;
58 	(void) s_gettok();
59 	if (p_expr11(v, flag) < 0)
60 		return -1;
61 	switch (v->v_type) {
62 	case V_NUM:
63 		break;
64 	case V_STR:
65 		switch (op) {
66 		case T_MINUS:
67 		case T_NOT:
68 		case T_COMP:
69 			p_error("%s: Numeric operand required.", opname);
70 			str_free(v->v_str);
71 			v->v_type = V_ERR;
72 			return 0;
73 		}
74 		break;
75 	case V_ERR:
76 		return 0;
77 	}
78 	switch (op) {
79 	case T_DOLLAR:
80 	case T_DQ:
81 		if (v->v_type == V_NUM) {
82 			int tmp = cx.x_type == X_BUF && cx.x_arg != 0 &&
83 				v->v_num > 0 && v->v_num <= cx.x_narg;
84 			if (op == T_DQ)
85 				v->v_num = tmp;
86 			else if (tmp)
87 				*v = cx.x_arg[v->v_num - 1];
88 			else {
89 				p_error("%d: No such argument.", v->v_num);
90 				v->v_type = V_ERR;
91 			}
92 		} else {
93 			char *name = v->v_str;
94 			struct var *r = var_lookup(name);
95 			if (op == T_DQ) {
96 				v->v_type = V_NUM;
97 				v->v_num = r != 0;
98 			} else if (r != 0)
99 				*v = r->r_val;
100 			else {
101 				p_error("%s: Undefined variable.", name);
102 				v->v_type = V_ERR;
103 			}
104 			str_free(name);
105 		}
106 		if (v->v_type == V_STR && (v->v_str = str_cpy(v->v_str)) == 0) {
107 			p_memerror();
108 			return -1;
109 		}
110 		break;
111 	case T_MINUS:
112 		v->v_num = - v->v_num;
113 		break;
114 	case T_NOT:
115 		v->v_num = ! v->v_num;
116 		break;
117 	case T_COMP:
118 		v->v_num = ~ v->v_num;
119 		break;
120 	}
121 	return 0;
122 }
123 
124 /*
125  * string, number, ( expr )
126  * Plus function calls.
127  *
128  * Always return v_type == V_ERR when flag == 0.
129  */
130 p_expr12(v, flag)
131 register struct value *v;
132 char flag;
133 {
134 	v->v_type = V_ERR;
135 	switch (token) {
136 	case T_NUM:
137 		if (flag) {
138 			v->v_type = V_NUM;
139 			v->v_num = token_num;
140 		}
141 		(void) s_gettok();
142 		break;
143 	case T_STR:
144 		if (flag) {
145 			v->v_type = V_STR;
146 			v->v_str = token_str;
147 		} else
148 			str_free(token_str);
149 		(void) s_gettok();
150 		break;
151 	case T_LP:
152 		(void) s_gettok();
153 		if (p_expr(v, flag) < 0) {
154 			p_synerror();
155 			return -1;
156 		}
157 		if (token != T_RP) {
158 			p_synerror();
159 			val_free(*v);
160 			return -1;
161 		}
162 		(void) s_gettok();
163 		break;
164 	default:
165 		return -1;
166 	}
167 	while (token == T_LP) {
168 		char *cmd;
169 
170 		if (p_convstr(v) < 0)
171 			return -1;
172 		cmd = v->v_type == V_STR ? v->v_str : 0;
173 		if (p_function(cmd, v, flag) < 0) {
174 			if (cmd)
175 				str_free(cmd);
176 			return -1;
177 		}
178 		if (cmd)
179 			str_free(cmd);
180 	}
181 	return 0;
182 }
183