Code changes, but not Makefile changes, for enabling plugins for Win32.
authorgram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 7 Feb 2000 17:08:27 +0000 (17:08 +0000)
committergram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 7 Feb 2000 17:08:27 +0000 (17:08 +0000)
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@1605 f5534014-38df-0310-8fa8-9805f1628bb7

config.h.win32
gtk/plugins_dlg.c
plugins.c
plugins/gryphon/packet-gryphon.c
plugins/plugin_api.c [new file with mode: 0644]
plugins/plugin_api.h [new file with mode: 0644]
proto.c
proto.h

index 5f620b6cd17f060d1de38734782e6494705186f3..ea3e6e4a18f5f730c62eda2c938711daeb172045 100644 (file)
@@ -84,3 +84,4 @@
 #define _WINDOWS                1*/
 
 #define HAVE_PLUGINS           1
+#define PLUGINS_NEED_ADDRESS_TABLE 1
index 6839b7ea92c8131f9c9bb7d078758e671e27cbe6..15d858f353b5679c8ccfd0de99d7f794df955cf0 100644 (file)
@@ -1,7 +1,7 @@
 /* plugins_dlg.c
  * Dialog boxes for plugins
  *
- * $Id: plugins_dlg.c,v 1.12 2000/01/17 20:30:17 guy Exp $
+ * $Id: plugins_dlg.c,v 1.13 2000/02/07 17:07:54 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 #include "prefs_dlg.h"
 #include "simple_dialog.h"
 
+#ifdef PLUGINS_NEED_ADDRESS_TABLE
+#include "plugins/plugin_api.h"
+extern plugin_address_table_t  patable;
+#endif
+
 #ifdef HAVE_PLUGINS
 
 static gint selected_row;
@@ -238,12 +243,12 @@ plugins_enable_cb(GtkWidget *button, gpointer clist)
 {
     plugin    *pt_plug;
     gpointer symbol;
-    void     (*proto_init)(void);
+    void     (*plugin_init)(void*);
 
     /* nothing selected */
     if (selected_row == -1) return;
     /* already enabled */
-    if (!strcmp(selected_enabled, "Yes")) return;
+    if (strcmp(selected_enabled, "Yes") == 0) return;
 
     if ((pt_plug = enable_plugin(selected_name, selected_version)) == NULL)
     {
@@ -253,10 +258,21 @@ plugins_enable_cb(GtkWidget *button, gpointer clist)
 
     /* Try to get the initialization routine for the plugin, and, if it
        has one, call it. */
-    if (g_module_symbol(pt_plug->handle, "proto_init", &symbol) == TRUE) {
-       proto_init = symbol;
-       proto_init();
-    }
+    if (g_module_symbol(pt_plug->handle, "plugin_init", &symbol) == TRUE) {
+       plugin_init = symbol;
+#ifdef PLUGINS_NEED_ADDRESS_TABLE
+                   plugin_init(&patable);
+#else
+                   plugin_init(NULL);
+#endif
+       }
+#ifdef PLUGINS_NEED_ADDRESS_TABLE
+       else {
+               simple_dialog(ESD_TYPE_WARN, NULL, "Failed to find plugin_init()");
+               return;
+       }
+#endif
+
 
     gtk_clist_set_text(GTK_CLIST(clist), selected_row, 3, "Yes");
 }
index 486fa049b4ce95b9b920ae20b98954803a6887f3..f5db9ee3535e9a193b6912a62cbf3ece9409f5ce 100644 (file)
--- a/plugins.c
+++ b/plugins.c
@@ -1,7 +1,7 @@
 /* plugins.c
  * plugin routines
  *
- * $Id: plugins.c,v 1.8 2000/02/03 21:31:03 oabad Exp $
+ * $Id: plugins.c,v 1.9 2000/02/07 17:07:44 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 #include "globals.h"
 #include "util.h"
 
+#ifdef PLUGINS_NEED_ADDRESS_TABLE
+#include "plugins/plugin_api.h"
+plugin_address_table_t patable;
+extern int hf_text_only;
+#endif
 
 /* linked list of all plugins */
 plugin *plugin_list;
 
+#ifdef WIN32
+static gchar std_plug_dir[] = "c:/program files/ethereal/plugins/0.8";
+static gchar local_plug_dir[] = "c:/ethereal/plugins/0.8";
+#else
 static gchar std_plug_dir[] = "/usr/lib/ethereal/plugins/0.8";
 static gchar local_plug_dir[] = "/usr/local/lib/ethereal/plugins/0.8";
+#endif
 static gchar *user_plug_dir = NULL;
 static gchar *plugin_status_file = NULL;
 
@@ -289,7 +299,7 @@ check_plugin_status(gchar *name, gchar *version, GModule *handle,
     gchar   *ref_string;
     guint16  ref_string_len;
     gchar    line[512];
-    void   (*proto_init)();
+    void   (*plugin_init)(void*);
     dfilter *filter;
 
     if (!statusfile) return;
@@ -306,9 +316,18 @@ check_plugin_status(gchar *name, gchar *version, GModule *handle,
        else { /* found the plugin */
            if (line[ref_string_len+1] == '1') {
                enable_plugin(name, version);
-               if (g_module_symbol(handle, "proto_init", (gpointer*)&proto_init) == TRUE) {
-                   proto_init();
+               if (g_module_symbol(handle, "plugin_init", (gpointer*)&plugin_init) == TRUE) {
+#ifdef PLUGINS_NEED_ADDRESS_TABLE
+                   plugin_init(&patable);
+#else
+                   plugin_init(NULL);
+#endif
+               }
+#ifdef PLUGINS_NEED_ADDRESS_TABLE
+               else {
+                       return;
                }
+#endif
            }
 
            if (fgets(line, 512, statusfile) == NULL) return;
@@ -360,12 +379,11 @@ plugins_scan_dir(const char *dirname)
            if (!(strcmp(file->d_name, "..") &&
                  strcmp(file->d_name, "."))) continue;
 
-            /* skip anything but .la */
+            /* skip anything but files with LT_LIB_EXT */
             dot = strrchr(file->d_name, '.');
-            if (dot == NULL || ! strcmp(dot, LT_LIB_EXT)) continue;
+            if (dot == NULL || strcmp(dot, LT_LIB_EXT) != 0) continue;
 
            sprintf(filename, "%s/%s", dirname, file->d_name);
-
            if ((handle = g_module_open(filename, 0)) == NULL) continue;
            name = (gchar *)file->d_name;
            if (g_module_symbol(handle, "version", (gpointer*)&version) == FALSE)
@@ -430,6 +448,32 @@ init_plugins()
 
     if (plugin_list == NULL)      /* ensure init_plugins is only run once */
     {
+
+#ifdef PLUGINS_NEED_ADDRESS_TABLE
+#ifdef pi
+#undef pi
+#endif
+       /* Intialize address table */
+       patable.check_col                       = check_col;
+       patable.col_add_fstr                    = col_add_fstr;
+       patable.col_append_fstr                 = col_append_str;
+       patable.col_add_str                     = col_add_str;
+       patable.col_append_str                  = col_append_str;
+
+       patable.dfilter_init                    = dfilter_init;
+       patable.dfilter_cleanup                 = dfilter_cleanup;
+
+       patable.pi                              = &pi;
+
+       patable.proto_register_protocol         = proto_register_protocol;
+       patable.proto_register_field_array      = proto_register_field_array;
+       patable.proto_register_subtree_array    = proto_register_subtree_array;
+
+       patable.proto_item_add_subtree          = proto_item_add_subtree;
+       patable._proto_tree_add_item_value      = _proto_tree_add_item_value;
+       patable.hf_text_only                    = hf_text_only;
+#endif
+
        plugins_scan_dir(std_plug_dir);
        plugins_scan_dir(local_plug_dir);
        if ((strcmp(std_plug_dir, PLUGIN_DIR) != 0) &&
index e019b0ad08f089fc9052575c4cb0de9c08a400c4..e741cf9aec494589b51a61f5f02bfce776b98dd8 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-gryphon.c
  * Routines for Gryphon protocol packet disassembly
  *
- * $Id: packet-gryphon.c,v 1.4 2000/01/08 19:37:11 gram Exp $
+ * $Id: packet-gryphon.c,v 1.5 2000/02/07 17:08:27 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Steve Limkemann <stevelim@dgtech.com>
@@ -29,6 +29,8 @@
 #include "config.h"
 #endif
 
+#include "plugins/plugin_api.h"
+
 #include "moduleinfo.h"
 
 #ifdef HAVE_SYS_TYPES_H
@@ -37,6 +39,7 @@
 
 #include <string.h>
 #include <ctype.h>
+#include <time.h>
 
 #include <glib.h>
 #ifdef HAVE_NETINET_IN_H
 #include "dfilter.h"
 #include "packet-gryphon.h"
 
-const gchar version[] = VERSION;
-const gchar desc[] = "DG Gryphon Protocol";
-const gchar protocol[] = "tcp";
-const gchar filter_string[] = "tcp.port == 7000";
+DLLEXPORT const gchar version[] = VERSION;
+DLLEXPORT const gchar desc[] = "DG Gryphon Protocol";
+DLLEXPORT const gchar protocol[] = "tcp";
+DLLEXPORT const gchar filter_string[] = "tcp.port == 7000";
+
+#ifndef G_HAVE_GINT64
+#error "Sorry, this won't compile without 64-bit integer support"
+#endif                                                                  
 
 static int proto_gryphon = -1;
 
@@ -78,14 +85,10 @@ static gint ett_gryphon_pgm_list = -1;
 static gint ett_gryphon_pgm_status = -1;
 static gint ett_gryphon_pgm_options = -1;
 
-#define gryphon_LTX_desc          desc
-#define gryphon_LTX_dissector     dissector
-#define gryphon_LTX_filter_string filter_string
-#define gryphon_LTX_proto_init    proto_init
-#define gryphon_LTX_protocol      protocol
-#define gryphon_LTX_version       version
 
-void dissector(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+
+DLLEXPORT void
+dissector(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
 {
 
     proto_tree     *gryphon_tree, *header_tree, *body_tree;
@@ -647,15 +650,15 @@ resp_time (int src, const u_char **data, const u_char *dataend, int *offset, int
 {
     int     hours, minutes, seconds, fraction;
     union {
-       unsigned int       lng[2];
-       unsigned long long int  lnglng;
+       unsigned int            lng[2];
+       unsigned gint64         lnglng;
     } ts;
     unsigned int    timestamp;
     unsigned char   date[45];
-    
+   
     ts.lng[1] = pntohl ((unsigned int *)(*data));
     ts.lng[0] = pntohl ((unsigned int *)((*data)+4));
-    timestamp = ts.lnglng / 100000LL;
+    timestamp = ts.lnglng / 100000L;
     strncpy (date, ctime((time_t*)&timestamp), sizeof(date));
     date[strlen(date)-1] = 0x00;
     proto_tree_add_text(pt, *offset, 8, "Date/Time: %s", date);
@@ -1517,8 +1520,8 @@ blm_mode (int src, const u_char **data, const u_char *dataend, int *offset, int
     BUMP (*offset, *data, 4);
 }
 
-void
-proto_init(void)
+DLLEXPORT void
+plugin_init(plugin_address_table_t *pat)
 {
     static hf_register_info hf[] = {
        { &hf_gryph_src,
@@ -1560,7 +1563,7 @@ proto_init(void)
        &ett_gryphon_pgm_status,
        &ett_gryphon_pgm_options,
     };
-    
+    plugin_address_table_init(pat);
     dfilter_cleanup();
     proto_gryphon = proto_register_protocol("DG Gryphon Protocol", "gryphon");
     proto_register_field_array(proto_gryphon, hf, array_length(hf));
diff --git a/plugins/plugin_api.c b/plugins/plugin_api.c
new file mode 100644 (file)
index 0000000..50627a5
--- /dev/null
@@ -0,0 +1,147 @@
+/* plugin_api.c
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include "plugin_api.h"
+
+static plugin_address_table_t  *patable = NULL;
+packet_info                    *p_pi;
+
+
+#ifdef pi
+#undef pi
+#endif
+
+void
+plugin_address_table_init(plugin_address_table_t *pat)
+{
+       patable = pat;
+       p_pi = pat->pi;
+}
+
+gint
+check_col(frame_data* fd, gint col)
+{
+       return patable->check_col(fd, col);
+}
+
+/*void col_add_fstr(frame_data*, gint, gchar*, ...);
+void col_append_fstr(frame_data*, gint, gchar*, ...);*/
+
+void
+col_add_str(frame_data* fd, gint col, const gchar* str)
+{
+       patable->col_add_str(fd, col, str);
+}
+
+void
+col_append_str(frame_data* fd, gint col, gchar* str)
+{
+       patable->col_append_str(fd, col, str);
+}
+
+void
+dfilter_init(void)
+{
+       patable->dfilter_init();
+}
+
+void
+dfilter_cleanup(void)
+{
+       patable->dfilter_cleanup();
+}
+
+int
+proto_register_protocol(char* name, char* abbrev)
+{
+       return patable->proto_register_protocol(name, abbrev);
+}
+
+void
+proto_register_field_array(int parent, hf_register_info* hf, int num_records)
+{
+       patable->proto_register_field_array(parent, hf, num_records);
+}
+
+void
+proto_register_subtree_array(int** indices, int num_indices)
+{
+       patable->proto_register_subtree_array(indices, num_indices);
+}
+
+proto_tree*
+proto_item_add_subtree(proto_item* pi, gint idx)
+{
+       patable->proto_item_add_subtree(pi, idx);
+}
+
+proto_item *
+proto_tree_add_item(proto_tree *tree, int hfindex, gint start, gint length, ...)
+{
+       proto_item      *pi;
+       va_list         ap;
+
+       va_start(ap, length);
+       pi = patable->_proto_tree_add_item_value(tree, hfindex, start, length, 0, 1, ap);
+       va_end(ap);
+
+       return pi;
+}
+
+proto_item *
+proto_tree_add_item_hidden(proto_tree *tree, int hfindex, gint start, gint length, ...)
+{
+       proto_item      *pi;
+       va_list         ap;
+
+       va_start(ap, length);
+       pi = patable->_proto_tree_add_item_value(tree, hfindex, start, length, 0, 0, ap);
+       va_end(ap);
+
+       return pi;
+}
+
+proto_item *
+proto_tree_add_item_format(proto_tree *tree, int hfindex, gint start, gint length, ...)
+{
+       proto_item      *pi;
+       va_list         ap;
+
+       va_start(ap, length);
+       pi = patable->_proto_tree_add_item_value(tree, hfindex, start, length, 1, 1, ap);
+       va_end(ap);
+
+       return pi;
+}
+
+proto_item *
+proto_tree_add_notext(proto_tree *tree, gint start, gint length, ...)
+{
+       proto_item      *pi;
+       va_list         ap;
+
+       va_start(ap, length);
+       pi = patable->_proto_tree_add_item_value(tree, patable->hf_text_only, start, length, 0, 1, ap);
+       va_end(ap);
+
+       return pi;
+}
+
+proto_item *
+proto_tree_add_text(proto_tree *tree, gint start, gint length, ...)
+{
+       proto_item      *pi;
+       va_list         ap;
+
+       va_start(ap, length);
+       pi = patable->_proto_tree_add_item_value(tree, patable->hf_text_only, start, length, 1, 1, ap);
+       va_end(ap);
+
+       return pi;
+}
diff --git a/plugins/plugin_api.h b/plugins/plugin_api.h
new file mode 100644 (file)
index 0000000..781456d
--- /dev/null
@@ -0,0 +1,96 @@
+/* plugin_api.h
+ */
+
+#ifndef __PACKET_H__
+#include "packet.h"
+#endif
+
+#ifdef PLUGINS_NEED_ADDRESS_TABLE
+#define DLLEXPORT    __declspec(dllexport)
+
+/* Some OSes (Win32) have DLLs that cannot reference symbols in the parent executable.
+   So, the executable needs to provide a table of pointers for the DLL plugin to use. */
+
+/* Typedefs to make our plugin_address_table_t struct look prettier */
+typedef gint (*addr_check_col)(frame_data*, gint);
+typedef void (*addr_col_add_fstr)(frame_data*, gint, gchar*, ...);
+typedef void (*addr_col_append_fstr)(frame_data*, gint, gchar*, ...);
+typedef void (*addr_col_add_str)(frame_data*, gint, const gchar*);
+typedef void (*addr_col_append_str)(frame_data*, gint, gchar*);
+
+typedef void (*addr_dfilter_init)(void);
+typedef void (*addr_dfilter_cleanup)(void);
+
+typedef int (*addr_proto_register_protocol)(char*, char*);
+typedef void (*addr_proto_register_field_array)(int, hf_register_info*, int);
+typedef void (*addr_proto_register_subtree_array)(int**, int);
+
+typedef proto_tree* (*addr_proto_item_add_subtree)(proto_item*, gint);
+typedef proto_item* (*addr_proto_tree_add_item)(proto_tree*, int, gint, gint, ...);
+typedef proto_item* (*addr_proto_tree_add_item_hidden)(proto_tree*, int, gint, gint, ...);
+typedef proto_item* (*addr_proto_tree_add_item_format)(proto_tree*, int, gint, gint, ...);
+typedef proto_item* (*addr_proto_tree_add_notext)(proto_tree*, gint, gint, ...);
+typedef proto_item* (*addr_proto_tree_add_item_value)(proto_tree*, int, gint, gint, int, int,
+                               va_list);
+extern packet_info *p_pi;
+
+typedef struct  {
+
+       addr_check_col                          check_col;
+       addr_col_add_fstr                       col_add_fstr;
+       addr_col_append_fstr                    col_append_fstr;
+       addr_col_add_str                        col_add_str;
+       addr_col_append_str                     col_append_str;
+
+       addr_dfilter_init                       dfilter_init;
+       addr_dfilter_cleanup                    dfilter_cleanup;
+
+       packet_info                             *pi;
+
+       addr_proto_register_protocol            proto_register_protocol;
+       addr_proto_register_field_array         proto_register_field_array;
+       addr_proto_register_subtree_array       proto_register_subtree_array;
+
+       addr_proto_item_add_subtree             proto_item_add_subtree;
+       addr_proto_tree_add_item_value          _proto_tree_add_item_value;
+       int                                     hf_text_only;
+} plugin_address_table_t;
+
+/* The parent executable will send us the pointer to a filled in
+   plugin_address_table_t struct, and we keep a copy of that pointer
+   so that we can use functions in the parent executable. */
+void plugin_address_table_init(plugin_address_table_t*);
+
+/* Wrapper functions that use plugin_address_table_t */
+gint check_col(frame_data*, gint);
+void col_add_fstr(frame_data*, gint, gchar*, ...);
+void col_append_fstr(frame_data*, gint, gchar*, ...);
+void col_add_str(frame_data*, gint, const gchar*);
+void col_append_str(frame_data*, gint, gchar*);
+
+void dfilter_init(void);
+void dfilter_cleanup(void);
+
+int proto_register_protocol(char*, char*);
+void proto_register_field_array(int, hf_register_info*, int);
+void proto_register_subtree_array(int**, int);
+
+proto_tree* proto_item_add_subtree(proto_item*, gint);
+proto_item* proto_tree_add_item(proto_tree*, int, gint, gint, ...);
+proto_item* proto_tree_add_item_hidden(proto_tree*, int, gint, gint, ...);
+proto_item* proto_tree_add_item_format(proto_tree*, int, gint, gint, ...);
+proto_item* proto_tree_add_notext(proto_tree*, gint, gint, ...);
+proto_item* proto_tree_add_text(proto_tree*, gint, gint, ...);
+
+#define pi     (*p_pi)
+
+
+#else
+
+/* ! PLUGINS_NEED_ACCESS_TABLE */
+#define DLLEXPORT 
+typedef void   plugin_address_table_t;
+#define plugin_address_table_init(x) ;
+
+#endif
+
diff --git a/proto.c b/proto.c
index 50d2b99a838f7401062fe9835181916112c204d2..c78e552054ed064aa44127455a68795868b837eb 100644 (file)
--- a/proto.c
+++ b/proto.c
@@ -1,7 +1,7 @@
 /* proto.c
  * Routines for protocol tree
  *
- * $Id: proto.c,v 1.52 2000/01/22 04:59:55 guy Exp $
+ * $Id: proto.c,v 1.53 2000/02/07 17:07:45 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -75,9 +75,6 @@ proto_tree_free_node(GNode *node, gpointer data);
 static struct header_field_info*
 find_hfinfo_record(int hfindex);
 
-static proto_item *
-proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
-       gint length, int include_format, int visible, va_list ap);
 
 static void fill_label_boolean(field_info *fi, gchar *label_str);
 static void fill_label_uint(field_info *fi, gchar *label_str);
@@ -235,7 +232,7 @@ proto_tree_add_item(proto_tree *tree, int hfindex, gint start, gint length, ...)
        va_list         ap;
 
        va_start(ap, length);
-       pi = proto_tree_add_item_value(tree, hfindex, start, length, 0, 1, ap);
+       pi = _proto_tree_add_item_value(tree, hfindex, start, length, 0, 1, ap);
        va_end(ap);
 
        return pi;
@@ -248,7 +245,7 @@ proto_tree_add_item_hidden(proto_tree *tree, int hfindex, gint start, gint lengt
        va_list         ap;
 
        va_start(ap, length);
-       pi = proto_tree_add_item_value(tree, hfindex, start, length, 0, 0, ap);
+       pi = _proto_tree_add_item_value(tree, hfindex, start, length, 0, 0, ap);
        va_end(ap);
 
        return pi;
@@ -261,7 +258,7 @@ proto_tree_add_item_format(proto_tree *tree, int hfindex, gint start, gint lengt
        va_list         ap;
 
        va_start(ap, length);
-       pi = proto_tree_add_item_value(tree, hfindex, start, length, 1, 1, ap);
+       pi = _proto_tree_add_item_value(tree, hfindex, start, length, 1, 1, ap);
        va_end(ap);
 
        return pi;
@@ -274,7 +271,7 @@ proto_tree_add_notext(proto_tree *tree, gint start, gint length, ...)
        va_list         ap;
 
        va_start(ap, length);
-       pi = proto_tree_add_item_value(tree, hf_text_only, start, length, 0, 1, ap);
+       pi = _proto_tree_add_item_value(tree, hf_text_only, start, length, 0, 1, ap);
        va_end(ap);
 
        return pi;
@@ -287,14 +284,14 @@ proto_tree_add_text(proto_tree *tree, gint start, gint length, ...)
        va_list         ap;
 
        va_start(ap, length);
-       pi = proto_tree_add_item_value(tree, hf_text_only, start, length, 1, 1, ap);
+       pi = _proto_tree_add_item_value(tree, hf_text_only, start, length, 1, 1, ap);
        va_end(ap);
 
        return pi;
 }
 
-static proto_item *
-proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
+proto_item *
+_proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
        gint length, int include_format, int visible, va_list ap)
 {
        proto_item      *pi;
diff --git a/proto.h b/proto.h
index 78100c3fbc8f125824a1e6b1e084a71928170e79..bc45113bb645e0d2d77dd33b287df56933610491 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -1,7 +1,7 @@
 /* proto.h
  * Definitions for protocol display
  *
- * $Id: proto.h,v 1.21 2000/01/22 04:59:55 guy Exp $
+ * $Id: proto.h,v 1.22 2000/02/07 17:07:45 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -179,6 +179,12 @@ proto_register_field_array(int parent, hf_register_info *hf, int num_records);
 void
 proto_register_subtree_array(gint **indices, int num_indices);
 
+/* We have to make this prototype accessible for plugin_api.c, but we
+   don't want anybody except plugin_api.c to use it directly */
+proto_item *
+_proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
+       gint length, int include_format, int visible, va_list ap);
+
 proto_item *
 proto_tree_add_item(proto_tree *tree, int hfindex, gint start,
        gint length, ...);