From Yaniv Kaul: constify parameters
[obnox/wireshark/wip.git] / epan / proto.c
index 5b077987ec51b9d3ff0b779265cb895b1eb9d8d3..287bf7383511cfd1863cfe313098b1522c8e8a98 100644 (file)
 #include "charsets.h"
 #include "asm_utils.h"
 #include "column-utils.h"
+#include "to_str.h"
 
 #include "wspython/wspy_register.h"
 
 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
 #define SUBTREE_MAX_LEVELS 256
+/* Throw an exception if we exceed this many tree items. */
+/* XXX - This should probably be a preference */
+#define MAX_TREE_ITEMS (1 * 1000 * 1000)
 
 
 typedef struct __subtree_lvl {
@@ -69,8 +73,8 @@ struct ptvcursor {
 };
 
 /* Candidates for assembler */
-int
-wrs_count_bitshift(guint32 bitmask)
+static int
+wrs_count_bitshift(const guint32 bitmask)
 {
        int bitshift = 0;
 
@@ -79,37 +83,55 @@ wrs_count_bitshift(guint32 bitmask)
        return bitshift;
 }
 
-
-
 #define cVALS(x) (const value_string*)(x)
 
-#if 1
-#define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
+/** See inlined comments.
+ @param tree the tree to append this item to
+ @param hfindex field index
+ @param hfinfo header_field
+ @return the header field matching 'hfinfo' */
+#define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
        /* If this item is not referenced we dont have to do much work  \
           at all but we should still return a node so that             \
           field items below this node ( think proto_item_add_subtree() )\
           will still have somewhere to attach to                       \
           or else filtering will not work (they would be ignored since tree\
           would be NULL).                                              \
-          DONT try to fake a node where PITEM_FINFO(pi) is NULL        \
-          since dissectors that want to do proto_item_set_len() or     \
-          other operations that dereference this would crash.          \
-          We dont fake FT_PROTOCOL either since these are cheap and    \
-          some stuff (proto hier stat) assumes they always exist.      \
+          We fake FT_PROTOCOL unless some clients have requested us    \
+          not to do so. \
        */                                                              \
+       if (!tree)                                                      \
+               return(NULL);                                           \
+       PTREE_DATA(tree)->count++;                                      \
+       if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {                 \
+               /* Let the exception handler add items to the tree */   \
+               PTREE_DATA(tree)->count = 0;                            \
+               THROW_MESSAGE(DissectorError,                           \
+                       ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
+       }                                                               \
+       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);                       \
        if(!(PTREE_DATA(tree)->visible)){                               \
-               if(PITEM_FINFO(tree)){                                  \
-                       register header_field_info *hfinfo;             \
-                       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);       \
-                       if((hfinfo->ref_count == 0)                     \
-                       && (hfinfo->type!=FT_PROTOCOL)){                \
+                       if((hfinfo->ref_type != HF_REF_TYPE_DIRECT)     \
+                       && (hfinfo->type!=FT_PROTOCOL ||                \
+                               PTREE_DATA(tree)->fake_protocols)){     \
                                /* just return tree back to the caller */\
                                return tree;                            \
                        }                                               \
-               }                                                       \
+       }
+
+/** See inlined comments.
+ @param tree the tree to append this item to
+ @param pi the created protocol item we're about to return */
+#if 1
+#define TRY_TO_FAKE_THIS_REPR(tree, pi) \
+       DISSECTOR_ASSERT(tree); \
+       if(!(PTREE_DATA(tree)->visible)) { \
+               /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
+                * items string representation */ \
+               return pi; \
        }
 #else
-#define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
+#define TRY_TO_FAKE_THIS_REPR(tree, pi)
 #endif
 
 static gboolean
@@ -122,34 +144,33 @@ static void fill_label_bitfield(field_info *fi, gchar *label_str);
 static void fill_label_int(field_info *fi, gchar *label_str);
 static void fill_label_int64(field_info *fi, gchar *label_str);
 
-int hfinfo_bitwidth(header_field_info *hfinfo);
-static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
-static const char* hfinfo_uint_format(header_field_info *hfinfo);
-static const char* hfinfo_uint_value_format(header_field_info *hfinfo);
-static const char* hfinfo_uint64_format(header_field_info *hfinfo);
-static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
-static const char* hfinfo_int_format(header_field_info *hfinfo);
-static const char* hfinfo_int_value_format(header_field_info *hfinfo);
-static const char* hfinfo_int64_format(header_field_info *hfinfo);
+static const char* hfinfo_uint_vals_format(const header_field_info *hfinfo);
+static const char* hfinfo_uint_format(const header_field_info *hfinfo);
+static const char* hfinfo_uint_value_format(const header_field_info *hfinfo);
+static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
+static const char* hfinfo_int_vals_format(const header_field_info *hfinfo);
+static const char* hfinfo_int_format(const header_field_info *hfinfo);
+static const char* hfinfo_int_value_format(const header_field_info *hfinfo);
+static const char* hfinfo_int64_format(const header_field_info *hfinfo);
 
 static proto_item*
 proto_tree_add_node(proto_tree *tree, field_info *fi);
 
 static header_field_info *
-get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
-    gint *item_length);
+get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
+       gint *item_length);
 
 static field_info *
 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
-    gint start, gint item_length);
+       const gint start, const gint item_length);
 
 static field_info *
 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
-        gint start, gint *length);
+               const gint start, gint *length);
 
 static proto_item *
 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
-        gint start, gint *length, field_info **pfi);
+               gint start, gint *length, field_info **pfi);
 
 static void
 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
@@ -181,7 +202,7 @@ proto_tree_set_ipv4(field_info *fi, guint32 value);
 static void
 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
 static void
-proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
+proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
 static void
 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
 static void
@@ -205,10 +226,10 @@ proto_tree_set_uint64(field_info *fi, guint64 value);
 static void
 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian);
 static gboolean
-proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len, gint ett,
-       const gint **fields, gboolean little_endian, int flags, gboolean first);
+proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset, const int len, const gint ett,
+       const gint **fields, const gboolean little_endian, const int flags, gboolean first);
 
-static int proto_register_field_init(header_field_info *hfinfo, int parent);
+static int proto_register_field_init(header_field_info *hfinfo, const int parent);
 
 /* special-case header field used within proto.c */
 int hf_text_only = -1;
@@ -229,12 +250,14 @@ struct _protocol {
 /* List of all protocols */
 static GList *protocols = NULL;
 
-#define INITIAL_NUM_PROTOCOL_HFINFO     200
-
+#define INITIAL_NUM_PROTOCOL_HFINFO    1500
 
 /* Contains information about protocols and header fields. Used when
  * dissectors register their data */
+#if GLIB_CHECK_VERSION(2,10,0)
+#else
 static GMemChunk *gmc_hfinfo = NULL;
+#endif
 
 /* Contains information about a field when a dissector calls
  * proto_tree_add_item.  */
@@ -246,8 +269,6 @@ static field_info *field_info_tmp=NULL;
 #define FIELD_INFO_FREE(fi)                                    \
        SLAB_FREE(fi, field_info)
 
-
-
 /* Contains the space for proto_nodes. */
 SLAB_ITEM_TYPE_DEFINE(proto_node)
 static SLAB_FREE_LIST_DEFINE(proto_node)
@@ -260,8 +281,6 @@ static SLAB_FREE_LIST_DEFINE(proto_node)
 #define PROTO_NODE_FREE(node)                          \
        SLAB_FREE(node, proto_node)
 
-
-
 /* String space for protocol and field items for the GUI */
 SLAB_ITEM_TYPE_DEFINE(item_label_t)
 static SLAB_FREE_LIST_DEFINE(item_label_t)
@@ -270,12 +289,10 @@ static SLAB_FREE_LIST_DEFINE(item_label_t)
 #define ITEM_LABEL_FREE(il)                            \
        SLAB_FREE(il, item_label_t)
 
-
 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
        DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
        hfinfo=gpa_hfinfo.hfi[hfindex];
 
-
 /* List which stores protocols and fields that have been registered */
 typedef struct _gpa_hfinfo_t {
        guint32 len;
@@ -325,21 +342,23 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da
 {
        static hf_register_info hf[] = {
                { &hf_text_only,
-               { "Text item",  "", FT_NONE, BASE_NONE, NULL, 0x0,
+               { "Text item",  "text", FT_NONE, BASE_NONE, NULL, 0x0,
                        NULL, HFILL }},
        };
 
+       proto_cleanup();
 
-       proto_names = g_hash_table_new(g_int_hash, g_int_equal);
+       proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
        proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
        proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
 
-       proto_cleanup();
-
+#if GLIB_CHECK_VERSION(2,10,0)
+#else
        gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
                sizeof(header_field_info),
-               INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
-               G_ALLOC_ONLY);
+                       INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
+                       G_ALLOC_ONLY);
+#endif
 
        gpa_hfinfo.len=0;
        gpa_hfinfo.allocated_len=0;
@@ -360,8 +379,8 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da
           do. */
        register_all_protocols_func(cb, client_data);
 #ifdef HAVE_PYTHON
-        /* Now scan for python protocols */
-        register_all_py_protocols_func(cb, client_data);
+               /* Now scan for python protocols */
+               register_all_py_protocols_func(cb, client_data);
 #endif
 
 #ifdef HAVE_PLUGINS
@@ -380,8 +399,8 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da
        register_all_handoffs_func(cb, client_data);
 
 #ifdef HAVE_PYTHON
-        /* Now do the same with python dissectors */
-        register_all_py_handoffs_func(cb, client_data);
+               /* Now do the same with python dissectors */
+               register_all_py_handoffs_func(cb, client_data);
 #endif
 
 #ifdef HAVE_PLUGINS
@@ -396,8 +415,7 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da
 
        /* We've assigned all the subtree type values; allocate the array
           for them, and zero it out. */
-       tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
-       memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
+       tree_is_expanded = g_new0(gboolean, num_tree_types);
 }
 
 void
@@ -409,8 +427,45 @@ proto_cleanup(void)
                gpa_name_tree = NULL;
        }
 
-       if (gmc_hfinfo)
+       while (protocols) {
+               protocol_t *protocol = protocols->data;
+               header_field_info *hfinfo;
+               PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
+               DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
+
+#if GLIB_CHECK_VERSION(2,10,0)
+               g_slice_free(header_field_info, hfinfo);
+#else
+               g_mem_chunk_free(gmc_hfinfo, hfinfo);
+#endif
+
+               g_list_free(protocol->fields);
+               protocols = g_list_remove(protocols, protocol);
+               g_free(protocol);
+       }
+
+       if (proto_names) {
+               g_hash_table_destroy(proto_names);
+               proto_names = NULL;
+       }
+
+       if (proto_short_names) {
+               g_hash_table_destroy(proto_short_names);
+               proto_short_names = NULL;
+       }
+
+       if (proto_filter_names) {
+               g_hash_table_destroy(proto_filter_names);
+               proto_filter_names = NULL;
+       }
+
+#if GLIB_CHECK_VERSION(2,10,0)
+#else
+       if (gmc_hfinfo) {
                g_mem_chunk_destroy(gmc_hfinfo);
+               gmc_hfinfo = NULL;
+       }
+#endif
 
        if(gpa_hfinfo.allocated_len){
                gpa_hfinfo.len=0;
@@ -419,12 +474,12 @@ proto_cleanup(void)
                gpa_hfinfo.hfi=NULL;
        }
        g_free(tree_is_expanded);
-
+    tree_is_expanded = NULL;
 }
 
 static gboolean
 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
-    gpointer data)
+       gpointer data)
 {
        proto_node *pnode = tree;
        proto_node *child;
@@ -443,7 +498,7 @@ proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
                current = child;
                child = current->next;
                if (proto_tree_traverse_pre_order((proto_tree *)current, func,
-                   data))
+                       data))
                        return TRUE;
        }
 
@@ -452,7 +507,7 @@ proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
 
 gboolean
 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
-    gpointer data)
+       gpointer data)
 {
        proto_node *pnode = tree;
        proto_node *child;
@@ -468,7 +523,7 @@ proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
                current = child;
                child = current->next;
                if (proto_tree_traverse_post_order((proto_tree *)current, func,
-                   data))
+                       data))
                        return TRUE;
        }
        if (func(pnode, data))
@@ -479,7 +534,7 @@ proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
 
 void
 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
-    gpointer data)
+       gpointer data)
 {
        proto_node *node = tree;
        proto_node *current;
@@ -502,23 +557,22 @@ proto_tree_free(proto_tree *tree)
 static void
 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
 {
-       GPtrArray   *ptrs = value;
+       GPtrArray       *ptrs = value;
        gint hfid = (gint)(long)key;
        header_field_info *hfinfo;
 
-
        PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
-       if(hfinfo->ref_count){
+       if(hfinfo->ref_type != HF_REF_TYPE_NONE) {
                /* when a field is referenced by a filter this also
                   affects the refcount for the parent protocol so we need
                   to adjust the refcount for the parent as well
                */
-               if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
+               if( hfinfo->parent != -1 ) {
                        header_field_info *parent_hfinfo;
                        PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
-                       parent_hfinfo->ref_count -= hfinfo->ref_count;
+                       parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
                }
-               hfinfo->ref_count = 0;
+               hfinfo->ref_type = HF_REF_TYPE_NONE;
        }
 
        g_ptr_array_free(ptrs, TRUE);
@@ -527,15 +581,17 @@ free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
 static void
 free_node_tree_data(tree_data_t *tree_data)
 {
-        /* Free all the GPtrArray's in the interesting_hfids hash. */
-        g_hash_table_foreach(tree_data->interesting_hfids,
-            free_GPtrArray_value, NULL);
+       if (tree_data->interesting_hfids) {
+               /* Free all the GPtrArray's in the interesting_hfids hash. */
+               g_hash_table_foreach(tree_data->interesting_hfids,
+                       free_GPtrArray_value, NULL);
 
-        /* And then destroy the hash. */
-        g_hash_table_destroy(tree_data->interesting_hfids);
+               /* And then destroy the hash. */
+               g_hash_table_destroy(tree_data->interesting_hfids);
+       }
 
-        /* And finally the tree_data_t itself. */
-        g_free(tree_data);
+       /* And finally the tree_data_t itself. */
+       g_free(tree_data);
 }
 
 #define FREE_NODE_FIELD_INFO(finfo)    \
@@ -548,7 +604,7 @@ free_node_tree_data(tree_data_t *tree_data)
 static gboolean
 proto_tree_free_node(proto_node *node, gpointer data _U_)
 {
-       field_info *finfo = PITEM_FINFO(node);
+       field_info *finfo = PNODE_FINFO(node);
 #if 0
        proto_node *parent = node->parent;
 #endif
@@ -601,18 +657,28 @@ proto_tree_free_node(proto_node *node, gpointer data _U_)
  * By setting this correctly, the proto_tree creation is sped up by not
  * having to call g_vsnprintf and copy strings around.
  */
-void
+gboolean
 proto_tree_set_visible(proto_tree *tree, gboolean visible)
 {
+       gboolean old_visible = PTREE_DATA(tree)->visible;
+
        PTREE_DATA(tree)->visible = visible;
+
+       return old_visible;
+}
+
+void
+proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
+{
+       PTREE_DATA(tree)->fake_protocols = fake_protocols;
 }
 
 /* Assume dissector set only its protocol fields.
-   This function is called by dissectors and allowes to speed up filtering
-   in wireshark, if this function returns FALSE it is safe to reset tree to NULL
+   This function is called by dissectors and allows the speeding up of filtering
+   in wireshark; if this function returns FALSE it is safe to reset tree to NULL
    and thus skip calling most of the expensive proto_tree_add_...()
    functions.
-   If the tree is visible we implicitely assume the field is referenced.
+   If the tree is visible we implicitly assume the field is referenced.
 */
 gboolean
 proto_field_is_referenced(proto_tree *tree, int proto_id)
@@ -627,7 +693,10 @@ proto_field_is_referenced(proto_tree *tree, int proto_id)
                return TRUE;
 
        PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
-       if (hfinfo->ref_count != 0)
+       if (hfinfo->ref_type != HF_REF_TYPE_NONE)
+               return TRUE;
+
+       if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
                return TRUE;
 
        return FALSE;
@@ -645,14 +714,15 @@ proto_registrar_get_nth(guint hfindex)
 }
 
 
-/*  Prefix initialization
- *    this allows for a dissector to register a display filter name prefix
- *    so that it can delay the initialization of the hf array as long as
- *    possible.
+/*     Prefix initialization
+ *       this allows for a dissector to register a display filter name prefix
+ *       so that it can delay the initialization of the hf array as long as
+ *       possible.
  */
 
 /* compute a hash for the part before the dot of a display filter */
-static guint prefix_hash (gconstpointer key) {
+static guint
+prefix_hash (gconstpointer key) {
        /* end the string at the dot and compute its hash */
        gchar* copy = ep_strdup(key);
        gchar* c = copy;
@@ -663,27 +733,28 @@ static guint prefix_hash (gconstpointer key) {
                        break;
                }
        }
-       
+
        return g_str_hash(copy);
 }
 
 /* are both strings equal up to the end or the dot? */
-static gboolean prefix_equal (gconstpointer ap,gconstpointer bp) {
+static gboolean
+prefix_equal (gconstpointer ap,gconstpointer bp) {
        const gchar* a = ap;
        const gchar* b = bp;
-       
+
        do {
                gchar ac = *a++;
                gchar bc = *b++;
-               
+
                if ((ac == '.' || ac == '\0') && (bc == '.' || bc == '\0')) return TRUE;
-               
+
                if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
                if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
-               
+
                if (ac != bc) return FALSE;
        } while(1);
-       
+
        return FALSE;
 }
 
@@ -698,18 +769,20 @@ proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
        if (! prefixes ) {
                prefixes = g_hash_table_new(prefix_hash,prefix_equal);
        }
-       
+
        g_hash_table_insert(prefixes,(gpointer)prefix,pi);
 }
 
 /* helper to call all prefix initializers */
-static gboolean initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
+static gboolean
+initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
        ((prefix_initializer_t)v)(k);
        return TRUE;
 }
 
 /** Initialize every remaining uninitialized prefix. */
-void proto_initialize_all_prefixes(void) {
+void
+proto_initialize_all_prefixes(void) {
        g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
 }
 
@@ -723,50 +796,53 @@ proto_registrar_get_byname(const char *field_name)
 {
        header_field_info* hfinfo;
        prefix_initializer_t pi;
-       
-       DISSECTOR_ASSERT(field_name != NULL);
+
+       if (!field_name)
+               return NULL;
 
        hfinfo = g_tree_lookup(gpa_name_tree, field_name);
-       
+
        if (hfinfo) return hfinfo;
-       
-       if  (!prefixes) return NULL;
-       
+
+       if      (!prefixes) return NULL;
+
        if(( pi = g_hash_table_lookup(prefixes,field_name) )) {
                pi(field_name);
                g_hash_table_remove(prefixes,field_name);
        } else {
                return NULL;
        }
-       
+
        return g_tree_lookup(gpa_name_tree, field_name);
 }
 
 
-void ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
+void
+ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
 {
-  subtree_lvl * pushed_tree;
+       subtree_lvl * pushed_tree;
 
-  DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
-  ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
+       DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
+       ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
 
-  pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
-  DISSECTOR_ASSERT(pushed_tree != NULL);
-  if (ptvc->pushed_tree)
-    memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
-  ptvc->pushed_tree = pushed_tree;
+       pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
+       DISSECTOR_ASSERT(pushed_tree != NULL);
+       if (ptvc->pushed_tree)
+               memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
+       ptvc->pushed_tree = pushed_tree;
 }
 
-void ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
+void
+ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
 {
-  ptvc->pushed_tree = NULL;
-  ptvc->pushed_tree_max = 0;
-  DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
-  ptvc->pushed_tree_index = 0;
+       ptvc->pushed_tree = NULL;
+       ptvc->pushed_tree_max = 0;
+       DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
+       ptvc->pushed_tree_index = 0;
 }
 
 /* Allocates an initializes a ptvcursor_t with 3 variables:
- *     proto_tree, tvbuff, and offset. */
+ *     proto_tree, tvbuff, and offset. */
 ptvcursor_t*
 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
 {
@@ -808,10 +884,10 @@ ptvcursor_current_offset(ptvcursor_t* ptvc)
 proto_tree*
 ptvcursor_tree(ptvcursor_t* ptvc)
 {
-  if (!ptvc)
-    return NULL;
+       if (!ptvc)
+               return NULL;
 
-  return ptvc->tree;
+       return ptvc->tree;
 }
 
 void
@@ -824,43 +900,44 @@ ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
 proto_tree*
 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
 {
-  subtree_lvl * subtree;
-  if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
-    ptvcursor_new_subtree_levels(ptvc);
+       subtree_lvl * subtree;
+       if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
+               ptvcursor_new_subtree_levels(ptvc);
 
-  subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
-  subtree->tree = ptvc->tree;
-  subtree->it= NULL;
-  ptvc->pushed_tree_index++;
-  return ptvcursor_set_subtree(ptvc, it, ett_subtree);
+       subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
+       subtree->tree = ptvc->tree;
+       subtree->it= NULL;
+       ptvc->pushed_tree_index++;
+       return ptvcursor_set_subtree(ptvc, it, ett_subtree);
 }
 
 /* pops a subtree */
 void
 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
 {
-  subtree_lvl * subtree;
-  if (ptvc->pushed_tree_index <= 0)
-    return;
+       subtree_lvl * subtree;
+       if (ptvc->pushed_tree_index <= 0)
+               return;
+
+       ptvc->pushed_tree_index--;
+       subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
+       if (subtree->it != NULL)
+               proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
 
-  ptvc->pushed_tree_index--;
-  subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
-  if (subtree->it != NULL)
-    proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
-  ptvc->tree = subtree->tree;
+       ptvc->tree = subtree->tree;
 }
 
 /* saves the current tvb offset and the item in the current subtree level */
 static void
 ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
 {
-  subtree_lvl * subtree;
+       subtree_lvl * subtree;
 
-  DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
+       DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
 
-  subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
-  subtree->it = it;
-  subtree->cursor_offset = ptvcursor_current_offset(ptvc);
+       subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
+       subtree->it = it;
+       subtree->cursor_offset = ptvcursor_current_offset(ptvc);
 }
 
 /* Creates a subtree and adds it to the cursor as the working tree but does not
@@ -868,16 +945,17 @@ ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
 proto_tree*
 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
 {
-  ptvc->tree = proto_item_add_subtree(it, ett_subtree);
-  return ptvc->tree;
+       ptvc->tree = proto_item_add_subtree(it, ett_subtree);
+       return ptvc->tree;
 }
 
-proto_tree* ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
+proto_tree*
+ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
 {
-  ptvcursor_push_subtree(ptvc, it, ett_subtree);
-  if (length == SUBTREE_UNDEFINED_LENGTH)
-    ptvcursor_subtree_set_item(ptvc, it);
-  return ptvcursor_tree(ptvc);
+       ptvcursor_push_subtree(ptvc, it, ett_subtree);
+       if (length == SUBTREE_UNDEFINED_LENGTH)
+               ptvcursor_subtree_set_item(ptvc, it);
+       return ptvcursor_tree(ptvc);
 }
 
 /* Add an item to the tree and create a subtree
@@ -885,12 +963,14 @@ proto_tree* ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint
  * In this case, when the subtree will be closed, the parent item length will
  * be equal to the advancement of the cursor since the creation of the subtree.
  */
-proto_tree* ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
-gboolean little_endian, gint ett_subtree)
+proto_tree*
+ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
+                          gboolean little_endian, gint ett_subtree)
 {
-  proto_item * it;
-  it = ptvcursor_add_no_advance(ptvc, hfindex, length, little_endian);
-  return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
+       proto_item * it;
+
+       it = ptvcursor_add_no_advance(ptvc, hfindex, length, little_endian);
+       return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
 }
 
 static proto_item *
@@ -901,20 +981,27 @@ proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint lengt
  * In this case, when the subtree will be closed, the item length will be equal
  * to the advancement of the cursor since the creation of the subtree.
  */
-proto_tree * ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
-    gint ett_subtree, const char *format, ...)
+proto_tree *
+ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
+                               gint ett_subtree, const char *format, ...)
 {
-  proto_item * it;
-  va_list      ap;
+       proto_item *    it;
+       va_list ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(ptvcursor_tree(ptvc), hf_text_only, hfinfo);
+
+       it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
+                                         ptvcursor_current_offset(ptvc), length);
 
-  it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
-      ptvcursor_current_offset(ptvc), length);
+       if (it == NULL)
+               return(NULL);
 
-  va_start(ap, format);
-  proto_tree_set_representation(it, format, ap);
-  va_end(ap);
+       va_start(ap, format);
+       proto_tree_set_representation(it, format, ap);
+       va_end(ap);
 
-  return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
+       return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
 }
 
 /* Add a text-only node, leaving it to our caller to fill the text in */
@@ -933,15 +1020,20 @@ proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint lengt
 /* Add a text-only node to the proto_tree */
 proto_item *
 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
-       const char *format, ...)
+                       const char *format, ...)
 {
        proto_item      *pi;
        va_list         ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
 
        pi = proto_tree_add_text_node(tree, tvb, start, length);
        if (pi == NULL)
                return(NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -952,14 +1044,19 @@ proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
 /* Add a text-only node to the proto_tree (va_list version) */
 proto_item *
 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
-       gint length, const char *format, va_list ap)
+                          gint length, const char *format, va_list ap)
 {
        proto_item      *pi;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
 
        pi = proto_tree_add_text_node(tree, tvb, start, length);
        if (pi == NULL)
                return(NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        proto_tree_set_representation(pi, format, ap);
 
        return pi;
@@ -1000,17 +1097,17 @@ get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
 
        case 2:
                value = little_endian ? tvb_get_letohs(tvb, offset)
-                                     : tvb_get_ntohs(tvb, offset);
+                                         : tvb_get_ntohs(tvb, offset);
                break;
 
        case 3:
                value = little_endian ? tvb_get_letoh24(tvb, offset)
-                                     : tvb_get_ntoh24(tvb, offset);
+                                         : tvb_get_ntoh24(tvb, offset);
                break;
 
        case 4:
                value = little_endian ? tvb_get_letohl(tvb, offset)
-                                     : tvb_get_ntohl(tvb, offset);
+                                         : tvb_get_ntohl(tvb, offset);
                break;
 
        default:
@@ -1039,7 +1136,7 @@ get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
 
        case 3:
                value = little_endian ? tvb_get_letoh24(tvb, offset)
-                                     : tvb_get_ntoh24(tvb, offset);
+                                         : tvb_get_ntoh24(tvb, offset);
                if (value & 0x00800000) {
                        /* Sign bit is set; sign-extend it. */
                        value |= 0xFF000000;
@@ -1048,7 +1145,7 @@ get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
 
        case 4:
                value = little_endian ? tvb_get_letohl(tvb, offset)
-                                     : tvb_get_ntohl(tvb, offset);
+                                         : tvb_get_ntohl(tvb, offset);
                break;
 
        default:
@@ -1059,18 +1156,45 @@ get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
        return value;
 }
 
+static GPtrArray *proto_lookup_or_create_interesting_hfids(proto_tree *tree,
+                                                                                                        header_field_info      *hfinfo)
+{
+       GPtrArray *ptrs = NULL;
+
+       DISSECTOR_ASSERT(tree);
+       DISSECTOR_ASSERT(hfinfo);
+
+       if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
+               if (PTREE_DATA(tree)->interesting_hfids == NULL) {
+                       /* Initialize the hash because we now know that it is needed */
+                       PTREE_DATA(tree)->interesting_hfids =
+                               g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
+               }
+
+               ptrs = g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
+                                                               GINT_TO_POINTER(hfinfo->id));
+               if (!ptrs) {
+                       /* First element triggers the creation of pointer array */
+                       ptrs = g_ptr_array_new();
+                       g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
+                                                               GINT_TO_POINTER(hfinfo->id), ptrs);
+               }
+       }
+
+       return ptrs;
+}
+
 /* Add an item to a proto_tree, using the text label registered to that item;
    the item is extracted from the tvbuff handed to it. */
 static proto_item *
-proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
-    tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
+proto_tree_new_item(field_info *new_fi, proto_tree *tree,
+       tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
 {
        proto_item      *pi;
        guint32         value, n;
        float           floatval;
        double          doubleval;
        char            *string;
-       GHashTable      *hash;
        GPtrArray       *ptrs;
 
        /* there is a possibility here that we might raise an exception
@@ -1119,7 +1243,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
 
                case FT_BOOLEAN:
                        proto_tree_set_boolean(new_fi,
-                           get_uint_value(tvb, start, length, little_endian));
+                               get_uint_value(tvb, start, length, little_endian));
                        break;
 
                /* XXX - make these just FT_UINT? */
@@ -1128,7 +1252,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
                case FT_UINT24:
                case FT_UINT32:
                        proto_tree_set_uint(new_fi,
-                           get_uint_value(tvb, start, length, little_endian));
+                               get_uint_value(tvb, start, length, little_endian));
                        break;
 
                case FT_INT64:
@@ -1143,33 +1267,33 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
                case FT_INT24:
                case FT_INT32:
                        proto_tree_set_int(new_fi,
-                           get_int_value(tvb, start, length, little_endian));
+                               get_int_value(tvb, start, length, little_endian));
                        break;
 
                case FT_IPv4:
-                       DISSECTOR_ASSERT(length == 4);
+                       DISSECTOR_ASSERT(length == FT_IPv4_LEN);
                        value = tvb_get_ipv4(tvb, start);
                        proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
                        break;
 
                case FT_IPXNET:
-                       DISSECTOR_ASSERT(length == 4);
+                       DISSECTOR_ASSERT(length == FT_IPXNET_LEN);
                        proto_tree_set_ipxnet(new_fi,
-                           get_uint_value(tvb, start, 4, FALSE));
+                               get_uint_value(tvb, start, 4, FALSE));
                        break;
 
                case FT_IPv6:
-                       DISSECTOR_ASSERT(length == 16);
-                       proto_tree_set_ipv6_tvb(new_fi, tvb, start);
+                       DISSECTOR_ASSERT(length >=0 && length <= FT_IPv6_LEN);
+                       proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
                        break;
 
                case FT_ETHER:
-                       DISSECTOR_ASSERT(length == 6);
+                       DISSECTOR_ASSERT(length == FT_ETHER_LEN);
                        proto_tree_set_ether_tvb(new_fi, tvb, start);
                        break;
 
                case FT_GUID:
-                       DISSECTOR_ASSERT(length == 16);
+                       DISSECTOR_ASSERT(length == FT_GUID_LEN);
                        proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
                        break;
 
@@ -1242,7 +1366,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
                                 * '\0' there, as the packet might
                                 * be malformed.  (XXX - should we
                                 * throw an exception if there's no
-                                * trailing '\0'?)  Therefore, we
+                                * trailing '\0'?)      Therefore, we
                                 * allocate a buffer of length
                                 * "length+1", and put in a trailing
                                 * '\0', just to be safe.
@@ -1259,7 +1383,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
                        proto_tree_set_string(new_fi, string);
                        break;
 
-               case FT_EBCDIC:
+                       case FT_EBCDIC:
                        proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
                        break;
 
@@ -1298,14 +1422,9 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
 
        /* If the proto_tree wants to keep a record of this finfo
         * for quick lookup, then record it. */
-       if (new_fi->hfinfo->ref_count) {
-               /*HERE*/
-               hash = PTREE_DATA(tree)->interesting_hfids;
-               ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
-               if (ptrs) {
-                       g_ptr_array_add(ptrs, new_fi);
-               }
-       }
+       ptrs = proto_lookup_or_create_interesting_hfids(tree, new_fi->hfinfo);
+       if (ptrs)
+               g_ptr_array_add(ptrs, new_fi);
 
        return pi;
 }
@@ -1314,7 +1433,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
    and returns proto_item* */
 proto_item*
 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
-    gboolean little_endian)
+                 gboolean little_endian)
 {
        field_info              *new_fi;
        header_field_info       *hfinfo;
@@ -1322,9 +1441,12 @@ ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
        guint32                 n;
        int                     offset;
 
+       /* We can't fake it just yet. We have to advance the cursor
+       TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
+
        offset = ptvc->offset;
        hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
-           &item_length);
+               &item_length);
        ptvc->offset += length;
        if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
                /*
@@ -1334,59 +1456,55 @@ ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
                n = get_uint_value(ptvc->tvb, offset, length, little_endian);
                ptvc->offset += n;
        }
-       if (ptvc->tree == NULL)
-               return NULL;
 
-       TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex);
+       /* Coast clear. Try and fake it */
+       TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
 
-       new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
-           item_length);
+       new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
        if (new_fi == NULL)
                return NULL;
 
-       return proto_tree_new_item(new_fi, ptvc->tree, hfindex, ptvc->tvb,
-           offset, length, little_endian);
+       return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
+               offset, length, little_endian);
 }
 
 /* Add an item to a proto_tree, using the text label registered to that item;
    the item is extracted from the tvbuff handed to it. */
 proto_item *
-proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
-    gint start, gint length, gboolean little_endian)
+proto_tree_add_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
+       const gint start, gint length, const gboolean little_endian)
 {
        field_info      *new_fi;
+       header_field_info       *hfinfo;
 
-       if (!tree)
-               return(NULL);
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
 
        if (new_fi == NULL)
                return(NULL);
 
-       return proto_tree_new_item(new_fi, tree, hfindex, tvb, start,
-           length, little_endian);
+       return proto_tree_new_item(new_fi, tree, tvb, start,
+               length, little_endian);
 }
 
 /* Add a FT_NONE to a proto_tree */
 proto_item *
-proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
+proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const gint start,
                gint length, const char *format, ...)
 {
        proto_item              *pi;
        va_list                 ap;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -1399,12 +1517,12 @@ proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
  * offset, and returns proto_item* */
 proto_item*
 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
-               gboolean endianness)
+                        gboolean endianness)
 {
        proto_item      *item;
 
        item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
-                       length, endianness);
+                                  length, endianness);
 
        return item;
 }
@@ -1431,27 +1549,23 @@ proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gin
 {
        proto_item              *pi;
        va_list                 ap;
-       header_field_info       *hfinfo;
        field_info              *new_fi;
+       header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
 
+       proto_tree_set_protocol_tvb(new_fi, (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
+
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
 
-       if (start == 0) {
-               proto_tree_set_protocol_tvb(new_fi, tvb);
-       }
-       else {
-               proto_tree_set_protocol_tvb(new_fi, NULL);
-       }
        return pi;
 }
 
@@ -1465,12 +1579,8 @@ proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
@@ -1486,11 +1596,16 @@ proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -1504,11 +1619,16 @@ proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint s
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -1525,8 +1645,6 @@ proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
        if (length > 0) {
                g_byte_array_append(bytes, start_ptr, length);
        }
-       col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str(bytes->data,
-                                                                  length));
        fvalue_set(&fi->value, bytes, TRUE);
 }
 
@@ -1546,12 +1664,8 @@ proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
                                hfinfo->type == FT_RELATIVE_TIME);
 
@@ -1568,11 +1682,16 @@ proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -1586,11 +1705,16 @@ proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -1602,16 +1726,8 @@ proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
 static void
 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
 {
-       header_field_info       *hfinfo;
-
        DISSECTOR_ASSERT(value_ptr != NULL);
-       hfinfo = fi->hfinfo;
 
-       if (hfinfo->type == FT_ABSOLUTE_TIME) {
-               col_custom_set_fstr(fi->hfinfo, "%s", abs_time_to_str(value_ptr));
-       } else if (hfinfo->type == FT_RELATIVE_TIME) {
-               col_custom_set_fstr(fi->hfinfo, "%s", rel_time_to_secs_str(value_ptr));
-       }
        fvalue_set(&fi->value, value_ptr, FALSE);
 }
 
@@ -1624,12 +1740,8 @@ proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
@@ -1644,11 +1756,16 @@ proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -1662,11 +1779,16 @@ proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -1690,12 +1812,8 @@ proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
-
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
@@ -1710,11 +1828,16 @@ proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -1728,11 +1851,16 @@ proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -1744,8 +1872,6 @@ proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
 static void
 proto_tree_set_ipv4(field_info *fi, guint32 value)
 {
-       col_custom_set_fstr(fi->hfinfo, "%s",
-                           ip_to_str((guint8 *)&value));
        fvalue_set_uinteger(&fi->value, value);
 }
 
@@ -1758,12 +1884,8 @@ proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
-
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
@@ -1779,11 +1901,16 @@ proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -1797,11 +1924,16 @@ proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -1818,9 +1950,9 @@ proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
 }
 
 static void
-proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
+proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
 {
-       proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
+       proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
 }
 
 /* Add a FT_GUID to a proto_tree */
@@ -1832,12 +1964,8 @@ proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
-
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
@@ -1853,11 +1981,16 @@ proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -1871,11 +2004,16 @@ proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -1888,8 +2026,6 @@ static void
 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
 {
        DISSECTOR_ASSERT(value_ptr != NULL);
-       col_custom_set_fstr(fi->hfinfo, "%s",
-                           guid_to_str(value_ptr));
        fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
 }
 
@@ -1911,12 +2047,8 @@ proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gin
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_OID);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
@@ -1932,11 +2064,16 @@ proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -1950,11 +2087,16 @@ proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint sta
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -1974,8 +2116,6 @@ proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
        if (length > 0) {
                g_byte_array_append(bytes, value_ptr, length);
        }
-       col_custom_set_fstr(fi->hfinfo, "%s",
-                           oid_resolved_from_encoded(value_ptr, length));
        fvalue_set(&fi->value, bytes, TRUE);
 }
 
@@ -1988,8 +2128,6 @@ proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
 static void
 proto_tree_set_uint64(field_info *fi, guint64 value)
 {
-       col_custom_set_fstr(fi->hfinfo, "%" G_GINT64_MODIFIER "u",
-                           value);
        fvalue_set_integer64(&fi->value, value);
 }
 
@@ -2041,12 +2179,8 @@ proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
@@ -2063,11 +2197,16 @@ proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -2081,11 +2220,16 @@ proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -2122,6 +2266,8 @@ proto_item_append_string(proto_item *pi, const char *str)
                return;
 
        fi = PITEM_FINFO(pi);
+       DISSECTOR_ASSERT(fi && "proto_tree_set_visible(tree, TRUE) should have been called previously");
+
        hfinfo = fi->hfinfo;
        if (hfinfo->type == FT_PROTOCOL) {
                /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
@@ -2138,11 +2284,8 @@ static void
 proto_tree_set_string(field_info *fi, const char* value)
 {
        if (value) {
-               col_custom_set_fstr(fi->hfinfo, "%s",
-                                   format_text(value, strlen(value)));
                fvalue_set(&fi->value, (gpointer) value, FALSE);
        } else {
-               col_custom_set_fstr(fi->hfinfo, "[ Null ]");
                fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
        }
 }
@@ -2183,12 +2326,8 @@ proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, g
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
-
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
@@ -2204,11 +2343,16 @@ proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -2222,11 +2366,16 @@ proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint s
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -2238,14 +2387,13 @@ proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint s
 static void
 proto_tree_set_ether(field_info *fi, const guint8* value)
 {
-       col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str_punct(value, 6, ':'));
        fvalue_set(&fi->value, (gpointer) value, FALSE);
 }
 
 static void
 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
 {
-       proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
+       proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
 }
 
 /* Add a FT_BOOLEAN to a proto_tree */
@@ -2257,12 +2405,8 @@ proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
@@ -2278,11 +2422,16 @@ proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -2296,11 +2445,16 @@ proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -2324,12 +2478,8 @@ proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, g
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
-
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
@@ -2344,11 +2494,16 @@ proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -2362,11 +2517,16 @@ proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint s
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -2378,8 +2538,6 @@ proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint s
 static void
 proto_tree_set_float(field_info *fi, float value)
 {
-       col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(FLT_DIG) "f",
-                           value);
        fvalue_set_floating(&fi->value, value);
 }
 
@@ -2392,12 +2550,8 @@ proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
@@ -2412,11 +2566,16 @@ proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -2430,11 +2589,16 @@ proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -2446,8 +2610,6 @@ proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint
 static void
 proto_tree_set_double(field_info *fi, double value)
 {
-       col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(DBL_DIG) "g",
-                           value);
        fvalue_set_floating(&fi->value, value);
 }
 
@@ -2460,12 +2622,8 @@ proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        switch(hfinfo->type) {
                case FT_UINT8:
                case FT_UINT16:
@@ -2490,11 +2648,16 @@ proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -2508,11 +2671,16 @@ proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -2540,23 +2708,6 @@ proto_tree_set_uint(field_info *fi, guint32 value)
                }
        }
 
-       if (hfinfo->type == FT_BOOLEAN) {
-               const true_false_string  *tfstring = &tfs_true_false;
-               if (hfinfo->strings) {
-                       tfstring = (const struct true_false_string*) hfinfo->strings;
-               }
-               col_custom_set_fstr(fi->hfinfo, "%s", integer ? tfstring->true_string : tfstring->false_string);
-       } else if (hfinfo->strings) {
-               if (hfinfo->display & BASE_RANGE_STRING) {
-                       col_custom_set_fstr(fi->hfinfo, "%s", rval_to_str(integer, hfinfo->strings, "%u"));
-               } else {
-                       col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%u"));
-               }
-       } else if (IS_BASE_DUAL(hfinfo->display)) {
-               col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer, integer);
-       } else {
-               col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer);
-       }
        fvalue_set_uinteger(&fi->value, integer);
 }
 
@@ -2569,12 +2720,8 @@ proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
@@ -2589,11 +2736,16 @@ proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -2607,11 +2759,16 @@ proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -2628,12 +2785,8 @@ proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gin
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        switch(hfinfo->type) {
                case FT_INT8:
                case FT_INT16:
@@ -2657,11 +2810,16 @@ proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi = NULL;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -2675,11 +2833,16 @@ proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint sta
 {
        proto_item              *pi = NULL;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -2707,17 +2870,6 @@ proto_tree_set_int(field_info *fi, gint32 value)
                }
        }
 
-       if (hfinfo->strings) {
-               if (hfinfo->display & BASE_RANGE_STRING) {
-                       col_custom_set_fstr(fi->hfinfo, "%s", rval_to_str(integer, hfinfo->strings, "%d"));
-               } else {
-                       col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%d"));
-               }
-       } else if (IS_BASE_DUAL(hfinfo->display)) {
-               col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer, integer);
-       } else {
-               col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer);
-       }
        fvalue_set_sinteger(&fi->value, integer);
 }
 
@@ -2730,12 +2882,8 @@ proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, g
        field_info              *new_fi;
        header_field_info       *hfinfo;
 
-       if (!tree)
-               return (NULL);
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
 
        pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
@@ -2750,11 +2898,16 @@ proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -2768,11 +2921,16 @@ proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint s
 {
        proto_item              *pi;
        va_list                 ap;
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
        if (pi == NULL)
                return (NULL);
 
+       TRY_TO_FAKE_THIS_REPR(tree, pi);
+
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
        va_end(ap);
@@ -2780,9 +2938,6 @@ proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint s
        return pi;
 }
 
-/* Throw an exception if we exceed this many tree items. */
-/* XXX - This should probably be a preference */
-#define MAX_TREE_ITEMS (1 * 1000 * 1000)
 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
 static proto_item *
 proto_tree_add_node(proto_tree *tree, field_info *fi)
@@ -2794,13 +2949,13 @@ proto_tree_add_node(proto_tree *tree, field_info *fi)
         * Make sure "tree" is ready to have subtrees under it, by
         * checking whether it's been given an ett_ value.
         *
-        * "tnode->finfo" may be null; that's the case for the root
+        * "PNODE_FINFO(tnode)" may be null; that's the case for the root
         * node of the protocol tree.  That node is not displayed,
         * so it doesn't need an ett_ value to remember whether it
         * was expanded.
         */
        tnode = tree;
-       tfi = tnode->finfo;
+       tfi = PNODE_FINFO(tnode);
        if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
                REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
                        fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
@@ -2808,19 +2963,11 @@ proto_tree_add_node(proto_tree *tree, field_info *fi)
        }
 
        DISSECTOR_ASSERT(tfi == NULL ||
-           (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
-
-       PTREE_DATA(tree)->count++;
-       if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
-               /* Let the exception handler add items to the tree */
-               PTREE_DATA(tree)->count = 0;
-               THROW_MESSAGE(DissectorError,
-                       ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
-       }
+               (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
 
        PROTO_NODE_NEW(pnode);
        pnode->parent = tnode;
-       pnode->finfo = fi;
+       PNODE_FINFO(pnode) = fi;
        pnode->tree_data = PTREE_DATA(tree);
 
        if (tnode->last_child != NULL) {
@@ -2840,11 +2987,10 @@ proto_tree_add_node(proto_tree *tree, field_info *fi)
  * non-NULL. */
 static proto_item *
 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
-    gint *length, field_info **pfi)
+       gint *length, field_info **pfi)
 {
        proto_item      *pi;
        field_info      *fi;
-       GHashTable      *hash;
        GPtrArray       *ptrs;
 
        if (!tree)
@@ -2855,14 +3001,9 @@ proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
 
        /* If the proto_tree wants to keep a record of this finfo
         * for quick lookup, then record it. */
-       if (fi->hfinfo->ref_count) {
-               /*HERE*/
-               hash = PTREE_DATA(tree)->interesting_hfids;
-               ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
-               if (ptrs) {
-                       g_ptr_array_add(ptrs, fi);
-               }
-       }
+       ptrs = proto_lookup_or_create_interesting_hfids(tree, fi->hfinfo);
+       if (ptrs)
+               g_ptr_array_add(ptrs, fi);
 
        /* Does the caller want to know the fi pointer? */
        if (pfi) {
@@ -2874,8 +3015,8 @@ proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
 
 
 static header_field_info *
-get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
-    gint *item_length)
+get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
+       gint *item_length)
 {
        header_field_info       *hfinfo;
        gint                    length_remaining;
@@ -2994,8 +3135,8 @@ get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
                        if (tvb) {
                                length_remaining = tvb_length_remaining(tvb, start);
                                if (*item_length < 0 ||
-                                   (*item_length > 0 &&
-                                     (length_remaining < *item_length)))
+                                       (*item_length > 0 &&
+                                         (length_remaining < *item_length)))
                                        *item_length = length_remaining;
                        }
                }
@@ -3009,7 +3150,7 @@ get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
 
 static field_info *
 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
-    gint start, gint item_length)
+       const gint start, const gint item_length)
 {
        field_info              *fi;
 
@@ -3036,8 +3177,8 @@ new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
 }
 
 static field_info *
-alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
-    gint *length)
+alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, const gint start,
+       gint *length)
 {
        header_field_info       *hfinfo;
        gint                    item_length;
@@ -3055,7 +3196,11 @@ proto_tree_set_representation_value(proto_item *pi, const char *format, va_list
 {
        int     ret;    /*tmp return value */
        field_info *fi = PITEM_FINFO(pi);
-       header_field_info *hf = fi->hfinfo;
+       header_field_info *hf;
+
+       DISSECTOR_ASSERT(fi);
+
+       hf = fi->hfinfo;
 
        if (!PROTO_ITEM_IS_HIDDEN(pi)) {
                ITEM_LABEL_NEW(fi->rep);
@@ -3088,8 +3233,8 @@ proto_tree_set_representation_value(proto_item *pi, const char *format, va_list
                         */
                        char *oldrep;
 
-                       /*  Argh, we cannot reuse 'ap' here.  So make a copy
-                        *  of what we formatted for (re)use below.
+                       /*      Argh, we cannot reuse 'ap' here.  So make a copy
+                        *      of what we formatted for (re)use below.
                         */
                        oldrep = g_strdup(fi->rep->representation);
 
@@ -3111,6 +3256,8 @@ proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
        int                                     ret;    /*tmp return value */
        field_info *fi = PITEM_FINFO(pi);
 
+       DISSECTOR_ASSERT(fi);
+
        if (!PROTO_ITEM_IS_HIDDEN(pi)) {
                ITEM_LABEL_NEW(fi->rep);
                ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
@@ -3121,8 +3268,8 @@ proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
                         */
                        char *oldrep;
 
-                       /*  Argh, we cannot reuse 'ap' here.  So make a copy
-                        *  of what we formatted for (re)use below.
+                       /*      Argh, we cannot reuse 'ap' here.  So make a copy
+                        *      of what we formatted for (re)use below.
                         */
                        oldrep = g_strdup(fi->rep->representation);
 
@@ -3133,6 +3280,189 @@ proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
        }
 }
 
+/* -------------------------- */
+const gchar *
+proto_custom_set(proto_tree* tree, const int field_id,
+                                                        gchar *result,
+                                                        gchar *expr, const int size )
+{
+       guint32         u_integer;
+       gint32          integer;
+       guint8          *bytes;
+       ipv4_addr       *ipv4;
+       struct e_in6_addr *ipv6;
+       address         addr;
+       guint32         n_addr; /* network-order IPv4 address */
+
+       const true_false_string  *tfstring;
+       int             len;
+       GPtrArray       *finfos;
+       field_info      *finfo;
+       header_field_info* hfinfo;
+
+       g_assert(field_id >= 0);
+
+       hfinfo = proto_registrar_get_nth((guint)field_id);
+
+       /* do we need to rewind ? */
+       if (!hfinfo)
+               return "";
+
+       while (hfinfo) {
+               finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
+
+               if (!finfos || !(len = g_ptr_array_len(finfos))) {
+                       hfinfo = hfinfo->same_name_next;
+                       continue;
+               }
+               /* get the last one  */
+               finfo = g_ptr_array_index(finfos, len -1);
+
+               switch(hfinfo->type) {
+
+               case FT_NONE: /* Nothing to add */
+                       result[0] = '\0';
+                       break;
+
+               case FT_PROTOCOL:
+                       g_strlcpy(result, "Yes", size);
+                       break;
+
+               case FT_UINT_BYTES:
+               case FT_BYTES:
+                       bytes = fvalue_get(&finfo->value);
+                       g_strlcpy(result, bytes_to_str(bytes, fvalue_length(&finfo->value)), size);
+                       break;
+
+               case FT_ABSOLUTE_TIME:
+                       g_strlcpy(result,
+                               abs_time_to_str(fvalue_get(&finfo->value), hfinfo->display),
+                               size);
+                       break;
+
+               case FT_RELATIVE_TIME:
+                       g_strlcpy(result, rel_time_to_secs_str(fvalue_get(&finfo->value)), size);
+                       break;
+
+               case FT_BOOLEAN:
+                       u_integer = fvalue_get_uinteger(&finfo->value);
+                       tfstring = (const true_false_string *)&tfs_true_false;
+                       if (hfinfo->strings) {
+                               tfstring = (const struct true_false_string*) hfinfo->strings;
+                       }
+                       g_strlcpy(result, u_integer ? tfstring->true_string : tfstring->false_string, size);
+                       break;
+
+               case FT_UINT8:
+               case FT_UINT16:
+               case FT_UINT24:
+               case FT_UINT32:
+               case FT_FRAMENUM:
+                       u_integer = fvalue_get_uinteger(&finfo->value);
+                       if (hfinfo->strings) {
+                               if (hfinfo->display & BASE_RANGE_STRING) {
+                                       g_strlcpy(result, rval_to_str(u_integer, hfinfo->strings, "%u"), size);
+                               } else {
+                                       g_strlcpy(result, val_to_str(u_integer, cVALS(hfinfo->strings), "%u"), size);
+                               }
+                       } else if (IS_BASE_DUAL(hfinfo->display)) {
+                               g_snprintf(result, size, hfinfo_uint_value_format(hfinfo), u_integer, u_integer);
+                       } else {
+                               g_snprintf(result, size, hfinfo_uint_value_format(hfinfo), u_integer);
+                       }
+                       break;
+
+               case FT_INT64:
+               case FT_UINT64:
+                       g_snprintf(result, size, "%" G_GINT64_MODIFIER "u", fvalue_get_integer64(&finfo->value));
+                       break;
+
+               /* XXX - make these just FT_INT? */
+               case FT_INT8:
+               case FT_INT16:
+               case FT_INT24:
+               case FT_INT32:
+                       integer = fvalue_get_sinteger(&finfo->value);
+                       if (hfinfo->strings) {
+                               if (hfinfo->display & BASE_RANGE_STRING) {
+                                       g_strlcpy(result, rval_to_str(integer, hfinfo->strings, "%d"), size);
+                               } else {
+                                       g_strlcpy(result, val_to_str(integer, cVALS(hfinfo->strings), "%d"), size);
+                       }
+                       } else if (IS_BASE_DUAL(hfinfo->display)) {
+                               g_snprintf(result, size, hfinfo_int_value_format(hfinfo), integer, integer);
+                       } else {
+                               g_snprintf(result, size, hfinfo_int_value_format(hfinfo), integer);
+                       }
+                       break;
+
+               case FT_IPv4:
+                       ipv4 = fvalue_get(&finfo->value);
+                       n_addr = ipv4_get_net_order_addr(ipv4);
+                       g_strlcpy(result, ip_to_str((guint8 *)&n_addr), size);
+                       break;
+
+               case FT_IPv6:
+                       ipv6 = fvalue_get(&finfo->value);
+                       SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
+                       address_to_str_buf(&addr, result, size);
+                       break;
+
+               case FT_ETHER:
+                       g_strlcpy(result, bytes_to_str_punct(fvalue_get(&finfo->value), 6, ':'), size);
+                       break;
+
+               case FT_GUID:
+                       g_strlcpy(result, guid_to_str((e_guid_t *)fvalue_get(&finfo->value)), size);
+                       break;
+
+               case FT_OID:
+                       bytes = fvalue_get(&finfo->value);
+                       g_strlcpy(result, oid_resolved_from_encoded(bytes, fvalue_length(&finfo->value)), size);
+                       break;
+
+               case FT_FLOAT:
+                       g_snprintf(result, size, "%." STRINGIFY(FLT_DIG) "f", fvalue_get_floating(&finfo->value));
+                       break;
+
+               case FT_DOUBLE:
+                       g_snprintf(result, size, "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
+                       break;
+
+               case FT_EBCDIC:
+               case FT_STRING:
+               case FT_STRINGZ:
+               case FT_UINT_STRING:
+                       bytes = fvalue_get(&finfo->value);
+                       g_strlcpy(result, format_text(bytes, strlen(bytes)), size);
+                       break;
+
+               case FT_IPXNET: /*XXX really No column custom ?*/
+               case FT_PCRE:
+               default:
+                       g_error("hfinfo->type %d (%s) not handled\n",
+                                       hfinfo->type,
+                                       ftype_name(hfinfo->type));
+                       DISSECTOR_ASSERT_NOT_REACHED();
+                       break;
+               }
+
+               switch(hfinfo->type) {
+               case FT_EBCDIC:
+               case FT_STRING:
+               case FT_STRINGZ:
+               case FT_UINT_STRING:
+                       g_snprintf(expr, size, "\"%s\"",result);
+               default:
+                       g_strlcpy(expr, result, size);
+                       break;
+               }
+               return hfinfo->abbrev;
+       }
+       return "";
+}
+
+
 /* Set text of proto_item after having already been created. */
 void
 proto_item_set_text(proto_item *pi, const char *format, ...)
@@ -3145,6 +3475,8 @@ proto_item_set_text(proto_item *pi, const char *format, ...)
        }
 
        fi = PITEM_FINFO(pi);
+       if (fi==NULL)
+               return;
 
        if(fi->rep){
                ITEM_LABEL_FREE(fi->rep);
@@ -3187,20 +3519,24 @@ proto_item_append_text(proto_item *pi, const char *format, ...)
                curlen = strlen(fi->rep->representation);
                if (ITEM_LABEL_LENGTH > curlen) {
                        g_vsnprintf(fi->rep->representation + curlen,
-                           ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
+                               ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
                }
                va_end(ap);
        }
 }
 
 void
-proto_item_set_len(proto_item *pi, gint length)
+proto_item_set_len(proto_item *pi, const gint length)
 {
        field_info *fi;
 
        if (pi == NULL)
                return;
+
        fi = PITEM_FINFO(pi);
+       if (fi == NULL)
+               return;
+
        DISSECTOR_ASSERT(length >= 0);
        fi->length = length;
 
@@ -3222,17 +3558,21 @@ proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
 
        if (pi == NULL)
                return;
+
        fi = PITEM_FINFO(pi);
+       if (fi == NULL)
+               return;
+
        end += TVB_RAW_OFFSET(tvb);
        DISSECTOR_ASSERT(end >= fi->start);
        fi->length = end - fi->start;
 }
 
 int
-proto_item_get_len(proto_item *pi)
+proto_item_get_len(const proto_item *pi)
 {
        field_info *fi = PITEM_FINFO(pi);
-       return fi->length;
+       return fi ? fi->length : -1;
 }
 
 
@@ -3243,15 +3583,15 @@ proto_item_get_len(proto_item *pi)
 }
 
 gboolean
-proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
+proto_item_set_expert_flags(proto_item *pi, const int group, const guint severity)
 {
-       if(pi == NULL || pi->finfo == NULL)
+       if(pi == NULL || PITEM_FINFO(pi) == NULL)
                return FALSE;
 
        /* only change things if severity is worse or at least equal than before */
-       if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
-               FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
-               FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
+       if(severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
+               FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
+               FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
 
                return TRUE;
        }
@@ -3259,22 +3599,19 @@ proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
        return FALSE;
 }
 
-
-
 proto_tree*
 proto_tree_create_root(void)
 {
-       proto_node  *pnode;
+       proto_node      *pnode;
 
        /* Initialize the proto_node */
        PROTO_NODE_NEW(pnode);
        pnode->parent = NULL;
-       pnode->finfo = NULL;
+       PNODE_FINFO(pnode) = NULL;
        pnode->tree_data = g_new(tree_data_t, 1);
 
-       /* Initialize the tree_data_t */
-       pnode->tree_data->interesting_hfids =
-           g_hash_table_new(g_direct_hash, g_direct_equal);
+       /* Don't initialize the tree_data_t. Wait until we know we need it */
+       pnode->tree_data->interesting_hfids = NULL;
 
        /* Set the default to FALSE so it's easier to
         * find errors; if we expect to see the protocol tree
@@ -3282,6 +3619,9 @@ proto_tree_create_root(void)
         * changed, then we'll find out very quickly. */
        pnode->tree_data->visible = FALSE;
 
+       /* Make sure that we fake protocols (if possible) */
+       pnode->tree_data->fake_protocols = TRUE;
+
        /* Keep track of the number of children */
        pnode->tree_data->count = 0;
 
@@ -3292,18 +3632,15 @@ proto_tree_create_root(void)
 /* "prime" a proto_tree with a single hfid that a dfilter
  * is interested in. */
 void
-proto_tree_prime_hfid(proto_tree *tree, gint hfid)
+proto_tree_prime_hfid(proto_tree *tree _U_, const gint hfid)
 {
        header_field_info *hfinfo;
 
-       g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
-               GINT_TO_POINTER(hfid), g_ptr_array_new());
-
        PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
        /* this field is referenced by a filter so increase the refcount.
           also increase the refcount for the parent, i.e the protocol.
        */
-       hfinfo->ref_count++;
+       hfinfo->ref_type = HF_REF_TYPE_DIRECT;
        /* only increase the refcount if there is a parent.
           if this is a protocol and not a field then parent will be -1
           and there is no parent to add any refcounting for.
@@ -3311,26 +3648,35 @@ proto_tree_prime_hfid(proto_tree *tree, gint hfid)
        if (hfinfo->parent != -1) {
                header_field_info *parent_hfinfo;
                PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
-               parent_hfinfo->ref_count++;
+
+               /* Mark parent as indirectly referenced unless it is already directly
+                * referenced, i.e. the user has specified the parent in a filter.
+                */
+               if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
+                       parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
        }
 }
 
 proto_tree*
-proto_item_add_subtree(proto_item *pi,  gint idx) {
+proto_item_add_subtree(proto_item *pi, const gint idx) {
        field_info *fi;
 
        if (!pi)
                return(NULL);
 
-       fi = PITEM_FINFO(pi);
        DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
+
+       fi = PITEM_FINFO(pi);
+       if (!fi)
+               return (proto_tree*) pi;
+
        fi->tree_type = idx;
 
        return (proto_tree*) pi;
 }
 
 proto_tree*
-proto_item_get_subtree(proto_item *pi) {
+proto_item_get_subtree(const proto_item *pi) {
        field_info *fi;
 
        if (!pi)
@@ -3342,7 +3688,7 @@ proto_item_get_subtree(proto_item *pi) {
 }
 
 proto_item*
-proto_item_get_parent(proto_item *ti) {
+proto_item_get_parent(const proto_item *ti) {
        if (!ti)
                return (NULL);
        return ti->parent;
@@ -3362,7 +3708,7 @@ proto_item_get_parent_nth(proto_item *ti, int gen) {
 
 
 proto_item*
-proto_tree_get_parent(proto_tree *tree) {
+proto_tree_get_parent(const proto_tree *tree) {
        if (!tree)
                return (NULL);
        return (proto_item*) tree;
@@ -3381,53 +3727,61 @@ proto_tree_get_root(proto_tree *tree) {
 void
 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
 {
-    DISSECTOR_ASSERT(item_to_move->parent == tree);
-    DISSECTOR_ASSERT(fixed_item->parent == tree);
+       /* This function doesn't generate any values. It only reorganizes the prococol tree
+        * so we can bail out immediately if it isn't visible. */
+       if (!tree || !PTREE_DATA(tree)->visible)
+               return;
+
+       DISSECTOR_ASSERT(item_to_move->parent == tree);
+       DISSECTOR_ASSERT(fixed_item->parent == tree);
 
-    /*** cut item_to_move out ***/
+       /*** cut item_to_move out ***/
 
-    /* is item_to_move the first? */
-    if(tree->first_child == item_to_move) {
-        /* simply change first child to next */
-        tree->first_child = item_to_move->next;
+       /* is item_to_move the first? */
+       if(tree->first_child == item_to_move) {
+               /* simply change first child to next */
+               tree->first_child = item_to_move->next;
 
-        DISSECTOR_ASSERT(tree->last_child != item_to_move);
-    } else {
-        proto_item *curr_item;
-        /* find previous and change it's next */
-        for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
-            if(curr_item->next == item_to_move) {
-                break;
-            }
-        }
+               DISSECTOR_ASSERT(tree->last_child != item_to_move);
+       } else {
+               proto_item *curr_item;
+               /* find previous and change it's next */
+               for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
+                       if(curr_item->next == item_to_move) {
+                               break;
+                       }
+               }
 
-        DISSECTOR_ASSERT(curr_item);
+               DISSECTOR_ASSERT(curr_item);
 
-        curr_item->next = item_to_move->next;
+               curr_item->next = item_to_move->next;
 
-        /* fix last_child if required */
-        if(tree->last_child == item_to_move) {
-            tree->last_child = curr_item;
-        }
-    }
+               /* fix last_child if required */
+               if(tree->last_child == item_to_move) {
+                       tree->last_child = curr_item;
+               }
+       }
 
-    /*** insert to_move after fixed ***/
-    item_to_move->next = fixed_item->next;
-    fixed_item->next = item_to_move;
-    if(tree->last_child == fixed_item) {
-        tree->last_child = item_to_move;
-    }
+       /*** insert to_move after fixed ***/
+       item_to_move->next = fixed_item->next;
+       fixed_item->next = item_to_move;
+       if(tree->last_child == fixed_item) {
+               tree->last_child = item_to_move;
+       }
 }
 
 void
-proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
+proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, const gint length)
 {
        field_info *fi;
 
        if (tree == NULL)
                return;
 
-       fi = tree->finfo;
+       fi = PTREE_FINFO(tree);
+       if (fi == NULL)
+               return;
+
        start += TVB_RAW_OFFSET(tvb);
        DISSECTOR_ASSERT(start >= 0);
        DISSECTOR_ASSERT(length >= 0);
@@ -3439,114 +3793,118 @@ proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length
 int
 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
 {
-    protocol_t *protocol;
-    header_field_info *hfinfo;
-    int proto_id;
-    char *existing_name;
-    gint *key;
-    guint i;
-    guchar c;
-    gboolean found_invalid;
-
-    /*
-     * Make sure there's not already a protocol with any of those
-     * names.  Crash if there is, as that's an error in the code
-     * or an inappropriate plugin.
-     * This situation has to be fixed to not register more than one
-     * protocol with the same name.
-     *
-     * This is done by reducing the number of strcmp (and alike) calls as much as possible,
-     * as this significally slows down startup time.
-     *
-     * Drawback: As a hash value is used to reduce insert time,
-     * this might lead to a hash collision.
-     * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
-     * very unlikely.
-     */
-
-    key = g_malloc (sizeof(gint));
-    *key = wrs_str_hash(name);
-    existing_name = g_hash_table_lookup(proto_names, key);
-    if (existing_name != NULL) {
-        /* g_error will terminate the program */
-        g_error("Duplicate protocol name \"%s\"!"
-            " This might be caused by an inappropriate plugin or a development error.", name);
-    }
-    g_hash_table_insert(proto_names, key, (gpointer)name);
-
-    existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
-    if (existing_name != NULL) {
-        g_error("Duplicate protocol short_name \"%s\"!"
-            " This might be caused by an inappropriate plugin or a development error.", short_name);
-    }
-    g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
-
-    found_invalid = FALSE;
-    for (i = 0; i < strlen(filter_name); i++) {
-        c = filter_name[i];
-        if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
-            found_invalid = TRUE;
-        }
-    }
-    if (found_invalid) {
-        g_error("Protocol filter name \"%s\" has one or more invalid characters."
-            " Allowed are lower characters, digits, '-', '_' and '.'."
-            " This might be caused by an inappropriate plugin or a development error.", filter_name);
-    }
-    existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
-    if (existing_name != NULL) {
-        g_error("Duplicate protocol filter_name \"%s\"!"
-            " This might be caused by an inappropriate plugin or a development error.", filter_name);
-    }
-    g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
-
-    /* Add this protocol to the list of known protocols; the list
-       is sorted by protocol short name. */
-    protocol = g_malloc(sizeof (protocol_t));
-    protocol->name = name;
-    protocol->short_name = short_name;
-    protocol->filter_name = filter_name;
-    protocol->fields = NULL;
-    protocol->is_enabled = TRUE; /* protocol is enabled by default */
-    protocol->can_toggle = TRUE;
-    protocol->is_private = FALSE;
-    /* list will be sorted later by name, when all protocols completed registering */
-    protocols = g_list_prepend(protocols, protocol);
-
-    /* Here we do allocate a new header_field_info struct */
-    hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
-    hfinfo->name = name;
-    hfinfo->abbrev = filter_name;
-    hfinfo->type = FT_PROTOCOL;
-    hfinfo->display = BASE_NONE;
-    hfinfo->strings = protocol;
-    hfinfo->bitmask = 0;
-    hfinfo->bitshift = 0;
-    hfinfo->ref_count = 0;
-    hfinfo->blurb = NULL;
-    hfinfo->parent = -1; /* this field differentiates protos and fields */
-
-    proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
-    protocol->proto_id = proto_id;
-    return proto_id;
+       protocol_t *protocol;
+       header_field_info *hfinfo;
+       int proto_id;
+       char *existing_name;
+       gint *key;
+       guint i;
+       guchar c;
+       gboolean found_invalid;
+
+       /*
+        * Make sure there's not already a protocol with any of those
+        * names.  Crash if there is, as that's an error in the code
+        * or an inappropriate plugin.
+        * This situation has to be fixed to not register more than one
+        * protocol with the same name.
+        *
+        * This is done by reducing the number of strcmp (and alike) calls as much as possible,
+        * as this significally slows down startup time.
+        *
+        * Drawback: As a hash value is used to reduce insert time,
+        * this might lead to a hash collision.
+        * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
+        * very unlikely.
+        */
+
+       key = g_malloc (sizeof(gint));
+       *key = wrs_str_hash(name);
+       existing_name = g_hash_table_lookup(proto_names, key);
+       if (existing_name != NULL) {
+               /* g_error will terminate the program */
+               g_error("Duplicate protocol name \"%s\"!"
+                       " This might be caused by an inappropriate plugin or a development error.", name);
+       }
+       g_hash_table_insert(proto_names, key, (gpointer)name);
+
+       existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
+       if (existing_name != NULL) {
+               g_error("Duplicate protocol short_name \"%s\"!"
+                       " This might be caused by an inappropriate plugin or a development error.", short_name);
+       }
+       g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
+
+       found_invalid = FALSE;
+       for (i = 0; i < strlen(filter_name); i++) {
+               c = filter_name[i];
+               if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
+                       found_invalid = TRUE;
+               }
+       }
+       if (found_invalid) {
+               g_error("Protocol filter name \"%s\" has one or more invalid characters."
+                       " Allowed are lower characters, digits, '-', '_' and '.'."
+                       " This might be caused by an inappropriate plugin or a development error.", filter_name);
+       }
+       existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
+       if (existing_name != NULL) {
+               g_error("Duplicate protocol filter_name \"%s\"!"
+                       " This might be caused by an inappropriate plugin or a development error.", filter_name);
+       }
+       g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
+
+       /* Add this protocol to the list of known protocols; the list
+          is sorted by protocol short name. */
+       protocol = g_new(protocol_t, 1);
+       protocol->name = name;
+       protocol->short_name = short_name;
+       protocol->filter_name = filter_name;
+       protocol->fields = NULL;
+       protocol->is_enabled = TRUE; /* protocol is enabled by default */
+       protocol->can_toggle = TRUE;
+       protocol->is_private = FALSE;
+       /* list will be sorted later by name, when all protocols completed registering */
+       protocols = g_list_prepend(protocols, protocol);
+
+       /* Here we do allocate a new header_field_info struct */
+#if GLIB_CHECK_VERSION(2,10,0)
+       hfinfo = g_slice_new(header_field_info);
+#else
+       hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
+#endif
+       hfinfo->name = name;
+       hfinfo->abbrev = filter_name;
+       hfinfo->type = FT_PROTOCOL;
+       hfinfo->display = BASE_NONE;
+       hfinfo->strings = protocol;
+       hfinfo->bitmask = 0;
+       hfinfo->bitshift = 0;
+       hfinfo->ref_type = HF_REF_TYPE_NONE;
+       hfinfo->blurb = NULL;
+       hfinfo->parent = -1; /* this field differentiates protos and fields */
+
+       proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
+       protocol->proto_id = proto_id;
+       return proto_id;
 }
 
 void
-proto_mark_private(int proto_id)
+proto_mark_private(const int proto_id)
 {
-    protocol_t *protocol = find_protocol_by_id(proto_id);
-    if (protocol)
-        protocol->is_private = TRUE;
+       protocol_t *protocol = find_protocol_by_id(proto_id);
+       if (protocol)
+               protocol->is_private = TRUE;
 }
 
 gboolean
-proto_is_private(int proto_id)
+proto_is_private(const int proto_id)
 {
-    protocol_t *protocol = find_protocol_by_id(proto_id);
-    if (protocol)
-        return protocol->is_private;
-    else
-        return FALSE;
+       protocol_t *protocol = find_protocol_by_id(proto_id);
+       if (protocol)
+               return protocol->is_private;
+       else
+               return FALSE;
 }
 
 /*
@@ -3583,7 +3941,7 @@ proto_get_next_protocol(void **cookie)
 }
 
 header_field_info *
-proto_get_first_protocol_field(int proto_id, void **cookie)
+proto_get_first_protocol_field(const int proto_id, void **cookie)
 {
        protocol_t *protocol = find_protocol_by_id(proto_id);
        hf_register_info *ptr;
@@ -3612,7 +3970,7 @@ proto_get_next_protocol_field(void **cookie)
 }
 
 protocol_t *
-find_protocol_by_id(int proto_id)
+find_protocol_by_id(const int proto_id)
 {
        header_field_info *hfinfo;
 
@@ -3634,7 +3992,7 @@ static gint compare_filter_name(gconstpointer proto_arg,
 }
 
 int
-proto_get_id(protocol_t *protocol)
+proto_get_id(const protocol_t *protocol)
 {
        return protocol->proto_id;
 }
@@ -3645,7 +4003,7 @@ int proto_get_id_by_filter_name(const gchar* filter_name)
        protocol_t *protocol;
 
        list_entry = g_list_find_custom(protocols, filter_name,
-           compare_filter_name);
+               compare_filter_name);
 
        if (list_entry == NULL)
                return -1;
@@ -3654,7 +4012,7 @@ int proto_get_id_by_filter_name(const gchar* filter_name)
 }
 
 const char *
-proto_get_protocol_name(int proto_id)
+proto_get_protocol_name(const int proto_id)
 {
        protocol_t *protocol;
 
@@ -3663,7 +4021,7 @@ proto_get_protocol_name(int proto_id)
 }
 
 const char *
-proto_get_protocol_short_name(protocol_t *protocol)
+proto_get_protocol_short_name(const protocol_t *protocol)
 {
        if (protocol == NULL)
                return "(none)";
@@ -3671,7 +4029,7 @@ proto_get_protocol_short_name(protocol_t *protocol)
 }
 
 const char *
-proto_get_protocol_long_name(protocol_t *protocol)
+proto_get_protocol_long_name(const protocol_t *protocol)
 {
        if (protocol == NULL)
                return "(none)";
@@ -3679,7 +4037,7 @@ proto_get_protocol_long_name(protocol_t *protocol)
 }
 
 const char *
-proto_get_protocol_filter_name(int proto_id)
+proto_get_protocol_filter_name(const int proto_id)
 {
        protocol_t *protocol;
 
@@ -3690,13 +4048,13 @@ proto_get_protocol_filter_name(int proto_id)
 }
 
 gboolean
-proto_is_protocol_enabled(protocol_t *protocol)
+proto_is_protocol_enabled(const protocol_t *protocol)
 {
        return protocol->is_enabled;
 }
 
 gboolean
-proto_can_toggle_protocol(int proto_id)
+proto_can_toggle_protocol(const int proto_id)
 {
        protocol_t *protocol;
 
@@ -3705,7 +4063,7 @@ proto_can_toggle_protocol(int proto_id)
 }
 
 void
-proto_set_decoding(int proto_id, gboolean enabled)
+proto_set_decoding(const int proto_id, const gboolean enabled)
 {
        protocol_t *protocol;
 
@@ -3732,7 +4090,7 @@ proto_enable_all(void)
 }
 
 void
-proto_set_cant_toggle(int proto_id)
+proto_set_cant_toggle(const int proto_id)
 {
        protocol_t *protocol;
 
@@ -3743,7 +4101,7 @@ proto_set_cant_toggle(int proto_id)
 /* for use with static arrays only, since we don't allocate our own copies
 of the header_field_info struct contained within the hf_register_info struct */
 void
-proto_register_field_array(int parent, hf_register_info *hf, int num_records)
+proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
 {
        int                     field_id, i;
        hf_register_info        *ptr = hf;
@@ -3761,8 +4119,8 @@ proto_register_field_array(int parent, hf_register_info *hf, int num_records)
                 */
                if (*ptr->p_id != -1 && *ptr->p_id != 0) {
                        fprintf(stderr,
-                           "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
-                           ptr->hfinfo.abbrev);
+                               "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
+                               ptr->hfinfo.abbrev);
                        return;
                }
 
@@ -3772,7 +4130,7 @@ proto_register_field_array(int parent, hf_register_info *hf, int num_records)
                                proto->last_field = proto->fields;
                        } else {
                                proto->last_field =
-                                   g_list_append(proto->last_field, ptr)->next;
+                                       g_list_append(proto->last_field, ptr)->next;
                        }
                }
                field_id = proto_register_field_init(&ptr->hfinfo, parent);
@@ -3785,12 +4143,12 @@ static
 const guchar fld_abbrev_chars[256] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.'     */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9'      */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O'      */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.'    */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9'     */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O'     */
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o'      */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z'      */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o'     */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z'     */
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
@@ -3830,15 +4188,15 @@ static void tmp_fld_check_assert(header_field_info *hfinfo) {
        case FT_INT24:
        case FT_INT32:
        case FT_INT64:
-               /*  Hexadecimal and octal are, in printf() and everywhere else,
-                *  unsigned so don't allow dissectors to register a signed
-                *  field to be displayed unsigned.  (Else how would we
-                *  display values negative values?)
+               /*      Hexadecimal and octal are, in printf() and everywhere else,
+                *      unsigned so don't allow dissectors to register a signed
+                *      field to be displayed unsigned.  (Else how would we
+                *      display values negative values?)
                 *
-                *  If you want to take out this check, be sure to fix
-                *  hfinfo_numeric_format() so that it does not assert out
-                *  when trying to construct a hexadecimal representation of
-                *  FT_INT*.
+                *      If you want to take out this check, be sure to fix
+                *      hfinfo_numeric_format() so that it does not assert out
+                *      when trying to construct a hexadecimal representation of
+                *      FT_INT*.
                 */
                DISSECTOR_ASSERT(hfinfo->display != BASE_HEX &&
                                 hfinfo->display != BASE_HEX_DEC &&
@@ -3860,22 +4218,33 @@ static void tmp_fld_check_assert(header_field_info *hfinfo) {
                DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
                break;
 
+       case FT_PROTOCOL:
        case FT_FRAMENUM:
-       case FT_STRING:
-       case FT_STRINGZ:
-       case FT_EBCDIC:
-               /* Don't allow bitfields or value strings for frame numbers and strings */
+               DISSECTOR_ASSERT(hfinfo->display == BASE_NONE);
+               DISSECTOR_ASSERT(hfinfo->bitmask == 0);
+               break;
+
+       case FT_BOOLEAN:
+               break;
+
+       case FT_ABSOLUTE_TIME:
+               DISSECTOR_ASSERT(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
+                   hfinfo->display == ABSOLUTE_TIME_UTC ||
+                   hfinfo->display == ABSOLUTE_TIME_DOY_UTC);
                DISSECTOR_ASSERT(hfinfo->bitmask == 0);
                DISSECTOR_ASSERT(hfinfo->strings == NULL);
                break;
 
        default:
+               DISSECTOR_ASSERT(hfinfo->display == BASE_NONE);
+               DISSECTOR_ASSERT(hfinfo->bitmask == 0);
+               DISSECTOR_ASSERT(hfinfo->strings == NULL);
                break;
        }
 }
 
 static int
-proto_register_field_init(header_field_info *hfinfo, int parent)
+proto_register_field_init(header_field_info *hfinfo, const int parent)
 {
 
        tmp_fld_check_assert(hfinfo);
@@ -3929,8 +4298,8 @@ proto_register_field_init(header_field_info *hfinfo, int parent)
 
                g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
                /* GLIB 2.x - if it is already present
-         * the previous hfinfo with the same name is saved
-         * to same_name_hfinfo by value destroy callback */
+                * the previous hfinfo with the same name is saved
+                * to same_name_hfinfo by value destroy callback */
                if (same_name_hfinfo) {
                        /* There's already a field with this name.
                         * Put it after that field in the list of
@@ -3940,7 +4309,7 @@ proto_register_field_init(header_field_info *hfinfo, int parent)
                         * we end up with a linked-list of same-named hfinfo's,
                         * with the root of the list being the hfinfo in the GTree */
                        same_name_next_hfinfo =
-                           same_name_hfinfo->same_name_next;
+                               same_name_hfinfo->same_name_next;
 
                        hfinfo->same_name_next = same_name_next_hfinfo;
                        if (same_name_next_hfinfo)
@@ -3955,7 +4324,7 @@ proto_register_field_init(header_field_info *hfinfo, int parent)
 }
 
 void
-proto_register_subtree_array(gint *const *indices, int num_indices)
+proto_register_subtree_array(gint *const *indices, const int num_indices)
 {
        int     i;
        gint    *const *ptr = indices;
@@ -3973,10 +4342,10 @@ proto_register_subtree_array(gint *const *indices, int num_indices)
         */
        if (tree_is_expanded != NULL) {
                tree_is_expanded =
-                   g_realloc(tree_is_expanded,
-                       (num_tree_types+num_indices)*sizeof (gboolean));
+                       g_realloc(tree_is_expanded,
+                               (num_tree_types+num_indices)*sizeof (gboolean));
                memset(tree_is_expanded + num_tree_types, 0,
-                   num_indices*sizeof (gboolean));
+                       num_indices*sizeof (gboolean));
        }
 
        /*
@@ -3985,14 +4354,22 @@ proto_register_subtree_array(gint *const *indices, int num_indices)
         * first element is pointed to by "indices", and update
         * "num_tree_types" appropriately.
         */
-       for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
+       for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
+               if (**ptr != -1) {
+                       /* g_error will terminate the program */
+                       g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
+                               " This is a development error:"
+                               " Either the subtree item type has already been assigned or"
+                               " was not initialized to -1.");
+               }
                **ptr = num_tree_types;
+       }
 }
 
 void
 proto_item_fill_label(field_info *fi, gchar *label_str)
 {
-       header_field_info               *hfinfo = fi->hfinfo;
+       header_field_info               *hfinfo;
 
        guint8                          *bytes;
        guint32                         integer;
@@ -4002,6 +4379,15 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
        const gchar                     *name;
        int                                     ret;    /*tmp return value */
 
+       if (!fi) {
+               if (label_str)
+                       label_str[0]= '\0';
+               /* XXX: Check validity of hfinfo->type */
+               return;
+       }
+
+       hfinfo = fi->hfinfo;
+
        switch(hfinfo->type) {
                case FT_NONE:
                case FT_PROTOCOL:
@@ -4021,7 +4407,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                                         bytes_to_str(bytes, fvalue_length(&fi->value)));
                                if (ret >= ITEM_LABEL_LENGTH) {
                                        /* Uh oh, we don't have enough room.  Tell the
-                                        *  user that the field is truncated.
+                                        *      user that the field is truncated.
                                         */
                                        g_snprintf(label_str, ITEM_LABEL_LENGTH,
                                                         "%s [truncated]: %s",
@@ -4035,16 +4421,15 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                        break;
 
                /* Four types of integers to take care of:
-                *      Bitfield, with val_string
-                *      Bitfield, w/o val_string
-                *      Non-bitfield, with val_string
-                *      Non-bitfield, w/o val_string
+                *      Bitfield, with val_string
+                *      Bitfield, w/o val_string
+                *      Non-bitfield, with val_string
+                *      Non-bitfield, w/o val_string
                 */
                case FT_UINT8:
                case FT_UINT16:
                case FT_UINT24:
                case FT_UINT32:
-               case FT_FRAMENUM:
                        if (hfinfo->bitmask) {
                                fill_label_bitfield(fi, label_str);
                        } else {
@@ -4052,6 +4437,10 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                        }
                        break;
 
+               case FT_FRAMENUM:
+                       fill_label_uint(fi, label_str);
+                       break;
+
                case FT_UINT64:
                        fill_label_uint64(fi, label_str);
                        break;
@@ -4083,7 +4472,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                case FT_ABSOLUTE_TIME:
                        g_snprintf(label_str, ITEM_LABEL_LENGTH,
                                "%s: %s", hfinfo->name,
-                               abs_time_to_str(fvalue_get(&fi->value)));
+                               abs_time_to_str(fvalue_get(&fi->value), hfinfo->display));
                        break;
 
                case FT_RELATIVE_TIME:
@@ -4147,7 +4536,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
 
                case FT_STRING:
                case FT_STRINGZ:
-               case FT_EBCDIC:
+               case FT_EBCDIC:
                case FT_UINT_STRING:
                        bytes = fvalue_get(&fi->value);
                        ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
@@ -4155,7 +4544,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                                         format_text(bytes, strlen(bytes)));
                        if (ret >= ITEM_LABEL_LENGTH) {
                                /* Uh oh, we don't have enough room.  Tell the
-                                *  user that the field is truncated.
+                                *      user that the field is truncated.
                                 */
                                g_snprintf(label_str, ITEM_LABEL_LENGTH,
                                                 "%s [truncated]: %s",
@@ -4182,7 +4571,7 @@ fill_label_boolean(field_info *fi, gchar *label_str)
        guint32 value;
 
        header_field_info               *hfinfo = fi->hfinfo;
-       const true_false_string         *tfstring = &tfs_true_false;
+       const true_false_string         *tfstring = (const true_false_string *)&tfs_true_false;
 
        if (hfinfo->strings) {
                tfstring = (const struct true_false_string*) hfinfo->strings;
@@ -4397,7 +4786,7 @@ fill_label_int64(field_info *fi, gchar *label_str)
 }
 
 int
-hfinfo_bitwidth(header_field_info *hfinfo)
+hfinfo_bitwidth(const header_field_info *hfinfo)
 {
        int bitwidth = 0;
 
@@ -4433,13 +4822,12 @@ hfinfo_bitwidth(header_field_info *hfinfo)
 }
 
 static const char*
-hfinfo_uint_vals_format(header_field_info *hfinfo)
+hfinfo_uint_vals_format(const header_field_info *hfinfo)
 {
        const char *format = NULL;
 
-       /* bit operation to reset the potential BASE_RANGE_STRING (or others in
-        * the future?) */
-       switch(hfinfo->display & BASE_STRUCTURE_RESET) {
+       /* Get the underlying BASE_ value */
+       switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
                case BASE_NONE:
                        format = "%s: %s";
                        break;
@@ -4448,7 +4836,7 @@ hfinfo_uint_vals_format(header_field_info *hfinfo)
                        format = "%s: %s (%u)";
                        break;
                case BASE_OCT: /* I'm lazy */
-                       format = "%s: %s (%o)";
+                       format = "%s: %s (%#o)";
                        break;
                case BASE_HEX:
                case BASE_HEX_DEC:
@@ -4478,7 +4866,7 @@ hfinfo_uint_vals_format(header_field_info *hfinfo)
 }
 
 static const char*
-hfinfo_uint_format(header_field_info *hfinfo)
+hfinfo_uint_format(const header_field_info *hfinfo)
 {
        const char *format = NULL;
 
@@ -4513,7 +4901,7 @@ hfinfo_uint_format(header_field_info *hfinfo)
                                }
                                break;
                        case BASE_OCT: /* I'm lazy */
-                               format = "%s: %o";
+                               format = "%s: %#o";
                                break;
                        case BASE_HEX:
                                switch(hfinfo->type) {
@@ -4562,7 +4950,7 @@ hfinfo_uint_format(header_field_info *hfinfo)
 }
 
 static const char*
-hfinfo_uint_value_format(header_field_info *hfinfo)
+hfinfo_uint_value_format(const header_field_info *hfinfo)
 {
        const char *format = NULL;
 
@@ -4597,7 +4985,7 @@ hfinfo_uint_value_format(header_field_info *hfinfo)
                                }
                                break;
                        case BASE_OCT:
-                               format = "%o";
+                               format = "%#o";
                                break;
                        case BASE_HEX:
                                switch(hfinfo->type) {
@@ -4646,13 +5034,12 @@ hfinfo_uint_value_format(header_field_info *hfinfo)
 }
 
 static const char*
-hfinfo_int_vals_format(header_field_info *hfinfo)
+hfinfo_int_vals_format(const header_field_info *hfinfo)
 {
        const char *format = NULL;
 
-       /* bit operation to reset the potential BASE_RANGE_STRING (or others in
-        * the future?)*/
-       switch(hfinfo->display & BASE_STRUCTURE_RESET) {
+       /* Get the underlying BASE_ value */
+       switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
                case BASE_NONE:
                        format = "%s: %s";
                        break;
@@ -4661,7 +5048,7 @@ hfinfo_int_vals_format(header_field_info *hfinfo)
                        format = "%s: %s (%d)";
                        break;
                case BASE_OCT: /* I'm lazy */
-                       format = "%s: %s (%o)";
+                       format = "%s: %s (%#o)";
                        break;
                case BASE_HEX:
                case BASE_HEX_DEC:
@@ -4691,7 +5078,7 @@ hfinfo_int_vals_format(header_field_info *hfinfo)
 }
 
 static const char*
-hfinfo_uint64_format(header_field_info *hfinfo)
+hfinfo_uint64_format(const header_field_info *hfinfo)
 {
        const char *format = NULL;
 
@@ -4704,7 +5091,7 @@ hfinfo_uint64_format(header_field_info *hfinfo)
                        format = "%s: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "x)";
                        break;
                case BASE_OCT: /* I'm lazy */
-                       format = "%s: %" G_GINT64_MODIFIER "o";
+                       format = "%s: %#" G_GINT64_MODIFIER "o";
                        break;
                case BASE_HEX:
                        format = "%s: 0x%016" G_GINT64_MODIFIER "x";
@@ -4720,7 +5107,7 @@ hfinfo_uint64_format(header_field_info *hfinfo)
 }
 
 static const char*
-hfinfo_int_format(header_field_info *hfinfo)
+hfinfo_int_format(const header_field_info *hfinfo)
 {
        const char *format = NULL;
 
@@ -4749,7 +5136,7 @@ hfinfo_int_format(header_field_info *hfinfo)
                        }
                        break;
                case BASE_OCT: /* I'm lazy */
-                       format = "%s: %o";
+                       format = "%s: %#o";
                        break;
                case BASE_HEX:
                        switch(hfinfo->type) {
@@ -4797,7 +5184,7 @@ hfinfo_int_format(header_field_info *hfinfo)
 }
 
 static const char*
-hfinfo_int_value_format(header_field_info *hfinfo)
+hfinfo_int_value_format(const header_field_info *hfinfo)
 {
        const char *format = NULL;
 
@@ -4826,7 +5213,7 @@ hfinfo_int_value_format(header_field_info *hfinfo)
                        }
                        break;
                case BASE_OCT:
-                       format = "%o";
+                       format = "%#o";
                        break;
                case BASE_HEX:
                        switch(hfinfo->type) {
@@ -4874,7 +5261,7 @@ hfinfo_int_value_format(header_field_info *hfinfo)
 }
 
 static const char*
-hfinfo_int64_format(header_field_info *hfinfo)
+hfinfo_int64_format(const header_field_info *hfinfo)
 {
        const char *format = NULL;
 
@@ -4887,7 +5274,7 @@ hfinfo_int64_format(header_field_info *hfinfo)
                        format = "%s: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "x)";
                        break;
                case BASE_OCT: /* I'm lazy */
-                       format = "%s: %" G_GINT64_MODIFIER "o";
+                       format = "%s: %#" G_GINT64_MODIFIER "o";
                        break;
                case BASE_HEX:
                        format = "%s: 0x%016" G_GINT64_MODIFIER "x";
@@ -4902,8 +5289,6 @@ hfinfo_int64_format(header_field_info *hfinfo)
        return format;
 }
 
-
-
 int
 proto_registrar_n(void)
 {
@@ -4911,7 +5296,7 @@ proto_registrar_n(void)
 }
 
 const char*
-proto_registrar_get_name(int n)
+proto_registrar_get_name(const int n)
 {
        header_field_info *hfinfo;
 
@@ -4920,7 +5305,7 @@ proto_registrar_get_name(int n)
 }
 
 const char*
-proto_registrar_get_abbrev(int n)
+proto_registrar_get_abbrev(const int n)
 {
        header_field_info *hfinfo;
 
@@ -4929,7 +5314,7 @@ proto_registrar_get_abbrev(int n)
 }
 
 int
-proto_registrar_get_ftype(int n)
+proto_registrar_get_ftype(const int n)
 {
        header_field_info *hfinfo;
 
@@ -4938,7 +5323,7 @@ proto_registrar_get_ftype(int n)
 }
 
 int
-proto_registrar_get_parent(int n)
+proto_registrar_get_parent(const int n)
 {
        header_field_info *hfinfo;
 
@@ -4947,7 +5332,7 @@ proto_registrar_get_parent(int n)
 }
 
 gboolean
-proto_registrar_is_protocol(int n)
+proto_registrar_is_protocol(const int n)
 {
        header_field_info *hfinfo;
 
@@ -4960,7 +5345,7 @@ proto_registrar_is_protocol(int n)
  * 0 means undeterminable at time of registration
  * -1 means the field is not registered. */
 gint
-proto_registrar_get_length(int n)
+proto_registrar_get_length(const int n)
 {
        header_field_info *hfinfo;
 
@@ -4968,12 +5353,10 @@ proto_registrar_get_length(int n)
        return ftype_length(hfinfo->type);
 }
 
-
-
 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
  * it exists anywhere, or FALSE if it exists nowhere. */
 gboolean
-proto_check_for_protocol_or_field(proto_tree* tree, int id)
+proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
 {
        GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
 
@@ -4994,14 +5377,28 @@ proto_check_for_protocol_or_field(proto_tree* tree, int id)
  * The caller should *not* free the GPtrArray*; proto_tree_free_node()
  * handles that. */
 GPtrArray*
-proto_get_finfo_ptr_array(proto_tree *tree, int id)
+proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
 {
-       return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
-           GINT_TO_POINTER(id));
+       if (!tree)
+               return NULL;
+
+       if (PTREE_DATA(tree)->interesting_hfids != NULL)
+               return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
+                                                               GINT_TO_POINTER(id));
+       else
+               return NULL;
 }
 
+gboolean
+proto_tracking_interesting_fields(const proto_tree *tree)
+{
+       if (!tree)
+               return FALSE;
+
+       return (PTREE_DATA(tree)->interesting_hfids != NULL);
+}
 
-/* Helper struct for proto_find_info() and  proto_all_finfos() */
+/* Helper struct for proto_find_info() and     proto_all_finfos() */
 typedef struct {
        GPtrArray       *array;
        int             id;
@@ -5011,7 +5408,7 @@ typedef struct {
 static gboolean
 find_finfo(proto_node *node, gpointer data)
 {
-       field_info *fi = PITEM_FINFO(node);
+       field_info *fi = PNODE_FINFO(node);
        if (fi && fi->hfinfo) {
                if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
                        g_ptr_array_add(((ffdata_t*)data)->array, fi);
@@ -5026,10 +5423,10 @@ find_finfo(proto_node *node, gpointer data)
 * This works on any proto_tree, primed or unprimed, but actually searches
 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
 * The caller does need to free the returned GPtrArray with
-* g_ptr_array_free(<array>, FALSE).
+* g_ptr_array_free(<array>, TRUE).
 */
 GPtrArray*
-proto_find_finfo(proto_tree *tree, int id)
+proto_find_finfo(proto_tree *tree, const int id)
 {
        ffdata_t        ffdata;
 
@@ -5045,7 +5442,7 @@ proto_find_finfo(proto_tree *tree, int id)
 static gboolean
 every_finfo(proto_node *node, gpointer data)
 {
-       field_info *fi = PITEM_FINFO(node);
+       field_info *fi = PNODE_FINFO(node);
        if (fi && fi->hfinfo) {
                g_ptr_array_add(((ffdata_t*)data)->array, fi);
        }
@@ -5076,9 +5473,9 @@ typedef struct {
 } offset_search_t;
 
 static gboolean
-check_for_offset(proto_node *node, gpointer data)
+check_for_offset(proto_node *node, const gpointer data)
 {
-       field_info          *fi = PITEM_FINFO(node);
+       field_info                      *fi = PNODE_FINFO(node);
        offset_search_t         *offsearch = data;
 
        /* !fi == the top most container node which holds nothing */
@@ -5115,7 +5512,7 @@ proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
        return offsearch.finfo;
 }
 
-/* Dumps the protocols in the registration database to stdout.  An independent
+/* Dumps the protocols in the registration database to stdout. An independent
  * program can take this output and format it into nice tables or HTML or
  * whatever.
  *
@@ -5133,14 +5530,14 @@ proto_registrar_dump_protocols(void)
        void                    *cookie = NULL;
 
        for (i = proto_get_first_protocol(&cookie); i != -1;
-           i = proto_get_next_protocol(&cookie)) {
+               i = proto_get_next_protocol(&cookie)) {
                protocol = find_protocol_by_id(i);
                printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
-                   protocol->filter_name);
+                       protocol->filter_name);
        }
 }
 
-/* Dumps the value_strings, range_strings or true/false strings for fields 
+/* Dumps the value_strings, range_strings or true/false strings for fields
  * that have them. There is one record per line. Fields are tab-delimited.
  * There are three types of records: Value String, Range String
  * and True/False String. The first field, 'V', 'R' or 'T', indicates
@@ -5197,7 +5594,7 @@ proto_registrar_dump_values(void)
                         * fields with the same name are really just versions
                         * of the same field stored in different bits, and
                         * should have the same type/radix/value list, and
-                        * just differ in their bit masks.  (If a field isn't
+                        * just differ in their bit masks.      (If a field isn't
                         * a bitfield, but can be, say, 1 or 2 bytes long,
                         * it can just be made FT_UINT16, meaning the
                         * *maximum* length is 2 bytes, and be used
@@ -5212,7 +5609,7 @@ proto_registrar_dump_values(void)
                        range = NULL;
                        tfs   = NULL;
 
-                       if ((hfinfo->display & BASE_STRUCTURE_RESET) != BASE_CUSTOM &&
+                       if ((hfinfo->display & BASE_DISPLAY_E_MASK) != BASE_CUSTOM &&
                                (hfinfo->type == FT_UINT8 ||
                                hfinfo->type == FT_UINT16 ||
                                hfinfo->type == FT_UINT24 ||
@@ -5260,7 +5657,7 @@ proto_registrar_dump_values(void)
                                vi = 0;
                                while (range[vi].strptr) {
                                        /* Print in the proper base */
-                                       if ((hfinfo->display & BASE_STRUCTURE_RESET) == BASE_HEX) {
+                                       if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_HEX) {
                                                printf("R\t%s\t0x%x\t0x%x\t%s\n",
                                                                hfinfo->abbrev,
                                                                range[vi].value_min,
@@ -5331,12 +5728,11 @@ proto_registrar_dump_values(void)
  * Field 8 = bitmask: format: hex: 0x....
  */
 void
-
-proto_registrar_dump_fields(int format)
+proto_registrar_dump_fields(const int format)
 {
        header_field_info       *hfinfo, *parent_hfinfo;
        int                     i, len;
-       const char              *enum_name;
+       const char              *enum_name;
        const char              *base_name;
        const char              *blurb;
        char                    width[5];
@@ -5348,8 +5744,8 @@ proto_registrar_dump_fields(int format)
                /*
                 * Skip the pseudo-field for "proto_tree_add_text()" since
                 * we don't want it in the list of filterable fields.
-         */
-        if (hfinfo->id == hf_text_only)
+                */
+               if (hfinfo->id == hf_text_only)
                        continue;
 
                /* format for protocols */
@@ -5364,7 +5760,7 @@ proto_registrar_dump_fields(int format)
                         * fields with the same name are really just versions
                         * of the same field stored in different bits, and
                         * should have the same type/radix/value list, and
-                        * just differ in their bit masks.  (If a field isn't
+                        * just differ in their bit masks.      (If a field isn't
                         * a bitfield, but can be, say, 1 or 2 bytes long,
                         * it can just be made FT_UINT16, meaning the
                         * *maximum* length is 2 bytes, and be used
@@ -5391,7 +5787,7 @@ proto_registrar_dump_fields(int format)
                                        hfinfo->type == FT_INT64) {
 
 
-                                       switch(hfinfo->display & BASE_STRUCTURE_RESET) {
+                                       switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
                                                case BASE_NONE:
                                                        base_name = "BASE_NONE";
                                                        break;
@@ -5452,7 +5848,7 @@ proto_registrar_dump_fields(int format)
 }
 
 static const char*
-hfinfo_numeric_format(header_field_info *hfinfo)
+hfinfo_numeric_format(const header_field_info *hfinfo)
 {
        const char *format = NULL;
 
@@ -5463,8 +5859,8 @@ hfinfo_numeric_format(header_field_info *hfinfo)
                 */
                format = "%s == %u";
        } else {
-               /* Pick the proper format string, ignoring BASE_RANGE_STRING flag */
-               switch(hfinfo->display & ~BASE_RANGE_STRING) {
+               /* Get the underlying BASE_ value */
+               switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
                        case BASE_DEC:
                        case BASE_DEC_HEX:
                        case BASE_OCT: /* I'm lazy */
@@ -5534,7 +5930,7 @@ hfinfo_numeric_format(header_field_info *hfinfo)
  */
 static gboolean
 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
-    char **filter)
+       char **filter)
 {
        header_field_info       *hfinfo;
        int                     abbrev_len;
@@ -5550,7 +5946,7 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
        DISSECTOR_ASSERT(hfinfo);
        abbrev_len = (int) strlen(hfinfo->abbrev);
 
-       if (hfinfo->strings && (hfinfo->display & BASE_STRUCTURE_RESET) == BASE_NONE) {
+       if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
                const gchar *str = NULL;
 
                switch(hfinfo->type) {
@@ -5618,7 +6014,6 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
                case FT_UINT16:
                case FT_UINT24:
                case FT_UINT32:
-               case FT_FRAMENUM:
                        if (filter != NULL) {
                                format = hfinfo_numeric_format(hfinfo);
                                if(is_signed_num) {
@@ -5628,18 +6023,28 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
                                } else {
                                        *filter = ep_strdup_printf(format,
                                                   hfinfo->abbrev,
-                                                  fvalue_get_uinteger(&finfo->value));
+                                                          fvalue_get_uinteger(&finfo->value));
                                }
                        }
                        break;
 
+               case FT_FRAMENUM:
+                       DISSECTOR_ASSERT(!is_signed_num);
+                       if (filter != NULL) {
+                               format = hfinfo_numeric_format(hfinfo);
+                               *filter = ep_strdup_printf(format,
+                                          hfinfo->abbrev,
+                                                  fvalue_get_uinteger(&finfo->value));
+                       }
+                       break;
+
                case FT_INT64:
                case FT_UINT64:
                        if (filter != NULL) {
                                format = hfinfo_numeric_format(hfinfo);
                                *filter = ep_strdup_printf(format,
-                                   hfinfo->abbrev,
-                                   fvalue_get_integer64(&finfo->value));
+                                       hfinfo->abbrev,
+                                       fvalue_get_integer64(&finfo->value));
                        }
                        break;
 
@@ -5649,7 +6054,6 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
                        break;
 
                case FT_NONE:
-               case FT_PCRE:
                        /*
                         * If the length is 0, just match the name of the
                         * field.
@@ -5706,7 +6110,7 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
                                ptr = *filter;
 
                                ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
-                                   "frame[%d:%d] == ", finfo->start, length);
+                                       "frame[%d:%d] == ", finfo->start, length);
                                for (i=0;i<length; i++) {
                                        c = tvb_get_guint8(finfo->ds_tvb, start);
                                        start++;
@@ -5720,12 +6124,18 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
                        }
                        break;
 
+               case FT_PCRE:
+                       /* FT_PCRE never appears as a type for a registered field. It is
+                        * only used internally. */
+                       DISSECTOR_ASSERT_NOT_REACHED();
+                       break;
+
                /* By default, use the fvalue's "to_string_repr" method. */
                default:
                        /* Figure out the string length needed.
-                        *      The ft_repr length.
-                        *      4 bytes for " == ".
-                        *      1 byte for trailing NUL.
+                        *      The ft_repr length.
+                        *      4 bytes for " == ".
+                        *      1 byte for trailing NUL.
                         */
                        if (filter != NULL) {
                                dfilter_len = fvalue_string_repr_len(&finfo->value,
@@ -5735,10 +6145,10 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
 
                                /* Create the string */
                                g_snprintf(*filter, dfilter_len, "%s == ",
-                                   hfinfo->abbrev);
+                                       hfinfo->abbrev);
                                fvalue_to_string_repr(&finfo->value,
-                                   FTREPR_DFILTER,
-                                   &(*filter)[abbrev_len + 4]);
+                                       FTREPR_DFILTER,
+                                       &(*filter)[abbrev_len + 4]);
                        }
                        break;
        }
@@ -5774,13 +6184,12 @@ proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
        return filter;
 }
 
-
 /* This function is common code for both proto_tree_add_bitmask() and
- *  proto_tree_add_bitmask_text() functions.
+ *     proto_tree_add_bitmask_text() functions.
  */
 static gboolean
-proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len, gint ett,
-       const int **fields, gboolean little_endian, int flags, gboolean first)
+proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset, const int len, const gint ett,
+       const int **fields, const gboolean little_endian, const int flags, gboolean first)
 {
        guint32 value = 0, tmpval;
        proto_tree *tree = NULL;
@@ -5842,10 +6251,10 @@ proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len
                        else if (hf->strings) {
                                if (hf->display & BASE_RANGE_STRING) {
                                        proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
-                                                              hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
+                                                                  hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
                                } else {
                                        proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
-                                                              hf->name, val_to_str(tmpval, cVALS(hf->strings), "Unknown"));
+                                                                  hf->name, val_to_str(tmpval, cVALS(hf->strings), "Unknown"));
                                }
                                first = FALSE;
                        }
@@ -5911,12 +6320,12 @@ proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len
  * This array is terminated by a NULL entry.
  *
  * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
- * FT_integer fields that have a value_string attached will have the 
+ * FT_integer fields that have a value_string attached will have the
  * matched string displayed on the expansion line.
  */
 proto_item *
-proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, int hf_hdr,
-               gint ett, const int **fields, gboolean little_endian)
+proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset, const int hf_hdr,
+               const gint ett, const int **fields, const gboolean little_endian)
 {
        proto_item *item = NULL;
        header_field_info *hf;
@@ -5937,9 +6346,9 @@ proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, int
 
 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
 proto_item *
-proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, guint len,
+proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset, const guint len,
                const char *name, const char *fallback,
-               gint ett, const int **fields, gboolean little_endian, int flags)
+               const gint ett, const int **fields, const gboolean little_endian, const int flags)
 {
        proto_item *item = NULL;
 
@@ -5956,33 +6365,35 @@ proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb, guint offset
 }
 
 proto_item *
-proto_tree_add_bits_item(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
+proto_tree_add_bits_item(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const gint bit_offset, const gint no_of_bits, const gboolean little_endian)
 {
-       return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
+       header_field_info       *hfinfo;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hfinfo);
 
+       return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
 }
+
 /*
  * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
- * set vill be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
+ * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
  * Offset should be given in bits from the start of the tvb.
  */
 
 proto_item *
-proto_tree_add_bits_ret_val(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, guint64 *return_value, gboolean little_endian)
+proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const gint bit_offset, const gint no_of_bits, guint64 *return_value, const gboolean little_endian)
 {
        const char *format = NULL;
        gint    offset;
        guint   length;
        guint8  tot_no_bits;
-       guint8  remaining_bits;
-       guint64 mask = 0,tmp;
        char *str;
        header_field_info *hf_field;
        guint64 value = 0;
-       int bit;
-       int i;
+       const true_false_string *tfstring;
 
-       hf_field = proto_registrar_get_nth(hf_index);
+       /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
+       PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
 
        if(hf_field -> bitmask != 0) {
                REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
@@ -6000,8 +6411,8 @@ proto_tree_add_bits_ret_val(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint
         */
        tot_no_bits = ((bit_offset&0x7)+no_of_bits);
        length = tot_no_bits>>3;
-       remaining_bits = tot_no_bits % 8;
-       if ((remaining_bits)!=0)
+       /* If we are using part of the next octet, increase length by 1 */
+       if (tot_no_bits & 0x07)
                length++;
 
        if (no_of_bits < 9){
@@ -6021,43 +6432,10 @@ proto_tree_add_bits_ret_val(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint
                *return_value=value;
        }
 
-       mask = 1;
-       mask = mask << (no_of_bits-1);
-
-       /* prepare the string */
-       str=ep_alloc(256);
-       str[0]='\0';
-       for(bit=0;bit<((int)(bit_offset&0x07));bit++){
-               if(bit&&(!(bit%4))){
-                       strcat(str, " ");
-               }
-               strcat(str,".");
-       }
-
-       /* read the bits for the int */
-       for(i=0;i<no_of_bits;i++){
-               if(bit&&(!(bit%4))){
-                       strcat(str, " ");
-               }
-               if(bit&&(!(bit%8))){
-                       strcat(str, " ");
-               }
-               bit++;
-               tmp = value & mask;
-               if(tmp != 0){
-                       strcat(str, "1");
-               } else {
-                       strcat(str, "0");
-               }
-               mask = mask>>1;
-       }
+       /* Coast clear. Try and fake it */
+       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
 
-       for(;bit%8;bit++){
-               if(bit&&(!(bit%4))){
-                       strcat(str, " ");
-               }
-               strcat(str,".");
-       }
+       str = decode_bits_in_field(bit_offset, no_of_bits, value);
 
        strcat(str," = ");
        strcat(str,hf_field->name);
@@ -6065,19 +6443,13 @@ proto_tree_add_bits_ret_val(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint
        switch(hf_field->type){
        case FT_BOOLEAN:
                /* Boolean field */
-               if (hf_field->strings) {
-                       const true_false_string *tfstring =
-                               (const true_false_string *) hf_field->strings;
-                       return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
-                               "%s: %s",
-                               str,
-                               (guint32)value ? tfstring->true_string : tfstring->false_string);
-               }else{
-                       return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
-                               "%s: %u",
-                               str,
-                               (guint32)value);
-               }
+               tfstring = (const true_false_string *) &tfs_true_false;
+               if (hf_field->strings)
+                       tfstring = (const true_false_string *) hf_field->strings;
+               return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
+                       "%s: %s",
+                       str,
+                       (guint32)value ? tfstring->true_string : tfstring->false_string);
                break;
 
        case FT_UINT8:
@@ -6124,6 +6496,198 @@ proto_tree_add_bits_ret_val(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint
        }
 }
 
+proto_item *
+proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const gint bit_offset, const gint no_of_bits, void *value_ptr, gchar *value_str)
+{
+       gint    offset;
+       guint   length;
+       guint8  tot_no_bits;
+       char *str;
+       header_field_info *hf_field;
+       guint64 value = 0;
+
+       /* We do not have to return a value, try to fake it as soon as possible */
+       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
+
+       if(hf_field -> bitmask != 0) {
+               REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
+                                                                                         hf_field->abbrev, hf_field->name));
+       }
+
+       DISSECTOR_ASSERT(bit_offset >= 0);
+       DISSECTOR_ASSERT(no_of_bits > 0);
+
+       /* Byte align offset */
+       offset = bit_offset>>3;
+
+       /*
+        * Calculate the number of octets used to hold the bits
+        */
+       tot_no_bits = ((bit_offset&0x7)+no_of_bits);
+       length = tot_no_bits>>3;
+       /* If we are using part of the next octet, increase length by 1 */
+       if (tot_no_bits & 0x07)
+               length++;
+
+       if (no_of_bits < 9){
+               value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
+       }else if(no_of_bits < 17){
+               value = tvb_get_bits16(tvb, bit_offset, no_of_bits, FALSE);
+       }else if(no_of_bits < 33){
+               value = tvb_get_bits32(tvb, bit_offset, no_of_bits, FALSE);
+       }else if(no_of_bits < 65){
+               value = tvb_get_bits64(tvb, bit_offset, no_of_bits, FALSE);
+       }else{
+               DISSECTOR_ASSERT_NOT_REACHED();
+               return NULL;
+       }
+
+       str = decode_bits_in_field(bit_offset, no_of_bits, value);
+
+       strcat(str," = ");
+       strcat(str,hf_field->name);
+
+       /*
+        * This function does not receive an actual value but a dimensionless pointer to that value.
+        * For this reason, the type of the header field is examined in order to determine
+        * what kind of value we should read from this address.
+        * The caller of this function must make sure that for the specific header field type the address of
+        * a compatible value is provided.
+        */
+       switch(hf_field->type){
+       case FT_BOOLEAN:
+               return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
+                       "%s: %s", str, value_str);
+               break;
+
+       case FT_UINT8:
+       case FT_UINT16:
+       case FT_UINT24:
+       case FT_UINT32:
+               return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
+                               "%s: %s", str, value_str);
+               break;
+
+       case FT_UINT64:
+               return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, *(guint64 *)value_ptr,
+                               "%s: %s", str, value_str);
+               break;
+
+       case FT_INT8:
+       case FT_INT16:
+       case FT_INT24:
+       case FT_INT32:
+               return proto_tree_add_int_format(tree, hf_index, tvb, offset, length, *(gint32 *)value_ptr,
+                               "%s: %s", str, value_str);
+               break;
+
+       case FT_FLOAT:
+               return proto_tree_add_float_format(tree, hf_index, tvb, offset, length, *(float *)value_ptr,
+                               "%s: %s", str, value_str);
+               break;
+
+       default:
+               DISSECTOR_ASSERT_NOT_REACHED();
+               return NULL;
+               break;
+       }
+}
+
+#define CREATE_VALUE_STRING(dst,format,ap) \
+       va_start(ap,format); \
+       dst = ep_strdup_vprintf(format, ap); \
+       va_end(ap);
+
+proto_item *
+proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const gint bit_offset, const gint no_of_bits,
+       guint32 value, const char *format, ...)
+{
+       va_list ap;
+       gchar* dst;
+       header_field_info *hf_field;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
+
+       switch(hf_field->type){
+       case FT_UINT8:
+       case FT_UINT16:
+       case FT_UINT24:
+       case FT_UINT32:
+               break;
+
+       default:
+               DISSECTOR_ASSERT_NOT_REACHED();
+               return NULL;
+               break;
+       }
+
+       CREATE_VALUE_STRING(dst,format,ap);
+
+       return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
+}
+
+proto_item *
+proto_tree_add_float_bits_format_value(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const gint bit_offset, const gint no_of_bits,
+       float value, const char *format, ...)
+{
+       va_list ap;
+       gchar* dst;
+       header_field_info *hf_field;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
+
+       DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
+       
+       CREATE_VALUE_STRING(dst,format,ap);
+
+       return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
+}
+
+proto_item *
+proto_tree_add_int_bits_format_value(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const gint bit_offset, const gint no_of_bits,
+       gint32 value, const char *format, ...)
+{
+       va_list ap;
+       gchar* dst;
+       header_field_info *hf_field;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
+
+       switch(hf_field->type){
+       case FT_INT8:
+       case FT_INT16:
+       case FT_INT24:
+       case FT_INT32:
+               break;
+
+       default:
+               DISSECTOR_ASSERT_NOT_REACHED();
+               return NULL;
+               break;
+       }
+
+       CREATE_VALUE_STRING(dst,format,ap);
+
+       return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
+}
+
+proto_item *
+proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const gint bit_offset, const gint no_of_bits,
+       guint32 value, const char *format, ...)
+{
+       va_list ap;
+       gchar* dst;
+       header_field_info *hf_field;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
+
+       DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
+       
+       CREATE_VALUE_STRING(dst,format,ap);
+
+       return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
+}
+
 guchar
 proto_check_field_name(const gchar *field_name)
 {