2 * $Id: gencode.c,v 1.10 2003/06/13 10:03:25 guy Exp $
4 * Ethereal - Network traffic analyzer
5 * By Gerald Combs <gerald@ethereal.com>
6 * Copyright 2001 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #include "dfilter-int.h"
29 #include "syntax-tree.h"
30 #include "sttype-range.h"
31 #include "sttype-test.h"
32 #include "ftypes/ftypes.h"
33 #include <epan/gdebug.h>
36 gencode(dfwork_t *dfw, stnode_t *st_node);
39 dfw_append_insn(dfwork_t *dfw, dfvm_insn_t *insn)
41 insn->id = dfw->next_insn_id;
43 g_ptr_array_add(dfw->insns, insn);
46 /* returns register number */
48 dfw_append_read_tree(dfwork_t *dfw, header_field_info *hfinfo)
51 dfvm_value_t *val1, *val2;
53 gboolean added_new_hfinfo = FALSE;
55 /* Rewind to find the first field of this name. */
56 while (hfinfo->same_name_prev) {
57 hfinfo = hfinfo->same_name_prev;
60 /* Keep track of which registers
61 * were used for which hfinfo's so that we
62 * can re-use registers. */
63 reg = GPOINTER_TO_UINT(
64 g_hash_table_lookup(dfw->loaded_fields, hfinfo));
66 /* Reg's are stored in has as reg+1, so
67 * that the non-existence of a hfinfo in
68 * the hash, or 0, can be differentiated from
69 * a hfinfo being loaded into register #0. */
73 reg = dfw->next_register++;
74 g_hash_table_insert(dfw->loaded_fields,
75 hfinfo, GUINT_TO_POINTER(reg + 1));
77 added_new_hfinfo = TRUE;
80 insn = dfvm_insn_new(READ_TREE);
81 val1 = dfvm_value_new(HFINFO);
82 val1->value.hfinfo = hfinfo;
83 val2 = dfvm_value_new(REGISTER);
84 val2->value.numeric = reg;
88 dfw_append_insn(dfw, insn);
90 if (added_new_hfinfo) {
92 /* Record the FIELD_ID in hash of interesting fields. */
93 g_hash_table_insert(dfw->interesting_fields,
94 GINT_TO_POINTER(hfinfo->id),
95 GUINT_TO_POINTER(TRUE));
96 hfinfo = hfinfo->same_name_next;
103 /* returns register number */
105 dfw_append_put_fvalue(dfwork_t *dfw, fvalue_t *fv)
108 dfvm_value_t *val1, *val2;
111 insn = dfvm_insn_new(PUT_FVALUE);
112 val1 = dfvm_value_new(FVALUE);
113 val1->value.fvalue = fv;
114 val2 = dfvm_value_new(REGISTER);
115 reg = dfw->next_register++;
116 val2->value.numeric = reg;
119 dfw_append_insn(dfw, insn);
124 /* returns register number */
126 dfw_append_mk_range(dfwork_t *dfw, stnode_t *node)
129 header_field_info *hfinfo;
133 hfinfo = sttype_range_hfinfo(node);
134 hf_reg = dfw_append_read_tree(dfw, hfinfo);
136 insn = dfvm_insn_new(MK_RANGE);
138 val = dfvm_value_new(REGISTER);
139 val->value.numeric = hf_reg;
142 val = dfvm_value_new(REGISTER);
143 reg =dfw->next_register++;
144 val->value.numeric = reg;
147 val = dfvm_value_new(DRANGE);
148 val->value.drange = sttype_range_drange(node);
151 sttype_range_remove_drange(node);
153 dfw_append_insn(dfw, insn);
160 gen_relation(dfwork_t *dfw, dfvm_opcode_t op, stnode_t *st_arg1, stnode_t *st_arg2)
162 sttype_id_t type1, type2;
164 dfvm_value_t *val1, *val2;
165 dfvm_value_t *jmp1 = NULL, *jmp2 = NULL;
166 int reg1 = -1, reg2 = -1;
167 header_field_info *hfinfo;
169 type1 = stnode_type_id(st_arg1);
170 type2 = stnode_type_id(st_arg2);
172 if (type1 == STTYPE_FIELD) {
173 hfinfo = stnode_data(st_arg1);
174 reg1 = dfw_append_read_tree(dfw, hfinfo);
176 insn = dfvm_insn_new(IF_FALSE_GOTO);
177 jmp1 = dfvm_value_new(INSN_NUMBER);
179 dfw_append_insn(dfw, insn);
181 else if (type1 == STTYPE_FVALUE) {
182 reg1 = dfw_append_put_fvalue(dfw, stnode_data(st_arg1));
184 else if (type1 == STTYPE_RANGE) {
185 reg1 = dfw_append_mk_range(dfw, st_arg1);
188 g_assert_not_reached();
191 if (type2 == STTYPE_FIELD) {
192 hfinfo = stnode_data(st_arg2);
193 reg2 = dfw_append_read_tree(dfw, hfinfo);
195 insn = dfvm_insn_new(IF_FALSE_GOTO);
196 jmp2 = dfvm_value_new(INSN_NUMBER);
198 dfw_append_insn(dfw, insn);
200 else if (type2 == STTYPE_FVALUE) {
201 reg2 = dfw_append_put_fvalue(dfw, stnode_data(st_arg2));
203 else if (type2 == STTYPE_RANGE) {
204 reg2 = dfw_append_mk_range(dfw, st_arg2);
207 g_assert_not_reached();
210 insn = dfvm_insn_new(op);
211 val1 = dfvm_value_new(REGISTER);
212 val1->value.numeric = reg1;
213 val2 = dfvm_value_new(REGISTER);
214 val2->value.numeric = reg2;
217 dfw_append_insn(dfw, insn);
220 jmp1->value.numeric = dfw->next_insn_id;
224 jmp2->value.numeric = dfw->next_insn_id;
230 gen_test(dfwork_t *dfw, stnode_t *st_node)
233 stnode_t *st_arg1, *st_arg2;
237 header_field_info *hfinfo;
239 sttype_test_get(st_node, &st_op, &st_arg1, &st_arg2);
242 case TEST_OP_UNINITIALIZED:
243 g_assert_not_reached();
247 val1 = dfvm_value_new(HFINFO);
248 hfinfo = stnode_data(st_arg1);
250 /* Rewind to find the first field of this name. */
251 while (hfinfo->same_name_prev) {
252 hfinfo = hfinfo->same_name_prev;
254 val1->value.hfinfo = hfinfo;
255 insn = dfvm_insn_new(CHECK_EXISTS);
257 dfw_append_insn(dfw, insn);
259 /* Record the FIELD_ID in hash of interesting fields. */
261 g_hash_table_insert(dfw->interesting_fields,
262 GINT_TO_POINTER(hfinfo->id),
263 GUINT_TO_POINTER(TRUE));
264 hfinfo = hfinfo->same_name_next;
270 gencode(dfw, st_arg1);
271 insn = dfvm_insn_new(NOT);
272 dfw_append_insn(dfw, insn);
276 gencode(dfw, st_arg1);
278 insn = dfvm_insn_new(IF_FALSE_GOTO);
279 val1 = dfvm_value_new(INSN_NUMBER);
281 dfw_append_insn(dfw, insn);
283 gencode(dfw, st_arg2);
284 val1->value.numeric = dfw->next_insn_id;
288 gencode(dfw, st_arg1);
290 insn = dfvm_insn_new(IF_TRUE_GOTO);
291 val1 = dfvm_value_new(INSN_NUMBER);
293 dfw_append_insn(dfw, insn);
295 gencode(dfw, st_arg2);
296 val1->value.numeric = dfw->next_insn_id;
300 gen_relation(dfw, ANY_EQ, st_arg1, st_arg2);
304 gen_relation(dfw, ANY_NE, st_arg1, st_arg2);
308 gen_relation(dfw, ANY_GT, st_arg1, st_arg2);
312 gen_relation(dfw, ANY_GE, st_arg1, st_arg2);
316 gen_relation(dfw, ANY_LT, st_arg1, st_arg2);
320 gen_relation(dfw, ANY_LE, st_arg1, st_arg2);
326 gencode(dfwork_t *dfw, stnode_t *st_node)
330 name = stnode_type_name(st_node);
332 switch (stnode_type_id(st_node)) {
334 gen_test(dfw, st_node);
337 g_assert_not_reached();
343 dfw_gencode(dfwork_t *dfw)
345 dfw->insns = g_ptr_array_new();
346 dfw->loaded_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
347 dfw->interesting_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
348 gencode(dfw, dfw->st_root);
349 dfw_append_insn(dfw, dfvm_insn_new(RETURN));
360 get_hash_key(gpointer key, gpointer value _U_, gpointer user_data)
362 int field_id = GPOINTER_TO_INT(key);
363 hash_key_iterator *hki = user_data;
365 hki->fields[hki->i] = field_id;
370 dfw_interesting_fields(dfwork_t *dfw, int *caller_num_fields)
372 int num_fields = g_hash_table_size(dfw->interesting_fields);
374 hash_key_iterator hki;
376 if (num_fields == 0) {
377 *caller_num_fields = 0;
381 hki.fields = g_new(int, num_fields);
384 g_hash_table_foreach(dfw->interesting_fields, get_hash_key, &hki);
385 *caller_num_fields = num_fields;