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>
41 static uat_t* dfilter_macro_uat = NULL;
42 static dfilter_macro_t* macros = NULL;
43 static guint num_macros;
45 void dfilter_macro_foreach(dfilter_macro_cb_t cb, void* data) {
48 for (i = 0; i < num_macros; i++) {
49 cb(&(macros[i]),data);
54 static void macro_fprint(dfilter_macro_t* m, void* ud) {
57 fprintf(f,"%s\t%s\n",m->name,m->text);
60 void dfilter_macro_save(const gchar* filename, gchar** error) {
61 FILE* f = fopen(filename,"w");
64 *error = ep_strdup_printf("Could not open file: '%s', error: %s\n", filename, strerror(errno) );
68 dfilter_macro_foreach(macro_fprint, f);
76 static void macro_dump(dfilter_macro_t* m _U_, void* ud _U_) {
77 gchar** part = m->parts;
78 int* args_pos = m->args_pos;
80 printf("\n->%s\t%s\t%d [%d]\n\t'%s'\n",
81 m->name, m->text, m->argc, m->usable, *(part++));
84 printf("\t$%d '%s'\n",*args_pos,*part);
91 #define macro_dump(a,b)
94 void dfilter_macro_dump(void) {
96 dfilter_macro_foreach(macro_dump, NULL);
100 static gchar* dfilter_macro_resolve(gchar* name, gchar** args, gchar** error) {
103 dfilter_macro_t* m = NULL;
109 for (i = 0; i < num_macros; i++) {
110 dfilter_macro_t* c = &(macros[i]);
111 if ( c->usable && g_str_equal(c->name,name) ) {
118 *error = ep_strdup_printf("macro '%s' does not exist", name);
123 while(args[argc]) argc++;
126 if (argc != m->argc) {
127 *error = ep_strdup_printf("wrong number of arguments for macro '%s', expecting %d instead of %d",
128 name, m->argc, argc);
132 arg_pos_p = m->args_pos;
135 text = g_string_new(*(parts++));
138 g_string_sprintfa(text,"%s%s",
139 args[*(arg_pos_p++)],
143 ret = ep_strdup(text->str);
145 g_string_free(text,TRUE);
151 gchar* dfilter_macro_apply(const gchar* text, guint depth, gchar** error) {
152 enum { OUTSIDE, STARTING, NAME, ARGS } state = OUTSIDE;
154 GString* name = NULL;
156 GPtrArray* args = NULL;
158 const gchar* r = text;
159 gboolean changed = FALSE;
162 *error = "too much nesting in macros";
166 #define FGS(n) if (n) g_string_free(n,TRUE); n = NULL
168 #define FREE_ALL() do { \
172 while(args->len) { void* p = g_ptr_array_remove_index_fast(args,0); if (p) g_free(p); } \
173 g_ptr_array_free(args,TRUE); \
174 args = NULL; } } while(0)
177 out = g_string_sized_new(64);
191 g_string_append_c(out,c);
199 args = g_ptr_array_new();
200 arg = g_string_sized_new(32);
201 name = g_string_sized_new(32);
207 g_string_append_c(out,'$');
211 g_string_append_c(out,'$');
212 g_string_append_c(out,c);
221 if ( isalnum(c) || c == '_' ) {
222 g_string_append_c(name,c);
223 } else if ( c == ':') {
225 } else if ( c == '}') {
228 g_ptr_array_add(args,NULL);
230 resolved = dfilter_macro_resolve(name->str, (gchar**)args->pdata, error);
231 if (*error) goto on_error;
235 g_string_append(out,resolved);
240 } else if ( c == '\0') {
241 *error = "end of filter in the middle of a macro expression";
244 *error = "invalid char in macro name";
251 *error = "end of filter in the middle of a macro expression";
254 g_ptr_array_add(args,arg->str);
255 g_string_free(arg,FALSE);
257 arg = g_string_sized_new(32);
262 g_string_append_c(arg,c);
265 *error = "end of filter in the middle of a macro expression";
269 g_string_append_c(arg,c);
273 g_ptr_array_add(args,arg->str);
274 g_ptr_array_add(args,NULL);
276 g_string_free(arg,FALSE);
279 resolved = dfilter_macro_resolve(name->str, (gchar**)args->pdata, error);
280 if (*error) goto on_error;
284 g_string_append(out,resolved);
302 gchar* resolved = dfilter_macro_apply(out->str, depth++, error);
303 g_string_free(out,TRUE);
304 return (*error) ? NULL : resolved;
306 gchar* out_str = ep_strdup(out->str);
307 g_string_free(out,TRUE);
314 if (! *error) *error = "unknown error in macro expression";
315 g_string_free(out,TRUE);
320 static void macro_update(void* mp, gchar** error) {
321 dfilter_macro_t* m = mp;
332 for (i = 0; i < num_macros; i++) {
333 if (m == &(macros[i])) continue;
335 if ( g_str_equal(m->name,macros[i].name) ) {
336 *error = ep_strdup_printf("macro '%s' exists already", m->name);
342 parts = g_ptr_array_new();
343 args_pos = g_array_new(FALSE,FALSE,sizeof(int));
345 m->priv = part = w = g_strdup(m->text);
347 g_ptr_array_add(parts,part);
367 if (c >= '0' && c <= '9') {
380 argc = argc < arg_pos ? arg_pos : argc;
382 g_array_append_val(args_pos,arg_pos);
383 g_ptr_array_add(parts,w);
394 g_ptr_array_add(parts,NULL);
396 if (m->parts) g_free(m->parts);
398 m->parts = (gchar**)parts->pdata;
400 if (m->args_pos) g_free(m->args_pos);
402 m->args_pos = (int*)args_pos->data;
404 g_ptr_array_free(parts,FALSE);
405 g_array_free(args_pos,FALSE);
416 static void macro_free(void* r) {
417 dfilter_macro_t* m = r;
426 static void* macro_copy(void* dest, const void* orig, unsigned len _U_) {
427 dfilter_macro_t* d = dest;
428 const dfilter_macro_t* m = orig;
431 d->name = g_strdup(m->name);
432 d->text = g_strdup(m->text);
433 d->usable = m->usable;
436 do nparts++; while (m->parts[nparts]);
437 d->priv = g_strdup(m->priv);
438 d->parts = g_memdup(m->parts,nparts*sizeof(void*));
439 d->args_pos = g_memdup(m->args_pos,(--nparts)*sizeof(int));
446 gboolean macro_name_chk(void* r _U_, const char* in_name, unsigned name_len, char** error) {
449 for (i=0; i < name_len; i++) {
450 if (!(in_name[i] == '_' || isalnum(in_name[i]) ) ) {
451 *error = "invalid char in name";
459 static void macro_name_set(void* r, const char* in_name, unsigned len) {
460 dfilter_macro_t* m = r;
461 char* name = g_malloc(len+1);
462 memcpy(name,in_name,len);
468 static void macro_name_tostr(void* r, char** out_name, unsigned* out_len) {
469 dfilter_macro_t* m = r;
470 *out_len = strlen(m->name);
474 gboolean macro_text_chk(void* r _U_, const char* in_name, unsigned name_len, char** error) {
477 for (i=0; i < name_len; i++) {
478 if (! isprint(in_name[i]) ) {
479 *error = "invalid char in text";
487 static void macro_text_set(void* r, const char* in_name, unsigned len) {
488 dfilter_macro_t* m = r;
489 char* text = g_malloc(len+1);
490 memcpy(text,in_name,len);
496 static void macro_text_tostr(void* r, char** out_name, unsigned* out_len) {
497 dfilter_macro_t* m = r;
498 *out_len = strlen(m->text);
502 void dfilter_macro_init(void) {
504 dfilter_macro_uat = uat_new("Display Filter Macros",
505 sizeof(dfilter_macro_t),
506 DFILTER_MACRO_FILENAME,
513 "name", PT_TXTMOD_STRING, macro_name_chk, macro_name_set, macro_name_tostr,
514 "text", PT_TXTMOD_STRING, macro_text_chk, macro_text_set, macro_text_tostr,
518 report_failure("error while loading '" DFILTER_MACRO_FILENAME "':\n%s",error);
523 void dfilter_macro_get_uat(void** p) {
524 *p = dfilter_macro_uat;