xref: /netbsd/external/bsd/pcc/dist/pcc/cc/cpp/cpy.y (revision 6550d01e)
1 /*	Id: cpy.y,v 1.18 2010/02/25 15:49:00 ragge Exp 	*/
2 /*	$NetBSD: cpy.y,v 1.1.1.3 2010/06/03 18:57:35 plunky Exp $	*/
3 
4 /*
5  * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /*
32  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
33  *
34  * Redistribution and use in source and binary forms, with or without
35  * modification, are permitted provided that the following conditions
36  * are met:
37  *
38  * Redistributions of source code and documentation must retain the above
39  * copyright notice, this list of conditions and the following disclaimer.
40  * Redistributions in binary form must reproduce the above copyright
41  * notice, this list of conditions and the following disclaimer in the
42  * documentation and/or other materials provided with the distribution.
43  * All advertising materials mentioning features or use of this software
44  * must display the following acknowledgement:
45  * 	This product includes software developed or owned by Caldera
46  *	International, Inc.
47  * Neither the name of Caldera International, Inc. nor the names of other
48  * contributors may be used to endorse or promote products derived from
49  * this software without specific prior written permission.
50  *
51  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
52  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
53  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
54  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
55  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
56  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
60  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
61  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
62  * POSSIBILITY OF SUCH DAMAGE.
63  */
64 
65 %{
66 
67 #include "cpp.h"
68 
69 void yyerror(const char *);
70 int yylex(void);
71 int setd(int l, int r);
72 
73 #define	EVALUNARY(tok, l, r) l.nd_val = tok r.nd_val; l.op = r.op
74 #define	EVALBIN(tok, d, l, r)	\
75 	d.op = setd(l.op, r.op); d.nd_val = l.nd_val tok r.nd_val
76 #define	EVALUBIN(tok, d, l, r, t)				\
77 	d.op = setd(l.op, r.op);				\
78 	if (d.op == NUMBER) d.nd_val = l.nd_val tok r.nd_val;	\
79 	else d.nd_uval = l.nd_uval tok r.nd_uval;		\
80 	if (t && d.op) d.op = NUMBER
81 #define	XEVALUBIN(tok, d, l, r)					\
82 	if (r.nd_val) { EVALUBIN(tok, d, l, r, 0); } else d.op = 0
83 %}
84 
85 %term stop
86 %term EQ NE LE GE LS RS
87 %term ANDAND OROR IDENT NUMBER UNUMBER DEFINED
88 /*
89  * The following terminals are not used in the yacc code.
90  */
91 %term STRING WSPACE CMNT
92 
93 %left ','
94 %right '?' ':'
95 %left OROR
96 %left ANDAND
97 %left '|' '^'
98 %left '&'
99 %binary EQ NE
100 %binary '<' '>' LE GE
101 %left LS RS
102 %left '+' '-'
103 %left '*' '/' '%'
104 %right '!' '~' UMINUS
105 %left '('
106 
107 %union {
108 	struct nd node;
109 }
110 
111 %type <node>	term e NUMBER UNUMBER
112 
113 %%
114 S:	e '\n'	{
115 		if ($1.op == 0)
116 			error("division by zero");
117 		return $1.nd_val;
118 	}
119 
120 e:	  e '*' e
121 		{ EVALUBIN(*, $$, $1, $3, 0); }
122 	| e '/' e
123 		{ XEVALUBIN(/, $$, $1, $3); }
124 	| e '%' e
125 		{ XEVALUBIN(%, $$, $1, $3); }
126 	| e '+' e
127 		{ EVALBIN(+, $$, $1, $3); }
128 	| e '-' e
129 		{ EVALBIN(-, $$, $1, $3); }
130 	| e LS e
131 		{ EVALBIN(<<, $$, $1, $3); }
132 	| e RS e
133 		{ EVALUBIN(>>, $$, $1, $3, 0); }
134 	| e '<' e
135 		{ EVALUBIN(<, $$, $1, $3, 1); }
136 	| e '>' e
137 		{ EVALUBIN(>, $$, $1, $3, 1); }
138 	| e LE e
139 		{ EVALUBIN(<=, $$, $1, $3, 1); }
140 	| e GE e
141 		{ EVALUBIN(>=, $$, $1, $3, 1); }
142 	| e EQ e
143 		{ EVALUBIN(==, $$, $1, $3, 1); }
144 	| e NE e
145 		{ EVALUBIN(!=, $$, $1, $3, 1); }
146 	| e '&' e
147 		{ EVALBIN(&, $$, $1, $3); }
148 	| e '^' e
149 		{ EVALBIN(^, $$, $1, $3); }
150 	| e '|' e
151 		{ EVALBIN(|, $$, $1, $3); }
152 	| e ANDAND e {
153 		$$ = $1;
154 		if ($1.nd_val) {
155 			$$.op = setd($1.op, $3.op);
156 			$$.nd_val = ($3.nd_val != 0);
157 		}
158 		if ($$.op == UNUMBER) $$.op = NUMBER;
159 	}
160 	| e OROR e {
161 		if ($1.nd_val != 0) {
162 			$$.nd_val = ($1.nd_val != 0);
163 			$$.op = $1.op;
164 		} else {
165 			$$.nd_val = ($3.nd_val != 0);
166 			$$.op = setd($1.op, $3.op);
167 		}
168 		if ($$.op == UNUMBER) $$.op = NUMBER;
169 	}
170 	| e '?' e ':' e {
171 		if ($1.op == 0)
172 			$$ = $1;
173 		else if ($1.nd_val)
174 			$$ = $3;
175 		else
176 			$$ = $5;
177 	}
178 	| e ',' e {
179 		$$.op = setd($1.op, $3.op);
180 		$$.nd_val = $3.nd_val;
181 		if ($$.op) $$.op =  $3.op;
182 	}
183 	| term
184 		{$$ = $1;}
185 term:
186 	  '-' term %prec UMINUS
187 		{ EVALUNARY(-, $$, $2); }
188 	| '+' term %prec UMINUS
189 		{$$ = $2;}
190 	| '!' term
191 		{ $$.nd_val = ! $2.nd_val; $$.op = $2.op ? NUMBER : 0; }
192 	| '~' term
193 		{ EVALUNARY(~, $$, $2); }
194 	| '(' e ')'
195 		{$$ = $2;}
196 	| DEFINED '(' NUMBER ')'
197 		{$$= $3;}
198 	| DEFINED NUMBER
199 		{$$ = $2;}
200 	| NUMBER
201 		{$$ = $1;}
202 %%
203 
204 void
205 yyerror(const char *err)
206 {
207 	error(err);
208 }
209 
210 /*
211  * Set return type of an expression.
212  */
213 int
214 setd(int l, int r)
215 {
216 	if (!l || !r)
217 		return 0; /* div by zero involved */
218 	if (l == UNUMBER || r == UNUMBER)
219 		return UNUMBER;
220 	return NUMBER;
221 }
222 
223