xref: /OK3568_Linux_fs/kernel/scripts/dtc/dtc-parser.y (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun %locations
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun %{
8*4882a593Smuzhiyun #include <stdio.h>
9*4882a593Smuzhiyun #include <inttypes.h>
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include "dtc.h"
12*4882a593Smuzhiyun #include "srcpos.h"
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun extern int yylex(void);
15*4882a593Smuzhiyun extern void yyerror(char const *s);
16*4882a593Smuzhiyun #define ERROR(loc, ...) \
17*4882a593Smuzhiyun 	do { \
18*4882a593Smuzhiyun 		srcpos_error((loc), "Error", __VA_ARGS__); \
19*4882a593Smuzhiyun 		treesource_error = true; \
20*4882a593Smuzhiyun 	} while (0)
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define YYERROR_CALL(msg) yyerror(msg)
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun extern struct dt_info *parser_output;
25*4882a593Smuzhiyun extern bool treesource_error;
26*4882a593Smuzhiyun %}
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun %union {
29*4882a593Smuzhiyun 	char *propnodename;
30*4882a593Smuzhiyun 	char *labelref;
31*4882a593Smuzhiyun 	uint8_t byte;
32*4882a593Smuzhiyun 	struct data data;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	struct {
35*4882a593Smuzhiyun 		struct data	data;
36*4882a593Smuzhiyun 		int		bits;
37*4882a593Smuzhiyun 	} array;
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	struct property *prop;
40*4882a593Smuzhiyun 	struct property *proplist;
41*4882a593Smuzhiyun 	struct node *node;
42*4882a593Smuzhiyun 	struct node *nodelist;
43*4882a593Smuzhiyun 	struct reserve_info *re;
44*4882a593Smuzhiyun 	uint64_t integer;
45*4882a593Smuzhiyun 	unsigned int flags;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun %token DT_V1
49*4882a593Smuzhiyun %token DT_PLUGIN
50*4882a593Smuzhiyun %token DT_MEMRESERVE
51*4882a593Smuzhiyun %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
52*4882a593Smuzhiyun %token DT_BITS
53*4882a593Smuzhiyun %token DT_DEL_PROP
54*4882a593Smuzhiyun %token DT_DEL_NODE
55*4882a593Smuzhiyun %token DT_OMIT_NO_REF
56*4882a593Smuzhiyun %token <propnodename> DT_PROPNODENAME
57*4882a593Smuzhiyun %token <integer> DT_LITERAL
58*4882a593Smuzhiyun %token <integer> DT_CHAR_LITERAL
59*4882a593Smuzhiyun %token <byte> DT_BYTE
60*4882a593Smuzhiyun %token <data> DT_STRING
61*4882a593Smuzhiyun %token <labelref> DT_LABEL
62*4882a593Smuzhiyun %token <labelref> DT_LABEL_REF
63*4882a593Smuzhiyun %token <labelref> DT_PATH_REF
64*4882a593Smuzhiyun %token DT_INCBIN
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun %type <data> propdata
67*4882a593Smuzhiyun %type <data> propdataprefix
68*4882a593Smuzhiyun %type <flags> header
69*4882a593Smuzhiyun %type <flags> headers
70*4882a593Smuzhiyun %type <re> memreserve
71*4882a593Smuzhiyun %type <re> memreserves
72*4882a593Smuzhiyun %type <array> arrayprefix
73*4882a593Smuzhiyun %type <data> bytestring
74*4882a593Smuzhiyun %type <prop> propdef
75*4882a593Smuzhiyun %type <proplist> proplist
76*4882a593Smuzhiyun %type <labelref> dt_ref
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun %type <node> devicetree
79*4882a593Smuzhiyun %type <node> nodedef
80*4882a593Smuzhiyun %type <node> subnode
81*4882a593Smuzhiyun %type <nodelist> subnodes
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun %type <integer> integer_prim
84*4882a593Smuzhiyun %type <integer> integer_unary
85*4882a593Smuzhiyun %type <integer> integer_mul
86*4882a593Smuzhiyun %type <integer> integer_add
87*4882a593Smuzhiyun %type <integer> integer_shift
88*4882a593Smuzhiyun %type <integer> integer_rela
89*4882a593Smuzhiyun %type <integer> integer_eq
90*4882a593Smuzhiyun %type <integer> integer_bitand
91*4882a593Smuzhiyun %type <integer> integer_bitxor
92*4882a593Smuzhiyun %type <integer> integer_bitor
93*4882a593Smuzhiyun %type <integer> integer_and
94*4882a593Smuzhiyun %type <integer> integer_or
95*4882a593Smuzhiyun %type <integer> integer_trinary
96*4882a593Smuzhiyun %type <integer> integer_expr
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun %%
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun sourcefile:
101*4882a593Smuzhiyun 	  headers memreserves devicetree
102*4882a593Smuzhiyun 		{
103*4882a593Smuzhiyun 			parser_output = build_dt_info($1, $2, $3,
104*4882a593Smuzhiyun 			                              guess_boot_cpuid($3));
105*4882a593Smuzhiyun 		}
106*4882a593Smuzhiyun 	;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun header:
109*4882a593Smuzhiyun 	  DT_V1 ';'
110*4882a593Smuzhiyun 		{
111*4882a593Smuzhiyun 			$$ = DTSF_V1;
112*4882a593Smuzhiyun 		}
113*4882a593Smuzhiyun 	| DT_V1 ';' DT_PLUGIN ';'
114*4882a593Smuzhiyun 		{
115*4882a593Smuzhiyun 			$$ = DTSF_V1 | DTSF_PLUGIN;
116*4882a593Smuzhiyun 		}
117*4882a593Smuzhiyun 	;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun headers:
120*4882a593Smuzhiyun 	  header
121*4882a593Smuzhiyun 	| header headers
122*4882a593Smuzhiyun 		{
123*4882a593Smuzhiyun 			if ($2 != $1)
124*4882a593Smuzhiyun 				ERROR(&@2, "Header flags don't match earlier ones");
125*4882a593Smuzhiyun 			$$ = $1;
126*4882a593Smuzhiyun 		}
127*4882a593Smuzhiyun 	;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun memreserves:
130*4882a593Smuzhiyun 	  /* empty */
131*4882a593Smuzhiyun 		{
132*4882a593Smuzhiyun 			$$ = NULL;
133*4882a593Smuzhiyun 		}
134*4882a593Smuzhiyun 	| memreserve memreserves
135*4882a593Smuzhiyun 		{
136*4882a593Smuzhiyun 			$$ = chain_reserve_entry($1, $2);
137*4882a593Smuzhiyun 		}
138*4882a593Smuzhiyun 	;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun memreserve:
141*4882a593Smuzhiyun 	  DT_MEMRESERVE integer_prim integer_prim ';'
142*4882a593Smuzhiyun 		{
143*4882a593Smuzhiyun 			$$ = build_reserve_entry($2, $3);
144*4882a593Smuzhiyun 		}
145*4882a593Smuzhiyun 	| DT_LABEL memreserve
146*4882a593Smuzhiyun 		{
147*4882a593Smuzhiyun 			add_label(&$2->labels, $1);
148*4882a593Smuzhiyun 			$$ = $2;
149*4882a593Smuzhiyun 		}
150*4882a593Smuzhiyun 	;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun dt_ref: DT_LABEL_REF | DT_PATH_REF;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun devicetree:
155*4882a593Smuzhiyun 	  '/' nodedef
156*4882a593Smuzhiyun 		{
157*4882a593Smuzhiyun 			$$ = name_node($2, "");
158*4882a593Smuzhiyun 		}
159*4882a593Smuzhiyun 	| devicetree '/' nodedef
160*4882a593Smuzhiyun 		{
161*4882a593Smuzhiyun 			$$ = merge_nodes($1, $3);
162*4882a593Smuzhiyun 		}
163*4882a593Smuzhiyun 	| dt_ref nodedef
164*4882a593Smuzhiyun 		{
165*4882a593Smuzhiyun 			/*
166*4882a593Smuzhiyun 			 * We rely on the rule being always:
167*4882a593Smuzhiyun 			 *   versioninfo plugindecl memreserves devicetree
168*4882a593Smuzhiyun 			 * so $-1 is what we want (plugindecl)
169*4882a593Smuzhiyun 			 */
170*4882a593Smuzhiyun 			if (!($<flags>-1 & DTSF_PLUGIN))
171*4882a593Smuzhiyun 				ERROR(&@2, "Label or path %s not found", $1);
172*4882a593Smuzhiyun 			$$ = add_orphan_node(
173*4882a593Smuzhiyun 					name_node(build_node(NULL, NULL, NULL),
174*4882a593Smuzhiyun 						  ""),
175*4882a593Smuzhiyun 					$2, $1);
176*4882a593Smuzhiyun 		}
177*4882a593Smuzhiyun 	| devicetree DT_LABEL dt_ref nodedef
178*4882a593Smuzhiyun 		{
179*4882a593Smuzhiyun 			struct node *target = get_node_by_ref($1, $3);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 			if (target) {
182*4882a593Smuzhiyun 				add_label(&target->labels, $2);
183*4882a593Smuzhiyun 				merge_nodes(target, $4);
184*4882a593Smuzhiyun 			} else
185*4882a593Smuzhiyun 				ERROR(&@3, "Label or path %s not found", $3);
186*4882a593Smuzhiyun 			$$ = $1;
187*4882a593Smuzhiyun 		}
188*4882a593Smuzhiyun 	| devicetree DT_PATH_REF nodedef
189*4882a593Smuzhiyun 		{
190*4882a593Smuzhiyun 			/*
191*4882a593Smuzhiyun 			 * We rely on the rule being always:
192*4882a593Smuzhiyun 			 *   versioninfo plugindecl memreserves devicetree
193*4882a593Smuzhiyun 			 * so $-1 is what we want (plugindecl)
194*4882a593Smuzhiyun 			 */
195*4882a593Smuzhiyun 			if ($<flags>-1 & DTSF_PLUGIN) {
196*4882a593Smuzhiyun 				add_orphan_node($1, $3, $2);
197*4882a593Smuzhiyun 			} else {
198*4882a593Smuzhiyun 				struct node *target = get_node_by_ref($1, $2);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 				if (target)
201*4882a593Smuzhiyun 					merge_nodes(target, $3);
202*4882a593Smuzhiyun 				else
203*4882a593Smuzhiyun 					ERROR(&@2, "Label or path %s not found", $2);
204*4882a593Smuzhiyun 			}
205*4882a593Smuzhiyun 			$$ = $1;
206*4882a593Smuzhiyun 		}
207*4882a593Smuzhiyun 	| devicetree DT_LABEL_REF nodedef
208*4882a593Smuzhiyun 		{
209*4882a593Smuzhiyun 			struct node *target = get_node_by_ref($1, $2);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 			if (target) {
212*4882a593Smuzhiyun 				merge_nodes(target, $3);
213*4882a593Smuzhiyun 			} else {
214*4882a593Smuzhiyun 				/*
215*4882a593Smuzhiyun 				 * We rely on the rule being always:
216*4882a593Smuzhiyun 				 *   versioninfo plugindecl memreserves devicetree
217*4882a593Smuzhiyun 				 * so $-1 is what we want (plugindecl)
218*4882a593Smuzhiyun 				 */
219*4882a593Smuzhiyun 				if ($<flags>-1 & DTSF_PLUGIN)
220*4882a593Smuzhiyun 					add_orphan_node($1, $3, $2);
221*4882a593Smuzhiyun 				else
222*4882a593Smuzhiyun 					ERROR(&@2, "Label or path %s not found", $2);
223*4882a593Smuzhiyun 			}
224*4882a593Smuzhiyun 			$$ = $1;
225*4882a593Smuzhiyun 		}
226*4882a593Smuzhiyun 	| devicetree DT_DEL_NODE dt_ref ';'
227*4882a593Smuzhiyun 		{
228*4882a593Smuzhiyun 			struct node *target = get_node_by_ref($1, $3);
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 			if (target)
231*4882a593Smuzhiyun 				delete_node(target);
232*4882a593Smuzhiyun 			else
233*4882a593Smuzhiyun 				ERROR(&@3, "Label or path %s not found", $3);
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 			$$ = $1;
237*4882a593Smuzhiyun 		}
238*4882a593Smuzhiyun 	| devicetree DT_OMIT_NO_REF dt_ref ';'
239*4882a593Smuzhiyun 		{
240*4882a593Smuzhiyun 			struct node *target = get_node_by_ref($1, $3);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 			if (target)
243*4882a593Smuzhiyun 				omit_node_if_unused(target);
244*4882a593Smuzhiyun 			else
245*4882a593Smuzhiyun 				ERROR(&@3, "Label or path %s not found", $3);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 			$$ = $1;
249*4882a593Smuzhiyun 		}
250*4882a593Smuzhiyun 	;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun nodedef:
253*4882a593Smuzhiyun 	  '{' proplist subnodes '}' ';'
254*4882a593Smuzhiyun 		{
255*4882a593Smuzhiyun 			$$ = build_node($2, $3, &@$);
256*4882a593Smuzhiyun 		}
257*4882a593Smuzhiyun 	;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun proplist:
260*4882a593Smuzhiyun 	  /* empty */
261*4882a593Smuzhiyun 		{
262*4882a593Smuzhiyun 			$$ = NULL;
263*4882a593Smuzhiyun 		}
264*4882a593Smuzhiyun 	| proplist propdef
265*4882a593Smuzhiyun 		{
266*4882a593Smuzhiyun 			$$ = chain_property($2, $1);
267*4882a593Smuzhiyun 		}
268*4882a593Smuzhiyun 	;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun propdef:
271*4882a593Smuzhiyun 	  DT_PROPNODENAME '=' propdata ';'
272*4882a593Smuzhiyun 		{
273*4882a593Smuzhiyun 			$$ = build_property($1, $3, &@$);
274*4882a593Smuzhiyun 		}
275*4882a593Smuzhiyun 	| DT_PROPNODENAME ';'
276*4882a593Smuzhiyun 		{
277*4882a593Smuzhiyun 			$$ = build_property($1, empty_data, &@$);
278*4882a593Smuzhiyun 		}
279*4882a593Smuzhiyun 	| DT_DEL_PROP DT_PROPNODENAME ';'
280*4882a593Smuzhiyun 		{
281*4882a593Smuzhiyun 			$$ = build_property_delete($2);
282*4882a593Smuzhiyun 		}
283*4882a593Smuzhiyun 	| DT_LABEL propdef
284*4882a593Smuzhiyun 		{
285*4882a593Smuzhiyun 			add_label(&$2->labels, $1);
286*4882a593Smuzhiyun 			$$ = $2;
287*4882a593Smuzhiyun 		}
288*4882a593Smuzhiyun 	;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun propdata:
291*4882a593Smuzhiyun 	  propdataprefix DT_STRING
292*4882a593Smuzhiyun 		{
293*4882a593Smuzhiyun 			$$ = data_merge($1, $2);
294*4882a593Smuzhiyun 		}
295*4882a593Smuzhiyun 	| propdataprefix arrayprefix '>'
296*4882a593Smuzhiyun 		{
297*4882a593Smuzhiyun 			$$ = data_merge($1, $2.data);
298*4882a593Smuzhiyun 		}
299*4882a593Smuzhiyun 	| propdataprefix '[' bytestring ']'
300*4882a593Smuzhiyun 		{
301*4882a593Smuzhiyun 			$$ = data_merge($1, $3);
302*4882a593Smuzhiyun 		}
303*4882a593Smuzhiyun 	| propdataprefix dt_ref
304*4882a593Smuzhiyun 		{
305*4882a593Smuzhiyun 			$1 = data_add_marker($1, TYPE_STRING, $2);
306*4882a593Smuzhiyun 			$$ = data_add_marker($1, REF_PATH, $2);
307*4882a593Smuzhiyun 		}
308*4882a593Smuzhiyun 	| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
309*4882a593Smuzhiyun 		{
310*4882a593Smuzhiyun 			FILE *f = srcfile_relative_open($4.val, NULL);
311*4882a593Smuzhiyun 			struct data d;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 			if ($6 != 0)
314*4882a593Smuzhiyun 				if (fseek(f, $6, SEEK_SET) != 0)
315*4882a593Smuzhiyun 					die("Couldn't seek to offset %llu in \"%s\": %s",
316*4882a593Smuzhiyun 					    (unsigned long long)$6, $4.val,
317*4882a593Smuzhiyun 					    strerror(errno));
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 			d = data_copy_file(f, $8);
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 			$$ = data_merge($1, d);
322*4882a593Smuzhiyun 			fclose(f);
323*4882a593Smuzhiyun 		}
324*4882a593Smuzhiyun 	| propdataprefix DT_INCBIN '(' DT_STRING ')'
325*4882a593Smuzhiyun 		{
326*4882a593Smuzhiyun 			FILE *f = srcfile_relative_open($4.val, NULL);
327*4882a593Smuzhiyun 			struct data d = empty_data;
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 			d = data_copy_file(f, -1);
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 			$$ = data_merge($1, d);
332*4882a593Smuzhiyun 			fclose(f);
333*4882a593Smuzhiyun 		}
334*4882a593Smuzhiyun 	| propdata DT_LABEL
335*4882a593Smuzhiyun 		{
336*4882a593Smuzhiyun 			$$ = data_add_marker($1, LABEL, $2);
337*4882a593Smuzhiyun 		}
338*4882a593Smuzhiyun 	;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun propdataprefix:
341*4882a593Smuzhiyun 	  /* empty */
342*4882a593Smuzhiyun 		{
343*4882a593Smuzhiyun 			$$ = empty_data;
344*4882a593Smuzhiyun 		}
345*4882a593Smuzhiyun 	| propdata ','
346*4882a593Smuzhiyun 		{
347*4882a593Smuzhiyun 			$$ = $1;
348*4882a593Smuzhiyun 		}
349*4882a593Smuzhiyun 	| propdataprefix DT_LABEL
350*4882a593Smuzhiyun 		{
351*4882a593Smuzhiyun 			$$ = data_add_marker($1, LABEL, $2);
352*4882a593Smuzhiyun 		}
353*4882a593Smuzhiyun 	;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun arrayprefix:
356*4882a593Smuzhiyun 	DT_BITS DT_LITERAL '<'
357*4882a593Smuzhiyun 		{
358*4882a593Smuzhiyun 			unsigned long long bits;
359*4882a593Smuzhiyun 			enum markertype type = TYPE_UINT32;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 			bits = $2;
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 			switch (bits) {
364*4882a593Smuzhiyun 			case 8: type = TYPE_UINT8; break;
365*4882a593Smuzhiyun 			case 16: type = TYPE_UINT16; break;
366*4882a593Smuzhiyun 			case 32: type = TYPE_UINT32; break;
367*4882a593Smuzhiyun 			case 64: type = TYPE_UINT64; break;
368*4882a593Smuzhiyun 			default:
369*4882a593Smuzhiyun 				ERROR(&@2, "Array elements must be"
370*4882a593Smuzhiyun 				      " 8, 16, 32 or 64-bits");
371*4882a593Smuzhiyun 				bits = 32;
372*4882a593Smuzhiyun 			}
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 			$$.data = data_add_marker(empty_data, type, NULL);
375*4882a593Smuzhiyun 			$$.bits = bits;
376*4882a593Smuzhiyun 		}
377*4882a593Smuzhiyun 	| '<'
378*4882a593Smuzhiyun 		{
379*4882a593Smuzhiyun 			$$.data = data_add_marker(empty_data, TYPE_UINT32, NULL);
380*4882a593Smuzhiyun 			$$.bits = 32;
381*4882a593Smuzhiyun 		}
382*4882a593Smuzhiyun 	| arrayprefix integer_prim
383*4882a593Smuzhiyun 		{
384*4882a593Smuzhiyun 			if ($1.bits < 64) {
385*4882a593Smuzhiyun 				uint64_t mask = (1ULL << $1.bits) - 1;
386*4882a593Smuzhiyun 				/*
387*4882a593Smuzhiyun 				 * Bits above mask must either be all zero
388*4882a593Smuzhiyun 				 * (positive within range of mask) or all one
389*4882a593Smuzhiyun 				 * (negative and sign-extended). The second
390*4882a593Smuzhiyun 				 * condition is true if when we set all bits
391*4882a593Smuzhiyun 				 * within the mask to one (i.e. | in the
392*4882a593Smuzhiyun 				 * mask), all bits are one.
393*4882a593Smuzhiyun 				 */
394*4882a593Smuzhiyun 				if (($2 > mask) && (($2 | mask) != -1ULL))
395*4882a593Smuzhiyun 					ERROR(&@2, "Value out of range for"
396*4882a593Smuzhiyun 					      " %d-bit array element", $1.bits);
397*4882a593Smuzhiyun 			}
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 			$$.data = data_append_integer($1.data, $2, $1.bits);
400*4882a593Smuzhiyun 		}
401*4882a593Smuzhiyun 	| arrayprefix dt_ref
402*4882a593Smuzhiyun 		{
403*4882a593Smuzhiyun 			uint64_t val = ~0ULL >> (64 - $1.bits);
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 			if ($1.bits == 32)
406*4882a593Smuzhiyun 				$1.data = data_add_marker($1.data,
407*4882a593Smuzhiyun 							  REF_PHANDLE,
408*4882a593Smuzhiyun 							  $2);
409*4882a593Smuzhiyun 			else
410*4882a593Smuzhiyun 				ERROR(&@2, "References are only allowed in "
411*4882a593Smuzhiyun 					    "arrays with 32-bit elements.");
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 			$$.data = data_append_integer($1.data, val, $1.bits);
414*4882a593Smuzhiyun 		}
415*4882a593Smuzhiyun 	| arrayprefix DT_LABEL
416*4882a593Smuzhiyun 		{
417*4882a593Smuzhiyun 			$$.data = data_add_marker($1.data, LABEL, $2);
418*4882a593Smuzhiyun 		}
419*4882a593Smuzhiyun 	;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun integer_prim:
422*4882a593Smuzhiyun 	  DT_LITERAL
423*4882a593Smuzhiyun 	| DT_CHAR_LITERAL
424*4882a593Smuzhiyun 	| '(' integer_expr ')'
425*4882a593Smuzhiyun 		{
426*4882a593Smuzhiyun 			$$ = $2;
427*4882a593Smuzhiyun 		}
428*4882a593Smuzhiyun 	;
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun integer_expr:
431*4882a593Smuzhiyun 	integer_trinary
432*4882a593Smuzhiyun 	;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun integer_trinary:
435*4882a593Smuzhiyun 	  integer_or
436*4882a593Smuzhiyun 	| integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
437*4882a593Smuzhiyun 	;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun integer_or:
440*4882a593Smuzhiyun 	  integer_and
441*4882a593Smuzhiyun 	| integer_or DT_OR integer_and { $$ = $1 || $3; }
442*4882a593Smuzhiyun 	;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun integer_and:
445*4882a593Smuzhiyun 	  integer_bitor
446*4882a593Smuzhiyun 	| integer_and DT_AND integer_bitor { $$ = $1 && $3; }
447*4882a593Smuzhiyun 	;
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun integer_bitor:
450*4882a593Smuzhiyun 	  integer_bitxor
451*4882a593Smuzhiyun 	| integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
452*4882a593Smuzhiyun 	;
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun integer_bitxor:
455*4882a593Smuzhiyun 	  integer_bitand
456*4882a593Smuzhiyun 	| integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
457*4882a593Smuzhiyun 	;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun integer_bitand:
460*4882a593Smuzhiyun 	  integer_eq
461*4882a593Smuzhiyun 	| integer_bitand '&' integer_eq { $$ = $1 & $3; }
462*4882a593Smuzhiyun 	;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun integer_eq:
465*4882a593Smuzhiyun 	  integer_rela
466*4882a593Smuzhiyun 	| integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
467*4882a593Smuzhiyun 	| integer_eq DT_NE integer_rela { $$ = $1 != $3; }
468*4882a593Smuzhiyun 	;
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun integer_rela:
471*4882a593Smuzhiyun 	  integer_shift
472*4882a593Smuzhiyun 	| integer_rela '<' integer_shift { $$ = $1 < $3; }
473*4882a593Smuzhiyun 	| integer_rela '>' integer_shift { $$ = $1 > $3; }
474*4882a593Smuzhiyun 	| integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
475*4882a593Smuzhiyun 	| integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
476*4882a593Smuzhiyun 	;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun integer_shift:
479*4882a593Smuzhiyun 	  integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; }
480*4882a593Smuzhiyun 	| integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; }
481*4882a593Smuzhiyun 	| integer_add
482*4882a593Smuzhiyun 	;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun integer_add:
485*4882a593Smuzhiyun 	  integer_add '+' integer_mul { $$ = $1 + $3; }
486*4882a593Smuzhiyun 	| integer_add '-' integer_mul { $$ = $1 - $3; }
487*4882a593Smuzhiyun 	| integer_mul
488*4882a593Smuzhiyun 	;
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun integer_mul:
491*4882a593Smuzhiyun 	  integer_mul '*' integer_unary { $$ = $1 * $3; }
492*4882a593Smuzhiyun 	| integer_mul '/' integer_unary
493*4882a593Smuzhiyun 		{
494*4882a593Smuzhiyun 			if ($3 != 0) {
495*4882a593Smuzhiyun 				$$ = $1 / $3;
496*4882a593Smuzhiyun 			} else {
497*4882a593Smuzhiyun 				ERROR(&@$, "Division by zero");
498*4882a593Smuzhiyun 				$$ = 0;
499*4882a593Smuzhiyun 			}
500*4882a593Smuzhiyun 		}
501*4882a593Smuzhiyun 	| integer_mul '%' integer_unary
502*4882a593Smuzhiyun 		{
503*4882a593Smuzhiyun 			if ($3 != 0) {
504*4882a593Smuzhiyun 				$$ = $1 % $3;
505*4882a593Smuzhiyun 			} else {
506*4882a593Smuzhiyun 				ERROR(&@$, "Division by zero");
507*4882a593Smuzhiyun 				$$ = 0;
508*4882a593Smuzhiyun 			}
509*4882a593Smuzhiyun 		}
510*4882a593Smuzhiyun 	| integer_unary
511*4882a593Smuzhiyun 	;
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun integer_unary:
514*4882a593Smuzhiyun 	  integer_prim
515*4882a593Smuzhiyun 	| '-' integer_unary { $$ = -$2; }
516*4882a593Smuzhiyun 	| '~' integer_unary { $$ = ~$2; }
517*4882a593Smuzhiyun 	| '!' integer_unary { $$ = !$2; }
518*4882a593Smuzhiyun 	;
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun bytestring:
521*4882a593Smuzhiyun 	  /* empty */
522*4882a593Smuzhiyun 		{
523*4882a593Smuzhiyun 			$$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
524*4882a593Smuzhiyun 		}
525*4882a593Smuzhiyun 	| bytestring DT_BYTE
526*4882a593Smuzhiyun 		{
527*4882a593Smuzhiyun 			$$ = data_append_byte($1, $2);
528*4882a593Smuzhiyun 		}
529*4882a593Smuzhiyun 	| bytestring DT_LABEL
530*4882a593Smuzhiyun 		{
531*4882a593Smuzhiyun 			$$ = data_add_marker($1, LABEL, $2);
532*4882a593Smuzhiyun 		}
533*4882a593Smuzhiyun 	;
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun subnodes:
536*4882a593Smuzhiyun 	  /* empty */
537*4882a593Smuzhiyun 		{
538*4882a593Smuzhiyun 			$$ = NULL;
539*4882a593Smuzhiyun 		}
540*4882a593Smuzhiyun 	| subnode subnodes
541*4882a593Smuzhiyun 		{
542*4882a593Smuzhiyun 			$$ = chain_node($1, $2);
543*4882a593Smuzhiyun 		}
544*4882a593Smuzhiyun 	| subnode propdef
545*4882a593Smuzhiyun 		{
546*4882a593Smuzhiyun 			ERROR(&@2, "Properties must precede subnodes");
547*4882a593Smuzhiyun 			YYERROR;
548*4882a593Smuzhiyun 		}
549*4882a593Smuzhiyun 	;
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun subnode:
552*4882a593Smuzhiyun 	  DT_PROPNODENAME nodedef
553*4882a593Smuzhiyun 		{
554*4882a593Smuzhiyun 			$$ = name_node($2, $1);
555*4882a593Smuzhiyun 		}
556*4882a593Smuzhiyun 	| DT_DEL_NODE DT_PROPNODENAME ';'
557*4882a593Smuzhiyun 		{
558*4882a593Smuzhiyun 			$$ = name_node(build_node_delete(&@$), $2);
559*4882a593Smuzhiyun 		}
560*4882a593Smuzhiyun 	| DT_OMIT_NO_REF subnode
561*4882a593Smuzhiyun 		{
562*4882a593Smuzhiyun 			$$ = omit_node_if_unused($2);
563*4882a593Smuzhiyun 		}
564*4882a593Smuzhiyun 	| DT_LABEL subnode
565*4882a593Smuzhiyun 		{
566*4882a593Smuzhiyun 			add_label(&$2->labels, $1);
567*4882a593Smuzhiyun 			$$ = $2;
568*4882a593Smuzhiyun 		}
569*4882a593Smuzhiyun 	;
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun %%
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun void yyerror(char const *s)
574*4882a593Smuzhiyun {
575*4882a593Smuzhiyun 	ERROR(&yylloc, "%s", s);
576*4882a593Smuzhiyun }
577