second iteration:

* fields of an uat table now are passed using an array of uat_filed_t
* field callbacks take two more userdata arguments
* add some macros to define uat field callbacks.
* uats can be registered as preferences for a specific protocol
   - the preference widget is a button that opens the uat's window
* dfilter-macro => reflect changes to API


svn path=/trunk/; revision=20695
This commit is contained in:
Luis Ontanon 2007-02-03 14:25:02 +00:00
parent 009d38e6a0
commit d70a58f881
12 changed files with 517 additions and 327 deletions

View File

@ -165,13 +165,14 @@ gchar* dfilter_macro_apply(const gchar* text, guint depth, gchar** error) {
#define FGS(n) if (n) g_string_free(n,TRUE); n = NULL
#define FREE_ALL() do { \
FGS(name); \
FGS(arg); \
if (args) { \
while(args->len) { void* p = g_ptr_array_remove_index_fast(args,0); if (p) g_free(p); } \
g_ptr_array_free(args,TRUE); \
args = NULL; } } while(0)
#define FREE_ALL() \
do { \
FGS(name); \
FGS(arg); \
if (args) { \
while(args->len) { void* p = g_ptr_array_remove_index_fast(args,0); if (p) g_free(p); } \
g_ptr_array_free(args,TRUE); \
args = NULL; } } while(0)
*error = NULL;
out = g_string_sized_new(64);
@ -443,7 +444,8 @@ static void* macro_copy(void* dest, const void* orig, unsigned len _U_) {
return d;
}
gboolean macro_name_chk(void* r _U_, const char* in_name, unsigned name_len, char** error) {
gboolean macro_name_chk(void* r _U_, const char* in_name, unsigned name_len, void* u1 _U_, void* u2 _U_, char** error) {
guint i;
for (i=0; i < name_len; i++) {
@ -453,54 +455,19 @@ gboolean macro_name_chk(void* r _U_, const char* in_name, unsigned name_len, cha
}
}
return TRUE;
return i > 0 ? TRUE : FALSE;
}
static void macro_name_set(void* r, const char* in_name, unsigned len) {
dfilter_macro_t* m = r;
char* name = g_malloc(len+1);
memcpy(name,in_name,len);
name[len] = '\0';
g_free(m->name);
m->name = name;
}
static void macro_name_tostr(void* r, char** out_name, unsigned* out_len) {
dfilter_macro_t* m = r;
*out_len = strlen(m->name);
*out_name = m->name;
}
gboolean macro_text_chk(void* r _U_, const char* in_name, unsigned name_len, char** error) {
guint i;
for (i=0; i < name_len; i++) {
if (! isprint(in_name[i]) ) {
*error = "invalid char in text";
return FALSE;
}
}
return TRUE;
}
static void macro_text_set(void* r, const char* in_name, unsigned len) {
dfilter_macro_t* m = r;
char* text = g_malloc(len+1);
memcpy(text,in_name,len);
text[len] = '\0';
g_free(m->text);
m->text = text;
}
static void macro_text_tostr(void* r, char** out_name, unsigned* out_len) {
dfilter_macro_t* m = r;
*out_len = strlen(m->text);
*out_name = m->text;
}
UAT_CSTRING_CB_DEF(macro,name,dfilter_macro_t)
UAT_CSTRING_CB_DEF(macro,text,dfilter_macro_t)
void dfilter_macro_init(void) {
char* error = NULL;
static uat_field_t uat_fields[] = {
UAT_FLD_CSTRING_OTHER(macro,name,macro_name_chk),
UAT_FLD_CSTRING_ISPRINT(macro,text),
UAT_END_FIELDS
};
dfilter_macro_uat = uat_new("Display Filter Macros",
sizeof(dfilter_macro_t),
DFILTER_MACRO_FILENAME,
@ -509,15 +476,7 @@ void dfilter_macro_init(void) {
macro_copy,
macro_update,
macro_free,
&error,
"name", PT_TXTMOD_STRING, macro_name_chk, macro_name_set, macro_name_tostr,
"text", PT_TXTMOD_STRING, macro_text_chk, macro_text_set, macro_text_tostr,
NULL );
if(error) {
report_failure("error while loading '" DFILTER_MACRO_FILENAME "':\n%s",error);
}
uat_fields);
}
void dfilter_macro_get_uat(void** p) {

View File

@ -56,6 +56,7 @@ typedef enum {
PREF_STRING,
PREF_RANGE,
PREF_STATIC_TEXT,
PREF_UAT,
PREF_OBSOLETE
} pref_type_t;
@ -71,6 +72,7 @@ struct preference {
gint *enump;
const char **string;
range_t **range;
void* uat;
} varp; /* pointer to variable storing the value */
union {
guint uint;

View File

@ -48,6 +48,7 @@
#include <wiretap/file_util.h>
#include <epan/prefs-int.h>
#include <epan/uat-int.h>
/* Internal functions */
static module_t *prefs_register_module_or_subtree(module_t *parent,
@ -638,6 +639,24 @@ void prefs_register_static_text_preference(module_t *module, const char *name,
register_preference(module, name, title, description, PREF_STATIC_TEXT);
}
/*
* Register a uat 'preference'. It adds a button that opens the uat's window in the
* preferences tab of the module.
*/
extern void prefs_register_uat_preference(module_t *module,
const char *name,
const char *title,
const char *description,
void* uat) {
pref_t* preference = register_preference(module, name, title, description, PREF_UAT);
preference->varp.uat = uat;
}
/*
* Register a preference that used to be supported but no longer is.
*/
@ -941,6 +960,8 @@ init_prefs(void) {
if (prefs_initialized)
return;
uat_load_all();
prefs.pr_format = PR_FMT_TEXT;
prefs.pr_dest = PR_DEST_CMD;
prefs.pr_file = g_strdup("wireshark.out");
@ -1103,7 +1124,7 @@ read_prefs(int *gpf_errno_return, int *gpf_read_errno_return,
FILE *pf;
init_prefs();
/*
* If we don't already have the pathname of the global preferences
* file, construct it. Then, in either case, try to open the file.
@ -2133,6 +2154,7 @@ set_pref(gchar *pref_name, gchar *value, void *private_data _U_)
}
case PREF_STATIC_TEXT:
case PREF_UAT:
{
break;
}
@ -2248,6 +2270,7 @@ write_pref(gpointer data, gpointer user_data)
}
case PREF_STATIC_TEXT:
case PREF_UAT:
{
/* Nothing to do */
break;

View File

@ -313,6 +313,16 @@ extern void prefs_register_range_preference(module_t *module, const char *name,
extern void prefs_register_static_text_preference(module_t *module, const char *name,
const char *title, const char *description);
/*
* Register a uat 'preference'. It adds a button that opens the uat's window in the
* preferences tab of the module.
*/
extern void prefs_register_uat_preference(module_t *module,
const char *name,
const char* title,
const char *description,
void* uat);
/*
* Register a preference that used to be supported but no longer is.
*/

View File

@ -39,19 +39,11 @@ typedef struct _uat_rep_t uat_rep_t;
typedef void (*uat_rep_fld_free_cb_t)(uat_fld_rep_t*);
typedef void (*uat_rep_free_cb_t)(uat_rep_t*);
typedef struct _uat_fld_t {
char* name;
uat_text_mode_t mode;
uat_fld_chk_cb_t chk_cb;
uat_fld_set_cb_t set_cb;
uat_fld_tostr_cb_t tostr_cb;
typedef struct _fld_data_t {
guint colnum;
uat_fld_rep_t* rep;
uat_rep_fld_free_cb_t free_rep;
struct _uat_fld_t* next;
} uat_fld_t;
} fld_data_t;
struct _uat_t {
char* name;
@ -63,23 +55,31 @@ struct _uat_t {
uat_update_cb_t update_cb;
uat_free_cb_t free_cb;
uat_fld_t* fields;
uat_field_t* fields;
guint ncols;
GArray* user_data;
gboolean finalized;
uat_rep_t* rep;
uat_rep_free_cb_t free_rep;
};
gchar* uat_get_actual_filename(uat_t* uat, gboolean for_writing);
void uat_init(void);
void uat_reset(void);
void* uat_add_record(uat_t*, const void* orig_rec_ptr);
void uat_remove_record_idx(uat_t*, guint rec_idx);
void uat_destroy(uat_t*);
gboolean uat_save(uat_t* dt, char** error);
gboolean uat_load(uat_t* dt, char** error);
gboolean uat_save(uat_t* , char** );
gboolean uat_load(uat_t* , char** );
void uat_load_all(void);
#define UAT_UPDATE(uat) do { *((uat)->user_ptr) = (void*)((uat)->user_data->data); *((uat)->nrows_p) = (uat)->user_data->len; } while(0)
#define UAT_INDEX_PTR(uat,idx) (uat->user_data->data + (uat->record_size * (idx)))

View File

@ -39,7 +39,9 @@
#include <glib.h>
#include <epan/emem.h>
#include <epan/report_err.h>
#include <epan/filesystem.h>
#include <epan/packet.h>
#include "uat-int.h"
@ -49,83 +51,7 @@ void uat_init(void) {
all_uats = g_ptr_array_new();
}
uat_t* uat_start(const char* name,
size_t size,
char* filename,
void** data_ptr,
guint* num_items_ptr,
uat_copy_cb_t copy_cb,
uat_update_cb_t update_cb,
uat_free_cb_t free_cb) {
uat_t* uat = g_malloc(sizeof(uat_t));
if (!all_uats)
all_uats = g_ptr_array_new();
g_ptr_array_add(all_uats,uat);
g_assert(name && size && filename && data_ptr && num_items_ptr);
uat->name = g_strdup(name);
uat->record_size = size;
uat->filename = g_strdup(filename);
uat->user_ptr = data_ptr;
uat->nrows_p = num_items_ptr;
uat->copy_cb = copy_cb;
uat->update_cb = update_cb;
uat->free_cb = free_cb;
uat->fields = NULL;
uat->ncols = 0;
uat->user_data = g_array_new(FALSE,FALSE,uat->record_size);
uat->finalized = FALSE;
uat->rep = NULL;
uat->free_rep = NULL;
return uat;
}
void uat_add_field(uat_t* uat,
const char* name,
uat_text_mode_t mode,
uat_fld_chk_cb_t chk_cb,
uat_fld_set_cb_t set_cb,
uat_fld_tostr_cb_t tostr_cb) {
uat_fld_t* f = g_malloc(sizeof(uat_fld_t));
g_assert( name && set_cb && tostr_cb && (! uat->finalized )
&& (mode == PT_TXTMOD_STRING || mode == PT_TXTMOD_HEXBYTES) );
f->name = g_strdup(name);
f->mode = mode;
f->chk_cb = chk_cb;
f->set_cb = set_cb;
f->tostr_cb = tostr_cb;
f->rep = NULL;
f->free_rep = NULL;
f->colnum = uat->ncols;
f->next = NULL;
uat->ncols++;
if (uat->fields) {
uat_fld_t* c;
for (c = uat->fields; c->next; c = c->next) ;
c->next = f;
} else {
uat->fields = f;
}
}
void uat_finalize(uat_t* uat) {
UAT_UPDATE(uat);
uat->finalized = TRUE;
}
uat_t* uat_new(const char* uat_name,
uat_t* uat_new(const char* name,
size_t size,
char* filename,
void** data_ptr,
@ -133,44 +59,52 @@ uat_t* uat_new(const char* uat_name,
uat_copy_cb_t copy_cb,
uat_update_cb_t update_cb,
uat_free_cb_t free_cb,
char** error,
...) {
uat_t* uat = uat_start(uat_name, size, filename, data_ptr, numitems_ptr, copy_cb, update_cb, free_cb);
va_list ap;
char* name;
uat_text_mode_t mode;
uat_fld_chk_cb_t chk_cb;
uat_fld_set_cb_t set_cb;
uat_fld_tostr_cb_t tostr_cb;
va_start(ap,error);
uat_field_t* flds_array) {
uat_t* uat = g_malloc(sizeof(uat_t));
guint i;
name = va_arg(ap,char*);
if (!all_uats)
all_uats = g_ptr_array_new();
do {
mode = va_arg(ap,uat_text_mode_t);
chk_cb = va_arg(ap,uat_fld_chk_cb_t);
set_cb = va_arg(ap,uat_fld_set_cb_t);
tostr_cb = va_arg(ap,uat_fld_tostr_cb_t);
uat_add_field(uat, name, mode, chk_cb, set_cb, tostr_cb);
g_ptr_array_add(all_uats,uat);
g_assert(name && size && filename && data_ptr && numitems_ptr);
uat->name = g_strdup(name);
uat->record_size = size;
uat->filename = g_strdup(filename);
uat->user_ptr = data_ptr;
uat->nrows_p = numitems_ptr;
uat->copy_cb = copy_cb;
uat->update_cb = update_cb;
uat->free_cb = free_cb;
uat->fields = flds_array;
uat->user_data = g_array_new(FALSE,FALSE,uat->record_size);
uat->rep = NULL;
uat->free_rep = NULL;
for (i=0;flds_array[i].name;i++) {
fld_data_t* f = g_malloc(sizeof(fld_data_t));
f->colnum = i+1;
f->rep = NULL;
f->free_rep = NULL;
name = va_arg(ap,char*);
} while (name);
flds_array[i].priv = f;
}
va_end(ap);
uat->ncols = i;
uat_finalize(uat);
uat_load(uat,error);
*data_ptr = NULL;
*numitems_ptr = 0;
return uat;
}
void* uat_add_record(uat_t* uat, const void* data) {
void* rec;
g_assert( uat->finalized );
g_array_append_vals (uat->user_data, data, 1);
rec = uat->user_data->data + (uat->record_size * (uat->user_data->len-1));
@ -179,7 +113,6 @@ void* uat_add_record(uat_t* uat, const void* data) {
uat->copy_cb(rec, data, uat->record_size);
}
UAT_UPDATE(uat);
return rec;
@ -187,19 +120,22 @@ void* uat_add_record(uat_t* uat, const void* data) {
void uat_remove_record_idx(uat_t* uat, guint idx) {
g_assert( uat->finalized && idx < uat->user_data->len);
g_assert( idx < uat->user_data->len );
if (uat->free_cb) {
uat->free_cb(UAT_INDEX_PTR(uat,idx));
}
g_array_remove_index(uat->user_data, idx);
UAT_UPDATE(uat);
}
gchar* uat_get_actual_filename(uat_t* uat, gboolean for_writing) {
gchar* pers_fname = get_persconffile_path(uat->filename,for_writing);
if (! (file_exists(pers_fname) || for_writing) ) {
if (! for_writing ) {
gchar* data_fname = get_datafile_path(uat->filename);
if (file_exists(data_fname)) {
@ -207,14 +143,18 @@ gchar* uat_get_actual_filename(uat_t* uat, gboolean for_writing) {
}
}
if ((! file_exists(pers_fname) ) && (! for_writing ) ) {
return NULL;
}
return pers_fname;
}
static void putfld(FILE* fp, void* rec, uat_fld_t* f) {
static void putfld(FILE* fp, void* rec, uat_field_t* f) {
guint fld_len;
char* fld_ptr;
f->tostr_cb(rec,&fld_ptr,&fld_len);
f->cb.tostr(rec,&fld_ptr,&fld_len,f->cbdata.tostr,f->fld_data);
switch(f->mode){
case PT_TXTMOD_STRING: {
@ -254,9 +194,12 @@ static void putfld(FILE* fp, void* rec, uat_fld_t* f) {
gboolean uat_save(uat_t* uat, char** error) {
guint i;
gchar* fname = uat_get_actual_filename(uat,TRUE);
FILE* fp = fopen(fname,"w");
FILE* fp;
if (! fname ) return FALSE;
fp = fopen(fname,"w");
if (!fp) {
*error = ep_strdup_printf("uat_save: error opening '%s': %s",fname,strerror(errno));
return FALSE;
@ -266,18 +209,17 @@ gboolean uat_save(uat_t* uat, char** error) {
for ( i = 0 ; i < uat->user_data->len ; i++ ) {
void* rec = uat->user_data->data + (uat->record_size * i);
uat_fld_t* f;
uat_field_t* f;
guint j;
f = uat->fields;
putfld(fp, rec, f);
while (( f = f->next )) {
fputs(",",fp);
putfld(fp, rec, f);
for( j=0 ; j < uat->ncols ; j++ ) {
putfld(fp, rec, &(f[j]));
fputs((j == uat->ncols - 1) ? "\n" : "," ,fp);
}
fputs("\n",fp);
}
fclose(fp);
@ -286,6 +228,7 @@ gboolean uat_save(uat_t* uat, char** error) {
}
void uat_destroy(uat_t* uat) {
/* XXX still missing a destructor */
g_ptr_array_remove(all_uats,uat);
}
@ -303,7 +246,6 @@ void* uat_se_dup(uat_t* uat, guint* len_p) {
}
void uat_cleanup(void) {
while( all_uats->len ) {
uat_destroy((uat_t*)all_uats->pdata);
}
@ -311,3 +253,74 @@ void uat_cleanup(void) {
g_ptr_array_free(all_uats,TRUE);
}
void uat_load_all(void) {
guint i;
gchar* err;
for (i=0; i < all_uats->len; i++) {
uat_t* u = g_ptr_array_index(all_uats,i);
err = NULL;
uat_load(u, &err);
if (err) {
report_failure("Error loading table '%s': %s",u->name,err);
}
}
}
gboolean uat_fld_chk_str(void* u1 _U_, const char* strptr, unsigned len _U_, void* u2 _U_, void* u3 _U_, char** err) {
if (strptr == NULL) {
*err = "NULL pointer";
return FALSE;
}
*err = NULL;
return TRUE;
}
gboolean uat_fld_chk_proto(void* u1 _U_, const char* strptr, unsigned len, void* u2 _U_, void* u3 _U_, char** err) {
char* name = ep_strndup(strptr,len);
g_strdown(name);
g_strchug(name);
if (find_dissector(name)) {
*err = NULL;
return TRUE;
} else {
*err = "dissector not found";
return FALSE;
}
}
gboolean uat_fld_chk_num_dec(void* u1 _U_, const char* strptr, unsigned len, void* u2 _U_, void* u3 _U_, char** err) {
char* str = ep_strndup(strptr,len);
long i = strtol(str,&str,10);
if ( ( i == 0) && (errno == ERANGE || errno == EINVAL) ) {
*err = strerror(errno);
return FALSE;
}
*err = NULL;
return TRUE;
}
gboolean uat_fld_chk_num_hex(void* u1 _U_, const char* strptr, unsigned len, void* u2 _U_, void* u3 _U_, char** err) {
char* str = ep_strndup(strptr,len);
long i = strtol(str,&str,16);
if ( ( i == 0) && (errno == ERANGE || errno == EINVAL) ) {
*err = strerror(errno);
return FALSE;
}
*err = NULL;
return TRUE;
}
CHK_STR_IS_DEF(isprint)
CHK_STR_IS_DEF(isalpha)
CHK_STR_IS_DEF(isalnum)
CHK_STR_IS_DEF(isdigit)
CHK_STR_IS_DEF(isxdigit)

View File

@ -53,7 +53,6 @@
/* obscure data type to handle an uat */
typedef struct _uat_t uat_t;
/********************************************
* Callbacks:
* these instruct uat on how to deal with user info and data in records
@ -103,9 +102,9 @@ typedef void (*uat_update_cb_t)(void* , char** );
* it will return FALSE and may set *error to inform the user on what's
* wrong with the given input
* optional, if not given any input is considered OK and the set cb will be called
* chk(record, ptr, len, &error)
* chk(record, ptr, len, chk_data, fld_data, &error)
*/
typedef gboolean (*uat_fld_chk_cb_t)(void*, const char*, unsigned, char**);
typedef gboolean (*uat_fld_chk_cb_t)(void*, const char*, unsigned, void*, void*, char**);
/*
* Set Field CB
@ -115,19 +114,16 @@ typedef gboolean (*uat_fld_chk_cb_t)(void*, const char*, unsigned, char**);
* it will return FALSE and may set *error to inform the user on what's
* wrong with the given input
* it is mandatory
* set(record, ptr, len)
* set(record, ptr, len, set_data, fld_data)
*/
typedef void (*uat_fld_set_cb_t)(void*, const char*, unsigned);
typedef void (*uat_fld_set_cb_t)(void*, const char*, unsigned, void*, void*);
/*
* given a record returns a string representation of the field
* mandatory
* tostr(record, &ptr, &len)
* tostr(record, &out_ptr, &out_len, tostr_data, fld_data)
*/
typedef void (*uat_fld_tostr_cb_t)(void*, char**, unsigned*);
typedef void (*uat_fld_tostr_cb_t)(void*, char**, unsigned*, void*, void*);
/***********
* Text Mode
@ -174,6 +170,36 @@ typedef enum _uat_text_mode_t {
*/
} uat_text_mode_t;
/*
* Fields
*
*
*/
typedef struct _uat_field_t {
const char* name;
uat_text_mode_t mode;
struct {
uat_fld_chk_cb_t chk;
uat_fld_set_cb_t set;
uat_fld_tostr_cb_t tostr;
} cb;
struct {
void* chk;
void* set;
void* tostr;
} cbdata;
void* fld_data;
struct _fld_data_t* priv;
} uat_field_t;
#define FLDFILL NULL
#define UAT_END_FIELDS {0,PT_TXTMOD_NONE,{0,0,0},{0,0,0},0,FLDFILL}
/*
* uat_new()
@ -196,18 +222,6 @@ typedef enum _uat_text_mode_t {
*
* free_cb: will be called to destroy a struct in the dataset
*
*
* followed by a list of N quintuplets terminated by a NULL, each quituplet has:
*
* field_name: a string with the name of the field ([a-zA-Z0-9_-]+)
*
* field_mode: see comments for enum _uat_text_mode_t below
*
* field_chk_cb: a function that given a string will check the given value
*
* field_set_cb: a function that given a string will set the value in the data structure
*
* field_tostr_cb: a function that given a record generates a string,len pair representing this file
*
*/
uat_t* uat_new(const char* name,
@ -218,41 +232,9 @@ uat_t* uat_new(const char* name,
uat_copy_cb_t copy_cb,
uat_update_cb_t update_cb,
uat_free_cb_t free_cb,
char** error,
...);
uat_field_t* flds_array);
/*
* uat_start()
* as uat_new() but leaves the dyntable without fields
*/
uat_t* uat_start(const char* name,
size_t size,
char* filename,
void** data_ptr,
guint* num_items,
uat_copy_cb_t copy_cb,
uat_update_cb_t update_cb,
uat_free_cb_t free_cb);
/*
* uat_add_field()
* adds a field to a uat created with uat_start(),
* see uat_new() for description of arguments
*/
void uat_add_field(uat_t*,
const char* name,
uat_text_mode_t mode,
uat_fld_chk_cb_t chk_cb,
uat_fld_set_cb_t set_cb,
uat_fld_tostr_cb_t tostr_cb);
/*
* uat_finalize()
* once fields have been added it makes the uat usable, leaves it locked.
*/
void uat_finalize(uat_t*);
/*
* uat_dup()
* uat_se_dup()
@ -263,5 +245,144 @@ void uat_finalize(uat_t*);
void* uat_dup(uat_t*, guint* len_p); /* to be freed */
void* uat_se_dup(uat_t*, guint* len_p);
/*
* Some common uat_fld_chk_cbs
*/
gboolean uat_fld_chk_str(void*, const char*, unsigned, void*,void*, char** err);
gboolean uat_fld_chk_proto(void*, const char*, unsigned, void*,void*, char** err);
gboolean uat_fld_chk_num_dec(void*, const char*, unsigned, void*, void*, char** err);
gboolean uat_fld_chk_num_hex(void*, const char*, unsigned, void*, void*, char** err);
#define CHK_STR_IS_DECL(what) \
gboolean uat_fld_chk_str_ ## what (void*, const char*, unsigned, void*, void*, char**)
/* Some strings entirely made of ... already declared */
CHK_STR_IS_DECL(isprint);
CHK_STR_IS_DECL(isalpha);
CHK_STR_IS_DECL(isalnum);
CHK_STR_IS_DECL(isdigit);
CHK_STR_IS_DECL(isxdigit);
#define CHK_STR_IS_DEF(what) \
gboolean uat_fld_chk_str_ ## what (void* u1 _U_, const char* strptr, unsigned len, void* u2 _U_, void* u3 _U_, char** err) { \
guint i; for (i=0;i<len;i++) { \
char c = strptr[i]; \
if (! what(c)) { \
*err = ep_strdup_printf("invalid char pos=%d value=%.2x",i,c); return FALSE; } } \
*err = NULL; return TRUE; }
/*
* Macros
* to define basic uat_fld_set_cbs, uat_fld_tostr_cbs
* for those elements in uat_field_t array
*/
/*
* CSTRING macros,
* a simple c-string contained in (((rec_t*)rec)->(field_name))
*/
#define UAT_CSTRING_CB_DEF(basename,field_name,rec_t) \
static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* u1 _U_, void* u2 _U_) {\
if ((((rec_t*)rec)->field_name)) g_free((((rec_t*)rec)->field_name)); \
(((rec_t*)rec)->field_name) = g_strndup(buf,len); } \
static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* u1 _U_, void* u2 _U_) {\
if (((rec_t*)rec)->field_name ) { \
*out_ptr = (((rec_t*)rec)->field_name); *out_len = strlen((((rec_t*)rec)->field_name)); \
} else { \
*out_ptr = ""; *out_len = 0; } }
#define UAT_FLD_CSTRING(basename,field_name) \
{#field_name, PT_TXTMOD_STRING,{uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
#define UAT_FLD_CSTRING_ISPRINT(basename,field_name) \
{#field_name, PT_TXTMOD_STRING,{uat_fld_chk_str_isprint,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
#define UAT_FLD_CSTRING_OTHER(basename,field_name,chk) \
{#field_name, PT_TXTMOD_STRING,{ chk ,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
/*
* BUFFER macros,
* a buffer_ptr contained in (((rec_t*)rec)->(field_name))
* and its len in (((rec_t*)rec)->(len_name))
* XXX: UNTESTED
*/
#define UAT_BUFFER_CB_DEF(field_name,len_name,rec_t,ptr_element,len_element) \
static void basename ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* u1 _U_, void* u2 _U_) {\
if ((((rec_t*)rec)->(field_name))) g_free((((rec_t*)rec)->(field_name))); \
(((rec_t*)rec)->(field_name)) = g_memdup(buf,len); \
(((rec_t*)rec)->(len_name)) = len; \ } \
static void basename ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* u1 _U_, void* u2 _U_) {\
*out_ptr = ep_memdup(((rec_t*)rec)->(field_name),((rec_t*)rec)->(len_name)); \
*len_ptr = (((rec_t*)rec)->(len_name)); }
#define UAT_FLD_BUFFER(basename,field_name) \
{#field_name, PT_TXTMOD_HEXBYTES,{NULL,basename ## field_name ## _set_cb,basename ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
/*
* DEC Macros,
* a decimal number contained in
*/
#define UAT_DEC_CB_DEF(basename,field_name,rec_t) \
static void basename ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* u1 _U_, void* u2 _U_) {\
((rec_t*)rec)->(field_name) = strtol(buf,end,10); } \
static void basename ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* u1 _U_, void* u2 _U_) {\
*out_ptr = ep_strdup_printf("%d",((rec_t*)rec)->(field_name)); \
*out_len = strlen(*out_ptr); }
#define UAT_FLD_DEC(basename,field_name) \
{#field_name, PT_TXTMOD_STRING,{uat_fld_chk_num_dec,basename ## field_name ## _set_cb,basename ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
/*
* HEX Macros,
* an hexadecimal number contained in
*/
#define UAT_HEX_CB_DEF(basename,field_name,rec_t) \
static void basename ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* u1 _U_, void* u2 _U_) {\
((rec_t*)rec)->(field_name) = strtol(buf,end,16); } \
static void basename ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* u1 _U_, void* u2 _U_) {\
*out_ptr = ep_strdup_printf("%x",((rec_t*)rec)->(field_name)); \
*out_len = strlen(*out_ptr); }
#define UAT_FLD_HEX(basename,field_name) \
{#field_name, PT_TXTMOD_STRING,{uat_fld_chk_num_hex,basename ## field_name ## _set_cb,basename ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
/*
* ENUM macros
* enum_t: name = ((enum_t*)ptr)->strptr
* value = ((enum_t*)ptr)->value
* rec_t:
* value
*/
#define UAT_SET_ENUM_DEF(basename,field_name,rec_t,enum_t,default) \
void static void basename ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* enum, void* u2 _U_) {\
char* str = ep_strndup(buf,len); \
for(;((enum_t*)enum)->strptr;((enum_t*)enum)++) { \
if (g_strequal(((enum_t*)enum)->strptr,str)) { \
((rec_t*)rec)->(field_name) = ((enum_t*)enum)->value; return; } } \
(rec_t*)rec)->(field_name) = default; \
}
#define UAT_TOSTR_ENUM_DEF(basename,field_name,rec_t,enum_t) {\
static void basename ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* enum, void* u2 _U_) {\
for(;((enum_t*)enum)->strptr;((enum_t*)enum)++) { \
if ( ((enum_t*)enum)->value == ((rec_t*)rec)->(field_name) ) { \
*out_str = ((enum_t*)enum)->strptr; \
*out_len = strlen(*out_ptr); } } }
#define UAT_FLD_ENUM(basename,field_name,enum_t,enum) \
{#field_name, PT_TXTMOD_STRING,{uat_fld_chk_enum,basename ## field_name ## _set_cb,basename ## field_name ## _tostr_cb},{&(enum),&(enum),&(enum)},NULL,FLDFILL}
#endif

View File

@ -48,9 +48,9 @@
#include <epan/emem.h>
#include "uat-int.h"
static uat_t* uat;
static uat_fld_t* uat_fld;
static guint colnum;
static gchar* ptr;
static guint len;
static gchar* error;
@ -63,13 +63,14 @@
#define SET_FIELD() \
{ gchar* err; \
if (uat_fld->chk_cb) { \
if ( ! uat_fld->chk_cb(record, ptr, len, &err) ) { \
if (uat->fields[colnum].cb.chk) { \
if ( ! uat->fields[colnum].cb.chk(record, ptr, len, uat->fields[colnum].cbdata.chk,uat->fields[colnum].fld_data, &err) ) { \
ERROR(("%s",err)); \
}\
}\
uat_fld->set_cb(record, ptr, len);\
uat->fields[colnum].cb.set(record, ptr, len,uat->fields[colnum].cbdata.chk,uat->fields[colnum].fld_data);\
g_free(ptr);\
colnum++; \
} while(0)
#ifdef DEBUG_UAT_LOAD
@ -96,7 +97,7 @@ comment #[^\n]*\n
<START_OF_LINE>{newline} ;
<START_OF_LINE>{comment} ;
<NEXT_FIELD>{newline} {
ERROR(("expecting %s field in previuos line",uat_fld->name));
ERROR(("expecting %s field in previuos line",uat->fields[colnum].name));
BEGIN START_OF_LINE;
}
@ -104,7 +105,7 @@ comment #[^\n]*\n
ptr = undquote(yytext,yyleng,&len);
if (uat_fld->next) {
if (colnum < uat->ncols - 1) {
DUMP("quoted_str->s");
BEGIN SEPARATOR;
} else {
@ -117,10 +118,10 @@ comment #[^\n]*\n
ptr = unbinstring(yytext,yyleng,&len);
if (!ptr) {
ERROR(("uneven hexstring for field %s",uat_fld->name));
ERROR(("uneven hexstring for field %s",uat->fields[colnum].name));
}
if ( uat_fld->next ) {
if ( colnum < uat->ncols - 1 ) {
DUMP("binstring->s");
BEGIN SEPARATOR;
} else {
@ -135,7 +136,7 @@ comment #[^\n]*\n
SET_FIELD();
if ( ! (uat_fld = uat_fld->next) ) {
if ( colnum >= uat->ncols ) {
ERROR(("more fields than required"));
}
@ -143,12 +144,12 @@ comment #[^\n]*\n
}
<SEPARATOR>{newline} {
ERROR(("expecting field %s in previuos line",uat_fld->name));
ERROR(("expecting field %s in previuos line",uat->fields[colnum].name));
BEGIN START_OF_LINE;
}
<SEPARATOR>. {
ERROR(("unexpected char while looking for field %s",uat_fld->name));
ERROR(("unexpected char while looking for field %s",uat->fields[colnum].name));
BEGIN ERRORED;
}
@ -166,7 +167,7 @@ comment #[^\n]*\n
SET_FIELD();
rec = uat_add_record(uat, record);
if (uat->update_cb)
uat->update_cb(rec,&err);
@ -174,7 +175,7 @@ comment #[^\n]*\n
ERROR(("%s",err));
}
uat_fld = uat->fields;
colnum = 0;;
ptr = NULL;
len = 0;
memset(record,0,uat->record_size);
@ -333,19 +334,21 @@ done:
gboolean uat_load(uat_t* uat_in, char** err) {
gchar* fname = uat_get_actual_filename(uat_in, FALSE);
g_assert(uat_in->finalized);
uat = uat_in;
;
if (!fname) {
UAT_UPDATE(uat);
return TRUE;
}
if (!(yyin = fopen(fname,"r"))) {
*err = strerror(errno);
return FALSE;
}
error = NULL;
uat_fld = uat->fields;
colnum = 0;
record = g_malloc0(uat->record_size);
BEGIN START_OF_LINE;

View File

@ -34,7 +34,7 @@
#include "macros_dlg.h"
void macros_dialog_cb(GtkWidget *w _U_, gpointer data _U_) {
uat_t* dfmuat;
void* dfmuat;
dfilter_macro_get_uat(&dfmuat);
uat_window(dfmuat);
}

View File

@ -51,6 +51,7 @@
#include "compat_macros.h"
#include "help_dlg.h"
#include "keys.h"
#include "uat_gui.h"
#include <epan/prefs-int.h>
@ -77,6 +78,8 @@ static void prefs_tree_select_cb(GtkCTree *, GtkCTreeNode *, gint,
#else
static void prefs_tree_select_cb(GtkTreeSelection *, gpointer);
#endif
static GtkWidget* create_preference_uat(GtkWidget*, int, const gchar*, const gchar *, void*);
#define E_PREFSW_SCROLLW_KEY "prefsw_scrollw"
#define E_PREFSW_TREE_KEY "prefsw_tree"
@ -237,6 +240,14 @@ pref_show(pref_t *pref, gpointer user_data)
break;
}
case PREF_UAT:
{
pref->control = create_preference_uat(main_tb, pref->ordinal,
label_string, pref->description,
pref->varp.uat);
break;
}
case PREF_OBSOLETE:
g_assert_not_reached();
break;
@ -940,6 +951,35 @@ create_preference_static_text(GtkWidget *main_tb, int table_position,
return label;
}
static GtkWidget *
create_preference_uat(GtkWidget *main_tb,
int table_position,
const gchar *label_text,
const gchar *tooltip_text,
void* uat)
{
GtkTooltips *tooltips;
GtkWidget *button = NULL;
tooltips = OBJECT_GET_DATA(main_tb, E_TOOLTIPS_KEY);
set_option_label(main_tb, table_position, label_text, tooltip_text,
tooltips);
button = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_EDIT);
SIGNAL_CONNECT(button, "clicked", uat_window_cb, uat);
gtk_table_attach_defaults(GTK_TABLE(main_tb), button, 1, 2,
table_position, table_position+1);
if (tooltip_text != NULL && tooltips != NULL)
gtk_tooltips_set_tip(tooltips, button, tooltip_text, NULL);
gtk_widget_show(button);
return button;
}
static guint
pref_check(pref_t *pref, gpointer user_data)
{
@ -987,7 +1027,8 @@ pref_check(pref_t *pref, gpointer user_data)
}
break;
case PREF_STATIC_TEXT:
case PREF_STATIC_TEXT:
case PREF_UAT:
/* Value can't be bad. */
break;
@ -1090,6 +1131,7 @@ pref_fetch(pref_t *pref, gpointer user_data)
}
case PREF_STATIC_TEXT:
case PREF_UAT:
break;
case PREF_OBSOLETE:
@ -1208,6 +1250,7 @@ pref_clean(pref_t *pref, gpointer user_data _U_)
break;
case PREF_STATIC_TEXT:
case PREF_UAT:
break;
case PREF_OBSOLETE:
@ -1541,6 +1584,7 @@ pref_revert(pref_t *pref, gpointer user_data)
break;
case PREF_STATIC_TEXT:
case PREF_UAT:
break;
case PREF_OBSOLETE:

View File

@ -91,15 +91,16 @@ struct _uat_dlg_data {
static void append_row(uat_t* uat, guint idx) {
GPtrArray* a = g_ptr_array_new();
void* rec = UAT_INDEX_PTR(uat,idx);
uat_fld_t* f;
uat_field_t* f = uat->fields;
guint rownum;
guint colnum;
gtk_clist_freeze(GTK_CLIST(uat->rep->clist));
for ( f = uat->fields; f ; f = f->next ) {
for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
guint len;
char* ptr;
f->tostr_cb(rec,&ptr,&len);
f[colnum].cb.tostr(rec,&ptr,&len,f[colnum].cbdata.tostr,f[colnum].fld_data);
g_ptr_array_add(a,ptr);
}
@ -113,15 +114,16 @@ static void append_row(uat_t* uat, guint idx) {
static void reset_row(uat_t* uat, guint idx) {
void* rec = UAT_INDEX_PTR(uat,idx);
uat_fld_t* f;
uat_field_t* f = uat->fields;
guint colnum;
gtk_clist_freeze(GTK_CLIST(uat->rep->clist));
for ( f = uat->fields; f ; f = f->next ) {
for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
guint len;
char* ptr;
f->tostr_cb(rec,&ptr,&len);
gtk_clist_set_text(GTK_CLIST(uat->rep->clist), idx, f->colnum, ptr);
f[colnum].cb.tostr(rec,&ptr,&len,f[colnum].cbdata.tostr,f[colnum].fld_data);
gtk_clist_set_text(GTK_CLIST(uat->rep->clist), idx, colnum, ptr);
}
gtk_clist_thaw(GTK_CLIST(uat->rep->clist));
@ -131,23 +133,23 @@ static void reset_row(uat_t* uat, guint idx) {
static gboolean uat_dlg_cb(GtkWidget *win _U_, gpointer user_data) {
struct _uat_dlg_data* dd = user_data;
uat_fld_t* fld;
guint ncols = dd->uat->ncols;
uat_field_t* f = dd->uat->fields;
char* err = NULL;
guint i;
for (fld = dd->uat->fields, i = 0; fld ; fld = fld->next, i++) {
GtkWidget* entry = g_ptr_array_index(dd->entries,i);
const gchar* text = gtk_entry_get_text(GTK_ENTRY(entry));
guint colnum;
for ( colnum = 0; colnum < ncols; colnum++ ) {
const gchar* text = gtk_entry_get_text(GTK_ENTRY(g_ptr_array_index(dd->entries,colnum)));
unsigned len = strlen(text);
if (fld->chk_cb) {
if (! fld->chk_cb(dd->rec,text,len,&err)) {
err = ep_strdup_printf("error in field '%s': %s",fld->name,err);
if (f[colnum].cb.chk) {
if (! f[colnum].cb.chk(dd->rec, text, len, f[colnum].cbdata.tostr, f[colnum].fld_data, &err)) {
err = ep_strdup_printf("error in field '%s': %s",f[colnum].name,err);
goto on_failure;
}
}
fld->set_cb(dd->rec,text,len);
f[colnum].cb.set(dd->rec,text,len, f[colnum].cbdata.tostr, f[colnum].fld_data);
}
if (dd->uat->update_cb) {
@ -157,16 +159,19 @@ static gboolean uat_dlg_cb(GtkWidget *win _U_, gpointer user_data) {
err = ep_strdup_printf("error updating record: %s",err);
goto on_failure;
}
if (dd->is_new) {
uat_add_record(dd->uat, dd->rec);
if (dd->uat->free_cb) {
dd->uat->free_cb(dd->rec);
}
}
}
if (dd->is_new) {
void* rec_tmp = dd->rec;
dd->rec = uat_add_record(dd->uat, dd->rec);
if (dd->uat->free_cb) {
dd->uat->free_cb(rec_tmp);
}
g_free(rec_tmp);
}
uat_save(dd->uat,&err);
if (err) {
@ -180,7 +185,6 @@ static gboolean uat_dlg_cb(GtkWidget *win _U_, gpointer user_data) {
reset_row(dd->uat,dd->row);
}
if (dd->is_new) g_free(dd->rec);
g_ptr_array_free(dd->entries,TRUE);
window_destroy(GTK_WIDGET(dd->win));
@ -201,7 +205,7 @@ static gboolean uat_cancel_dlg_cb(GtkWidget *win _U_, gpointer user_data) {
if (dd->is_new) g_free(dd->rec);
g_ptr_array_free(dd->entries,TRUE);
window_destroy(GTK_WIDGET(dd->win));
g_free(dd);
return TRUE;
}
@ -209,8 +213,8 @@ static gboolean uat_cancel_dlg_cb(GtkWidget *win _U_, gpointer user_data) {
static void uat_dialog(uat_t* uat, gint row) {
GtkWidget *win, *main_tb, *main_vb, *bbox, *bt_cancel, *bt_ok;
struct _uat_dlg_data* dd = g_malloc(sizeof(struct _uat_dlg_data));
uat_fld_t* fld;
int i = 0;
uat_field_t* f = uat->fields;
guint colnum;
dd->entries = g_ptr_array_new();
dd->win = dlg_window_new(uat->name);
@ -237,28 +241,27 @@ static void uat_dialog(uat_t* uat, gint row) {
gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
for (fld = uat->fields; fld ; fld = fld->next) {
for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
GtkWidget *entry, *label;
label = gtk_label_new(fld->name);
label = gtk_label_new(f[colnum].name);
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, i+1, i + 2);
gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, colnum+1, colnum + 2);
gtk_widget_show(label);
entry = gtk_entry_new();
g_ptr_array_add(dd->entries,entry);
gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2, i+1, i + 2);
gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2, colnum+1, colnum + 2);
gtk_widget_show(entry);
if (! dd->is_new) {
gchar* text;
unsigned len;
fld->tostr_cb(dd->rec,&text,&len);
f[colnum].cb.tostr(dd->rec,&text,&len, f[colnum].cbdata.tostr, f[colnum].fld_data);
gtk_entry_set_text(GTK_ENTRY(entry),text);
}
i++;
}
bbox = dlg_button_row_new(GTK_STOCK_CANCEL,GTK_STOCK_OK, NULL);
@ -285,8 +288,17 @@ struct _uat_del {
static void uat_del_cb(GtkButton *button _U_, gpointer u) {
struct _uat_del* ud = u;
char* err = NULL;
uat_remove_record_idx(ud->uat, ud->idx);
gtk_clist_remove(GTK_CLIST(ud->uat->rep->clist),ud->idx);
uat_save(ud->uat,&err);
if (err) {
report_failure("an error happened while saving %s: %s",ud->uat->name,err);
}
window_destroy(GTK_WIDGET(ud->win));
window_present(GTK_WIDGET(ud->uat->rep->window));
g_free(ud);
@ -301,8 +313,8 @@ static void uat_cancel_del_cb(GtkButton *button _U_, gpointer u) {
static void uat_del_dlg(uat_t* uat, int idx) {
GtkWidget *win, *main_tb, *main_vb, *bbox, *bt_cancel, *bt_ok;
uat_fld_t* fld;
int i = 0;
uat_field_t* f = uat->fields;
guint colnum;
void* rec = UAT_INDEX_PTR(uat,idx);
struct _uat_del* ud = g_malloc(sizeof(struct _uat_del));
@ -326,26 +338,24 @@ static void uat_del_dlg(uat_t* uat, int idx) {
gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
for (fld = uat->fields; fld ; fld = fld->next) {
for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
GtkWidget *label;
gchar* text;
unsigned len;
fld->tostr_cb(rec,&text,&len);
f[colnum].cb.tostr(rec,&text,&len, f[colnum].cbdata.tostr, f[colnum].fld_data);
label = gtk_label_new(fld->name);
label = gtk_label_new(f[colnum].name);
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, i+1, i + 2);
gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, colnum+1, colnum + 2);
gtk_widget_show(label);
label = gtk_label_new(text);
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 1, 2, i+1, i + 2);
gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 1, 2, colnum+1, colnum + 2);
gtk_widget_show(label);
i++;
}
}
bbox = dlg_button_row_new(GTK_STOCK_CANCEL,GTK_STOCK_DELETE, NULL);
gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
@ -404,10 +414,12 @@ static void free_rep(GtkWindow *win _U_, uat_t* uat) {
}
GtkWidget* uat_window(uat_t* uat) {
GtkWidget* uat_window(void* u) {
uat_t* uat = u;
uat_field_t* f = uat->fields;
uat_rep_t* rep;
uat_fld_t* f;
guint i;
guint colnum;
if (uat->rep) {
window_present(uat->rep->window);
@ -440,9 +452,9 @@ GtkWidget* uat_window(uat_t* uat) {
rep->clist = gtk_clist_new(uat->ncols);
for ( f = uat->fields; f ; f = f->next ) {
gtk_clist_set_column_title(GTK_CLIST(rep->clist), f->colnum, f->name);
gtk_clist_set_column_auto_resize(GTK_CLIST(rep->clist), f->colnum, TRUE);
for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
gtk_clist_set_column_title(GTK_CLIST(rep->clist), colnum, f[colnum].name);
gtk_clist_set_column_auto_resize(GTK_CLIST(rep->clist), colnum, TRUE);
}
gtk_clist_column_titles_show(GTK_CLIST(rep->clist));
@ -514,3 +526,6 @@ GtkWidget* uat_window(uat_t* uat) {
return rep->window;
}
void uat_window_cb(GtkWidget* u _U_, void* uat) {
uat_window(uat);
}

View File

@ -29,8 +29,8 @@
#ifndef _UAT_GUI_H_
#define _UAT_GUI_H_
#include <epan/uat.h>
GtkWidget* uat_window(uat_t*);
GtkWidget* uat_window(void*);
void uat_window_cb(GtkWidget* unused, void* uat);
#endif