test: Sync with FreeBSD.
[dragonfly.git] / usr.bin / window / parser5.c
blobcb8103e2451cc72060319441b5fe8ea8bc36a8eb
1 /* @(#)parser5.c 8.1 (Berkeley) 6/6/93 */
2 /* $NetBSD: parser5.c,v 1.7 2009/04/14 08:50:06 lukem Exp $ */
4 /*
5 * Copyright (c) 1983, 1993
6 * The Regents of the University of California. All rights reserved.
8 * This code is derived from software contributed to Berkeley by
9 * Edward Wang at The University of California, Berkeley.
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.
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.
36 #include "defs.h"
37 #include "parser.h"
38 #include "var.h"
41 * unary $ $? + - ! ~
43 int
44 p_expr11(struct value *v, char flag)
46 int op;
47 const char *opname;
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);
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;
88 break;
89 case V_ERR:
90 return 0;
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;
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;
118 str_free(name);
120 if (v->v_type == V_STR && (v->v_str = str_cpy(v->v_str)) == 0) {
121 p_memerror();
122 return -1;
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;
135 return 0;
139 * string, number, ( expr )
140 * Plus function calls.
142 * Always return v_type == V_ERR when flag == 0.
145 p_expr12(struct value *v, char flag)
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;
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;
170 if (token != T_RP) {
171 p_synerror();
172 val_free(*v);
173 return -1;
175 (void) s_gettok();
176 break;
177 default:
178 return -1;
180 while (token == T_LP) {
181 char *cmd;
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;
191 if (cmd)
192 str_free(cmd);
194 return 0;