xref: /OK3568_Linux_fs/kernel/tools/bpf/bpf_exp.y (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * BPF asm code parser
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * This program is free software; you can distribute it and/or modify
5*4882a593Smuzhiyun  * it under the terms of the GNU General Public License as published
6*4882a593Smuzhiyun  * by the Free Software Foundation; either version 2 of the License,
7*4882a593Smuzhiyun  * or (at your option) any later version.
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * Syntax kept close to:
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * Steven McCanne and Van Jacobson. 1993. The BSD packet filter: a new
12*4882a593Smuzhiyun  * architecture for user-level packet capture. In Proceedings of the
13*4882a593Smuzhiyun  * USENIX Winter 1993 Conference Proceedings on USENIX Winter 1993
14*4882a593Smuzhiyun  * Conference Proceedings (USENIX'93). USENIX Association, Berkeley,
15*4882a593Smuzhiyun  * CA, USA, 2-2.
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  * Copyright 2013 Daniel Borkmann <borkmann@redhat.com>
18*4882a593Smuzhiyun  * Licensed under the GNU General Public License, version 2.0 (GPLv2)
19*4882a593Smuzhiyun  */
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun %{
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include <stdio.h>
24*4882a593Smuzhiyun #include <string.h>
25*4882a593Smuzhiyun #include <stdint.h>
26*4882a593Smuzhiyun #include <stdlib.h>
27*4882a593Smuzhiyun #include <stdbool.h>
28*4882a593Smuzhiyun #include <unistd.h>
29*4882a593Smuzhiyun #include <errno.h>
30*4882a593Smuzhiyun #include <assert.h>
31*4882a593Smuzhiyun #include <linux/filter.h>
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #include "bpf_exp.yacc.h"
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun enum jmp_type { JTL, JFL, JKL };
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun extern FILE *yyin;
38*4882a593Smuzhiyun extern int yylineno;
39*4882a593Smuzhiyun extern int yylex(void);
40*4882a593Smuzhiyun extern void yyerror(const char *str);
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun extern void bpf_asm_compile(FILE *fp, bool cstyle);
43*4882a593Smuzhiyun static void bpf_set_curr_instr(uint16_t op, uint8_t jt, uint8_t jf, uint32_t k);
44*4882a593Smuzhiyun static void bpf_set_curr_label(char *label);
45*4882a593Smuzhiyun static void bpf_set_jmp_label(char *label, enum jmp_type type);
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun %}
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun %union {
50*4882a593Smuzhiyun 	char *label;
51*4882a593Smuzhiyun 	uint32_t number;
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun %token OP_LDB OP_LDH OP_LD OP_LDX OP_ST OP_STX OP_JMP OP_JEQ OP_JGT OP_JGE
55*4882a593Smuzhiyun %token OP_JSET OP_ADD OP_SUB OP_MUL OP_DIV OP_AND OP_OR OP_XOR OP_LSH OP_RSH
56*4882a593Smuzhiyun %token OP_RET OP_TAX OP_TXA OP_LDXB OP_MOD OP_NEG OP_JNEQ OP_JLT OP_JLE OP_LDI
57*4882a593Smuzhiyun %token OP_LDXI
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun %token K_PKT_LEN
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun %token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%'
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun %token extension number label
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun %type <label> label
66*4882a593Smuzhiyun %type <number> extension
67*4882a593Smuzhiyun %type <number> number
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun %%
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun prog
72*4882a593Smuzhiyun 	: line
73*4882a593Smuzhiyun 	| prog line
74*4882a593Smuzhiyun 	;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun line
77*4882a593Smuzhiyun 	: instr
78*4882a593Smuzhiyun 	| labelled_instr
79*4882a593Smuzhiyun 	;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun labelled_instr
82*4882a593Smuzhiyun 	: labelled instr
83*4882a593Smuzhiyun 	;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun instr
86*4882a593Smuzhiyun 	: ldb
87*4882a593Smuzhiyun 	| ldh
88*4882a593Smuzhiyun 	| ld
89*4882a593Smuzhiyun 	| ldi
90*4882a593Smuzhiyun 	| ldx
91*4882a593Smuzhiyun 	| ldxi
92*4882a593Smuzhiyun 	| st
93*4882a593Smuzhiyun 	| stx
94*4882a593Smuzhiyun 	| jmp
95*4882a593Smuzhiyun 	| jeq
96*4882a593Smuzhiyun 	| jneq
97*4882a593Smuzhiyun 	| jlt
98*4882a593Smuzhiyun 	| jle
99*4882a593Smuzhiyun 	| jgt
100*4882a593Smuzhiyun 	| jge
101*4882a593Smuzhiyun 	| jset
102*4882a593Smuzhiyun 	| add
103*4882a593Smuzhiyun 	| sub
104*4882a593Smuzhiyun 	| mul
105*4882a593Smuzhiyun 	| div
106*4882a593Smuzhiyun 	| mod
107*4882a593Smuzhiyun 	| neg
108*4882a593Smuzhiyun 	| and
109*4882a593Smuzhiyun 	| or
110*4882a593Smuzhiyun 	| xor
111*4882a593Smuzhiyun 	| lsh
112*4882a593Smuzhiyun 	| rsh
113*4882a593Smuzhiyun 	| ret
114*4882a593Smuzhiyun 	| tax
115*4882a593Smuzhiyun 	| txa
116*4882a593Smuzhiyun 	;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun labelled
119*4882a593Smuzhiyun 	: label ':' { bpf_set_curr_label($1); }
120*4882a593Smuzhiyun 	;
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun ldb
123*4882a593Smuzhiyun 	: OP_LDB '[' 'x' '+' number ']' {
124*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $5); }
125*4882a593Smuzhiyun 	| OP_LDB '[' '%' 'x' '+' number ']' {
126*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $6); }
127*4882a593Smuzhiyun 	| OP_LDB '[' number ']' {
128*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, $3); }
129*4882a593Smuzhiyun 	| OP_LDB extension {
130*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
131*4882a593Smuzhiyun 				   SKF_AD_OFF + $2); }
132*4882a593Smuzhiyun 	;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun ldh
135*4882a593Smuzhiyun 	: OP_LDH '[' 'x' '+' number ']' {
136*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $5); }
137*4882a593Smuzhiyun 	| OP_LDH '[' '%' 'x' '+' number ']' {
138*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $6); }
139*4882a593Smuzhiyun 	| OP_LDH '[' number ']' {
140*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, $3); }
141*4882a593Smuzhiyun 	| OP_LDH extension {
142*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
143*4882a593Smuzhiyun 				   SKF_AD_OFF + $2); }
144*4882a593Smuzhiyun 	;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun ldi
147*4882a593Smuzhiyun 	: OP_LDI '#' number {
148*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }
149*4882a593Smuzhiyun 	| OP_LDI number {
150*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $2); }
151*4882a593Smuzhiyun 	;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun ld
154*4882a593Smuzhiyun 	: OP_LD '#' number {
155*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }
156*4882a593Smuzhiyun 	| OP_LD K_PKT_LEN {
157*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_LEN, 0, 0, 0); }
158*4882a593Smuzhiyun 	| OP_LD extension {
159*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
160*4882a593Smuzhiyun 				   SKF_AD_OFF + $2); }
161*4882a593Smuzhiyun 	| OP_LD 'M' '[' number ']' {
162*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); }
163*4882a593Smuzhiyun 	| OP_LD '[' 'x' '+' number ']' {
164*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $5); }
165*4882a593Smuzhiyun 	| OP_LD '[' '%' 'x' '+' number ']' {
166*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $6); }
167*4882a593Smuzhiyun 	| OP_LD '[' number ']' {
168*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, $3); }
169*4882a593Smuzhiyun 	;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun ldxi
172*4882a593Smuzhiyun 	: OP_LDXI '#' number {
173*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }
174*4882a593Smuzhiyun 	| OP_LDXI number {
175*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $2); }
176*4882a593Smuzhiyun 	;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun ldx
179*4882a593Smuzhiyun 	: OP_LDX '#' number {
180*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }
181*4882a593Smuzhiyun 	| OP_LDX K_PKT_LEN {
182*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LDX | BPF_W | BPF_LEN, 0, 0, 0); }
183*4882a593Smuzhiyun 	| OP_LDX 'M' '[' number ']' {
184*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_LDX | BPF_MEM, 0, 0, $4); }
185*4882a593Smuzhiyun 	| OP_LDXB number '*' '(' '[' number ']' '&' number ')' {
186*4882a593Smuzhiyun 		if ($2 != 4 || $9 != 0xf) {
187*4882a593Smuzhiyun 			fprintf(stderr, "ldxb offset not supported!\n");
188*4882a593Smuzhiyun 			exit(0);
189*4882a593Smuzhiyun 		} else {
190*4882a593Smuzhiyun 			bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }
191*4882a593Smuzhiyun 	| OP_LDX number '*' '(' '[' number ']' '&' number ')' {
192*4882a593Smuzhiyun 		if ($2 != 4 || $9 != 0xf) {
193*4882a593Smuzhiyun 			fprintf(stderr, "ldxb offset not supported!\n");
194*4882a593Smuzhiyun 			exit(0);
195*4882a593Smuzhiyun 		} else {
196*4882a593Smuzhiyun 			bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }
197*4882a593Smuzhiyun 	;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun st
200*4882a593Smuzhiyun 	: OP_ST 'M' '[' number ']' {
201*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ST, 0, 0, $4); }
202*4882a593Smuzhiyun 	;
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun stx
205*4882a593Smuzhiyun 	: OP_STX 'M' '[' number ']' {
206*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_STX, 0, 0, $4); }
207*4882a593Smuzhiyun 	;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun jmp
210*4882a593Smuzhiyun 	: OP_JMP label {
211*4882a593Smuzhiyun 		bpf_set_jmp_label($2, JKL);
212*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JA, 0, 0, 0); }
213*4882a593Smuzhiyun 	;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun jeq
216*4882a593Smuzhiyun 	: OP_JEQ '#' number ',' label ',' label {
217*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
218*4882a593Smuzhiyun 		bpf_set_jmp_label($7, JFL);
219*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
220*4882a593Smuzhiyun 	| OP_JEQ 'x' ',' label ',' label {
221*4882a593Smuzhiyun 		bpf_set_jmp_label($4, JTL);
222*4882a593Smuzhiyun 		bpf_set_jmp_label($6, JFL);
223*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
224*4882a593Smuzhiyun 	| OP_JEQ '%' 'x' ',' label ',' label {
225*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
226*4882a593Smuzhiyun 		bpf_set_jmp_label($7, JFL);
227*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
228*4882a593Smuzhiyun 	| OP_JEQ '#' number ',' label {
229*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
230*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
231*4882a593Smuzhiyun 	| OP_JEQ 'x' ',' label {
232*4882a593Smuzhiyun 		bpf_set_jmp_label($4, JTL);
233*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
234*4882a593Smuzhiyun 	| OP_JEQ '%' 'x' ',' label {
235*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
236*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
237*4882a593Smuzhiyun 	;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun jneq
240*4882a593Smuzhiyun 	: OP_JNEQ '#' number ',' label {
241*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JFL);
242*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
243*4882a593Smuzhiyun 	| OP_JNEQ 'x' ',' label {
244*4882a593Smuzhiyun 		bpf_set_jmp_label($4, JFL);
245*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
246*4882a593Smuzhiyun 	| OP_JNEQ '%' 'x' ',' label {
247*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JFL);
248*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
249*4882a593Smuzhiyun 	;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun jlt
252*4882a593Smuzhiyun 	: OP_JLT '#' number ',' label {
253*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JFL);
254*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
255*4882a593Smuzhiyun 	| OP_JLT 'x' ',' label {
256*4882a593Smuzhiyun 		bpf_set_jmp_label($4, JFL);
257*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
258*4882a593Smuzhiyun 	| OP_JLT '%' 'x' ',' label {
259*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JFL);
260*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
261*4882a593Smuzhiyun 	;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun jle
264*4882a593Smuzhiyun 	: OP_JLE '#' number ',' label {
265*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JFL);
266*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
267*4882a593Smuzhiyun 	| OP_JLE 'x' ',' label {
268*4882a593Smuzhiyun 		bpf_set_jmp_label($4, JFL);
269*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
270*4882a593Smuzhiyun 	| OP_JLE '%' 'x' ',' label {
271*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JFL);
272*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
273*4882a593Smuzhiyun 	;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun jgt
276*4882a593Smuzhiyun 	: OP_JGT '#' number ',' label ',' label {
277*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
278*4882a593Smuzhiyun 		bpf_set_jmp_label($7, JFL);
279*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
280*4882a593Smuzhiyun 	| OP_JGT 'x' ',' label ',' label {
281*4882a593Smuzhiyun 		bpf_set_jmp_label($4, JTL);
282*4882a593Smuzhiyun 		bpf_set_jmp_label($6, JFL);
283*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
284*4882a593Smuzhiyun 	| OP_JGT '%' 'x' ',' label ',' label {
285*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
286*4882a593Smuzhiyun 		bpf_set_jmp_label($7, JFL);
287*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
288*4882a593Smuzhiyun 	| OP_JGT '#' number ',' label {
289*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
290*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
291*4882a593Smuzhiyun 	| OP_JGT 'x' ',' label {
292*4882a593Smuzhiyun 		bpf_set_jmp_label($4, JTL);
293*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
294*4882a593Smuzhiyun 	| OP_JGT '%' 'x' ',' label {
295*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
296*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
297*4882a593Smuzhiyun 	;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun jge
300*4882a593Smuzhiyun 	: OP_JGE '#' number ',' label ',' label {
301*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
302*4882a593Smuzhiyun 		bpf_set_jmp_label($7, JFL);
303*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
304*4882a593Smuzhiyun 	| OP_JGE 'x' ',' label ',' label {
305*4882a593Smuzhiyun 		bpf_set_jmp_label($4, JTL);
306*4882a593Smuzhiyun 		bpf_set_jmp_label($6, JFL);
307*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
308*4882a593Smuzhiyun 	| OP_JGE '%' 'x' ',' label ',' label {
309*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
310*4882a593Smuzhiyun 		bpf_set_jmp_label($7, JFL);
311*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
312*4882a593Smuzhiyun 	| OP_JGE '#' number ',' label {
313*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
314*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
315*4882a593Smuzhiyun 	| OP_JGE 'x' ',' label {
316*4882a593Smuzhiyun 		bpf_set_jmp_label($4, JTL);
317*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
318*4882a593Smuzhiyun 	| OP_JGE '%' 'x' ',' label {
319*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
320*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
321*4882a593Smuzhiyun 	;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun jset
324*4882a593Smuzhiyun 	: OP_JSET '#' number ',' label ',' label {
325*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
326*4882a593Smuzhiyun 		bpf_set_jmp_label($7, JFL);
327*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }
328*4882a593Smuzhiyun 	| OP_JSET 'x' ',' label ',' label {
329*4882a593Smuzhiyun 		bpf_set_jmp_label($4, JTL);
330*4882a593Smuzhiyun 		bpf_set_jmp_label($6, JFL);
331*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
332*4882a593Smuzhiyun 	| OP_JSET '%' 'x' ',' label ',' label {
333*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
334*4882a593Smuzhiyun 		bpf_set_jmp_label($7, JFL);
335*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
336*4882a593Smuzhiyun 	| OP_JSET '#' number ',' label {
337*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
338*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }
339*4882a593Smuzhiyun 	| OP_JSET 'x' ',' label {
340*4882a593Smuzhiyun 		bpf_set_jmp_label($4, JTL);
341*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
342*4882a593Smuzhiyun 	| OP_JSET '%' 'x' ',' label {
343*4882a593Smuzhiyun 		bpf_set_jmp_label($5, JTL);
344*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
345*4882a593Smuzhiyun 	;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun add
348*4882a593Smuzhiyun 	: OP_ADD '#' number {
349*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_K, 0, 0, $3); }
350*4882a593Smuzhiyun 	| OP_ADD 'x' {
351*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }
352*4882a593Smuzhiyun 	| OP_ADD '%' 'x' {
353*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }
354*4882a593Smuzhiyun 	;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun sub
357*4882a593Smuzhiyun 	: OP_SUB '#' number {
358*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_K, 0, 0, $3); }
359*4882a593Smuzhiyun 	| OP_SUB 'x' {
360*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }
361*4882a593Smuzhiyun 	| OP_SUB '%' 'x' {
362*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }
363*4882a593Smuzhiyun 	;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun mul
366*4882a593Smuzhiyun 	: OP_MUL '#' number {
367*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_K, 0, 0, $3); }
368*4882a593Smuzhiyun 	| OP_MUL 'x' {
369*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }
370*4882a593Smuzhiyun 	| OP_MUL '%' 'x' {
371*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }
372*4882a593Smuzhiyun 	;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun div
375*4882a593Smuzhiyun 	: OP_DIV '#' number {
376*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_K, 0, 0, $3); }
377*4882a593Smuzhiyun 	| OP_DIV 'x' {
378*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }
379*4882a593Smuzhiyun 	| OP_DIV '%' 'x' {
380*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }
381*4882a593Smuzhiyun 	;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun mod
384*4882a593Smuzhiyun 	: OP_MOD '#' number {
385*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_K, 0, 0, $3); }
386*4882a593Smuzhiyun 	| OP_MOD 'x' {
387*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }
388*4882a593Smuzhiyun 	| OP_MOD '%' 'x' {
389*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }
390*4882a593Smuzhiyun 	;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun neg
393*4882a593Smuzhiyun 	: OP_NEG {
394*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_NEG, 0, 0, 0); }
395*4882a593Smuzhiyun 	;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun and
398*4882a593Smuzhiyun 	: OP_AND '#' number {
399*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_K, 0, 0, $3); }
400*4882a593Smuzhiyun 	| OP_AND 'x' {
401*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }
402*4882a593Smuzhiyun 	| OP_AND '%' 'x' {
403*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }
404*4882a593Smuzhiyun 	;
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun or
407*4882a593Smuzhiyun 	: OP_OR '#' number {
408*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_K, 0, 0, $3); }
409*4882a593Smuzhiyun 	| OP_OR 'x' {
410*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }
411*4882a593Smuzhiyun 	| OP_OR '%' 'x' {
412*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }
413*4882a593Smuzhiyun 	;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun xor
416*4882a593Smuzhiyun 	: OP_XOR '#' number {
417*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_K, 0, 0, $3); }
418*4882a593Smuzhiyun 	| OP_XOR 'x' {
419*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }
420*4882a593Smuzhiyun 	| OP_XOR '%' 'x' {
421*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }
422*4882a593Smuzhiyun 	;
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun lsh
425*4882a593Smuzhiyun 	: OP_LSH '#' number {
426*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_K, 0, 0, $3); }
427*4882a593Smuzhiyun 	| OP_LSH 'x' {
428*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }
429*4882a593Smuzhiyun 	| OP_LSH '%' 'x' {
430*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }
431*4882a593Smuzhiyun 	;
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun rsh
434*4882a593Smuzhiyun 	: OP_RSH '#' number {
435*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_K, 0, 0, $3); }
436*4882a593Smuzhiyun 	| OP_RSH 'x' {
437*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }
438*4882a593Smuzhiyun 	| OP_RSH '%' 'x' {
439*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }
440*4882a593Smuzhiyun 	;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun ret
443*4882a593Smuzhiyun 	: OP_RET 'a' {
444*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }
445*4882a593Smuzhiyun 	| OP_RET '%' 'a' {
446*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }
447*4882a593Smuzhiyun 	| OP_RET 'x' {
448*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }
449*4882a593Smuzhiyun 	| OP_RET '%' 'x' {
450*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }
451*4882a593Smuzhiyun 	| OP_RET '#' number {
452*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_RET | BPF_K, 0, 0, $3); }
453*4882a593Smuzhiyun 	;
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun tax
456*4882a593Smuzhiyun 	: OP_TAX {
457*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_MISC | BPF_TAX, 0, 0, 0); }
458*4882a593Smuzhiyun 	;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun txa
461*4882a593Smuzhiyun 	: OP_TXA {
462*4882a593Smuzhiyun 		bpf_set_curr_instr(BPF_MISC | BPF_TXA, 0, 0, 0); }
463*4882a593Smuzhiyun 	;
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun %%
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun static int curr_instr = 0;
468*4882a593Smuzhiyun static struct sock_filter out[BPF_MAXINSNS];
469*4882a593Smuzhiyun static char **labels, **labels_jt, **labels_jf, **labels_k;
470*4882a593Smuzhiyun 
bpf_assert_max(void)471*4882a593Smuzhiyun static void bpf_assert_max(void)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	if (curr_instr >= BPF_MAXINSNS) {
474*4882a593Smuzhiyun 		fprintf(stderr, "only max %u insns allowed!\n", BPF_MAXINSNS);
475*4882a593Smuzhiyun 		exit(0);
476*4882a593Smuzhiyun 	}
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun 
bpf_set_curr_instr(uint16_t code,uint8_t jt,uint8_t jf,uint32_t k)479*4882a593Smuzhiyun static void bpf_set_curr_instr(uint16_t code, uint8_t jt, uint8_t jf,
480*4882a593Smuzhiyun 			       uint32_t k)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun 	bpf_assert_max();
483*4882a593Smuzhiyun 	out[curr_instr].code = code;
484*4882a593Smuzhiyun 	out[curr_instr].jt = jt;
485*4882a593Smuzhiyun 	out[curr_instr].jf = jf;
486*4882a593Smuzhiyun 	out[curr_instr].k = k;
487*4882a593Smuzhiyun 	curr_instr++;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun 
bpf_set_curr_label(char * label)490*4882a593Smuzhiyun static void bpf_set_curr_label(char *label)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun 	bpf_assert_max();
493*4882a593Smuzhiyun 	labels[curr_instr] = label;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun 
bpf_set_jmp_label(char * label,enum jmp_type type)496*4882a593Smuzhiyun static void bpf_set_jmp_label(char *label, enum jmp_type type)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun 	bpf_assert_max();
499*4882a593Smuzhiyun 	switch (type) {
500*4882a593Smuzhiyun 	case JTL:
501*4882a593Smuzhiyun 		labels_jt[curr_instr] = label;
502*4882a593Smuzhiyun 		break;
503*4882a593Smuzhiyun 	case JFL:
504*4882a593Smuzhiyun 		labels_jf[curr_instr] = label;
505*4882a593Smuzhiyun 		break;
506*4882a593Smuzhiyun 	case JKL:
507*4882a593Smuzhiyun 		labels_k[curr_instr] = label;
508*4882a593Smuzhiyun 		break;
509*4882a593Smuzhiyun 	}
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun 
bpf_find_insns_offset(const char * label)512*4882a593Smuzhiyun static int bpf_find_insns_offset(const char *label)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun 	int i, max = curr_instr, ret = -ENOENT;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	for (i = 0; i < max; i++) {
517*4882a593Smuzhiyun 		if (labels[i] && !strcmp(label, labels[i])) {
518*4882a593Smuzhiyun 			ret = i;
519*4882a593Smuzhiyun 			break;
520*4882a593Smuzhiyun 		}
521*4882a593Smuzhiyun 	}
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	if (ret == -ENOENT) {
524*4882a593Smuzhiyun 		fprintf(stderr, "no such label \'%s\'!\n", label);
525*4882a593Smuzhiyun 		exit(0);
526*4882a593Smuzhiyun 	}
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	return ret;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun 
bpf_stage_1_insert_insns(void)531*4882a593Smuzhiyun static void bpf_stage_1_insert_insns(void)
532*4882a593Smuzhiyun {
533*4882a593Smuzhiyun 	yyparse();
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun 
bpf_reduce_k_jumps(void)536*4882a593Smuzhiyun static void bpf_reduce_k_jumps(void)
537*4882a593Smuzhiyun {
538*4882a593Smuzhiyun 	int i;
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	for (i = 0; i < curr_instr; i++) {
541*4882a593Smuzhiyun 		if (labels_k[i]) {
542*4882a593Smuzhiyun 			int off = bpf_find_insns_offset(labels_k[i]);
543*4882a593Smuzhiyun 			out[i].k = (uint32_t) (off - i - 1);
544*4882a593Smuzhiyun 		}
545*4882a593Smuzhiyun 	}
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun 
bpf_encode_jt_jf_offset(int off,int i)548*4882a593Smuzhiyun static uint8_t bpf_encode_jt_jf_offset(int off, int i)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun 	int delta = off - i - 1;
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	if (delta < 0 || delta > 255)
553*4882a593Smuzhiyun 		fprintf(stderr, "warning: insn #%d jumps to insn #%d, "
554*4882a593Smuzhiyun 				"which is out of range\n", i, off);
555*4882a593Smuzhiyun 	return (uint8_t) delta;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun 
bpf_reduce_jt_jumps(void)558*4882a593Smuzhiyun static void bpf_reduce_jt_jumps(void)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun 	int i;
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 	for (i = 0; i < curr_instr; i++) {
563*4882a593Smuzhiyun 		if (labels_jt[i]) {
564*4882a593Smuzhiyun 			int off = bpf_find_insns_offset(labels_jt[i]);
565*4882a593Smuzhiyun 			out[i].jt = bpf_encode_jt_jf_offset(off, i);
566*4882a593Smuzhiyun 		}
567*4882a593Smuzhiyun 	}
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun 
bpf_reduce_jf_jumps(void)570*4882a593Smuzhiyun static void bpf_reduce_jf_jumps(void)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun 	int i;
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	for (i = 0; i < curr_instr; i++) {
575*4882a593Smuzhiyun 		if (labels_jf[i]) {
576*4882a593Smuzhiyun 			int off = bpf_find_insns_offset(labels_jf[i]);
577*4882a593Smuzhiyun 			out[i].jf = bpf_encode_jt_jf_offset(off, i);
578*4882a593Smuzhiyun 		}
579*4882a593Smuzhiyun 	}
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun 
bpf_stage_2_reduce_labels(void)582*4882a593Smuzhiyun static void bpf_stage_2_reduce_labels(void)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun 	bpf_reduce_k_jumps();
585*4882a593Smuzhiyun 	bpf_reduce_jt_jumps();
586*4882a593Smuzhiyun 	bpf_reduce_jf_jumps();
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun 
bpf_pretty_print_c(void)589*4882a593Smuzhiyun static void bpf_pretty_print_c(void)
590*4882a593Smuzhiyun {
591*4882a593Smuzhiyun 	int i;
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 	for (i = 0; i < curr_instr; i++)
594*4882a593Smuzhiyun 		printf("{ %#04x, %2u, %2u, %#010x },\n", out[i].code,
595*4882a593Smuzhiyun 		       out[i].jt, out[i].jf, out[i].k);
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun 
bpf_pretty_print(void)598*4882a593Smuzhiyun static void bpf_pretty_print(void)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun 	int i;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	printf("%u,", curr_instr);
603*4882a593Smuzhiyun 	for (i = 0; i < curr_instr; i++)
604*4882a593Smuzhiyun 		printf("%u %u %u %u,", out[i].code,
605*4882a593Smuzhiyun 		       out[i].jt, out[i].jf, out[i].k);
606*4882a593Smuzhiyun 	printf("\n");
607*4882a593Smuzhiyun }
608*4882a593Smuzhiyun 
bpf_init(void)609*4882a593Smuzhiyun static void bpf_init(void)
610*4882a593Smuzhiyun {
611*4882a593Smuzhiyun 	memset(out, 0, sizeof(out));
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	labels = calloc(BPF_MAXINSNS, sizeof(*labels));
614*4882a593Smuzhiyun 	assert(labels);
615*4882a593Smuzhiyun 	labels_jt = calloc(BPF_MAXINSNS, sizeof(*labels_jt));
616*4882a593Smuzhiyun 	assert(labels_jt);
617*4882a593Smuzhiyun 	labels_jf = calloc(BPF_MAXINSNS, sizeof(*labels_jf));
618*4882a593Smuzhiyun 	assert(labels_jf);
619*4882a593Smuzhiyun 	labels_k = calloc(BPF_MAXINSNS, sizeof(*labels_k));
620*4882a593Smuzhiyun 	assert(labels_k);
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun 
bpf_destroy_labels(void)623*4882a593Smuzhiyun static void bpf_destroy_labels(void)
624*4882a593Smuzhiyun {
625*4882a593Smuzhiyun 	int i;
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 	for (i = 0; i < curr_instr; i++) {
628*4882a593Smuzhiyun 		free(labels_jf[i]);
629*4882a593Smuzhiyun 		free(labels_jt[i]);
630*4882a593Smuzhiyun 		free(labels_k[i]);
631*4882a593Smuzhiyun 		free(labels[i]);
632*4882a593Smuzhiyun 	}
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun 
bpf_destroy(void)635*4882a593Smuzhiyun static void bpf_destroy(void)
636*4882a593Smuzhiyun {
637*4882a593Smuzhiyun 	bpf_destroy_labels();
638*4882a593Smuzhiyun 	free(labels_jt);
639*4882a593Smuzhiyun 	free(labels_jf);
640*4882a593Smuzhiyun 	free(labels_k);
641*4882a593Smuzhiyun 	free(labels);
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun 
bpf_asm_compile(FILE * fp,bool cstyle)644*4882a593Smuzhiyun void bpf_asm_compile(FILE *fp, bool cstyle)
645*4882a593Smuzhiyun {
646*4882a593Smuzhiyun 	yyin = fp;
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	bpf_init();
649*4882a593Smuzhiyun 	bpf_stage_1_insert_insns();
650*4882a593Smuzhiyun 	bpf_stage_2_reduce_labels();
651*4882a593Smuzhiyun 	bpf_destroy();
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 	if (cstyle)
654*4882a593Smuzhiyun 		bpf_pretty_print_c();
655*4882a593Smuzhiyun 	else
656*4882a593Smuzhiyun 		bpf_pretty_print();
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun 	if (fp != stdin)
659*4882a593Smuzhiyun 		fclose(yyin);
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun 
yyerror(const char * str)662*4882a593Smuzhiyun void yyerror(const char *str)
663*4882a593Smuzhiyun {
664*4882a593Smuzhiyun 	fprintf(stderr, "error: %s at line %d\n", str, yylineno);
665*4882a593Smuzhiyun 	exit(1);
666*4882a593Smuzhiyun }
667