2 * $Id: gencode.c,v 1.4 2001/12/18 19:09:06 gram Exp $
4 * Ethereal - Network traffic analyzer
5 * By Gerald Combs <gerald@zing.org>
6 * Copyright 2001 Gerald Combs
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #include "dfilter-int.h"
30 #include "syntax-tree.h"
31 #include "sttype-range.h"
32 #include "sttype-test.h"
33 #include "ftypes/ftypes.h"
37 gencode(dfwork_t *dfw, stnode_t *st_node);
40 dfw_append_insn(dfwork_t *dfw, dfvm_insn_t *insn)
42 insn->id = dfw->next_insn_id;
44 g_ptr_array_add(dfw->insns, insn);
47 /* returns register number */
49 dfw_append_read_tree(dfwork_t *dfw, int field_id)
52 dfvm_value_t *val1, *val2;
55 /* Keep track of which registers
56 * were used for which field_id's so that we
57 * can re-use registers. */
58 reg = GPOINTER_TO_UINT(
59 g_hash_table_lookup(dfw->loaded_fields,
60 GINT_TO_POINTER(field_id)));
62 /* Reg's are stored in has as reg+1, so
63 * that the non-existence of a field_id in
64 * the hash, or 0, can be differentiated from
65 * a field_id being loaded into register #0. */
69 reg = dfw->next_register++;
70 g_hash_table_insert(dfw->loaded_fields,
71 GUINT_TO_POINTER(field_id),
72 GUINT_TO_POINTER(reg + 1));
74 /* Record the FIELD_ID in hash of interesting fields. */
75 g_hash_table_insert(dfw->interesting_fields,
76 GINT_TO_POINTER(field_id), GUINT_TO_POINTER(TRUE));
79 insn = dfvm_insn_new(READ_TREE);
80 val1 = dfvm_value_new(FIELD_ID);
81 val1->value.numeric = field_id;
82 val2 = dfvm_value_new(REGISTER);
83 val2->value.numeric = reg;
87 dfw_append_insn(dfw, insn);
92 /* returns register number */
94 dfw_append_put_fvalue(dfwork_t *dfw, fvalue_t *fv)
97 dfvm_value_t *val1, *val2;
100 insn = dfvm_insn_new(PUT_FVALUE);
101 val1 = dfvm_value_new(FVALUE);
102 val1->value.fvalue = fv;
103 val2 = dfvm_value_new(REGISTER);
104 reg = dfw->next_register++;
105 val2->value.numeric = reg;
108 dfw_append_insn(dfw, insn);
113 /* returns register number */
115 dfw_append_mk_range(dfwork_t *dfw, stnode_t *node)
118 header_field_info *hfinfo;
122 hfinfo = sttype_range_hfinfo(node);
123 hf_reg = dfw_append_read_tree(dfw, hfinfo->id);
125 insn = dfvm_insn_new(MK_RANGE);
127 val = dfvm_value_new(REGISTER);
128 val->value.numeric = hf_reg;
131 val = dfvm_value_new(REGISTER);
132 reg =dfw->next_register++;
133 val->value.numeric = reg;
136 val = dfvm_value_new(DRANGE);
137 val->value.drange = sttype_range_drange(node);
140 sttype_range_remove_drange(node);
142 dfw_append_insn(dfw, insn);
149 gen_relation(dfwork_t *dfw, dfvm_opcode_t op, stnode_t *st_arg1, stnode_t *st_arg2)
151 sttype_id_t type1, type2;
153 dfvm_value_t *val1, *val2;
154 dfvm_value_t *jmp1 = NULL, *jmp2 = NULL;
155 int reg1 = -1, reg2 = -1;
156 header_field_info *hfinfo;
158 type1 = stnode_type_id(st_arg1);
159 type2 = stnode_type_id(st_arg2);
161 if (type1 == STTYPE_FIELD) {
162 hfinfo = stnode_data(st_arg1);
163 reg1 = dfw_append_read_tree(dfw, hfinfo->id);
165 insn = dfvm_insn_new(IF_FALSE_GOTO);
166 jmp1 = dfvm_value_new(INSN_NUMBER);
168 dfw_append_insn(dfw, insn);
170 else if (type1 == STTYPE_FVALUE) {
171 reg1 = dfw_append_put_fvalue(dfw, stnode_data(st_arg1));
173 else if (type1 == STTYPE_RANGE) {
174 reg1 = dfw_append_mk_range(dfw, st_arg1);
177 g_assert_not_reached();
180 if (type2 == STTYPE_FIELD) {
181 hfinfo = stnode_data(st_arg2);
182 reg2 = dfw_append_read_tree(dfw, hfinfo->id);
184 insn = dfvm_insn_new(IF_FALSE_GOTO);
185 jmp2 = dfvm_value_new(INSN_NUMBER);
187 dfw_append_insn(dfw, insn);
189 else if (type2 == STTYPE_FVALUE) {
190 reg2 = dfw_append_put_fvalue(dfw, stnode_data(st_arg2));
193 g_assert_not_reached();
196 insn = dfvm_insn_new(op);
197 val1 = dfvm_value_new(REGISTER);
198 val1->value.numeric = reg1;
199 val2 = dfvm_value_new(REGISTER);
200 val2->value.numeric = reg2;
203 dfw_append_insn(dfw, insn);
206 jmp1->value.numeric = dfw->next_insn_id;
210 jmp2->value.numeric = dfw->next_insn_id;
216 gen_test(dfwork_t *dfw, stnode_t *st_node)
219 stnode_t *st_arg1, *st_arg2;
223 header_field_info *hfinfo;
225 sttype_test_get(st_node, &st_op, &st_arg1, &st_arg2);
228 case TEST_OP_UNINITIALIZED:
229 g_assert_not_reached();
233 val1 = dfvm_value_new(FIELD_ID);
234 hfinfo = stnode_data(st_arg1);
235 val1->value.numeric = hfinfo->id;
236 insn = dfvm_insn_new(CHECK_EXISTS);
238 dfw_append_insn(dfw, insn);
240 /* Record the FIELD_ID in hash of interesting fields. */
241 g_hash_table_insert(dfw->interesting_fields,
242 GINT_TO_POINTER(hfinfo->id), GUINT_TO_POINTER(TRUE));
247 gencode(dfw, st_arg1);
248 insn = dfvm_insn_new(NOT);
249 dfw_append_insn(dfw, insn);
253 gencode(dfw, st_arg1);
255 insn = dfvm_insn_new(IF_FALSE_GOTO);
256 val1 = dfvm_value_new(INSN_NUMBER);
258 dfw_append_insn(dfw, insn);
260 gencode(dfw, st_arg2);
261 val1->value.numeric = dfw->next_insn_id;
265 gencode(dfw, st_arg1);
267 insn = dfvm_insn_new(IF_TRUE_GOTO);
268 val1 = dfvm_value_new(INSN_NUMBER);
270 dfw_append_insn(dfw, insn);
272 gencode(dfw, st_arg2);
273 val1->value.numeric = dfw->next_insn_id;
277 gen_relation(dfw, ANY_EQ, st_arg1, st_arg2);
281 gen_relation(dfw, ANY_NE, st_arg1, st_arg2);
285 gen_relation(dfw, ANY_GT, st_arg1, st_arg2);
289 gen_relation(dfw, ANY_GE, st_arg1, st_arg2);
293 gen_relation(dfw, ANY_LT, st_arg1, st_arg2);
297 gen_relation(dfw, ANY_LE, st_arg1, st_arg2);
303 gencode(dfwork_t *dfw, stnode_t *st_node)
307 name = stnode_type_name(st_node);
309 switch (stnode_type_id(st_node)) {
311 gen_test(dfw, st_node);
314 g_assert_not_reached();
320 dfw_gencode(dfwork_t *dfw)
322 dfw->insns = g_ptr_array_new();
323 dfw->loaded_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
324 dfw->interesting_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
325 gencode(dfw, dfw->st_root);
326 dfw_append_insn(dfw, dfvm_insn_new(RETURN));
337 get_hash_key(gpointer key, gpointer value, gpointer user_data)
339 int field_id = GPOINTER_TO_INT(key);
340 hash_key_iterator *hki = user_data;
342 hki->fields[hki->i] = field_id;
347 dfw_interesting_fields(dfwork_t *dfw, int *caller_num_fields)
349 int num_fields = g_hash_table_size(dfw->interesting_fields);
351 hash_key_iterator hki;
353 if (num_fields == 0) {
354 *caller_num_fields = 0;
358 hki.fields = g_new(int, num_fields);
361 g_hash_table_foreach(dfw->interesting_fields, get_hash_key, &hki);
362 *caller_num_fields = num_fields;