File: iflib_comb.c

package info (click to toggle)
tcng 10b-4
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 3,644 kB
  • sloc: ansic: 19,040; pascal: 4,640; yacc: 2,619; sh: 1,914; perl: 1,546; lex: 772; makefile: 751
file content (109 lines) | stat: -rw-r--r-- 2,506 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
 * iflib_comb.c - Generation of if expressions
 *
 * Written 2001,2002 by Werner Almesberger
 * Copyright 2001 EPFL-ICA, Network Robots
 * Copyright 2002 Network Robots
 */


#include <stdlib.h>

#include "data.h"
#include "tree.h"
#include "param.h"
#include "op.h"
#include "filter.h"
#include "iflib.h"


/*
 * @@@ does not handle nested ifs properly
 */


/* ----- Add "class" decisions to if expression ---------------------------- */


static void complement_leaf_decisions(DATA *d,const CLASS *class)
{
    if (!d->op) {
	if (d->type == dt_decision) {
	    if (class == &class_is_drop) d->u.decision.result = dr_drop;
	    d->u.decision.class = class;
	}
	return;
    }
    complement_leaf_decisions(&d->op->a,class);
    complement_leaf_decisions(&d->op->b,class);
    complement_leaf_decisions(&d->op->c,class);
}


void complement_decisions(DATA *d,CLASS *class)
{
    *d = op_binary(&op_logical_and,*d,
      data_decision(class == &class_is_drop ? dr_drop : dr_class,class));
    complement_leaf_decisions(d,class);
}


/* ----- Iterate callback over if hierarchy -------------------------------- */


static void if_iterate_filters(const FILTER *filters,
  void (*fn)(const ELEMENT *e,void *user),void *user)
{
    const FILTER *filter;

    for (filter = filters; filter; filter = filter->next)
	if (filter->dsc == &if_dsc) {
	    const ELEMENT *element;

	    for (element = filter->elements; element; element = element->next)
		fn(element,user);
	}
}


static void if_iterate_classes(const CLASS *classes,
  void (*fn)(const ELEMENT *e,void *user),void *user)
{
    const CLASS *class;

    for (class = classes; class; class = class->next) {
	if_iterate_filters(class->filters,fn,user);
	if (class->child) if_iterate_classes(class->child,fn,user);
    }
}


void iflib_comb_iterate(const QDISC *qdisc,
  void (*fn)(const ELEMENT *e,void *user),void *user)
{
    if_iterate_filters(qdisc->filters,fn,user);
    if_iterate_classes(qdisc->classes,fn,user);
}


/* ----- Combine all ifs into single expression ---------------------------- */


static void iflib_combine_callback(const ELEMENT *e,void *user)
{
    DATA *root = user;
    DATA expr = data_clone(prm_data(e->params,&prm_if_expr));

    complement_decisions(&expr,e->parent.class);
    if (root->type == dt_none) *root = expr;
    else *root = op_binary(&op_logical_or,*root,expr);
}


DATA iflib_combine(const QDISC *qdisc)
{
    DATA d = data_none();

    iflib_comb_iterate(qdisc,iflib_combine_callback,&d);
    return d;
}