5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * 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.
34 #include "dfilter-int.h"
36 #include "dfilter-macro.h"
37 #include <epan/emem.h>
39 #include <epan/report_err.h>
40 #include <epan/proto.h>
48 static uat_t* dfilter_macro_uat = NULL;
49 static dfilter_macro_t* macros = NULL;
50 static guint num_macros;
51 static GHashTable* fvt_cache = NULL;
53 static gboolean free_value(gpointer k _U_, gpointer v, gpointer u _U_) {
54 fvt_cache_entry_t* e = v;
55 if (e->repr) g_free(e->repr);
60 static gboolean fvt_cache_cb(proto_node * node, gpointer data _U_) {
61 field_info* finfo = node->finfo;
64 if (!finfo) return FALSE;
66 if ((e = g_hash_table_lookup(fvt_cache,finfo->hfinfo->abbrev))) {
68 } else if (finfo->value.ftype->val_to_string_repr) {
69 switch (finfo->hfinfo->type) {
76 e = g_malloc(sizeof(fvt_cache_entry_t));
77 e->name = finfo->hfinfo->abbrev,
78 e->repr = fvalue_to_string_repr(&(finfo->value), FTREPR_DFILTER, NULL);
80 g_hash_table_insert(fvt_cache,(void*)finfo->hfinfo->abbrev,e);
85 void dfilter_macro_build_ftv_cache(void* tree_root) {
86 g_hash_table_foreach_remove(fvt_cache,free_value,NULL);
87 proto_tree_traverse_in_order(tree_root, fvt_cache_cb, NULL);
90 void dfilter_macro_foreach(dfilter_macro_cb_t cb, void* data) {
93 for (i = 0; i < num_macros; i++) {
94 cb(&(macros[i]),data);
99 static void macro_fprint(dfilter_macro_t* m, void* ud) {
102 fprintf(f,"%s\t%s\n",m->name,m->text);
105 void dfilter_macro_save(const gchar* filename, gchar** error) {
106 FILE* f = fopen(filename,"w");
109 *error = ep_strdup_printf("Could not open file: '%s', error: %s\n", filename, strerror(errno) );
113 dfilter_macro_foreach(macro_fprint, f);
121 static void macro_dump(dfilter_macro_t* m _U_, void* ud _U_) {
122 gchar** part = m->parts;
123 int* args_pos = m->args_pos;
125 printf("\n->%s\t%s\t%d [%d]\n\t'%s'\n",
126 m->name, m->text, m->argc, m->usable, *(part++));
129 printf("\t$%d '%s'\n",*args_pos,*part);
136 #define macro_dump(a,b)
139 void dfilter_macro_dump(void) {
141 dfilter_macro_foreach(macro_dump, NULL);
145 static gchar* dfilter_macro_resolve(gchar* name, gchar** args, const gchar** error) {
148 dfilter_macro_t* m = NULL;
149 fvt_cache_entry_t* e;
155 for (i = 0; i < num_macros; i++) {
156 dfilter_macro_t* c = &(macros[i]);
157 if ( c->usable && g_str_equal(c->name,name) ) {
164 if (fvt_cache && (e = g_hash_table_lookup(fvt_cache,name) )) {
168 *error = ep_strdup_printf("macro '%s' is unusable", name);
172 *error = ep_strdup_printf("macro '%s' does not exist", name);
178 while(args[argc]) argc++;
181 if (argc != m->argc) {
182 *error = ep_strdup_printf("wrong number of arguments for macro '%s', expecting %d instead of %d",
183 name, m->argc, argc);
187 arg_pos_p = m->args_pos;
190 text = g_string_new(*(parts++));
194 g_string_sprintfa(text,"%s%s",
195 args[*(arg_pos_p++)],
200 ret = ep_strdup(text->str);
202 g_string_free(text,TRUE);
208 gchar* dfilter_macro_apply(const gchar* text, guint depth, const gchar** error) {
209 enum { OUTSIDE, STARTING, NAME, ARGS } state = OUTSIDE;
211 GString* name = NULL;
213 GPtrArray* args = NULL;
215 const gchar* r = text;
216 gboolean changed = FALSE;
219 *error = "too much nesting in macros";
223 #define FGS(n) if (n) g_string_free(n,TRUE); n = NULL
230 while(args->len) { void* p = g_ptr_array_remove_index_fast(args,0); if (p) g_free(p); } \
231 g_ptr_array_free(args,TRUE); \
232 args = NULL; } } while(0)
235 out = g_string_sized_new(64);
249 g_string_append_c(out,c);
257 args = g_ptr_array_new();
258 arg = g_string_sized_new(32);
259 name = g_string_sized_new(32);
265 g_string_append_c(out,'$');
269 g_string_append_c(out,'$');
270 g_string_append_c(out,c);
279 if ( isalnum((int)c) || c == '_' || c == '-' || c == '.' ) {
280 g_string_append_c(name,c);
281 } else if ( c == ':') {
283 } else if ( c == '}') {
286 g_ptr_array_add(args,NULL);
288 resolved = dfilter_macro_resolve(name->str, (gchar**)args->pdata, error);
289 if (*error) goto on_error;
293 g_string_append(out,resolved);
298 } else if ( c == '\0') {
299 *error = "end of filter in the middle of a macro expression";
302 *error = "invalid char in macro name";
309 *error = "end of filter in the middle of a macro expression";
312 g_ptr_array_add(args,arg->str);
313 g_string_free(arg,FALSE);
315 arg = g_string_sized_new(32);
320 g_string_append_c(arg,c);
323 *error = "end of filter in the middle of a macro expression";
327 g_string_append_c(arg,c);
331 g_ptr_array_add(args,arg->str);
332 g_ptr_array_add(args,NULL);
334 g_string_free(arg,FALSE);
337 resolved = dfilter_macro_resolve(name->str, (gchar**)args->pdata, error);
338 if (*error) goto on_error;
342 g_string_append(out,resolved);
360 gchar* resolved = dfilter_macro_apply(out->str, depth++, error);
361 g_string_free(out,TRUE);
362 return (*error) ? NULL : resolved;
364 gchar* out_str = ep_strdup(out->str);
365 g_string_free(out,TRUE);
372 if (! *error) *error = "unknown error in macro expression";
373 g_string_free(out,TRUE);
378 static void macro_update(void* mp, const gchar** error) {
379 dfilter_macro_t* m = mp;
390 for (i = 0; i < num_macros; i++) {
391 if (m == &(macros[i])) continue;
393 if ( g_str_equal(m->name,macros[i].name) ) {
394 *error = ep_strdup_printf("macro '%s' exists already", m->name);
400 parts = g_ptr_array_new();
401 args_pos = g_array_new(FALSE,FALSE,sizeof(int));
403 m->priv = part = w = g_strdup(m->text);
405 g_ptr_array_add(parts,part);
425 if (c >= '0' && c <= '9') {
439 argc = argc < arg_pos ? arg_pos : argc;
441 g_array_append_val(args_pos,arg_pos);
442 g_ptr_array_add(parts,w);
453 g_ptr_array_add(parts,NULL);
455 if (m->parts) g_free(m->parts);
457 m->parts = (gchar**)parts->pdata;
459 if (m->args_pos) g_free(m->args_pos);
461 m->args_pos = (int*)(void *)args_pos->data;
463 g_ptr_array_free(parts,FALSE);
464 g_array_free(args_pos,FALSE);
475 static void macro_free(void* r) {
476 dfilter_macro_t* m = r;
485 static void* macro_copy(void* dest, const void* orig, unsigned len _U_) {
486 dfilter_macro_t* d = dest;
487 const dfilter_macro_t* m = orig;
490 d->name = g_strdup(m->name);
491 d->text = g_strdup(m->text);
492 d->usable = m->usable;
495 do nparts++; while (m->parts[nparts]);
496 d->priv = g_strdup(m->priv);
497 d->parts = g_memdup(m->parts,nparts*sizeof(void*));
498 d->args_pos = g_memdup(m->args_pos,(--nparts)*sizeof(int));
506 static gboolean macro_name_chk(void* r _U_, const char* in_name, unsigned name_len, void* u1 _U_, void* u2 _U_, const char** error) {
510 *error = "invalid name";
514 for (i=0; i < name_len; i++) {
515 if (!(in_name[i] == '_' || isalnum((guchar)in_name[i]) ) ) {
516 *error = "invalid char in name";
524 UAT_CSTRING_CB_DEF(macro,name,dfilter_macro_t)
525 UAT_CSTRING_CB_DEF(macro,text,dfilter_macro_t)
527 void dfilter_macro_init(void) {
528 static uat_field_t uat_fields[] = {
529 UAT_FLD_CSTRING_OTHER(macro,name,macro_name_chk,"The name of the macro."),
530 UAT_FLD_CSTRING_ISPRINT(macro,text,"The text this macro resolves to."),
534 dfilter_macro_uat = uat_new("Display Filter Macros",
535 sizeof(dfilter_macro_t),
536 DFILTER_MACRO_FILENAME,
540 "ChDisplayFilterMacrosSection",
546 fvt_cache = g_hash_table_new(g_str_hash,g_str_equal);
549 void dfilter_macro_get_uat(void** p) {
550 *p = dfilter_macro_uat;