Wireshark-dev: [Wireshark-dev] [Patch] additional lua dissector preference types
From: "Balint Reczey (IJ/ETH)" <Balint.Reczey@xxxxxxxxxxxx>
Date: Fri, 27 Apr 2007 13:28:50 +0200
Hi,

The attached patch adds ability of of creating radio button, drop-down
list and range type preference entries to the Lua plugin.
It also fixes a lua compile warning/error in wslua_gui.c.
The patch is written by Tamas Regos, he asked me to send it to the list.
Could someone commit it to the svn repo?

Cheers,
Balint
Index: epan/wslua/wslua_gui.c
===================================================================
--- epan/wslua/wslua_gui.c	(revision 21602)
+++ epan/wslua/wslua_gui.c	(working copy)
@@ -537,7 +537,7 @@
 	
 	const char* fname = luaL_checkstring(L,WSLUA_ARG_open_capture_file_FILENAME);
 	const char* filter = luaL_optstring(L,WSLUA_ARG_open_capture_file_FILTER,NULL);
-	char* error = NULL;
+	const char* error = NULL;
 
 	if (!ops->open_file) {
 		WSLUA_ERROR(wslua_open_capture_file, "does not work on TShark");
Index: epan/wslua/wslua.h
===================================================================
--- epan/wslua/wslua.h	(revision 21602)
+++ epan/wslua/wslua.h	(working copy)
@@ -4,6 +4,7 @@
  * Wireshark's interface to the Lua Programming Language
  *
  * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@xxxxxxxxx>
+ * (c) 2007, Tamas Regos <tamas.regos@xxxxxxxxxxxx>
  *
  * $Id$
  *
@@ -76,7 +77,19 @@
     guint32 mask;
 } wslua_field_t;
 
-typedef enum {PREF_NONE,PREF_BOOL,PREF_UINT,PREF_STRING} pref_type_t;
+/*
+ * PREF_OBSOLETE is used for preferences that a module used to support
+ * but no longer supports; we give different error messages for them.
+ */
+typedef enum {
+	PREF_UINT,
+	PREF_BOOL,
+	PREF_ENUM,
+	PREF_STRING,
+	PREF_RANGE,
+	PREF_STATIC_TEXT,
+	PREF_OBSOLETE
+} pref_type_t;
 
 typedef struct _wslua_pref_t {
     gchar* name;
@@ -87,8 +100,20 @@
         gboolean b;
         guint u;
         const gchar* s;
-		void* p;
+        gint e;
+	range_t *r;
+	void* p;
     } value;
+    union {
+  	guint32 max_value;		/* maximum value of a range */
+  	struct {
+  	    const enum_val_t *enumvals;	/* list of name & values */
+  	    gboolean radio_buttons;	/* TRUE if it should be shown as
+  					   radio buttons rather than as an
+  					   option menu or combo box in
+  					   the preferences tab */
+  	} enum_info;			/* for PREF_ENUM */
+    } info;			        /* display/text file information */
     
     struct _wslua_pref_t* next;
     struct _wslua_proto_t* proto;
Index: epan/wslua/wslua_proto.c
===================================================================
--- epan/wslua/wslua_proto.c	(revision 21602)
+++ epan/wslua/wslua_proto.c	(working copy)
@@ -4,6 +4,7 @@
  * wireshark's interface to the Lua Programming Language
  *
  * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@xxxxxxxxx>
+ * (c) 2007, Tamas Regos <tamas.regos@xxxxxxxxxxxx>
  *
  * $Id$
  *
@@ -32,6 +33,72 @@
 
 WSLUA_CLASS_DEFINE(Pref,NOP,NOP); /* A preference of a Protocol. */
 
+static range_t* get_range(lua_State *L, int idx_r, int idx_m)
+{
+  static range_t *ret;
+    range_convert_str(&ret,g_strdup(lua_tostring(L, idx_r)),(guint32)lua_tonumber(L, idx_m));
+  return ret;
+}
+
+static enum_val_t* get_enum(lua_State *L, int idx)
+{
+  double seq;
+  const gchar *str1, *str2;
+  enum_val_t *ret, last = {NULL, NULL, -1};
+  GArray* es = g_array_new(TRUE,TRUE,sizeof(enum_val_t));
+
+  luaL_checktype(L, idx, LUA_TTABLE);
+  lua_pushnil(L);  /* first key */
+
+  while (lua_next(L, idx)) {
+    enum_val_t e = {NULL, NULL, -1};
+
+    luaL_checktype(L, -1, LUA_TTABLE);
+    lua_pushnil(L);
+    lua_next(L, -2);
+    if (! lua_isstring(L,-1)) {
+        luaL_argerror(L,idx,"First value of an enum table must be string");
+        g_array_free(es,TRUE);
+        return NULL;
+    }
+    str1 = lua_tostring(L, -1);
+    
+    lua_pop(L, 1);
+    lua_next(L, -2);
+    if (! lua_isstring(L,-1)) {
+        luaL_argerror(L,idx,"Second value of an enum table must be string");
+        g_array_free(es,TRUE);
+        return NULL;
+    }
+    str2 = lua_tostring(L, -1);
+    
+    lua_pop(L, 1);
+    lua_next(L, -2);
+    if (! lua_isnumber(L,-1)) {
+        luaL_argerror(L,idx,"Third value of an enum table must be an integer");
+        g_array_free(es,TRUE);
+        return NULL;
+    }
+    seq = lua_tonumber(L, -1);
+
+    e.name = g_strdup(str1);
+    e.description = g_strdup(str2);
+    e.value = (guint32)seq;
+    
+    g_array_append_val(es,e);
+    
+    lua_pop(L, 3);  /* removes 'value'; keeps 'key' for next iteration */
+  }
+  
+  g_array_append_val(es,last);
+  
+  ret = (enum_val_t*)es->data;
+
+  g_array_free(es,FALSE);
+
+  return ret;
+}
+
 static int new_pref(lua_State* L, pref_type_t type) {
     const gchar* label = luaL_optstring(L,1,NULL);
     const gchar* descr = luaL_optstring(L,3,"");
@@ -60,6 +127,26 @@
             pref->value.s = def;
             break;
         }
+        case PREF_ENUM: {
+            guint32 def = (guint32)luaL_optnumber(L,2,0);
+            enum_val_t *enum_val = get_enum(L,4);
+            gboolean radio = lua_toboolean(L,5);
+            pref->value.e = def;
+            pref->info.enum_info.enumvals = enum_val;
+            pref->info.enum_info.radio_buttons = radio;
+            break;
+        }
+        case PREF_RANGE: {
+            range_t *range = get_range(L,4,5);
+            guint32 max = (guint32)luaL_optnumber(L,5,0);
+            pref->value.r = range;
+            pref->info.max_value = max;
+            break;
+        }
+        case PREF_STATIC_TEXT: {
+            /* This is just a static text. */
+	    break;
+        }
         default:
             g_assert_not_reached();
             break;
@@ -101,6 +188,39 @@
     return new_pref(L,PREF_STRING);
 }
 
+WSLUA_CONSTRUCTOR Pref_enum(lua_State* L) {
+	/*
+	 * Creates an enum preference to be added to a Protocol's prefs table.
+	 */
+#define WSLUA_ARG_Pref_enum_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
+#define WSLUA_ARG_Pref_enum_DEFAULT 2 /* The default value for this preference */
+#define WSLUA_ARG_Pref_enum_DESCR 3 /* A description of what this preference is */
+#define WSLUA_ARG_Pref_enum_ENUM 4 /* enum */
+#define WSLUA_ARG_Pref_enum_RADIO 5 /* radio_button or combobox */
+    return new_pref(L,PREF_ENUM);
+}
+
+WSLUA_CONSTRUCTOR Pref_range(lua_State* L) {
+	/*
+	 * Creates a range preference to be added to a Protocol's prefs table.
+	 */
+#define WSLUA_ARG_Pref_enum_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
+#define WSLUA_ARG_Pref_enum_DEFAULT 2 /* The default value for this preference */
+#define WSLUA_ARG_Pref_enum_DESCR 3 /* A description of what this preference is */
+#define WSLUA_ARG_Pref_enum_RANGE 4 /* The range */
+#define WSLUA_ARG_Pref_enum_MAX 5 /* The maximum value */
+    return new_pref(L,PREF_RANGE);
+}
+
+WSLUA_CONSTRUCTOR Pref_stext(lua_State* L) {
+	/*
+	 * Creates a static text preference to be added to a Protocol's prefs table.
+	 */
+#define WSLUA_ARG_Pref_enum_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
+#define WSLUA_ARG_Pref_enum_TEXT 2 /* The static text */
+    return new_pref(L,PREF_STATIC_TEXT);
+}
+
 static int Pref_gc(lua_State* L) {
     Pref pref = checkPref(L,1);
     
@@ -117,7 +237,10 @@
 WSLUA_METHODS Pref_methods[] = {
     {"bool",   Pref_bool},
     {"uint",   Pref_uint},
-    {"string",   Pref_string},
+    {"string", Pref_string},
+    {"enum",   Pref_enum},
+    {"range",  Pref_range},
+    {"statictext",  Pref_stext},
     {0,0}
 };
 
@@ -202,6 +325,29 @@
                                                      pref->desc,
                                                      &(pref->value.s));
                     break;
+                case PREF_ENUM:
+                    prefs_register_enum_preference(prefs->proto->prefs_module, 
+                                                     pref->name,
+                                                     pref->label,
+                                                     pref->desc,
+                                                     &(pref->value.e),
+                                                     pref->info.enum_info.enumvals,
+                                                     pref->info.enum_info.radio_buttons);
+                    break;
+                case PREF_RANGE:
+                    prefs_register_range_preference(prefs->proto->prefs_module, 
+                                                     pref->name,
+                                                     pref->label,
+                                                     pref->desc,
+                                                     &(pref->value.r),
+						     pref->info.max_value);
+                    break;
+                case PREF_STATIC_TEXT:
+                    prefs_register_static_text_preference(prefs->proto->prefs_module, 
+                                                     pref->name,
+                                                     pref->label,
+                                                     "This is just a static text");
+                    break;
                 default:
                     WSLUA_ERROR(Prefs__newindex,"unknow Pref type");
             }
@@ -234,6 +380,8 @@
                 case PREF_BOOL: lua_pushboolean(L, prefs->value.b); break;
                 case PREF_UINT: lua_pushnumber(L,(lua_Number)prefs->value.u); break;
                 case PREF_STRING: lua_pushstring(L,prefs->value.s); break;
+                case PREF_ENUM: lua_pushnumber(L,(lua_Number)prefs->value.e); break;
+                case PREF_RANGE: lua_pushstring(L,range_convert_range(prefs->value.r)); break;
                 default: WSLUA_ERROR(Prefs__index,"unknow Pref type");
             }
             WSLUA_RETURN(1); /* the current value of the preference */