xref: /dragonfly/usr.bin/window/parser5.c (revision 82730a9c)
1 /*	@(#)parser5.c	8.1 (Berkeley) 6/6/93	*/
2 /*	$NetBSD: parser5.c,v 1.7 2009/04/14 08:50:06 lukem Exp $	*/
3 
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.
19  * 3. Neither the name of the University nor the names of its contributors
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 
36 #include "defs.h"
37 #include "parser.h"
38 #include "var.h"
39 
40 /*
41  * unary $ $? + - ! ~
42  */
43 int
44 p_expr11(struct value *v, char flag)
45 {
46 	int op;
47 	const char *opname;
48 
49 	switch (token) {
50 	case T_DOLLAR:
51 		opname = "$";
52 		break;
53 	case T_DQ:
54 		opname = "$?";
55 		break;
56 	case T_PLUS:
57 		opname = "unary +";
58 		break;
59 	case T_MINUS:
60 		opname = "unary -";
61 		break;
62 	case T_NOT:
63 		opname = "!";
64 		break;
65 	case T_COMP:
66 		opname = "~";
67 		break;
68 	default:
69 		return p_expr12(v, flag);
70 	}
71 	op = token;
72 	(void) s_gettok();
73 	if (p_expr11(v, flag) < 0)
74 		return -1;
75 	switch (v->v_type) {
76 	case V_NUM:
77 		break;
78 	case V_STR:
79 		switch (op) {
80 		case T_MINUS:
81 		case T_NOT:
82 		case T_COMP:
83 			p_error("%s: Numeric operand required.", opname);
84 			str_free(v->v_str);
85 			v->v_type = V_ERR;
86 			return 0;
87 		}
88 		break;
89 	case V_ERR:
90 		return 0;
91 	}
92 	switch (op) {
93 	case T_DOLLAR:
94 	case T_DQ:
95 		if (v->v_type == V_NUM) {
96 			int tmp = cx.x_type == X_BUF && cx.x_arg != 0 &&
97 				v->v_num > 0 && v->v_num <= cx.x_narg;
98 			if (op == T_DQ)
99 				v->v_num = tmp;
100 			else if (tmp)
101 				*v = cx.x_arg[v->v_num - 1];
102 			else {
103 				p_error("%d: No such argument.", v->v_num);
104 				v->v_type = V_ERR;
105 			}
106 		} else {
107 			char *name = v->v_str;
108 			struct var *r = var_lookup(name);
109 			if (op == T_DQ) {
110 				v->v_type = V_NUM;
111 				v->v_num = r != NULL;
112 			} else if (r != NULL)
113 				*v = r->r_val;
114 			else {
115 				p_error("%s: Undefined variable.", name);
116 				v->v_type = V_ERR;
117 			}
118 			str_free(name);
119 		}
120 		if (v->v_type == V_STR && (v->v_str = str_cpy(v->v_str)) == 0) {
121 			p_memerror();
122 			return -1;
123 		}
124 		break;
125 	case T_MINUS:
126 		v->v_num = - v->v_num;
127 		break;
128 	case T_NOT:
129 		v->v_num = ! v->v_num;
130 		break;
131 	case T_COMP:
132 		v->v_num = ~ v->v_num;
133 		break;
134 	}
135 	return 0;
136 }
137 
138 /*
139  * string, number, ( expr )
140  * Plus function calls.
141  *
142  * Always return v_type == V_ERR when flag == 0.
143  */
144 int
145 p_expr12(struct value *v, char flag)
146 {
147 	v->v_type = V_ERR;
148 	switch (token) {
149 	case T_NUM:
150 		if (flag) {
151 			v->v_type = V_NUM;
152 			v->v_num = token_num;
153 		}
154 		(void) s_gettok();
155 		break;
156 	case T_STR:
157 		if (flag) {
158 			v->v_type = V_STR;
159 			v->v_str = token_str;
160 		} else
161 			str_free(token_str);
162 		(void) s_gettok();
163 		break;
164 	case T_LP:
165 		(void) s_gettok();
166 		if (p_expr(v, flag) < 0) {
167 			p_synerror();
168 			return -1;
169 		}
170 		if (token != T_RP) {
171 			p_synerror();
172 			val_free(*v);
173 			return -1;
174 		}
175 		(void) s_gettok();
176 		break;
177 	default:
178 		return -1;
179 	}
180 	while (token == T_LP) {
181 		char *cmd;
182 
183 		if (p_convstr(v) < 0)
184 			return -1;
185 		cmd = v->v_type == V_STR ? v->v_str : 0;
186 		if (p_function(cmd, v, flag) < 0) {
187 			if (cmd)
188 				str_free(cmd);
189 			return -1;
190 		}
191 		if (cmd)
192 			str_free(cmd);
193 	}
194 	return 0;
195 }
196