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