18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * BPF asm code parser
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * This program is free software; you can distribute it and/or modify
58c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published
68c2ecf20Sopenharmony_ci * by the Free Software Foundation; either version 2 of the License,
78c2ecf20Sopenharmony_ci * or (at your option) any later version.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Syntax kept close to:
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * Steven McCanne and Van Jacobson. 1993. The BSD packet filter: a new
128c2ecf20Sopenharmony_ci * architecture for user-level packet capture. In Proceedings of the
138c2ecf20Sopenharmony_ci * USENIX Winter 1993 Conference Proceedings on USENIX Winter 1993
148c2ecf20Sopenharmony_ci * Conference Proceedings (USENIX'93). USENIX Association, Berkeley,
158c2ecf20Sopenharmony_ci * CA, USA, 2-2.
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * Copyright 2013 Daniel Borkmann <borkmann@redhat.com>
188c2ecf20Sopenharmony_ci * Licensed under the GNU General Public License, version 2.0 (GPLv2)
198c2ecf20Sopenharmony_ci */
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci%{
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include <stdio.h>
248c2ecf20Sopenharmony_ci#include <string.h>
258c2ecf20Sopenharmony_ci#include <stdint.h>
268c2ecf20Sopenharmony_ci#include <stdlib.h>
278c2ecf20Sopenharmony_ci#include <stdbool.h>
288c2ecf20Sopenharmony_ci#include <unistd.h>
298c2ecf20Sopenharmony_ci#include <errno.h>
308c2ecf20Sopenharmony_ci#include <assert.h>
318c2ecf20Sopenharmony_ci#include <linux/filter.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#include "bpf_exp.yacc.h"
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cienum jmp_type { JTL, JFL, JKL };
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ciextern FILE *yyin;
388c2ecf20Sopenharmony_ciextern int yylineno;
398c2ecf20Sopenharmony_ciextern int yylex(void);
408c2ecf20Sopenharmony_ciextern void yyerror(const char *str);
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ciextern void bpf_asm_compile(FILE *fp, bool cstyle);
438c2ecf20Sopenharmony_cistatic void bpf_set_curr_instr(uint16_t op, uint8_t jt, uint8_t jf, uint32_t k);
448c2ecf20Sopenharmony_cistatic void bpf_set_curr_label(char *label);
458c2ecf20Sopenharmony_cistatic void bpf_set_jmp_label(char *label, enum jmp_type type);
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci%}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci%union {
508c2ecf20Sopenharmony_ci	char *label;
518c2ecf20Sopenharmony_ci	uint32_t number;
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci%token OP_LDB OP_LDH OP_LD OP_LDX OP_ST OP_STX OP_JMP OP_JEQ OP_JGT OP_JGE
558c2ecf20Sopenharmony_ci%token OP_JSET OP_ADD OP_SUB OP_MUL OP_DIV OP_AND OP_OR OP_XOR OP_LSH OP_RSH
568c2ecf20Sopenharmony_ci%token OP_RET OP_TAX OP_TXA OP_LDXB OP_MOD OP_NEG OP_JNEQ OP_JLT OP_JLE OP_LDI
578c2ecf20Sopenharmony_ci%token OP_LDXI
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci%token K_PKT_LEN
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci%token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%'
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci%token extension number label
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci%type <label> label
668c2ecf20Sopenharmony_ci%type <number> extension
678c2ecf20Sopenharmony_ci%type <number> number
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci%%
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ciprog
728c2ecf20Sopenharmony_ci	: line
738c2ecf20Sopenharmony_ci	| prog line
748c2ecf20Sopenharmony_ci	;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ciline
778c2ecf20Sopenharmony_ci	: instr
788c2ecf20Sopenharmony_ci	| labelled_instr
798c2ecf20Sopenharmony_ci	;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cilabelled_instr
828c2ecf20Sopenharmony_ci	: labelled instr
838c2ecf20Sopenharmony_ci	;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ciinstr
868c2ecf20Sopenharmony_ci	: ldb
878c2ecf20Sopenharmony_ci	| ldh
888c2ecf20Sopenharmony_ci	| ld
898c2ecf20Sopenharmony_ci	| ldi
908c2ecf20Sopenharmony_ci	| ldx
918c2ecf20Sopenharmony_ci	| ldxi
928c2ecf20Sopenharmony_ci	| st
938c2ecf20Sopenharmony_ci	| stx
948c2ecf20Sopenharmony_ci	| jmp
958c2ecf20Sopenharmony_ci	| jeq
968c2ecf20Sopenharmony_ci	| jneq
978c2ecf20Sopenharmony_ci	| jlt
988c2ecf20Sopenharmony_ci	| jle
998c2ecf20Sopenharmony_ci	| jgt
1008c2ecf20Sopenharmony_ci	| jge
1018c2ecf20Sopenharmony_ci	| jset
1028c2ecf20Sopenharmony_ci	| add
1038c2ecf20Sopenharmony_ci	| sub
1048c2ecf20Sopenharmony_ci	| mul
1058c2ecf20Sopenharmony_ci	| div
1068c2ecf20Sopenharmony_ci	| mod
1078c2ecf20Sopenharmony_ci	| neg
1088c2ecf20Sopenharmony_ci	| and
1098c2ecf20Sopenharmony_ci	| or
1108c2ecf20Sopenharmony_ci	| xor
1118c2ecf20Sopenharmony_ci	| lsh
1128c2ecf20Sopenharmony_ci	| rsh
1138c2ecf20Sopenharmony_ci	| ret
1148c2ecf20Sopenharmony_ci	| tax
1158c2ecf20Sopenharmony_ci	| txa
1168c2ecf20Sopenharmony_ci	;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cilabelled
1198c2ecf20Sopenharmony_ci	: label ':' { bpf_set_curr_label($1); }
1208c2ecf20Sopenharmony_ci	;
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cildb
1238c2ecf20Sopenharmony_ci	: OP_LDB '[' 'x' '+' number ']' {
1248c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $5); }
1258c2ecf20Sopenharmony_ci	| OP_LDB '[' '%' 'x' '+' number ']' {
1268c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $6); }
1278c2ecf20Sopenharmony_ci	| OP_LDB '[' number ']' {
1288c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, $3); }
1298c2ecf20Sopenharmony_ci	| OP_LDB extension {
1308c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
1318c2ecf20Sopenharmony_ci				   SKF_AD_OFF + $2); }
1328c2ecf20Sopenharmony_ci	;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cildh
1358c2ecf20Sopenharmony_ci	: OP_LDH '[' 'x' '+' number ']' {
1368c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $5); }
1378c2ecf20Sopenharmony_ci	| OP_LDH '[' '%' 'x' '+' number ']' {
1388c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $6); }
1398c2ecf20Sopenharmony_ci	| OP_LDH '[' number ']' {
1408c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, $3); }
1418c2ecf20Sopenharmony_ci	| OP_LDH extension {
1428c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
1438c2ecf20Sopenharmony_ci				   SKF_AD_OFF + $2); }
1448c2ecf20Sopenharmony_ci	;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cildi
1478c2ecf20Sopenharmony_ci	: OP_LDI '#' number {
1488c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }
1498c2ecf20Sopenharmony_ci	| OP_LDI number {
1508c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $2); }
1518c2ecf20Sopenharmony_ci	;
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_cild
1548c2ecf20Sopenharmony_ci	: OP_LD '#' number {
1558c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }
1568c2ecf20Sopenharmony_ci	| OP_LD K_PKT_LEN {
1578c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_LEN, 0, 0, 0); }
1588c2ecf20Sopenharmony_ci	| OP_LD extension {
1598c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
1608c2ecf20Sopenharmony_ci				   SKF_AD_OFF + $2); }
1618c2ecf20Sopenharmony_ci	| OP_LD 'M' '[' number ']' {
1628c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); }
1638c2ecf20Sopenharmony_ci	| OP_LD '[' 'x' '+' number ']' {
1648c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $5); }
1658c2ecf20Sopenharmony_ci	| OP_LD '[' '%' 'x' '+' number ']' {
1668c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $6); }
1678c2ecf20Sopenharmony_ci	| OP_LD '[' number ']' {
1688c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, $3); }
1698c2ecf20Sopenharmony_ci	;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_cildxi
1728c2ecf20Sopenharmony_ci	: OP_LDXI '#' number {
1738c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }
1748c2ecf20Sopenharmony_ci	| OP_LDXI number {
1758c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $2); }
1768c2ecf20Sopenharmony_ci	;
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_cildx
1798c2ecf20Sopenharmony_ci	: OP_LDX '#' number {
1808c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }
1818c2ecf20Sopenharmony_ci	| OP_LDX K_PKT_LEN {
1828c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LDX | BPF_W | BPF_LEN, 0, 0, 0); }
1838c2ecf20Sopenharmony_ci	| OP_LDX 'M' '[' number ']' {
1848c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_LDX | BPF_MEM, 0, 0, $4); }
1858c2ecf20Sopenharmony_ci	| OP_LDXB number '*' '(' '[' number ']' '&' number ')' {
1868c2ecf20Sopenharmony_ci		if ($2 != 4 || $9 != 0xf) {
1878c2ecf20Sopenharmony_ci			fprintf(stderr, "ldxb offset not supported!\n");
1888c2ecf20Sopenharmony_ci			exit(0);
1898c2ecf20Sopenharmony_ci		} else {
1908c2ecf20Sopenharmony_ci			bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }
1918c2ecf20Sopenharmony_ci	| OP_LDX number '*' '(' '[' number ']' '&' number ')' {
1928c2ecf20Sopenharmony_ci		if ($2 != 4 || $9 != 0xf) {
1938c2ecf20Sopenharmony_ci			fprintf(stderr, "ldxb offset not supported!\n");
1948c2ecf20Sopenharmony_ci			exit(0);
1958c2ecf20Sopenharmony_ci		} else {
1968c2ecf20Sopenharmony_ci			bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }
1978c2ecf20Sopenharmony_ci	;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_cist
2008c2ecf20Sopenharmony_ci	: OP_ST 'M' '[' number ']' {
2018c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ST, 0, 0, $4); }
2028c2ecf20Sopenharmony_ci	;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistx
2058c2ecf20Sopenharmony_ci	: OP_STX 'M' '[' number ']' {
2068c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_STX, 0, 0, $4); }
2078c2ecf20Sopenharmony_ci	;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_cijmp
2108c2ecf20Sopenharmony_ci	: OP_JMP label {
2118c2ecf20Sopenharmony_ci		bpf_set_jmp_label($2, JKL);
2128c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JA, 0, 0, 0); }
2138c2ecf20Sopenharmony_ci	;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_cijeq
2168c2ecf20Sopenharmony_ci	: OP_JEQ '#' number ',' label ',' label {
2178c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
2188c2ecf20Sopenharmony_ci		bpf_set_jmp_label($7, JFL);
2198c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
2208c2ecf20Sopenharmony_ci	| OP_JEQ 'x' ',' label ',' label {
2218c2ecf20Sopenharmony_ci		bpf_set_jmp_label($4, JTL);
2228c2ecf20Sopenharmony_ci		bpf_set_jmp_label($6, JFL);
2238c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
2248c2ecf20Sopenharmony_ci	| OP_JEQ '%' 'x' ',' label ',' label {
2258c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
2268c2ecf20Sopenharmony_ci		bpf_set_jmp_label($7, JFL);
2278c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
2288c2ecf20Sopenharmony_ci	| OP_JEQ '#' number ',' label {
2298c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
2308c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
2318c2ecf20Sopenharmony_ci	| OP_JEQ 'x' ',' label {
2328c2ecf20Sopenharmony_ci		bpf_set_jmp_label($4, JTL);
2338c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
2348c2ecf20Sopenharmony_ci	| OP_JEQ '%' 'x' ',' label {
2358c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
2368c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
2378c2ecf20Sopenharmony_ci	;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_cijneq
2408c2ecf20Sopenharmony_ci	: OP_JNEQ '#' number ',' label {
2418c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JFL);
2428c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
2438c2ecf20Sopenharmony_ci	| OP_JNEQ 'x' ',' label {
2448c2ecf20Sopenharmony_ci		bpf_set_jmp_label($4, JFL);
2458c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
2468c2ecf20Sopenharmony_ci	| OP_JNEQ '%' 'x' ',' label {
2478c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JFL);
2488c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
2498c2ecf20Sopenharmony_ci	;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_cijlt
2528c2ecf20Sopenharmony_ci	: OP_JLT '#' number ',' label {
2538c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JFL);
2548c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
2558c2ecf20Sopenharmony_ci	| OP_JLT 'x' ',' label {
2568c2ecf20Sopenharmony_ci		bpf_set_jmp_label($4, JFL);
2578c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
2588c2ecf20Sopenharmony_ci	| OP_JLT '%' 'x' ',' label {
2598c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JFL);
2608c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
2618c2ecf20Sopenharmony_ci	;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_cijle
2648c2ecf20Sopenharmony_ci	: OP_JLE '#' number ',' label {
2658c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JFL);
2668c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
2678c2ecf20Sopenharmony_ci	| OP_JLE 'x' ',' label {
2688c2ecf20Sopenharmony_ci		bpf_set_jmp_label($4, JFL);
2698c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
2708c2ecf20Sopenharmony_ci	| OP_JLE '%' 'x' ',' label {
2718c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JFL);
2728c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
2738c2ecf20Sopenharmony_ci	;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cijgt
2768c2ecf20Sopenharmony_ci	: OP_JGT '#' number ',' label ',' label {
2778c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
2788c2ecf20Sopenharmony_ci		bpf_set_jmp_label($7, JFL);
2798c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
2808c2ecf20Sopenharmony_ci	| OP_JGT 'x' ',' label ',' label {
2818c2ecf20Sopenharmony_ci		bpf_set_jmp_label($4, JTL);
2828c2ecf20Sopenharmony_ci		bpf_set_jmp_label($6, JFL);
2838c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
2848c2ecf20Sopenharmony_ci	| OP_JGT '%' 'x' ',' label ',' label {
2858c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
2868c2ecf20Sopenharmony_ci		bpf_set_jmp_label($7, JFL);
2878c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
2888c2ecf20Sopenharmony_ci	| OP_JGT '#' number ',' label {
2898c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
2908c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
2918c2ecf20Sopenharmony_ci	| OP_JGT 'x' ',' label {
2928c2ecf20Sopenharmony_ci		bpf_set_jmp_label($4, JTL);
2938c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
2948c2ecf20Sopenharmony_ci	| OP_JGT '%' 'x' ',' label {
2958c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
2968c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
2978c2ecf20Sopenharmony_ci	;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_cijge
3008c2ecf20Sopenharmony_ci	: OP_JGE '#' number ',' label ',' label {
3018c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
3028c2ecf20Sopenharmony_ci		bpf_set_jmp_label($7, JFL);
3038c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
3048c2ecf20Sopenharmony_ci	| OP_JGE 'x' ',' label ',' label {
3058c2ecf20Sopenharmony_ci		bpf_set_jmp_label($4, JTL);
3068c2ecf20Sopenharmony_ci		bpf_set_jmp_label($6, JFL);
3078c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
3088c2ecf20Sopenharmony_ci	| OP_JGE '%' 'x' ',' label ',' label {
3098c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
3108c2ecf20Sopenharmony_ci		bpf_set_jmp_label($7, JFL);
3118c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
3128c2ecf20Sopenharmony_ci	| OP_JGE '#' number ',' label {
3138c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
3148c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
3158c2ecf20Sopenharmony_ci	| OP_JGE 'x' ',' label {
3168c2ecf20Sopenharmony_ci		bpf_set_jmp_label($4, JTL);
3178c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
3188c2ecf20Sopenharmony_ci	| OP_JGE '%' 'x' ',' label {
3198c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
3208c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
3218c2ecf20Sopenharmony_ci	;
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_cijset
3248c2ecf20Sopenharmony_ci	: OP_JSET '#' number ',' label ',' label {
3258c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
3268c2ecf20Sopenharmony_ci		bpf_set_jmp_label($7, JFL);
3278c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }
3288c2ecf20Sopenharmony_ci	| OP_JSET 'x' ',' label ',' label {
3298c2ecf20Sopenharmony_ci		bpf_set_jmp_label($4, JTL);
3308c2ecf20Sopenharmony_ci		bpf_set_jmp_label($6, JFL);
3318c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
3328c2ecf20Sopenharmony_ci	| OP_JSET '%' 'x' ',' label ',' label {
3338c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
3348c2ecf20Sopenharmony_ci		bpf_set_jmp_label($7, JFL);
3358c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
3368c2ecf20Sopenharmony_ci	| OP_JSET '#' number ',' label {
3378c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
3388c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }
3398c2ecf20Sopenharmony_ci	| OP_JSET 'x' ',' label {
3408c2ecf20Sopenharmony_ci		bpf_set_jmp_label($4, JTL);
3418c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
3428c2ecf20Sopenharmony_ci	| OP_JSET '%' 'x' ',' label {
3438c2ecf20Sopenharmony_ci		bpf_set_jmp_label($5, JTL);
3448c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
3458c2ecf20Sopenharmony_ci	;
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ciadd
3488c2ecf20Sopenharmony_ci	: OP_ADD '#' number {
3498c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_K, 0, 0, $3); }
3508c2ecf20Sopenharmony_ci	| OP_ADD 'x' {
3518c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }
3528c2ecf20Sopenharmony_ci	| OP_ADD '%' 'x' {
3538c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }
3548c2ecf20Sopenharmony_ci	;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_cisub
3578c2ecf20Sopenharmony_ci	: OP_SUB '#' number {
3588c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_K, 0, 0, $3); }
3598c2ecf20Sopenharmony_ci	| OP_SUB 'x' {
3608c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }
3618c2ecf20Sopenharmony_ci	| OP_SUB '%' 'x' {
3628c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }
3638c2ecf20Sopenharmony_ci	;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_cimul
3668c2ecf20Sopenharmony_ci	: OP_MUL '#' number {
3678c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_K, 0, 0, $3); }
3688c2ecf20Sopenharmony_ci	| OP_MUL 'x' {
3698c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }
3708c2ecf20Sopenharmony_ci	| OP_MUL '%' 'x' {
3718c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }
3728c2ecf20Sopenharmony_ci	;
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_cidiv
3758c2ecf20Sopenharmony_ci	: OP_DIV '#' number {
3768c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_K, 0, 0, $3); }
3778c2ecf20Sopenharmony_ci	| OP_DIV 'x' {
3788c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }
3798c2ecf20Sopenharmony_ci	| OP_DIV '%' 'x' {
3808c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }
3818c2ecf20Sopenharmony_ci	;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_cimod
3848c2ecf20Sopenharmony_ci	: OP_MOD '#' number {
3858c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_K, 0, 0, $3); }
3868c2ecf20Sopenharmony_ci	| OP_MOD 'x' {
3878c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }
3888c2ecf20Sopenharmony_ci	| OP_MOD '%' 'x' {
3898c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }
3908c2ecf20Sopenharmony_ci	;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_cineg
3938c2ecf20Sopenharmony_ci	: OP_NEG {
3948c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_NEG, 0, 0, 0); }
3958c2ecf20Sopenharmony_ci	;
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ciand
3988c2ecf20Sopenharmony_ci	: OP_AND '#' number {
3998c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_K, 0, 0, $3); }
4008c2ecf20Sopenharmony_ci	| OP_AND 'x' {
4018c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }
4028c2ecf20Sopenharmony_ci	| OP_AND '%' 'x' {
4038c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }
4048c2ecf20Sopenharmony_ci	;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_cior
4078c2ecf20Sopenharmony_ci	: OP_OR '#' number {
4088c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_K, 0, 0, $3); }
4098c2ecf20Sopenharmony_ci	| OP_OR 'x' {
4108c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }
4118c2ecf20Sopenharmony_ci	| OP_OR '%' 'x' {
4128c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }
4138c2ecf20Sopenharmony_ci	;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_cixor
4168c2ecf20Sopenharmony_ci	: OP_XOR '#' number {
4178c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_K, 0, 0, $3); }
4188c2ecf20Sopenharmony_ci	| OP_XOR 'x' {
4198c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }
4208c2ecf20Sopenharmony_ci	| OP_XOR '%' 'x' {
4218c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }
4228c2ecf20Sopenharmony_ci	;
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_cilsh
4258c2ecf20Sopenharmony_ci	: OP_LSH '#' number {
4268c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_K, 0, 0, $3); }
4278c2ecf20Sopenharmony_ci	| OP_LSH 'x' {
4288c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }
4298c2ecf20Sopenharmony_ci	| OP_LSH '%' 'x' {
4308c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }
4318c2ecf20Sopenharmony_ci	;
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_cirsh
4348c2ecf20Sopenharmony_ci	: OP_RSH '#' number {
4358c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_K, 0, 0, $3); }
4368c2ecf20Sopenharmony_ci	| OP_RSH 'x' {
4378c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }
4388c2ecf20Sopenharmony_ci	| OP_RSH '%' 'x' {
4398c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }
4408c2ecf20Sopenharmony_ci	;
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ciret
4438c2ecf20Sopenharmony_ci	: OP_RET 'a' {
4448c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }
4458c2ecf20Sopenharmony_ci	| OP_RET '%' 'a' {
4468c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }
4478c2ecf20Sopenharmony_ci	| OP_RET 'x' {
4488c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }
4498c2ecf20Sopenharmony_ci	| OP_RET '%' 'x' {
4508c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }
4518c2ecf20Sopenharmony_ci	| OP_RET '#' number {
4528c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_RET | BPF_K, 0, 0, $3); }
4538c2ecf20Sopenharmony_ci	;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_citax
4568c2ecf20Sopenharmony_ci	: OP_TAX {
4578c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_MISC | BPF_TAX, 0, 0, 0); }
4588c2ecf20Sopenharmony_ci	;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_citxa
4618c2ecf20Sopenharmony_ci	: OP_TXA {
4628c2ecf20Sopenharmony_ci		bpf_set_curr_instr(BPF_MISC | BPF_TXA, 0, 0, 0); }
4638c2ecf20Sopenharmony_ci	;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci%%
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_cistatic int curr_instr = 0;
4688c2ecf20Sopenharmony_cistatic struct sock_filter out[BPF_MAXINSNS];
4698c2ecf20Sopenharmony_cistatic char **labels, **labels_jt, **labels_jf, **labels_k;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_cistatic void bpf_assert_max(void)
4728c2ecf20Sopenharmony_ci{
4738c2ecf20Sopenharmony_ci	if (curr_instr >= BPF_MAXINSNS) {
4748c2ecf20Sopenharmony_ci		fprintf(stderr, "only max %u insns allowed!\n", BPF_MAXINSNS);
4758c2ecf20Sopenharmony_ci		exit(0);
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ci}
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_cistatic void bpf_set_curr_instr(uint16_t code, uint8_t jt, uint8_t jf,
4808c2ecf20Sopenharmony_ci			       uint32_t k)
4818c2ecf20Sopenharmony_ci{
4828c2ecf20Sopenharmony_ci	bpf_assert_max();
4838c2ecf20Sopenharmony_ci	out[curr_instr].code = code;
4848c2ecf20Sopenharmony_ci	out[curr_instr].jt = jt;
4858c2ecf20Sopenharmony_ci	out[curr_instr].jf = jf;
4868c2ecf20Sopenharmony_ci	out[curr_instr].k = k;
4878c2ecf20Sopenharmony_ci	curr_instr++;
4888c2ecf20Sopenharmony_ci}
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_cistatic void bpf_set_curr_label(char *label)
4918c2ecf20Sopenharmony_ci{
4928c2ecf20Sopenharmony_ci	bpf_assert_max();
4938c2ecf20Sopenharmony_ci	labels[curr_instr] = label;
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic void bpf_set_jmp_label(char *label, enum jmp_type type)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	bpf_assert_max();
4998c2ecf20Sopenharmony_ci	switch (type) {
5008c2ecf20Sopenharmony_ci	case JTL:
5018c2ecf20Sopenharmony_ci		labels_jt[curr_instr] = label;
5028c2ecf20Sopenharmony_ci		break;
5038c2ecf20Sopenharmony_ci	case JFL:
5048c2ecf20Sopenharmony_ci		labels_jf[curr_instr] = label;
5058c2ecf20Sopenharmony_ci		break;
5068c2ecf20Sopenharmony_ci	case JKL:
5078c2ecf20Sopenharmony_ci		labels_k[curr_instr] = label;
5088c2ecf20Sopenharmony_ci		break;
5098c2ecf20Sopenharmony_ci	}
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_cistatic int bpf_find_insns_offset(const char *label)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	int i, max = curr_instr, ret = -ENOENT;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	for (i = 0; i < max; i++) {
5178c2ecf20Sopenharmony_ci		if (labels[i] && !strcmp(label, labels[i])) {
5188c2ecf20Sopenharmony_ci			ret = i;
5198c2ecf20Sopenharmony_ci			break;
5208c2ecf20Sopenharmony_ci		}
5218c2ecf20Sopenharmony_ci	}
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	if (ret == -ENOENT) {
5248c2ecf20Sopenharmony_ci		fprintf(stderr, "no such label \'%s\'!\n", label);
5258c2ecf20Sopenharmony_ci		exit(0);
5268c2ecf20Sopenharmony_ci	}
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	return ret;
5298c2ecf20Sopenharmony_ci}
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_cistatic void bpf_stage_1_insert_insns(void)
5328c2ecf20Sopenharmony_ci{
5338c2ecf20Sopenharmony_ci	yyparse();
5348c2ecf20Sopenharmony_ci}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_cistatic void bpf_reduce_k_jumps(void)
5378c2ecf20Sopenharmony_ci{
5388c2ecf20Sopenharmony_ci	int i;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	for (i = 0; i < curr_instr; i++) {
5418c2ecf20Sopenharmony_ci		if (labels_k[i]) {
5428c2ecf20Sopenharmony_ci			int off = bpf_find_insns_offset(labels_k[i]);
5438c2ecf20Sopenharmony_ci			out[i].k = (uint32_t) (off - i - 1);
5448c2ecf20Sopenharmony_ci		}
5458c2ecf20Sopenharmony_ci	}
5468c2ecf20Sopenharmony_ci}
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_cistatic uint8_t bpf_encode_jt_jf_offset(int off, int i)
5498c2ecf20Sopenharmony_ci{
5508c2ecf20Sopenharmony_ci	int delta = off - i - 1;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	if (delta < 0 || delta > 255)
5538c2ecf20Sopenharmony_ci		fprintf(stderr, "warning: insn #%d jumps to insn #%d, "
5548c2ecf20Sopenharmony_ci				"which is out of range\n", i, off);
5558c2ecf20Sopenharmony_ci	return (uint8_t) delta;
5568c2ecf20Sopenharmony_ci}
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_cistatic void bpf_reduce_jt_jumps(void)
5598c2ecf20Sopenharmony_ci{
5608c2ecf20Sopenharmony_ci	int i;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	for (i = 0; i < curr_instr; i++) {
5638c2ecf20Sopenharmony_ci		if (labels_jt[i]) {
5648c2ecf20Sopenharmony_ci			int off = bpf_find_insns_offset(labels_jt[i]);
5658c2ecf20Sopenharmony_ci			out[i].jt = bpf_encode_jt_jf_offset(off, i);
5668c2ecf20Sopenharmony_ci		}
5678c2ecf20Sopenharmony_ci	}
5688c2ecf20Sopenharmony_ci}
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_cistatic void bpf_reduce_jf_jumps(void)
5718c2ecf20Sopenharmony_ci{
5728c2ecf20Sopenharmony_ci	int i;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	for (i = 0; i < curr_instr; i++) {
5758c2ecf20Sopenharmony_ci		if (labels_jf[i]) {
5768c2ecf20Sopenharmony_ci			int off = bpf_find_insns_offset(labels_jf[i]);
5778c2ecf20Sopenharmony_ci			out[i].jf = bpf_encode_jt_jf_offset(off, i);
5788c2ecf20Sopenharmony_ci		}
5798c2ecf20Sopenharmony_ci	}
5808c2ecf20Sopenharmony_ci}
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_cistatic void bpf_stage_2_reduce_labels(void)
5838c2ecf20Sopenharmony_ci{
5848c2ecf20Sopenharmony_ci	bpf_reduce_k_jumps();
5858c2ecf20Sopenharmony_ci	bpf_reduce_jt_jumps();
5868c2ecf20Sopenharmony_ci	bpf_reduce_jf_jumps();
5878c2ecf20Sopenharmony_ci}
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_cistatic void bpf_pretty_print_c(void)
5908c2ecf20Sopenharmony_ci{
5918c2ecf20Sopenharmony_ci	int i;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	for (i = 0; i < curr_instr; i++)
5948c2ecf20Sopenharmony_ci		printf("{ %#04x, %2u, %2u, %#010x },\n", out[i].code,
5958c2ecf20Sopenharmony_ci		       out[i].jt, out[i].jf, out[i].k);
5968c2ecf20Sopenharmony_ci}
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_cistatic void bpf_pretty_print(void)
5998c2ecf20Sopenharmony_ci{
6008c2ecf20Sopenharmony_ci	int i;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	printf("%u,", curr_instr);
6038c2ecf20Sopenharmony_ci	for (i = 0; i < curr_instr; i++)
6048c2ecf20Sopenharmony_ci		printf("%u %u %u %u,", out[i].code,
6058c2ecf20Sopenharmony_ci		       out[i].jt, out[i].jf, out[i].k);
6068c2ecf20Sopenharmony_ci	printf("\n");
6078c2ecf20Sopenharmony_ci}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_cistatic void bpf_init(void)
6108c2ecf20Sopenharmony_ci{
6118c2ecf20Sopenharmony_ci	memset(out, 0, sizeof(out));
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	labels = calloc(BPF_MAXINSNS, sizeof(*labels));
6148c2ecf20Sopenharmony_ci	assert(labels);
6158c2ecf20Sopenharmony_ci	labels_jt = calloc(BPF_MAXINSNS, sizeof(*labels_jt));
6168c2ecf20Sopenharmony_ci	assert(labels_jt);
6178c2ecf20Sopenharmony_ci	labels_jf = calloc(BPF_MAXINSNS, sizeof(*labels_jf));
6188c2ecf20Sopenharmony_ci	assert(labels_jf);
6198c2ecf20Sopenharmony_ci	labels_k = calloc(BPF_MAXINSNS, sizeof(*labels_k));
6208c2ecf20Sopenharmony_ci	assert(labels_k);
6218c2ecf20Sopenharmony_ci}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_cistatic void bpf_destroy_labels(void)
6248c2ecf20Sopenharmony_ci{
6258c2ecf20Sopenharmony_ci	int i;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	for (i = 0; i < curr_instr; i++) {
6288c2ecf20Sopenharmony_ci		free(labels_jf[i]);
6298c2ecf20Sopenharmony_ci		free(labels_jt[i]);
6308c2ecf20Sopenharmony_ci		free(labels_k[i]);
6318c2ecf20Sopenharmony_ci		free(labels[i]);
6328c2ecf20Sopenharmony_ci	}
6338c2ecf20Sopenharmony_ci}
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_cistatic void bpf_destroy(void)
6368c2ecf20Sopenharmony_ci{
6378c2ecf20Sopenharmony_ci	bpf_destroy_labels();
6388c2ecf20Sopenharmony_ci	free(labels_jt);
6398c2ecf20Sopenharmony_ci	free(labels_jf);
6408c2ecf20Sopenharmony_ci	free(labels_k);
6418c2ecf20Sopenharmony_ci	free(labels);
6428c2ecf20Sopenharmony_ci}
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_civoid bpf_asm_compile(FILE *fp, bool cstyle)
6458c2ecf20Sopenharmony_ci{
6468c2ecf20Sopenharmony_ci	yyin = fp;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	bpf_init();
6498c2ecf20Sopenharmony_ci	bpf_stage_1_insert_insns();
6508c2ecf20Sopenharmony_ci	bpf_stage_2_reduce_labels();
6518c2ecf20Sopenharmony_ci	bpf_destroy();
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	if (cstyle)
6548c2ecf20Sopenharmony_ci		bpf_pretty_print_c();
6558c2ecf20Sopenharmony_ci	else
6568c2ecf20Sopenharmony_ci		bpf_pretty_print();
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	if (fp != stdin)
6598c2ecf20Sopenharmony_ci		fclose(yyin);
6608c2ecf20Sopenharmony_ci}
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_civoid yyerror(const char *str)
6638c2ecf20Sopenharmony_ci{
6648c2ecf20Sopenharmony_ci	fprintf(stderr, "error: %s at line %d\n", str, yylineno);
6658c2ecf20Sopenharmony_ci	exit(1);
6668c2ecf20Sopenharmony_ci}
667