2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
5 * Swiss federal institute of technology (ETH Zurich)
6 * Subject to the GPL, version 2.
9 /* yaac-func-prefix: yy */
22 #include "bpf_parser.tab.h"
26 #define MAX_INSTRUCTIONS 4096
28 int compile_filter
(char *file
, int verbose
, int bypass
);
30 static int curr_instr
= 0;
32 static struct sock_filter out
[MAX_INSTRUCTIONS
];
34 static char *labels
[MAX_INSTRUCTIONS
];
36 static char *labels_jt
[MAX_INSTRUCTIONS
];
37 static char *labels_jf
[MAX_INSTRUCTIONS
];
38 static char *labels_k
[MAX_INSTRUCTIONS
];
40 #define YYERROR_VERBOSE 0
42 #define YYENABLE_NLS 1
43 #define YYLTYPE_IS_TRIVIAL 1
47 extern
int yylex(void);
48 extern
void yyerror(const char *);
52 static inline
void check_max_instr
(void)
54 if
(curr_instr
>= MAX_INSTRUCTIONS
)
55 panic
("Exceeded maximal number of instructions!\n");
58 static inline
void set_curr_instr
(uint16_t code
, uint8_t jt
, uint8_t jf
, uint32_t k
)
62 out
[curr_instr
].code
= code
;
63 out
[curr_instr
].jt
= jt
;
64 out
[curr_instr
].jf
= jf
;
65 out
[curr_instr
].k
= k
;
70 static inline
void set_curr_label
(char *label
)
74 labels
[curr_instr
] = label
;
81 static inline
void set_jmp_label
(char *label
, int which
)
87 labels_jt
[curr_instr
] = label
;
90 labels_jf
[curr_instr
] = label
;
93 labels_k
[curr_instr
] = label
;
100 static int find_intr_offset_or_panic
(char *label_to_search
)
102 int i
, max
= curr_instr
, ret
= -ENOENT
;
104 bug_on
(!label_to_search
);
106 for
(i
= 0; i
< max
; ++i
) {
107 if
(labels
[i
] != NULL
) {
108 /* Both are \0-terminated! */
109 if
(!strcmp
(label_to_search
, labels
[i
])) {
117 panic
("No such label!\n");
129 %token OP_LDB OP_LDH OP_LD OP_LDX OP_ST OP_STX OP_JMP OP_JEQ OP_JGT OP_JGE
130 %token OP_JSET OP_ADD OP_SUB OP_MUL OP_DIV OP_AND OP_OR OP_XOR OP_LSH OP_RSH
131 %token OP_RET OP_TAX OP_TXA OP_LDXB OP_MOD OP_NEG OP_JNEQ OP_JLT OP_JLE OP_LDI
134 %token K_PKT_LEN K_PROTO K_TYPE K_NLATTR K_NLATTR_NEST K_MARK K_QUEUE K_HATYPE
135 %token K_RXHASH K_CPU K_IFIDX K_VLANT K_VLANP
139 %token
':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#'
143 %type
<number
> number
196 : label
':' { set_curr_label
($1); }
200 : OP_LDB
'[' 'x' '+' number
']' {
201 set_curr_instr
(BPF_LD | BPF_B | BPF_IND
, 0, 0, $5); }
202 | OP_LDB
'[' number
']' {
203 set_curr_instr
(BPF_LD | BPF_B | BPF_ABS
, 0, 0, $3); }
204 | OP_LDB HOPT K_PROTO
{
205 set_curr_instr
(BPF_LD | BPF_B | BPF_ABS
, 0, 0,
206 SKF_AD_OFF
+ SKF_AD_PROTOCOL
); }
207 | OP_LDB HOPT K_TYPE
{
208 set_curr_instr
(BPF_LD | BPF_B | BPF_ABS
, 0, 0,
209 SKF_AD_OFF
+ SKF_AD_PKTTYPE
); }
210 | OP_LDB HOPT K_IFIDX
{
211 set_curr_instr
(BPF_LD | BPF_B | BPF_ABS
, 0, 0,
212 SKF_AD_OFF
+ SKF_AD_IFINDEX
); }
213 | OP_LDB HOPT K_NLATTR
{
214 set_curr_instr
(BPF_LD | BPF_B | BPF_ABS
, 0, 0,
215 SKF_AD_OFF
+ SKF_AD_NLATTR
); }
216 | OP_LDB HOPT K_NLATTR_NEST
{
217 set_curr_instr
(BPF_LD | BPF_B | BPF_ABS
, 0, 0,
218 SKF_AD_OFF
+ SKF_AD_NLATTR_NEST
); }
219 | OP_LDB HOPT K_MARK
{
220 set_curr_instr
(BPF_LD | BPF_B | BPF_ABS
, 0, 0,
221 SKF_AD_OFF
+ SKF_AD_MARK
); }
222 | OP_LDB HOPT K_QUEUE
{
223 set_curr_instr
(BPF_LD | BPF_B | BPF_ABS
, 0, 0,
224 SKF_AD_OFF
+ SKF_AD_QUEUE
); }
225 | OP_LDB HOPT K_HATYPE
{
226 set_curr_instr
(BPF_LD | BPF_B | BPF_ABS
, 0, 0,
227 SKF_AD_OFF
+ SKF_AD_HATYPE
); }
228 | OP_LDB HOPT K_RXHASH
{
229 set_curr_instr
(BPF_LD | BPF_B | BPF_ABS
, 0, 0,
230 SKF_AD_OFF
+ SKF_AD_RXHASH
); }
231 | OP_LDB HOPT K_CPU
{
232 set_curr_instr
(BPF_LD | BPF_B | BPF_ABS
, 0, 0,
233 SKF_AD_OFF
+ SKF_AD_CPU
); }
234 | OP_LDB HOPT K_VLANT
{
235 set_curr_instr
(BPF_LD | BPF_B | BPF_ABS
, 0, 0,
236 SKF_AD_OFF
+ SKF_AD_VLAN_TAG
); }
237 | OP_LDB HOPT K_VLANP
{
238 set_curr_instr
(BPF_LD | BPF_B | BPF_ABS
, 0, 0,
239 SKF_AD_OFF
+ SKF_AD_VLAN_TAG_PRESENT
); }
243 : OP_LDH
'[' 'x' '+' number
']' {
244 set_curr_instr
(BPF_LD | BPF_H | BPF_IND
, 0, 0, $5); }
245 | OP_LDH
'[' number
']' {
246 set_curr_instr
(BPF_LD | BPF_H | BPF_ABS
, 0, 0, $3); }
247 | OP_LDH HOPT K_PROTO
{
248 set_curr_instr
(BPF_LD | BPF_H | BPF_ABS
, 0, 0,
249 SKF_AD_OFF
+ SKF_AD_PROTOCOL
); }
250 | OP_LDH HOPT K_TYPE
{
251 set_curr_instr
(BPF_LD | BPF_H | BPF_ABS
, 0, 0,
252 SKF_AD_OFF
+ SKF_AD_PKTTYPE
); }
253 | OP_LDH HOPT K_IFIDX
{
254 set_curr_instr
(BPF_LD | BPF_H | BPF_ABS
, 0, 0,
255 SKF_AD_OFF
+ SKF_AD_IFINDEX
); }
256 | OP_LDH HOPT K_NLATTR
{
257 set_curr_instr
(BPF_LD | BPF_H | BPF_ABS
, 0, 0,
258 SKF_AD_OFF
+ SKF_AD_NLATTR
); }
259 | OP_LDH HOPT K_NLATTR_NEST
{
260 set_curr_instr
(BPF_LD | BPF_H | BPF_ABS
, 0, 0,
261 SKF_AD_OFF
+ SKF_AD_NLATTR_NEST
); }
262 | OP_LDH HOPT K_MARK
{
263 set_curr_instr
(BPF_LD | BPF_H | BPF_ABS
, 0, 0,
264 SKF_AD_OFF
+ SKF_AD_MARK
); }
265 | OP_LDH HOPT K_QUEUE
{
266 set_curr_instr
(BPF_LD | BPF_H | BPF_ABS
, 0, 0,
267 SKF_AD_OFF
+ SKF_AD_QUEUE
); }
268 | OP_LDH HOPT K_HATYPE
{
269 set_curr_instr
(BPF_LD | BPF_H | BPF_ABS
, 0, 0,
270 SKF_AD_OFF
+ SKF_AD_HATYPE
); }
271 | OP_LDH HOPT K_RXHASH
{
272 set_curr_instr
(BPF_LD | BPF_H | BPF_ABS
, 0, 0,
273 SKF_AD_OFF
+ SKF_AD_RXHASH
); }
274 | OP_LDH HOPT K_CPU
{
275 set_curr_instr
(BPF_LD | BPF_H | BPF_ABS
, 0, 0,
276 SKF_AD_OFF
+ SKF_AD_CPU
); }
277 | OP_LDH HOPT K_VLANT
{
278 set_curr_instr
(BPF_LD | BPF_H | BPF_ABS
, 0, 0,
279 SKF_AD_OFF
+ SKF_AD_VLAN_TAG
); }
280 | OP_LDH HOPT K_VLANP
{
281 set_curr_instr
(BPF_LD | BPF_H | BPF_ABS
, 0, 0,
282 SKF_AD_OFF
+ SKF_AD_VLAN_TAG_PRESENT
); }
287 set_curr_instr
(BPF_LD | BPF_IMM
, 0, 0, $2); }
292 set_curr_instr
(BPF_LD | BPF_IMM
, 0, 0, $3); }
293 | OP_LD HOPT K_PKT_LEN
{
294 set_curr_instr
(BPF_LD | BPF_W | BPF_LEN
, 0, 0, 0); }
295 | OP_LD HOPT K_PROTO
{
296 set_curr_instr
(BPF_LD | BPF_W | BPF_ABS
, 0, 0,
297 SKF_AD_OFF
+ SKF_AD_PROTOCOL
); }
298 | OP_LD HOPT K_TYPE
{
299 set_curr_instr
(BPF_LD | BPF_W | BPF_ABS
, 0, 0,
300 SKF_AD_OFF
+ SKF_AD_PKTTYPE
); }
301 | OP_LD HOPT K_IFIDX
{
302 set_curr_instr
(BPF_LD | BPF_W | BPF_ABS
, 0, 0,
303 SKF_AD_OFF
+ SKF_AD_IFINDEX
); }
304 | OP_LD HOPT K_NLATTR
{
305 set_curr_instr
(BPF_LD | BPF_W | BPF_ABS
, 0, 0,
306 SKF_AD_OFF
+ SKF_AD_NLATTR
); }
307 | OP_LD HOPT K_NLATTR_NEST
{
308 set_curr_instr
(BPF_LD | BPF_W | BPF_ABS
, 0, 0,
309 SKF_AD_OFF
+ SKF_AD_NLATTR_NEST
); }
310 | OP_LD HOPT K_MARK
{
311 set_curr_instr
(BPF_LD | BPF_W | BPF_ABS
, 0, 0,
312 SKF_AD_OFF
+ SKF_AD_MARK
); }
313 | OP_LD HOPT K_QUEUE
{
314 set_curr_instr
(BPF_LD | BPF_W | BPF_ABS
, 0, 0,
315 SKF_AD_OFF
+ SKF_AD_QUEUE
); }
316 | OP_LD HOPT K_HATYPE
{
317 set_curr_instr
(BPF_LD | BPF_W | BPF_ABS
, 0, 0,
318 SKF_AD_OFF
+ SKF_AD_HATYPE
); }
319 | OP_LD HOPT K_RXHASH
{
320 set_curr_instr
(BPF_LD | BPF_W | BPF_ABS
, 0, 0,
321 SKF_AD_OFF
+ SKF_AD_RXHASH
); }
323 set_curr_instr
(BPF_LD | BPF_W | BPF_ABS
, 0, 0,
324 SKF_AD_OFF
+ SKF_AD_CPU
); }
325 | OP_LD HOPT K_VLANT
{
326 set_curr_instr
(BPF_LD | BPF_W | BPF_ABS
, 0, 0,
327 SKF_AD_OFF
+ SKF_AD_VLAN_TAG
); }
328 | OP_LD HOPT K_VLANP
{
329 set_curr_instr
(BPF_LD | BPF_W | BPF_ABS
, 0, 0,
330 SKF_AD_OFF
+ SKF_AD_VLAN_TAG_PRESENT
); }
331 | OP_LD
'M' '[' number
']' {
332 set_curr_instr
(BPF_LD | BPF_MEM
, 0, 0, $4); }
333 | OP_LD
'[' 'x' '+' number
']' {
334 set_curr_instr
(BPF_LD | BPF_W | BPF_IND
, 0, 0, $5); }
335 | OP_LD
'[' number
']' {
336 set_curr_instr
(BPF_LD | BPF_W | BPF_ABS
, 0, 0, $3); }
341 set_curr_instr
(BPF_LDX | BPF_IMM
, 0, 0, $2); }
345 : OP_LDX
'#' number
{
346 set_curr_instr
(BPF_LDX | BPF_IMM
, 0, 0, $3); }
347 | OP_LDX
'M' '[' number
']' {
348 set_curr_instr
(BPF_LDX | BPF_MEM
, 0, 0, $4); }
349 | OP_LDXB number
'*' '(' '[' number
']' '&' number
')' {
350 if
($2 != 4 ||
$9 != 0xf) {
351 panic
("ldxb offset not supported!\n");
353 set_curr_instr
(BPF_LDX | BPF_MSH | BPF_B
, 0, 0, $6); } }
354 | OP_LDX number
'*' '(' '[' number
']' '&' number
')' {
355 if
($2 != 4 ||
$9 != 0xf) {
356 panic
("ldxb offset not supported!\n");
358 set_curr_instr
(BPF_LDX | BPF_MSH | BPF_B
, 0, 0, $6); } }
362 : OP_ST
'M' '[' number
']' {
363 set_curr_instr
(BPF_ST
, 0, 0, $4); }
367 : OP_STX
'M' '[' number
']' {
368 set_curr_instr
(BPF_STX
, 0, 0, $4); }
373 set_jmp_label
($2, JKL
);
374 set_curr_instr
(BPF_JMP | BPF_JA
, 0, 0, 0); }
378 : OP_JEQ
'#' number
',' label
',' label
{
379 set_jmp_label
($5, JTL
);
380 set_jmp_label
($7, JFL
);
381 set_curr_instr
(BPF_JMP | BPF_JEQ | BPF_K
, 0, 0, $3); }
382 | OP_JEQ
'x' ',' label
',' label
{
383 set_jmp_label
($4, JTL
);
384 set_jmp_label
($6, JFL
);
385 set_curr_instr
(BPF_JMP | BPF_JEQ | BPF_X
, 0, 0, 0); }
386 | OP_JEQ
'#' number
',' label
{
387 set_jmp_label
($5, JTL
);
388 set_curr_instr
(BPF_JMP | BPF_JEQ | BPF_K
, 0, 0, $3); }
389 | OP_JEQ
'x' ',' label
{
390 set_jmp_label
($4, JTL
);
391 set_curr_instr
(BPF_JMP | BPF_JEQ | BPF_X
, 0, 0, 0); }
395 : OP_JNEQ
'#' number
',' label
{
396 set_jmp_label
($5, JFL
);
397 set_curr_instr
(BPF_JMP | BPF_JEQ | BPF_K
, 0, 0, $3); }
398 | OP_JNEQ
'x' ',' label
{
399 set_jmp_label
($4, JFL
);
400 set_curr_instr
(BPF_JMP | BPF_JEQ | BPF_X
, 0, 0, 0); }
404 : OP_JLT
'#' number
',' label
{
405 set_jmp_label
($5, JFL
);
406 set_curr_instr
(BPF_JMP | BPF_JGE | BPF_K
, 0, 0, $3); }
407 | OP_JLT
'x' ',' label
{
408 set_jmp_label
($4, JFL
);
409 set_curr_instr
(BPF_JMP | BPF_JGE | BPF_X
, 0, 0, 0); }
413 : OP_JLE
'#' number
',' label
{
414 set_jmp_label
($5, JFL
);
415 set_curr_instr
(BPF_JMP | BPF_JGT | BPF_K
, 0, 0, $3); }
416 | OP_JLE
'x' ',' label
{
417 set_jmp_label
($4, JFL
);
418 set_curr_instr
(BPF_JMP | BPF_JGT | BPF_X
, 0, 0, 0); }
422 : OP_JGT
'#' number
',' label
',' label
{
423 set_jmp_label
($5, JTL
);
424 set_jmp_label
($7, JFL
);
425 set_curr_instr
(BPF_JMP | BPF_JGT | BPF_K
, 0, 0, $3); }
426 | OP_JGT
'x' ',' label
',' label
{
427 set_jmp_label
($4, JTL
);
428 set_jmp_label
($6, JFL
);
429 set_curr_instr
(BPF_JMP | BPF_JGT | BPF_X
, 0, 0, 0); }
430 | OP_JGT
'#' number
',' label
{
431 set_jmp_label
($5, JTL
);
432 set_curr_instr
(BPF_JMP | BPF_JGT | BPF_K
, 0, 0, $3); }
433 | OP_JGT
'x' ',' label
{
434 set_jmp_label
($4, JTL
);
435 set_curr_instr
(BPF_JMP | BPF_JGT | BPF_X
, 0, 0, 0); }
439 : OP_JGE
'#' number
',' label
',' label
{
440 set_jmp_label
($5, JTL
);
441 set_jmp_label
($7, JFL
);
442 set_curr_instr
(BPF_JMP | BPF_JGE | BPF_K
, 0, 0, $3); }
443 | OP_JGE
'x' ',' label
',' label
{
444 set_jmp_label
($4, JTL
);
445 set_jmp_label
($6, JFL
);
446 set_curr_instr
(BPF_JMP | BPF_JGE | BPF_X
, 0, 0, 0); }
447 | OP_JGE
'#' number
',' label
{
448 set_jmp_label
($5, JTL
);
449 set_curr_instr
(BPF_JMP | BPF_JGE | BPF_K
, 0, 0, $3); }
450 | OP_JGE
'x' ',' label
{
451 set_jmp_label
($4, JTL
);
452 set_curr_instr
(BPF_JMP | BPF_JGE | BPF_X
, 0, 0, 0); }
456 : OP_JSET
'#' number
',' label
',' label
{
457 set_jmp_label
($5, JTL
);
458 set_jmp_label
($7, JFL
);
459 set_curr_instr
(BPF_JMP | BPF_JSET | BPF_K
, 0, 0, $3); }
460 | OP_JSET
'x' ',' label
',' label
{
461 set_jmp_label
($4, JTL
);
462 set_jmp_label
($6, JFL
);
463 set_curr_instr
(BPF_JMP | BPF_JSET | BPF_X
, 0, 0, 0); }
464 | OP_JSET
'#' number
',' label
{
465 set_jmp_label
($5, JTL
);
466 set_curr_instr
(BPF_JMP | BPF_JSET | BPF_K
, 0, 0, $3); }
467 | OP_JSET
'x' ',' label
{
468 set_jmp_label
($4, JTL
);
469 set_curr_instr
(BPF_JMP | BPF_JSET | BPF_X
, 0, 0, 0); }
473 : OP_ADD
'#' number
{
474 set_curr_instr
(BPF_ALU | BPF_ADD | BPF_K
, 0, 0, $3); }
476 set_curr_instr
(BPF_ALU | BPF_ADD | BPF_X
, 0, 0, 0); }
480 : OP_SUB
'#' number
{
481 set_curr_instr
(BPF_ALU | BPF_SUB | BPF_K
, 0, 0, $3); }
483 set_curr_instr
(BPF_ALU | BPF_SUB | BPF_X
, 0, 0, 0); }
487 : OP_MUL
'#' number
{
488 set_curr_instr
(BPF_ALU | BPF_MUL | BPF_K
, 0, 0, $3); }
490 set_curr_instr
(BPF_ALU | BPF_MUL | BPF_X
, 0, 0, 0); }
494 : OP_DIV
'#' number
{
495 set_curr_instr
(BPF_ALU | BPF_DIV | BPF_K
, 0, 0, $3); }
497 set_curr_instr
(BPF_ALU | BPF_DIV | BPF_X
, 0, 0, 0); }
501 : OP_MOD
'#' number
{
502 set_curr_instr
(BPF_ALU | BPF_MOD | BPF_K
, 0, 0, $3); }
504 set_curr_instr
(BPF_ALU | BPF_MOD | BPF_X
, 0, 0, 0); }
509 set_curr_instr
(BPF_ALU | BPF_NEG
, 0, 0, 0); }
513 : OP_AND
'#' number
{
514 set_curr_instr
(BPF_ALU | BPF_AND | BPF_K
, 0, 0, $3); }
516 set_curr_instr
(BPF_ALU | BPF_AND | BPF_X
, 0, 0, 0); }
521 set_curr_instr
(BPF_ALU | BPF_OR | BPF_K
, 0, 0, $3); }
523 set_curr_instr
(BPF_ALU | BPF_OR | BPF_X
, 0, 0, 0); }
527 : OP_XOR
'#' number
{
528 set_curr_instr
(BPF_ALU | BPF_XOR | BPF_K
, 0, 0, $3); }
530 set_curr_instr
(BPF_ALU | BPF_XOR | BPF_X
, 0, 0, 0); }
534 : OP_LSH
'#' number
{
535 set_curr_instr
(BPF_ALU | BPF_LSH | BPF_K
, 0, 0, $3); }
537 set_curr_instr
(BPF_ALU | BPF_LSH | BPF_X
, 0, 0, 0); }
541 : OP_RSH
'#' number
{
542 set_curr_instr
(BPF_ALU | BPF_RSH | BPF_K
, 0, 0, $3); }
544 set_curr_instr
(BPF_ALU | BPF_RSH | BPF_X
, 0, 0, 0); }
549 set_curr_instr
(BPF_RET | BPF_A
, 0, 0, 0); }
551 set_curr_instr
(BPF_RET | BPF_X
, 0, 0, 0); }
552 | OP_RET
'#' number
{
553 set_curr_instr
(BPF_RET | BPF_K
, 0, 0, $3); }
558 set_curr_instr
(BPF_MISC | BPF_TAX
, 0, 0, 0); }
563 set_curr_instr
(BPF_MISC | BPF_TXA
, 0, 0, 0); }
568 static void stage_1_inline
(void)
573 static void stage_2_label_reduce
(void)
575 int i
, max
= curr_instr
, off
;
577 /* 1. reduce k jumps */
578 for
(i
= 0; i
< max
; ++i
) {
579 if
(labels_k
[i
] != NULL
) {
580 off
= find_intr_offset_or_panic
(labels_k
[i
]);
581 out
[i
].k
= (uint32_t) (off
- i
- 1);
585 /* 1. reduce jt jumps */
586 for
(i
= 0; i
< max
; ++i
) {
587 if
(labels_jt
[i
] != NULL
) {
588 off
= find_intr_offset_or_panic
(labels_jt
[i
]);
589 out
[i
].jt
= (uint8_t) (off
- i
-1);
593 /* 1. reduce jf jumps */
594 for
(i
= 0; i
< max
; ++i
) {
595 if
(labels_jf
[i
] != NULL
) {
596 off
= find_intr_offset_or_panic
(labels_jf
[i
]);
597 out
[i
].jf
= (uint8_t) (off
- i
- 1);
602 int compile_filter
(char *file
, int verbose
, int bypass
)
605 struct sock_fprog res
;
607 if
(!strncmp
("-", file
, strlen
("-")))
610 yyin
= fopen
(file
, "r");
612 panic
("Cannot open file!\n");
614 memset
(out
, 0, sizeof
(out
));
615 memset
(labels
, 0, sizeof
(labels
));
616 memset
(labels_jf
, 0, sizeof
(labels_jf
));
617 memset
(labels_jt
, 0, sizeof
(labels_jt
));
618 memset
(labels_k
, 0, sizeof
(labels_k
));
621 stage_2_label_reduce
();
624 res.len
= curr_instr
;
627 printf
("Generated program:\n");
633 printf
("Validating: ");
637 if
(bpf_validate
(&res
) == 0) {
639 whine
("Semantic error! BPF validation "
642 panic
("Semantic error! BPF validation failed! "
643 "Try -V for debugging output!\n");
644 } else if
(verbose
) {
645 printf
("is runnable!\n");
651 for
(i
= 0; i
< res.len
; ++i
) {
652 printf
("{ 0x%x, %u, %u, 0x%08x },\n",
653 res.filter
[i
].code
, res.filter
[i
].jt
,
654 res.filter
[i
].jf
, res.filter
[i
].k
);
655 if
(labels
[i
] != NULL
)
657 if
(labels_jt
[i
] != NULL
)
659 if
(labels_jf
[i
] != NULL
)
661 if
(labels_k
[i
] != NULL
)
669 void yyerror(const char *err
)
671 panic
("Syntax error at line %d: %s! %s!\n",
672 yylineno
, yytext
, err
);