From Jiri Engelthaler via
[metze/wireshark/wip.git] / epan / proto.c
index 9d176b56550614d254fa761af03566ae21d7c5b2..fc1b0f7afcb102cc12d9ab1070208adb966b3294 100644 (file)
@@ -29,6 +29,7 @@
 #include <ctype.h>
 #include <glib.h>
 #include <float.h>
+#include <wsutil/swar.h>
 
 #include "packet.h"
 #include "ptvcursor.h"
@@ -71,17 +72,6 @@ struct ptvcursor {
        gint         offset;
 };
 
-/* Candidates for assembler */
-static int
-wrs_count_bitshift(const guint32 bitmask)
-{
-       int bitshift = 0;
-
-       while ((bitmask & (1 << bitshift)) == 0)
-               bitshift++;
-       return bitshift;
-}
-
 #define cVALS(x) (const value_string*)(x)
 
 /** See inlined comments.
@@ -105,7 +95,7 @@ wrs_count_bitshift(const guint32 bitmask)
                return NULL;                                            \
        PTREE_DATA(tree)->count++;                                      \
        if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {                 \
-               if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL) \
+               if (getenv("WIRESHARK_ABORT_ON_TOO_MANY_ITEMS") != NULL) \
                        g_error("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS); \
                /* Let the exception handler add items to the tree */   \
                PTREE_DATA(tree)->count = 0;                            \
@@ -125,12 +115,10 @@ wrs_count_bitshift(const guint32 bitmask)
        }
 
 /** See inlined comments.
- @param tree the tree to append this item to
  @param pi the created protocol item we're about to return */
-#define TRY_TO_FAKE_THIS_REPR(tree, pi) \
+#define TRY_TO_FAKE_THIS_REPR(pi) \
        g_assert(pi);                   \
-       g_assert(tree);                 \
-       if (!(PTREE_DATA(tree)->visible)) { \
+       if (!(PTREE_DATA(pi)->visible)) { \
                /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
                 * items string representation */ \
                return pi; \
@@ -139,24 +127,24 @@ wrs_count_bitshift(const guint32 bitmask)
 static const char *hf_try_val_to_str(guint32 value, const header_field_info *hfinfo);
 
 static void fill_label_boolean(field_info *fi, gchar *label_str);
-static void fill_label_uint64(field_info *fi, gchar *label_str);
-static void fill_label_bitfield(field_info *fi, gchar *label_str);
+static void fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed);
 static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
-static void fill_label_int64(field_info *fi, gchar *label_str);
+static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
 
+static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value);
 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
+static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
 
 static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
 static const char* hfinfo_int64_format(const header_field_info *hfinfo);
-static const char* hfinfo_numeric_value_format(const header_field_info *hfinfo);
 
 static proto_item *
 proto_tree_add_node(proto_tree *tree, field_info *fi);
 
 static void
-get_hfi_and_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
-                  gint *item_length);
+get_hfi_length(header_field_info *hfinfo, 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,
@@ -168,7 +156,7 @@ alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
 
 static proto_item *
 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
-                 gint start, gint *length, field_info **pfi);
+                 gint start, gint *length);
 
 static void
 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
@@ -192,6 +180,10 @@ proto_tree_set_ax25(field_info *fi, const guint8* value);
 static void
 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
 static void
+proto_tree_set_vines(field_info *fi, const guint8* value);
+static void
+proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
+static void
 proto_tree_set_ether(field_info *fi, const guint8* value);
 static void
 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
@@ -238,7 +230,7 @@ proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
 
 /* special-case header field used within proto.c */
-static header_field_info hfi_text_only = 
+static header_field_info hfi_text_only =
        { "Text item",  "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
 int hf_text_only = -1;
 
@@ -248,8 +240,8 @@ struct _protocol {
        const char *short_name;   /* short description */
        const char *filter_name;  /* name of this protocol in filters */
        int         proto_id;     /* field ID for this protocol */
-       GList      *fields;       /* fields for this protocol */
-       GList      *last_field;   /* pointer to end of list of fields */
+       GSList     *fields;       /* fields for this protocol */
+       GSList     *last_field;   /* pointer to end of list of fields */
        gboolean    is_enabled;   /* TRUE if protocol is enabled */
        gboolean    can_toggle;   /* TRUE if is_enabled can be changed */
        gboolean    is_private;   /* TRUE is protocol is private */
@@ -293,7 +285,8 @@ typedef struct _gpa_hfinfo_t {
        guint32             allocated_len;
        header_field_info **hfi;
 } gpa_hfinfo_t;
-gpa_hfinfo_t gpa_hfinfo;
+
+static gpa_hfinfo_t gpa_hfinfo;
 
 /* Balanced tree of abbreviations and IDs */
 static GTree *gpa_name_tree = NULL;
@@ -304,10 +297,10 @@ static void save_same_name_hfinfo(gpointer data)
        same_name_hfinfo = (header_field_info*)data;
 }
 
-/* Points to the first element of an array of Booleans, indexed by
+/* Points to the first element of an array of bits, indexed by
    a subtree item type; that array element is TRUE if subtrees of
    an item of that type are to be expanded. */
-gboolean       *tree_is_expanded;
+static guint32 *tree_is_expanded;
 
 /* Number of elements in that array. */
 int            num_tree_types;
@@ -402,7 +395,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_new0(gboolean, num_tree_types);
+       tree_is_expanded = g_new0(guint32, (num_tree_types/32)+1);
 }
 
 void
@@ -421,7 +414,7 @@ proto_cleanup(void)
                DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
 
                g_slice_free(header_field_info, hfinfo);
-               g_list_free(protocol->fields);
+               g_slist_free(protocol->fields);
                protocols = g_list_remove(protocols, protocol);
                g_free(protocol);
        }
@@ -651,7 +644,7 @@ proto_field_is_referenced(proto_tree *tree, int proto_id)
 }
 
 
-/* Finds a record in the hf_info_records array by id. */
+/* Finds a record in the hfinfo array by id. */
 header_field_info *
 proto_registrar_get_nth(guint hfindex)
 {
@@ -734,7 +727,7 @@ proto_initialize_all_prefixes(void) {
        g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
 }
 
-/* Finds a record in the hf_info_records array by name.
+/* Finds a record in the hfinfo array by name.
  * If it fails to find it in the already registered fields,
  * it tries to find and call an initializer in the prefixes
  * table and if so it looks again.
@@ -961,7 +954,7 @@ ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
        pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
                                      ptvcursor_current_offset(ptvc), length);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
+       TRY_TO_FAKE_THIS_REPR(pi);
 
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
@@ -976,7 +969,10 @@ proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint lengt
 {
        proto_item *pi;
 
-       pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length, NULL);
+       if (tree == NULL)
+               return NULL;
+
+       pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
 
        return pi;
 }
@@ -994,7 +990,7 @@ proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
 
        pi = proto_tree_add_text_node(tree, tvb, start, length);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
+       TRY_TO_FAKE_THIS_REPR(pi);
 
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
@@ -1015,7 +1011,7 @@ proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
 
        pi = proto_tree_add_text_node(tree, tvb, start, length);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
+       TRY_TO_FAKE_THIS_REPR(pi);
 
        proto_tree_set_representation(pi, format, ap);
 
@@ -1049,27 +1045,23 @@ proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
 /* We could probably get away with changing is_error to a minimum length value. */
 static void
 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
-       tree_data_t *tree_data = PTREE_DATA(tree);
-       field_info *fi_save = tree_data->fi_tmp;
+       if (tree) {
+               tree_data_t *tree_data = PTREE_DATA(tree);
+               field_info *fi_save = tree_data->fi_tmp;
 
-       /* Keep the current item from getting freed by proto_tree_new_item. */
-       tree_data->fi_tmp = NULL;
+               /* Keep the current item from getting freed by proto_tree_new_item. */
+               tree_data->fi_tmp = NULL;
 
-       expert_add_info_format(NULL, tree, PI_MALFORMED, is_error ? PI_ERROR : PI_WARN, "Trying to fetch %s with length %d", descr, length);
+               expert_add_info_format(NULL, tree, PI_MALFORMED, is_error ? PI_ERROR : PI_WARN, "Trying to fetch %s with length %d", descr, length);
 
-       tree_data->fi_tmp = fi_save;
+               tree_data->fi_tmp = fi_save;
+       }
 
        if (is_error) {
                THROW(ReportedBoundsError);
        }
 }
 
-/*
- * NOTE: to support code written when proto_tree_add_item() took a
- * gboolean as its last argument, with FALSE meaning "big-endian"
- * and TRUE meaning "little-endian", we treat any non-zero value of
- * "encoding" as meaning "little-endian".
- */
 static guint32
 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
 {
@@ -1083,18 +1075,18 @@ get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const
                break;
 
        case 2:
-               value = encoding ? tvb_get_letohs(tvb, offset)
-                                : tvb_get_ntohs(tvb, offset);
+               value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
+                                                      : tvb_get_ntohs(tvb, offset);
                break;
 
        case 3:
-               value = encoding ? tvb_get_letoh24(tvb, offset)
-                                : tvb_get_ntoh24(tvb, offset);
+               value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
+                                                      : tvb_get_ntoh24(tvb, offset);
                break;
 
        case 4:
-               value = encoding ? tvb_get_letohl(tvb, offset)
-                                : tvb_get_ntohl(tvb, offset);
+               value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
+                                                      : tvb_get_ntohl(tvb, offset);
                break;
 
        default:
@@ -1103,8 +1095,8 @@ get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const
                        value = 0;
                } else {
                        length_error = FALSE;
-                       value = encoding ? tvb_get_letohl(tvb, offset)
-                                        : tvb_get_ntohl(tvb, offset);
+                       value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
+                                                              : tvb_get_ntohl(tvb, offset);
                }
                report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
                break;
@@ -1164,33 +1156,30 @@ get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const g
        return value;
 }
 
-static GPtrArray *
-proto_lookup_or_create_interesting_hfids(proto_tree *tree,
-                                        header_field_info *hfinfo)
+static void
+tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
 {
-       GPtrArray *ptrs = NULL;
-
-       DISSECTOR_ASSERT(tree);
-       DISSECTOR_ASSERT(hfinfo);
+       const header_field_info *hfinfo = fi->hfinfo;
 
        if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
-               if (PTREE_DATA(tree)->interesting_hfids == NULL) {
+               GPtrArray *ptrs = NULL;
+
+               if (tree_data->interesting_hfids == NULL) {
                        /* Initialize the hash because we now know that it is needed */
-                       PTREE_DATA(tree)->interesting_hfids =
+                       tree_data->interesting_hfids =
                                g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
-               }
-
-               ptrs = (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
+               } else
+                       ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->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,
+                       g_hash_table_insert(tree_data->interesting_hfids,
                                            GINT_TO_POINTER(hfinfo->id), ptrs);
                }
-       }
 
-       return ptrs;
+               g_ptr_array_add(ptrs, fi);
+       }
 }
 
 /* Add an item to a proto_tree, using the text label registered to that item;
@@ -1208,7 +1197,6 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
        const char *string;
        nstime_t    time_stamp;
        guint32     tmpsecs;
-       GPtrArray  *ptrs;
        gboolean    length_error;
 
        /* there is a possibility here that we might raise an exception
@@ -1342,7 +1330,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
                                report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
                        }
                        proto_tree_set_ipxnet(new_fi,
-                               get_uint_value(tree, tvb, start, FT_IPXNET_LEN, FALSE));
+                               get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
                        break;
 
                case FT_IPv6:
@@ -1356,12 +1344,19 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
                case FT_AX25:
                        if (length != 7) {
                                length_error = length < 7 ? TRUE : FALSE;
-                               expert_add_info_format(NULL, tree, PI_MALFORMED, PI_ERROR, "Trying to fetch an AX.25 address with length %d", length);
-                               THROW(ReportedBoundsError);
+                               report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
                        }
                        proto_tree_set_ax25_tvb(new_fi, tvb, start);
                        break;
 
+               case FT_VINES:
+                       if (length != VINES_ADDR_LEN) {
+                               length_error = length < VINES_ADDR_LEN ? TRUE : FALSE;
+                               report_type_length_mismatch(tree, "a Vines address", length, length_error);
+                       }
+                       proto_tree_set_vines_tvb(new_fi, tvb, start);
+                       break;
+
                case FT_ETHER:
                        if (length != FT_ETHER_LEN) {
                                length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
@@ -1734,12 +1729,6 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
         */
        tree_data->fi_tmp = NULL;
 
-       /* If the proto_tree wants to keep a record of this finfo
-        * for quick lookup, then record it. */
-       ptrs = proto_lookup_or_create_interesting_hfids(tree, new_fi->hfinfo);
-       if (ptrs)
-               g_ptr_array_add(ptrs, new_fi);
-
        return pi;
 }
 
@@ -1760,7 +1749,7 @@ ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
 
        offset = ptvc->offset;
        PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
-       get_hfi_and_length(hfinfo, ptvc->tvb, offset, &length, &item_length);
+       get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length);
        ptvc->offset += length;
        if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
                /*
@@ -1786,7 +1775,7 @@ ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
  */
 static void
 test_length(header_field_info *hfinfo, proto_tree *tree, tvbuff_t *tvb,
-           gint start, gint length, gboolean little_endian)
+           gint start, gint length, const guint encoding)
 {
        gint size = length;
 
@@ -1796,7 +1785,7 @@ test_length(header_field_info *hfinfo, proto_tree *tree, tvbuff_t *tvb,
        if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
                guint32 n;
 
-               n = get_uint_value(tree, tvb, start, length, little_endian);
+               n = get_uint_value(tree, tvb, start, length, encoding);
                if (n > size + n) {
                        /* If n > size + n then we have an integer overflow, so
                         * set size to -1, which will force the
@@ -1808,25 +1797,32 @@ test_length(header_field_info *hfinfo, proto_tree *tree, tvbuff_t *tvb,
                else {
                        size += n;
                }
+       } else if (hfinfo->type == FT_STRINGZ) {
+               /* If we're fetching until the end of the TVB, only validate
+                * that the offset is within range.
+                */
+               if (length == -1)
+                       size = 0;
        }
+
        tvb_ensure_bytes_exist(tvb, start, size);
 }
 
 /* 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, const int hfindex, tvbuff_t *tvb,
+proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
                    const gint start, gint length, const guint encoding)
 {
        field_info        *new_fi;
-       header_field_info *hfinfo;
        gint              item_length;
 
-       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
-       get_hfi_and_length(hfinfo, tvb, start, &length, &item_length);
+       DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
+
+       get_hfi_length(hfinfo, tvb, start, &length, &item_length);
        test_length(hfinfo, tree, tvb, start, item_length, encoding);
 
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
 
        new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
 
@@ -1836,6 +1832,13 @@ proto_tree_add_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
        return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
 }
 
+proto_item *
+proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+                   const gint start, gint length, const guint encoding)
+{
+        return proto_tree_add_item_new(tree, proto_registrar_get_nth(hfindex), tvb, start, length, encoding);
+}
+
 /* Add a FT_NONE to a proto_tree */
 proto_item *
 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
@@ -1850,9 +1853,9 @@ proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
 
        DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, NULL);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
+       TRY_TO_FAKE_THIS_REPR(pi);
 
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
@@ -1898,18 +1901,17 @@ proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 {
        proto_item        *pi;
        va_list            ap;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
 
-       proto_tree_set_protocol_tvb(new_fi, (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
+       proto_tree_set_protocol_tvb(PNODE_FINFO(pi), (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
+       TRY_TO_FAKE_THIS_REPR(pi);
 
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
@@ -1925,15 +1927,14 @@ proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                     gint length, const guint8 *start_ptr)
 {
        proto_item        *pi;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_bytes(new_fi, start_ptr, length);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
 
        return pi;
 }
@@ -1957,8 +1958,6 @@ proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
                pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
                                          tvb_get_ptr(tvb, start, length));
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
        va_start(ap, format);
        proto_tree_set_representation_value(pi, format, ap);
        va_end(ap);
@@ -1984,7 +1983,7 @@ proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
                pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
                                          tvb_get_ptr(tvb, start, length));
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
+       TRY_TO_FAKE_THIS_REPR(pi);
 
        va_start(ap, format);
        proto_tree_set_representation(pi, format, ap);
@@ -2018,7 +2017,6 @@ proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                    gint length, nstime_t *value_ptr)
 {
        proto_item        *pi;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
@@ -2026,8 +2024,8 @@ proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
        DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
                         hfinfo->type == FT_RELATIVE_TIME);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_time(new_fi, value_ptr);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
 
        return pi;
 }
@@ -2039,17 +2037,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2061,17 +2055,15 @@ proto_tree_add_time_format(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 != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2091,15 +2083,14 @@ proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                      gint length, guint32 value)
 {
        proto_item        *pi;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_ipxnet(new_fi, value);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
 
        return pi;
 }
@@ -2111,17 +2102,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2133,17 +2120,15 @@ proto_tree_add_ipxnet_format(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 != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2161,15 +2146,14 @@ proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                    gint length, guint32 value)
 {
        proto_item        *pi;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_ipv4(new_fi, value);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_ipv4(PNODE_FINFO(pi), value);
 
        return pi;
 }
@@ -2181,17 +2165,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2203,17 +2183,15 @@ proto_tree_add_ipv4_format(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 != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2231,15 +2209,14 @@ proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                    gint length, const guint8* value_ptr)
 {
        proto_item        *pi;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_ipv6(new_fi, value_ptr);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_ipv6(PNODE_FINFO(pi), value_ptr);
 
        return pi;
 }
@@ -2252,17 +2229,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2274,17 +2247,15 @@ proto_tree_add_ipv6_format(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 != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2309,15 +2280,14 @@ proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                    gint length, const e_guid_t *value_ptr)
 {
        proto_item        *pi;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_guid(new_fi, value_ptr);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
 
        return pi;
 }
@@ -2330,17 +2300,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2352,17 +2318,15 @@ proto_tree_add_guid_format(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 != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2391,15 +2355,14 @@ proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                   gint length, const guint8* value_ptr)
 {
        proto_item        *pi;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_OID);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_oid(new_fi, value_ptr, length);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
 
        return pi;
 }
@@ -2412,17 +2375,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2434,17 +2393,15 @@ proto_tree_add_oid_format(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 != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2528,16 +2485,15 @@ proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                      gint length, const char* value)
 {
        proto_item        *pi;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
        DISSECTOR_ASSERT(length >= 0);
-       proto_tree_set_string(new_fi, value);
+       proto_tree_set_string(PNODE_FINFO(pi), value);
 
        return pi;
 }
@@ -2558,17 +2514,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2580,17 +2532,15 @@ proto_tree_add_string_format(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 != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2616,7 +2566,7 @@ proto_item_append_string(proto_item *pi, const char *str)
 {
        field_info        *fi;
        header_field_info *hfinfo;
-       gchar             *old_str, *new_str;
+       const gchar       *old_str, *new_str;
 
        if (!pi)
                return;
@@ -2633,8 +2583,11 @@ proto_item_append_string(proto_item *pi, const char *str)
        }
        DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
        old_str = (guint8 *)fvalue_get(&fi->value);
-       new_str = ep_strdup_printf("%s%s", old_str, str);
-       fvalue_set(&fi->value, new_str, FALSE);
+       if (old_str && old_str[0])
+               new_str = ep_strconcat(old_str, str, NULL);
+       else
+               new_str = str;
+       fvalue_set(&fi->value, (gpointer) new_str, FALSE);
 }
 
 /* Set the FT_STRING value */
@@ -2668,19 +2621,14 @@ proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
                const guint8* value)
 {
        proto_item              *pi;
-       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_AX25);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_ax25(new_fi, value);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_ax25(PNODE_FINFO(pi), value);
 
        return pi;
 }
@@ -2698,6 +2646,18 @@ proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
        proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
 }
 
+/* Set the FT_VINES value */
+static void
+proto_tree_set_vines(field_info *fi, const guint8* value)
+{
+       fvalue_set(&fi->value, (gpointer) value, FALSE);
+}
+
+static void
+proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
+{
+       proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
+}
 
 /* Add a FT_ETHER to a proto_tree */
 proto_item *
@@ -2705,15 +2665,14 @@ proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                     gint length, const guint8* value)
 {
        proto_item        *pi;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_ether(new_fi, value);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_ether(PNODE_FINFO(pi), value);
 
        return pi;
 }
@@ -2725,17 +2684,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2747,17 +2702,15 @@ proto_tree_add_ether_format(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 != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2781,15 +2734,14 @@ proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                       gint length, guint32 value)
 {
        proto_item        *pi;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_boolean(new_fi, value);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_boolean(PNODE_FINFO(pi), value);
 
        return pi;
 }
@@ -2801,17 +2753,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2823,17 +2771,15 @@ proto_tree_add_boolean_format(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_boolean(tree, hfindex, tvb, start, length, value);
+       if (pi != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2851,15 +2797,14 @@ proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                     gint length, float value)
 {
        proto_item        *pi;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_float(new_fi, value);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_float(PNODE_FINFO(pi), value);
 
        return pi;
 }
@@ -2871,17 +2816,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2893,17 +2834,15 @@ proto_tree_add_float_format(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 != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2921,15 +2860,14 @@ proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                      gint length, double value)
 {
        proto_item        *pi;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_double(new_fi, value);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_double(PNODE_FINFO(pi), value);
 
        return pi;
 }
@@ -2941,17 +2879,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2963,17 +2897,15 @@ proto_tree_add_double_format(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 != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -2991,7 +2923,6 @@ proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                    gint length, guint32 value)
 {
        proto_item        *pi = NULL;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
@@ -3002,9 +2933,8 @@ proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                case FT_UINT24:
                case FT_UINT32:
                case FT_FRAMENUM:
-                       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length,
-                                       &new_fi);
-                       proto_tree_set_uint(new_fi, value);
+                       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+                       proto_tree_set_uint(PNODE_FINFO(pi), value);
                        break;
 
                default:
@@ -3021,17 +2951,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -3043,17 +2969,15 @@ proto_tree_add_uint_format(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 != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -3073,9 +2997,7 @@ proto_tree_set_uint(field_info *fi, guint32 value)
                integer &= hfinfo->bitmask;
 
                /* Shift bits */
-               if (hfinfo->bitshift > 0) {
-                       integer >>= hfinfo->bitshift;
-               }
+               integer >>= hfinfo_bitshift(hfinfo);
        }
 
        fvalue_set_uinteger(&fi->value, integer);
@@ -3086,16 +3008,15 @@ proto_item *
 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                      gint length, guint64 value)
 {
-       proto_item        *pi = NULL;
-       field_info        *new_fi;
+       proto_item        *pi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_uint64(new_fi, value);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_uint64(PNODE_FINFO(pi), value);
 
        return pi;
 }
@@ -3107,17 +3028,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -3129,17 +3046,15 @@ proto_tree_add_uint64_format(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 != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -3150,7 +3065,6 @@ proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                   gint length, gint32 value)
 {
        proto_item        *pi = NULL;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
@@ -3160,9 +3074,8 @@ proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                case FT_INT16:
                case FT_INT24:
                case FT_INT32:
-                       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length,
-                                       &new_fi);
-                       proto_tree_set_int(new_fi, value);
+                       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+                       proto_tree_set_int(PNODE_FINFO(pi), value);
                        break;
 
                default:
@@ -3177,19 +3090,15 @@ proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
                                gint start, gint length, gint32 value,
                                const char *format, ...)
 {
-       proto_item        *pi = NULL;
-       va_list            ap;
-       header_field_info *hfinfo;
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
+       proto_item  *pi;
+       va_list      ap;
 
        pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -3199,19 +3108,17 @@ proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
                          gint start, gint length, gint32 value,
                          const char *format, ...)
 {
-       proto_item        *pi = NULL;
-       va_list            ap;
-       header_field_info *hfinfo;
-
-       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
+       proto_item *pi;
+       va_list     ap;
 
        pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
+       if (pi != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -3222,6 +3129,7 @@ proto_tree_set_int(field_info *fi, gint32 value)
 {
        header_field_info *hfinfo;
        guint32            integer;
+       gint               no_of_bits;
 
        hfinfo = fi->hfinfo;
        integer = (guint32) value;
@@ -3231,9 +3139,11 @@ proto_tree_set_int(field_info *fi, gint32 value)
                integer &= hfinfo->bitmask;
 
                /* Shift bits */
-               if (hfinfo->bitshift > 0) {
-                       integer >>= hfinfo->bitshift;
-               }
+               integer >>= hfinfo_bitshift(hfinfo);
+
+               no_of_bits = swar_count_bits(hfinfo->bitmask);
+               if (integer & (1 << (no_of_bits-1)))
+                       integer |= (-1 << no_of_bits);
        }
 
        fvalue_set_sinteger(&fi->value, integer);
@@ -3244,16 +3154,15 @@ proto_item *
 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                     gint length, gint64 value)
 {
-       proto_item        *pi = NULL;
-       field_info        *new_fi;
+       proto_item        *pi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_uint64(new_fi, (guint64)value);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_uint64(PNODE_FINFO(pi), (guint64)value);
 
        return pi;
 }
@@ -3265,17 +3174,13 @@ 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);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -3287,17 +3192,15 @@ proto_tree_add_int64_format(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 != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -3307,15 +3210,14 @@ proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
                     gint length, const guint64 value)
 {
        proto_item        *pi;
-       field_info        *new_fi;
        header_field_info *hfinfo;
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
        DISSECTOR_ASSERT(hfinfo->type == FT_EUI64);
 
-       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
-       proto_tree_set_eui64(new_fi, value);
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+       proto_tree_set_eui64(PNODE_FINFO(pi), value);
 
        return pi;
 }
@@ -3327,17 +3229,13 @@ proto_tree_add_eui64_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_eui64(tree, hfindex, tvb, start, length, value);
-
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation_value(pi, format, ap);
-       va_end(ap);
+       if (pi != tree) {
+               va_start(ap, format);
+               proto_tree_set_representation_value(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -3349,17 +3247,15 @@ proto_tree_add_eui64_format(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_eui64(tree, hfindex, tvb, start, length, value);
+       if (pi != tree) {
+               TRY_TO_FAKE_THIS_REPR(pi);
 
-       TRY_TO_FAKE_THIS_REPR(tree, pi);
-
-       va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
-       va_end(ap);
+               va_start(ap, format);
+               proto_tree_set_representation(pi, format, ap);
+               va_end(ap);
+       }
 
        return pi;
 }
@@ -3405,9 +3301,6 @@ proto_tree_add_node(proto_tree *tree, field_info *fi)
                /* XXX - is it safe to continue here? */
        }
 
-       DISSECTOR_ASSERT(tfi == NULL ||
-               (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
-
        PROTO_NODE_NEW(pnode);
        pnode->parent = tnode;
        PNODE_FINFO(pnode) = fi;
@@ -3421,47 +3314,33 @@ proto_tree_add_node(proto_tree *tree, field_info *fi)
                tnode->first_child = pnode;
        tnode->last_child = pnode;
 
+       tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
+
        return (proto_item *)pnode;
 }
 
 
 /* Generic way to allocate field_info and add to proto_tree.
- * Sets *pfi to address of newly-allocated field_info struct, if pfi is
- * non-NULL. */
+ * Sets *pfi to address of newly-allocated field_info struct */
 static proto_item *
 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
-                 gint *length, field_info **pfi)
+                 gint *length)
 {
        proto_item *pi;
        field_info *fi;
-       GPtrArray  *ptrs;
-
-       if (!tree)
-               return NULL;
 
        fi = alloc_field_info(tree, hfinfo, tvb, start, length);
        pi = proto_tree_add_node(tree, fi);
 
-       /* If the proto_tree wants to keep a record of this finfo
-        * for quick lookup, then record it. */
-       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) {
-               *pfi = fi;
-       }
-
        return pi;
 }
 
 
 static void
-get_hfi_and_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
+get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
                   gint *item_length)
 {
-       gint               length_remaining;
+       gint length_remaining;
 
        /*
         * We only allow a null tvbuff if the item has a zero length,
@@ -3620,10 +3499,21 @@ alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, con
 {
        gint               item_length;
 
-       get_hfi_and_length(hfinfo, tvb, start, length, &item_length);
+       get_hfi_length(hfinfo, tvb, start, length, &item_length);
        return new_field_info(tree, hfinfo, tvb, start, item_length);
 }
 
+static void
+label_mark_truncated_start(char *label_str)
+{
+       static const char trunc_str[] = "[truncated] ";
+       const size_t trunc_len = sizeof(trunc_str)-1;
+
+       memmove(label_str + trunc_len, label_str, ITEM_LABEL_LENGTH - trunc_len);
+       memcpy(label_str, trunc_str, trunc_len);
+       label_str[ITEM_LABEL_LENGTH-1] = '\0';
+}
+
 /* If the protocol tree is to be visible, set the representation of a
    proto_tree entry with the name of the field for the item and with
    the value formatted with the supplied printf-style format and
@@ -3631,34 +3521,34 @@ alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, con
 static void
 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
 {
-       int                ret; /*tmp return value */
-       field_info        *fi = PITEM_FINFO(pi);
-       header_field_info *hf;
+       g_assert(pi);
 
-       DISSECTOR_ASSERT(fi);
+       /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
+        * items string representation */
+       if (PTREE_DATA(pi)->visible && !PROTO_ITEM_IS_HIDDEN(pi)) {
+               int               ret = 0;
+               field_info        *fi = PITEM_FINFO(pi);
+               header_field_info *hf;
 
-       hf = fi->hfinfo;
+               DISSECTOR_ASSERT(fi);
+
+               hf = fi->hfinfo;
 
-       if (!PROTO_ITEM_IS_HIDDEN(pi)) {
                ITEM_LABEL_NEW(fi->rep);
                if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
-                       char tmpbuf[64];
                        guint32 val;
+                       char *p;
 
                        val = fvalue_get_uinteger(&fi->value);
-                       if (hf->bitshift > 0) {
-                               val <<= hf->bitshift;
-                       }
-                       decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
-                       /* put in the hf name */
-                       ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
-                                        "%s%s: ", tmpbuf, fi->hfinfo->name);
-               } else {
-                       /* put in the hf name */
-                       ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
-                                        "%s: ", fi->hfinfo->name);
+                       val <<= hfinfo_bitshift(hf);
+
+                       p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_bitwidth(hf));
+                       ret = (int) (p - fi->rep->representation);
                }
 
+               /* put in the hf name */
+               ret += g_snprintf(fi->rep->representation + ret, ITEM_LABEL_LENGTH - ret, "%s: ", hf->name);
+
                /* If possible, Put in the value of the string */
                if (ret < ITEM_LABEL_LENGTH) {
                        ret += g_vsnprintf(fi->rep->representation + ret,
@@ -3668,18 +3558,8 @@ proto_tree_set_representation_value(proto_item *pi, const char *format, va_list
                        /* Uh oh, we don't have enough room.  Tell the user
                         * that the field is truncated.
                         */
-                       char *oldrep;
-
-                       /*      Argh, we cannot reuse 'ap' here.  So make a copy
-                        *      of what we formatted for (re)use below.
-                        */
-                       oldrep = g_strdup(fi->rep->representation);
-
-                       g_snprintf(fi->rep->representation,
-                                  ITEM_LABEL_LENGTH,
-                                  "[truncated] %s",
-                                  oldrep);
-                       g_free(oldrep);
+                       /* XXX, label_mark_truncated() ? */
+                       label_mark_truncated_start(fi->rep->representation);
                }
        }
 }
@@ -3703,16 +3583,7 @@ proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
                        /* Uh oh, we don't have enough room.  Tell the user
                         * that the field is truncated.
                         */
-                       char *oldrep;
-
-                       /*      Argh, we cannot reuse 'ap' here.  So make a copy
-                        *      of what we formatted for (re)use below.
-                        */
-                       oldrep = g_strdup(fi->rep->representation);
-
-                       g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
-                                  "[truncated] %s", oldrep);
-                       g_free(oldrep);
+                       label_mark_truncated_start(fi->rep->representation);
                }
        }
 }
@@ -3727,13 +3598,20 @@ protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
        return (int) res;
 }
 
+static header_field_info *
+hfinfo_same_name_get_prev(const header_field_info *hfinfo)
+{
+       if (hfinfo->same_name_prev_id == -1)
+               return NULL;
+       return proto_registrar_get_nth(hfinfo->same_name_prev_id);
+}
+
 /* -------------------------- */
 const gchar *
 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
                 gchar *result, gchar *expr, const int size)
 {
-       guint32            u_integer;
-       gint32             integer;
+       guint32            number;
        guint8            *bytes;
        ipv4_addr         *ipv4;
        struct e_in6_addr *ipv6;
@@ -3748,6 +3626,10 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
        header_field_info*  hfinfo;
        const gchar        *abbrev        = NULL;
 
+       const char *hf_str_val;
+       char number_buf[32];
+       const char *number_out;
+
        g_assert(field_id >= 0);
 
        hfinfo = proto_registrar_get_nth((guint)field_id);
@@ -3758,8 +3640,8 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
 
        if (occurrence < 0) {
                /* Search other direction */
-               while (hfinfo->same_name_prev) {
-                       hfinfo = hfinfo->same_name_prev;
+               while (hfinfo->same_name_prev_id != -1) {
+                       hfinfo = proto_registrar_get_nth(hfinfo->same_name_prev_id);
                }
        }
 
@@ -3770,7 +3652,7 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
                        if (occurrence < 0) {
                                hfinfo = hfinfo->same_name_next;
                        } else {
-                               hfinfo = hfinfo->same_name_prev;
+                               hfinfo = hfinfo_same_name_get_prev(hfinfo);
                        }
                        continue;
                }
@@ -3780,7 +3662,7 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
                        if (occurrence < 0) {
                                hfinfo = hfinfo->same_name_next;
                        } else {
-                               hfinfo = hfinfo->same_name_prev;
+                               hfinfo = hfinfo_same_name_get_prev(hfinfo);
                        }
                        prev_len += len;
                        continue;
@@ -3847,61 +3729,66 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
                                break;
 
                        case FT_BOOLEAN:
-                               u_integer = fvalue_get_uinteger(&finfo->value);
+                               number = fvalue_get_uinteger(&finfo->value);
                                tfstring = (const true_false_string *)&tfs_true_false;
                                if (hfinfo->strings) {
                                        tfstring = (const struct true_false_string*) hfinfo->strings;
                                }
                                offset_r += protoo_strlcpy(result+offset_r,
-                                                          u_integer ?
+                                                          number ?
                                                             tfstring->true_string :
                                                             tfstring->false_string, size-offset_r);
 
-                               g_snprintf(expr+offset_e, size-offset_e, "%u",
-                                          fvalue_get_uinteger(&finfo->value) ? 1 : 0);
-                               offset_e = (int)strlen(expr);
+                               offset_e += protoo_strlcpy(expr+offset_e,
+                                                          number ? "1" : "0", size-offset_e);
                                break;
 
+                       /* XXX - make these just FT_NUMBER? */
+                       case FT_INT8:
+                       case FT_INT16:
+                       case FT_INT24:
+                       case FT_INT32:
                        case FT_UINT8:
                        case FT_UINT16:
                        case FT_UINT24:
                        case FT_UINT32:
                        case FT_FRAMENUM:
-                               u_integer = fvalue_get_uinteger(&finfo->value);
+                               hf_str_val = NULL;
+                               number = IS_FT_INT(hfinfo->type) ? 
+                                               (guint32) fvalue_get_sinteger(&finfo->value) :
+                                               fvalue_get_uinteger(&finfo->value);
+
                                if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
                                        gchar tmp[ITEM_LABEL_LENGTH];
                                        custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
 
                                        DISSECTOR_ASSERT(fmtfunc);
-                                       fmtfunc(tmp, u_integer);
-                                       g_snprintf(result+offset_r, size-offset_r, "%s", tmp);
+                                       fmtfunc(tmp, number);
+
+                                       offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
+
                                } else if (hfinfo->strings) {
-                                       const char *str_val = hf_try_val_to_str(u_integer, hfinfo);
+                                       number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
 
-                                       if (str_val)
-                                               g_strlcpy(result+offset_r, str_val, size-offset_r);
-                                       else
-                                               g_snprintf(result+offset_r, size-offset_r, "%u", u_integer);
+                                       if (!number_out)
+                                               number_out = hfinfo_number_value_format_display(hfinfo, BASE_DEC, number_buf, number);
 
-                               } else {
-                                       char buf[32];
-                                       const char *out;
+                                       offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
 
-                                       out = hfinfo_number_value_format(hfinfo, buf, u_integer);
+                               } else {
+                                       number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
 
-                                       g_strlcpy(result+offset_r, out, size-offset_r);
+                                       offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
                                }
 
-                               if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
-                                       g_snprintf(expr+offset_e, size-offset_e,
-                                                  "\"%s\"", result+offset_r);
+                               if (hf_str_val && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
+                                       g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
                                } else {
-                                       g_snprintf(expr+offset_e, size-offset_e,
-                                                  hfinfo_numeric_value_format(hfinfo),
-                                                  u_integer);
+                                       number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
+
+                                       g_strlcpy(expr+offset_e, number_out, size-offset_e);
                                }
 
-                               offset_r = (int)strlen(result);
                                offset_e = (int)strlen(expr);
                                break;
 
@@ -3924,47 +3811,6 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
                                                           eui64_to_str(fvalue_get_integer64(&finfo->value)),
                                                           size-offset_r);
                                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->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
-                                       gchar tmp[ITEM_LABEL_LENGTH];
-                                       custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
-
-                                       DISSECTOR_ASSERT(fmtfunc);
-                                       fmtfunc(tmp, integer);
-                                       g_snprintf(result+offset_r, size-offset_r, "%s", tmp);
-                               } else if (hfinfo->strings) {
-                                       const char *str_val = hf_try_val_to_str(integer, hfinfo);
-
-                                       if (str_val)
-                                               g_strlcpy(result+offset_r, str_val, size-offset_r);
-                                       else
-                                               g_snprintf(result+offset_r, size-offset_r, "%d", integer);
-
-                               } else {
-                                       char buf[32];
-                                       const char *out;
-
-                                       out = hfinfo_number_value_format(hfinfo, buf, integer);
-
-                                       g_strlcpy(result+offset_r, out, size-offset_r);
-                               }
-
-                               if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
-                                       g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", result+offset_r);
-                               } else {
-                                       g_snprintf(expr+offset_e, size-offset_e,
-                                                  hfinfo_numeric_value_format(hfinfo),
-                                                  integer);
-                               }
-
-                               offset_r = (int)strlen(result);
-                               offset_e = (int)strlen(expr);
-                               break;
 
                        case FT_IPv4:
                                ipv4 = (ipv4_addr *)fvalue_get(&finfo->value);
@@ -4067,7 +3913,7 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
 
                if (occurrence == 0) {
                        /* Fetch next hfinfo with same name (abbrev) */
-                       hfinfo = hfinfo->same_name_prev;
+                       hfinfo = hfinfo_same_name_get_prev(hfinfo);
                } else {
                        hfinfo = NULL;
                }
@@ -4163,10 +4009,10 @@ proto_item_prepend_text(proto_item *pi, const char *format, ...)
                 */
                if (fi->rep == NULL) {
                        ITEM_LABEL_NEW(fi->rep);
-                       proto_item_fill_label(fi, fi->rep->representation);
-               }
+                       proto_item_fill_label(fi, representation);
+               } else
+                       g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
 
-               g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
                va_start(ap, format);
                g_vsnprintf(fi->rep->representation,
                        ITEM_LABEL_LENGTH, format, ap);
@@ -4230,30 +4076,6 @@ proto_item_get_len(const proto_item *pi)
        return fi ? fi->length : -1;
 }
 
-
-/** clear flags according to the mask and set new flag values */
-#define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
-       (fi->flags = (fi)->flags & ~(mask)); \
-       (fi->flags = (fi)->flags | (flags_in)); \
-}
-
-gboolean
-proto_item_set_expert_flags(proto_item *pi, const int group, const guint severity)
-{
-       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(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;
-       }
-
-       return FALSE;
-}
-
 proto_tree *
 proto_tree_create_root(packet_info *pinfo)
 {
@@ -4543,7 +4365,6 @@ proto_register_protocol(const char *name, const char *short_name,
        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 */
@@ -4617,29 +4438,25 @@ header_field_info *
 proto_get_first_protocol_field(const int proto_id, void **cookie)
 {
        protocol_t       *protocol = find_protocol_by_id(proto_id);
-       hf_register_info *ptr;
 
        if ((protocol == NULL) || (protocol->fields == NULL))
                return NULL;
 
        *cookie = protocol->fields;
-       ptr = (hf_register_info *)protocol->fields->data;
-       return &ptr->hfinfo;
+       return (header_field_info *)protocol->fields->data;
 }
 
 header_field_info *
 proto_get_next_protocol_field(void **cookie)
 {
-       GList            *list_item = (GList *)*cookie;
-       hf_register_info *ptr;
+       GSList           *list_item = (GSList *)*cookie;
 
-       list_item = g_list_next(list_item);
+       list_item = g_slist_next(list_item);
        if (list_item == NULL)
                return NULL;
 
        *cookie = list_item;
-       ptr = (hf_register_info *)list_item->data;
-       return &ptr->hfinfo;
+       return (header_field_info *)list_item->data;
 }
 
 protocol_t *
@@ -4807,11 +4624,11 @@ proto_register_field_array(const int parent, hf_register_info *hf, const int num
 
                if (proto != NULL) {
                        if (proto->fields == NULL) {
-                               proto->fields = g_list_append(NULL, ptr);
+                               proto->fields = g_slist_append(NULL, &ptr->hfinfo);
                                proto->last_field = proto->fields;
                        } else {
                                proto->last_field =
-                                       g_list_append(proto->last_field, ptr)->next;
+                                       g_slist_append(proto->last_field, &ptr->hfinfo)->next;
                        }
                }
                field_id = proto_register_field_init(&ptr->hfinfo, parent);
@@ -4819,13 +4636,44 @@ proto_register_field_array(const int parent, hf_register_info *hf, const int num
        }
 }
 
+void
+proto_register_fields(const int parent, header_field_info **hfi, const int num_records)
+{
+       int               i;
+       protocol_t       *proto;
+
+       proto = find_protocol_by_id(parent);
+       for (i = 0; i < num_records; i++) {
+               /*
+                * Make sure we haven't registered this yet.
+                */
+               if (hfi[i]->id != -1) {
+                       fprintf(stderr,
+                               "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
+                               hfi[i]->abbrev);
+                       return;
+               }
+
+               if (proto != NULL) {
+                       if (proto->fields == NULL) {
+                               proto->fields = g_slist_append(NULL, hfi[i]);
+                               proto->last_field = proto->fields;
+                       } else {
+                               proto->last_field =
+                                       g_slist_append(proto->last_field, hfi[i])->next;
+                       }
+               }
+               proto_register_field_init(hfi[i], parent);
+       }
+}
+
 /* unregister already registered fields */
 void
 proto_unregister_field (const int parent, gint hf_id)
 {
        hf_register_info *hf;
        protocol_t       *proto;
-       GList            *field;
+       GSList           *field;
 
        if (hf_id == -1 || hf_id == 0)
                return;
@@ -4835,13 +4683,14 @@ proto_unregister_field (const int parent, gint hf_id)
                return;
        }
 
-       for (field = g_list_first (proto->fields); field; field = g_list_next (field)) {
+       for (field = proto->fields; field; field = field->next) {
                hf = (hf_register_info *)field->data;
                if (*hf->p_id == hf_id) {
                        /* Found the hf_id in this protocol */
                        g_tree_steal (gpa_name_tree, hf->hfinfo.abbrev);
-                       proto->fields = g_list_remove_link (proto->fields, field);
-                       proto->last_field = g_list_last (proto->fields);
+                       /* XXX, memleak? g_slist_delete_link() */
+                       proto->fields = g_slist_remove_link (proto->fields, field);
+                       proto->last_field = g_slist_last (proto->fields);
                        break;
                }
        }
@@ -4917,6 +4766,13 @@ static const value_string hf_display[] = {
        { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
        { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
        { BASE_CUSTOM|BASE_RANGE_STRING,  "BASE_CUSTOM|BASE_RANGE_STRING"  },
+       { BASE_NONE|BASE_VAL64_STRING,    "BASE_NONE|BASE_VAL64_STRING"    },
+       { BASE_DEC|BASE_VAL64_STRING,     "BASE_DEC|BASE_VAL64_STRING"     },
+       { BASE_HEX|BASE_VAL64_STRING,     "BASE_HEX|BASE_VAL64_STRING"     },
+       { BASE_OCT|BASE_VAL64_STRING,     "BASE_OCT|BASE_VAL64_STRING"     },
+       { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
+       { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
+       { BASE_CUSTOM|BASE_VAL64_STRING,  "BASE_CUSTOM|BASE_VAL64_STRING"  },
        { ABSOLUTE_TIME_LOCAL,            "ABSOLUTE_TIME_LOCAL"            },
        { ABSOLUTE_TIME_UTC,              "ABSOLUTE_TIME_UTC"              },
        { ABSOLUTE_TIME_DOY_UTC,          "ABSOLUTE_TIME_DOY_UTC"          },
@@ -4957,8 +4813,7 @@ tmp_fld_check_assert(header_field_info *hfinfo)
                    (hfinfo->type == FT_INT32)    ||
                    (hfinfo->type == FT_INT64)    ||
                    (hfinfo->type == FT_BOOLEAN)  ||
-                   (hfinfo->type == FT_PROTOCOL) ||
-                   (hfinfo->type == FT_FRAMENUM) ))
+                   (hfinfo->type == FT_PROTOCOL) ))
                g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
                        " (which is not allowed to have strings)\n",
                        hfinfo->name, hfinfo->abbrev,
@@ -5029,18 +4884,17 @@ tmp_fld_check_assert(header_field_info *hfinfo)
                         *      else, unsigned so don't allow dissectors to register a
                         *      signed field to be displayed unsigned.  (Else how would
                         *      we display 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 (hfinfo->display == BASE_HEX ||
-                           hfinfo->display == BASE_OCT)
-                               g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
-                                       hfinfo->name, hfinfo->abbrev,
-                                       val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
-                                       val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
+                       switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
+                               case BASE_HEX:
+                               case BASE_OCT:
+                               case BASE_DEC_HEX:
+                               case BASE_HEX_DEC:
+                                       g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
+                                               hfinfo->name, hfinfo->abbrev,
+                                               val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
+                                               val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
+                       }
                        /* FALL THROUGH */
                case FT_UINT8:
                case FT_UINT16:
@@ -5126,14 +4980,9 @@ proto_register_field_init(header_field_info *hfinfo, const int parent)
 
        tmp_fld_check_assert(hfinfo);
 
-       /* if this is a bitfield, compute bitshift */
-       if (hfinfo->bitmask) {
-               hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
-       }
-
        hfinfo->parent         = parent;
        hfinfo->same_name_next = NULL;
-       hfinfo->same_name_prev = NULL;
+       hfinfo->same_name_prev_id = -1;
 
        /* if we always add and never delete, then id == len - 1 is correct */
        if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
@@ -5192,10 +5041,10 @@ proto_register_field_init(header_field_info *hfinfo, const int parent)
 
                        hfinfo->same_name_next = same_name_next_hfinfo;
                        if (same_name_next_hfinfo)
-                               same_name_next_hfinfo->same_name_prev = hfinfo;
+                               same_name_next_hfinfo->same_name_prev_id = hfinfo->id;
 
                        same_name_hfinfo->same_name_next = hfinfo;
-                       hfinfo->same_name_prev = same_name_hfinfo;
+                       hfinfo->same_name_prev_id = same_name_hfinfo->id;
                }
        }
 
@@ -5220,11 +5069,12 @@ proto_register_subtree_array(gint *const *indices, const int num_indices)
         * dissector that registers ett values.)
         */
        if (tree_is_expanded != NULL) {
-               tree_is_expanded =
-                       (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));
+               tree_is_expanded = (guint32 *)g_realloc(tree_is_expanded, (1+((num_tree_types + num_indices)/32)) * sizeof(guint32));
+
+               /* set new items to 0 */
+               /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of guint32 to 0) */
+               for (i = num_tree_types; i < num_tree_types + num_indices; i++)
+                       tree_is_expanded[i >> 5] &= ~(1 << (i & 31));
        }
 
        /*
@@ -5245,32 +5095,73 @@ proto_register_subtree_array(gint *const *indices, const int num_indices)
        }
 }
 
-static int
-label_fill_descr(char *label_str, const header_field_info *hfinfo, const char *text, const char *descr)
+static inline gsize
+label_concat(char *label_str, gsize pos, const char *str)
+{
+       if (pos < ITEM_LABEL_LENGTH)
+               pos += g_strlcpy(label_str + pos, str, ITEM_LABEL_LENGTH - pos);
+
+       return pos;
+}
+
+static void
+label_mark_truncated(char *label_str, gsize name_pos)
+{
+       static const char trunc_str[] = " [truncated]";
+       const size_t trunc_len = sizeof(trunc_str)-1;
+
+       /* ..... field_name: dataaaaaaaaaaaaa
+        *                 |
+        *                 ^^^^^ name_pos
+        *
+        * ..... field_name [truncated]: dataaaaaaaaaaaaa */
+
+       if (name_pos < ITEM_LABEL_LENGTH - trunc_len) {
+               memmove(label_str + name_pos + trunc_len, label_str + name_pos, ITEM_LABEL_LENGTH - name_pos - trunc_len);
+               memcpy(label_str + name_pos, trunc_str, trunc_len);
+               label_str[ITEM_LABEL_LENGTH-1] = '\0';
+
+       } else if (name_pos < ITEM_LABEL_LENGTH)
+               g_strlcpy(label_str + name_pos, trunc_str, ITEM_LABEL_LENGTH - name_pos);
+}
+
+static gsize
+label_fill(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text)
 {
-       gint ret;
+       gsize name_pos;
+
+       /* "%s: %s", hfinfo->name, text */
+       name_pos = pos = label_concat(label_str, pos, hfinfo->name);
+       pos = label_concat(label_str, pos, ": ");
+       pos = label_concat(label_str, pos, text ? text : "(null)");
 
-       ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s (%s)", hfinfo->name, text, descr);
-       if (ret >= ITEM_LABEL_LENGTH) {
+       if (pos >= ITEM_LABEL_LENGTH) {
                /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
-               ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s [truncated]: %s (%s)", hfinfo->name, text, descr);
+               label_mark_truncated(label_str, name_pos);
        }
 
-       return ret;
+       return pos;
 }
 
-static int
-label_fill(char *label_str, const header_field_info *hfinfo, const char *text)
+static gsize
+label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text, const char *descr)
 {
-       gint ret;
+       gsize name_pos;
+
+       /* "%s: %s (%s)", hfinfo->name, text, descr */
+       name_pos = pos = label_concat(label_str, pos, hfinfo->name);
+       pos = label_concat(label_str, pos, ": ");
+       pos = label_concat(label_str, pos, text ? text : "(null)");
+       pos = label_concat(label_str, pos, " (");
+       pos = label_concat(label_str, pos, descr ? descr : "(null)");
+       pos = label_concat(label_str, pos, ")");
 
-       ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, text);
-       if (ret >= ITEM_LABEL_LENGTH) {
+       if (pos >= ITEM_LABEL_LENGTH) {
                /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
-               ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s [truncated]: %s", hfinfo->name, text);
+               label_mark_truncated(label_str, name_pos);
        }
 
-       return ret;
+       return pos;
 }
 
 void
@@ -5284,6 +5175,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
        e_guid_t          *guid;
        guint32            n_addr; /* network-order IPv4 address */
        const gchar       *name;
+       address            addr;
 
        if (!fi) {
                if (label_str)
@@ -5307,7 +5199,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                case FT_BYTES:
                case FT_UINT_BYTES:
                        bytes = (guint8 *)fvalue_get(&fi->value);
-                       label_fill(label_str, hfinfo,
+                       label_fill(label_str, 0, hfinfo,
                                        (bytes) ? bytes_to_str(bytes, fvalue_length(&fi->value)) : "<MISSING>");
                        break;
 
@@ -5322,7 +5214,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                case FT_UINT24:
                case FT_UINT32:
                        if (hfinfo->bitmask) {
-                               fill_label_bitfield(fi, label_str);
+                               fill_label_bitfield(fi, label_str, FALSE);
                        } else {
                                fill_label_number(fi, label_str, FALSE);
                        }
@@ -5333,19 +5225,22 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                        break;
 
                case FT_UINT64:
-                       fill_label_uint64(fi, label_str);
+                       fill_label_number64(fi, label_str, FALSE);
                        break;
 
                case FT_INT8:
                case FT_INT16:
                case FT_INT24:
                case FT_INT32:
-                       DISSECTOR_ASSERT(!hfinfo->bitmask);
-                       fill_label_number(fi, label_str, TRUE);
+                       if (hfinfo->bitmask) {
+                               fill_label_bitfield(fi, label_str, TRUE);
+                       } else {
+                               fill_label_number(fi, label_str, TRUE);
+                       }
                        break;
 
                case FT_INT64:
-                       fill_label_int64(fi, label_str);
+                       fill_label_number64(fi, label_str, TRUE);
                        break;
 
                case FT_FLOAT:
@@ -5361,7 +5256,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                        break;
 
                case FT_ABSOLUTE_TIME:
-                       label_fill(label_str, hfinfo,
+                       label_fill(label_str, 0, hfinfo,
                                   abs_time_to_str((const nstime_t *)fvalue_get(&fi->value),
                                                (absolute_time_display_e)hfinfo->display, TRUE));
                        break;
@@ -5381,14 +5276,24 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
 
                case FT_AX25:
                        bytes = (guint8 *)fvalue_get(&fi->value);
-                       label_fill_descr(label_str, hfinfo,
+                       label_fill_descr(label_str, 0, hfinfo,
                                   get_ax25_name(bytes),
                                   ax25_to_str(bytes));
                        break;
 
+               case FT_VINES:
+                       addr.type = AT_VINES;
+                       addr.len  = VINES_ADDR_LEN;
+                       addr.data = (guint8 *)fvalue_get(&fi->value);
+
+                       g_snprintf(label_str, ITEM_LABEL_LENGTH,
+                                  "%s: %s", hfinfo->name,
+                                  address_to_str( &addr ));
+                       break;
+
                case FT_ETHER:
                        bytes = (guint8 *)fvalue_get(&fi->value);
-                       label_fill_descr(label_str, hfinfo,
+                       label_fill_descr(label_str, 0, hfinfo,
                                   get_ether_name(bytes),
                                   ether_to_str(bytes));
                        break;
@@ -5396,37 +5301,37 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                case FT_IPv4:
                        ipv4 = (ipv4_addr *)fvalue_get(&fi->value);
                        n_addr = ipv4_get_net_order_addr(ipv4);
-                       label_fill_descr(label_str, hfinfo,
+                       label_fill_descr(label_str, 0, hfinfo,
                                   get_hostname(n_addr),
                                   ip_to_str((guint8*)&n_addr));
                        break;
 
                case FT_IPv6:
                        bytes = (guint8 *)fvalue_get(&fi->value);
-                       label_fill_descr(label_str, hfinfo,
+                       label_fill_descr(label_str, 0, hfinfo,
                                   get_hostname6((struct e_in6_addr *)bytes),
                                   ip6_to_str((struct e_in6_addr*)bytes));
                        break;
 
                case FT_GUID:
                        guid = (e_guid_t *)fvalue_get(&fi->value);
-                       label_fill(label_str, hfinfo, guid_to_str(guid));
+                       label_fill(label_str, 0, hfinfo, guid_to_str(guid));
                        break;
 
                case FT_OID:
                        bytes = (guint8 *)fvalue_get(&fi->value);
                        name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
                        if (name) {
-                               label_fill_descr(label_str, hfinfo,
+                               label_fill_descr(label_str, 0, hfinfo,
                                         oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
                        } else {
-                               label_fill(label_str, hfinfo,
+                               label_fill(label_str, 0, hfinfo,
                                         oid_encoded2string(bytes, fvalue_length(&fi->value)));
                        }
                        break;
                case FT_EUI64:
                        integer64 = fvalue_get_integer64(&fi->value);
-                       label_fill_descr(label_str, hfinfo,
+                       label_fill_descr(label_str, 0, hfinfo,
                                   get_eui64_name(integer64),
                                   eui64_to_str(integer64));
                        break;
@@ -5434,7 +5339,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                case FT_STRINGZ:
                case FT_UINT_STRING:
                        bytes = (guint8 *)fvalue_get(&fi->value);
-                       label_fill(label_str, hfinfo, format_text(bytes, strlen(bytes)));
+                       label_fill(label_str, 0, hfinfo, format_text(bytes, strlen(bytes)));
                        break;
 
                default:
@@ -5467,9 +5372,7 @@ fill_label_boolean(field_info *fi, gchar *label_str)
 
                /* Un-shift bits */
                unshifted_value = value;
-               if (hfinfo->bitshift > 0) {
-                       unshifted_value <<= hfinfo->bitshift;
-               }
+               unshifted_value <<= hfinfo_bitshift(hfinfo);
 
                /* Create the bitfield first */
                p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
@@ -5477,9 +5380,7 @@ fill_label_boolean(field_info *fi, gchar *label_str)
        }
 
        /* Fill in the textual info */
-       g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
-                  "%s: %s",  hfinfo->name,
-                  value ? tfstring->true_string : tfstring->false_string);
+       label_fill(label_str, bitfield_byte_length, hfinfo, value ? tfstring->true_string : tfstring->false_string);
 }
 
 static const char *
@@ -5491,9 +5392,28 @@ hf_try_val_to_str(guint32 value, const header_field_info *hfinfo)
        if (hfinfo->display & BASE_EXT_STRING)
                return try_val_to_str_ext(value, (const value_string_ext *) hfinfo->strings);
 
+       if (hfinfo->display & BASE_VAL64_STRING)
+               return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
+
        return try_val_to_str(value, (const value_string *) hfinfo->strings);
 }
 
+static const char *
+hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo)
+{
+       if (hfinfo->display & BASE_VAL64_STRING)
+               return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
+
+       /* If this is reached somebody registered a 64-bit field with a 32-bit
+        * value-string, which isn't right. */
+       DISSECTOR_ASSERT_NOT_REACHED();
+
+       /* This is necessary to squelch MSVC errors; is there
+          any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
+          never returns? */
+       return NULL;
+}
+
 static const char *
 hf_try_val_to_str_const(guint32 value, const header_field_info *hfinfo, const char *unknown_str)
 {
@@ -5502,9 +5422,17 @@ hf_try_val_to_str_const(guint32 value, const header_field_info *hfinfo, const ch
        return (str) ? str : unknown_str;
 }
 
+static const char *
+hf_try_val64_to_str_const(guint64 value, const header_field_info *hfinfo, const char *unknown_str)
+{
+       const char *str = hf_try_val64_to_str(value, hfinfo);
+
+       return (str) ? str : unknown_str;
+}
+
 /* Fills data for bitfield ints with val_strings */
 static void
-fill_label_bitfield(field_info *fi, gchar *label_str)
+fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed)
 {
        char       *p;
        int         bitfield_byte_length, bitwidth;
@@ -5520,10 +5448,14 @@ fill_label_bitfield(field_info *fi, gchar *label_str)
        bitwidth = hfinfo_bitwidth(hfinfo);
 
        /* Un-shift bits */
-       unshifted_value = fvalue_get_uinteger(&fi->value);
+       if (is_signed)
+               unshifted_value = fvalue_get_sinteger(&fi->value);
+       else
+               unshifted_value = fvalue_get_uinteger(&fi->value);
+
        value = unshifted_value;
-       if (hfinfo->bitshift > 0) {
-               unshifted_value <<= hfinfo->bitshift;
+       if (hfinfo->bitmask) {
+               unshifted_value <<= hfinfo_bitshift(hfinfo);
        }
 
        /* Create the bitfield first */
@@ -5537,46 +5469,21 @@ fill_label_bitfield(field_info *fi, gchar *label_str)
 
                DISSECTOR_ASSERT(fmtfunc);
                fmtfunc(tmp, value);
-               g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
-                          "%s: %s", hfinfo->name, tmp);
+               label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
        }
        else if (hfinfo->strings) {
                const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
 
                out = hfinfo_number_vals_format(hfinfo, buf, value);
                if (out == NULL) /* BASE_NONE so don't put integer in descr */
-                       g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
-                          "%s: %s",  hfinfo->name, val_str);
+                       label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
                else
-                       g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
-                          "%s: %s (%s)",  hfinfo->name, val_str, out);
+                       label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
        }
        else {
                out = hfinfo_number_value_format(hfinfo, buf, value);
 
-               g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
-                                  "%s: %s",  hfinfo->name, out);
-       }
-}
-
-static void
-fill_label_uint64(field_info *fi, gchar *label_str)
-{
-       const char        *format = NULL;
-       header_field_info *hfinfo = fi->hfinfo;
-       guint64            value;
-
-       /* Pick the proper format string */
-       format = hfinfo_uint64_format(hfinfo);
-       value  = fvalue_get_integer64(&fi->value);
-
-       /* Fill in the textual info */
-       if (IS_BASE_DUAL(hfinfo->display)) {
-               g_snprintf(label_str, ITEM_LABEL_LENGTH,
-                          format,  hfinfo->name, value, value);
-       } else {
-               g_snprintf(label_str, ITEM_LABEL_LENGTH,
-                          format,  hfinfo->name, value);
+               label_fill(label_str, bitfield_byte_length, hfinfo, out);
        }
 }
 
@@ -5601,43 +5508,79 @@ fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
 
                DISSECTOR_ASSERT(fmtfunc);
                fmtfunc(tmp, value);
-               label_fill(label_str, hfinfo, tmp);
+               label_fill(label_str, 0, hfinfo, tmp);
        }
        else if (hfinfo->strings) {
                const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
 
                out = hfinfo_number_vals_format(hfinfo, buf, value);
                if (out == NULL) /* BASE_NONE so don't put integer in descr */
-                       label_fill(label_str, hfinfo, val_str);
+                       label_fill(label_str, 0, hfinfo, val_str);
                else
-                       label_fill_descr(label_str, hfinfo, val_str, out);
+                       label_fill_descr(label_str, 0, hfinfo, val_str, out);
        }
        else {
                out = hfinfo_number_value_format(hfinfo, buf, value);
 
-               label_fill(label_str, hfinfo, out);
+               label_fill(label_str, 0, hfinfo, out);
        }
 }
 
 static void
-fill_label_int64(field_info *fi, gchar *label_str)
+fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
 {
        const char        *format = NULL;
        header_field_info *hfinfo = fi->hfinfo;
        guint64            value;
+       char               tmp[ITEM_LABEL_LENGTH+1];
 
        /* Pick the proper format string */
-       format = hfinfo_int64_format(hfinfo);
-       value  = fvalue_get_integer64(&fi->value);
+       if (is_signed)
+               format = hfinfo_int64_format(hfinfo);
+       else
+               format = hfinfo_uint64_format(hfinfo);
 
-       /* Fill in the textual info */
-       if (IS_BASE_DUAL(hfinfo->display)) {
-               g_snprintf(label_str, ITEM_LABEL_LENGTH,
-                          format,  hfinfo->name, value, value);
-       } else {
-               g_snprintf(label_str, ITEM_LABEL_LENGTH,
-                          format,  hfinfo->name, value);
+       value = fvalue_get_integer64(&fi->value);
+
+       /* Format the temporary string */
+       if (IS_BASE_DUAL(hfinfo->display))
+               g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value, value);
+       else
+               g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value);
+
+       if (hfinfo->strings) {
+               const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
+
+               if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
+                       label_fill(label_str, 0, hfinfo, val_str);
+               }
+               else {
+                       label_fill_descr(label_str, 0, hfinfo, val_str, tmp);
+               }
        }
+       else {
+               label_fill(label_str, 0, hfinfo, tmp);
+       }
+}
+
+int
+hfinfo_bitshift(const header_field_info *hfinfo)
+{
+       const guint32 bitmask = hfinfo->bitmask;
+
+#if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+       g_assert(bitmask != 0);
+
+       return __builtin_ctz(bitmask);
+#else
+       /* From http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup */
+       static const int table[32] = {
+               0,   1, 28,  2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17,  4, 8,
+               31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18,  6, 11,  5, 10, 9
+       };
+
+       return table[((guint32)((bitmask & -(gint32)bitmask) * 0x077CB531U)) >> 27];
+#endif
 }
 
 int
@@ -5710,7 +5653,7 @@ char *uint_to_str_back(char *ptr, guint32 value);
 char *int_to_str_back(char *ptr, gint32 value);
 
 static const char *
-_hfinfo_number_value_format(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
+hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
 {
        char *ptr = &buf[31];
        gboolean isint = IS_FT_INT(hfinfo->type);
@@ -5753,17 +5696,47 @@ _hfinfo_number_value_format(const header_field_info *hfinfo, int display, char b
 static const char *
 hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
 {
+       int display = hfinfo->display;
+
        if (hfinfo->type == FT_FRAMENUM) {
-               char *ptr = &buf[31];
+               /*
+                * Frame numbers are always displayed in decimal.
+                */
+               display = BASE_DEC;
+       }
 
-               *ptr = '\0';
+       return hfinfo_number_value_format_display(hfinfo, display, buf, value);
+}
+
+static const char *
+hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
+{
+       /* Get the underlying BASE_ value */
+       int display = hfinfo->display & BASE_DISPLAY_E_MASK;
+
+       if (hfinfo->type == FT_FRAMENUM) {
                /*
                 * Frame numbers are always displayed in decimal.
                 */
-               return uint_to_str_back(ptr, value);
+               display = BASE_DEC;
+       }
+
+       switch (display) {
+               case BASE_NONE:
+               /* case BASE_DEC: */
+               case BASE_DEC_HEX:
+               case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
+               case BASE_CUSTOM:
+                       display = BASE_DEC;
+                       break;
+
+               /* case BASE_HEX: */
+               case BASE_HEX_DEC:
+                       display = BASE_HEX;
+                       break;
        }
 
-       return _hfinfo_number_value_format(hfinfo, hfinfo->display, buf, value);
+       return hfinfo_number_value_format_display(hfinfo, display, buf, value);
 }
 
 static const char *
@@ -5780,7 +5753,7 @@ hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32
        if (display == BASE_HEX_DEC)
                display = BASE_HEX;
 
-       return _hfinfo_number_value_format(hfinfo, display, buf, value);
+       return hfinfo_number_value_format_display(hfinfo, display, buf, value);
 }
 
 static const char *
@@ -5789,21 +5762,21 @@ hfinfo_uint64_format(const header_field_info *hfinfo)
        const char *format = NULL;
 
        /* Pick the proper format string */
-       switch (hfinfo->display) {
+       switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
                case BASE_DEC:
-                       format = "%s: %" G_GINT64_MODIFIER "u";
+                       format = "%" G_GINT64_MODIFIER "u";
                        break;
                case BASE_DEC_HEX:
-                       format = "%s: %" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
+                       format = "%" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
                        break;
                case BASE_OCT: /* I'm lazy */
-                       format = "%s: %#" G_GINT64_MODIFIER "o";
+                       format = "%#" G_GINT64_MODIFIER "o";
                        break;
                case BASE_HEX:
-                       format = "%s: 0x%016" G_GINT64_MODIFIER "x";
+                       format = "0x%016" G_GINT64_MODIFIER "x";
                        break;
                case BASE_HEX_DEC:
-                       format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
+                       format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
                        break;
                default:
                        DISSECTOR_ASSERT_NOT_REACHED();
@@ -5818,21 +5791,21 @@ hfinfo_int64_format(const header_field_info *hfinfo)
        const char *format = NULL;
 
        /* Pick the proper format string */
-       switch (hfinfo->display) {
+       switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
                case BASE_DEC:
-                       format = "%s: %" G_GINT64_MODIFIER "d";
+                       format = "%" G_GINT64_MODIFIER "d";
                        break;
                case BASE_DEC_HEX:
-                       format = "%s: %" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
+                       format = "%" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
                        break;
                case BASE_OCT: /* I'm lazy */
-                       format = "%s: %#" G_GINT64_MODIFIER "o";
+                       format = "%#" G_GINT64_MODIFIER "o";
                        break;
                case BASE_HEX:
-                       format = "%s: 0x%016" G_GINT64_MODIFIER "x";
+                       format = "0x%016" G_GINT64_MODIFIER "x";
                        break;
                case BASE_HEX_DEC:
-                       format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
+                       format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
                        break;
                default:
                        DISSECTOR_ASSERT_NOT_REACHED();
@@ -6138,6 +6111,7 @@ proto_registrar_dump_values(void)
        header_field_info       *hfinfo;
        int                     i, len, vi;
        const value_string      *vals;
+       const val64_string      *vals64;
        const range_string      *range;
        const true_false_string *tfs;
 
@@ -6167,12 +6141,13 @@ proto_registrar_dump_values(void)
                         * *maximum* length is 2 bytes, and be used
                         * for all lengths.)
                         */
-                       if (hfinfo->same_name_prev != NULL)
+                       if (hfinfo->same_name_prev_id != -1)
                                continue;
 
-                       vals  = NULL;
-                       range = NULL;
-                       tfs   = NULL;
+                       vals   = NULL;
+                       vals64 = NULL;
+                       range  = NULL;
+                       tfs    = NULL;
 
                        if (hfinfo->strings != NULL) {
                                if ((hfinfo->display & BASE_DISPLAY_E_MASK) != BASE_CUSTOM &&
@@ -6191,6 +6166,8 @@ proto_registrar_dump_values(void)
                                                vals = VALUE_STRING_EXT_VS_P((const value_string_ext *)hfinfo->strings);
                                        } else if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
                                                vals = (const value_string *)hfinfo->strings;
+                                       } else if ((hfinfo->display & BASE_VAL64_STRING) == 0) {
+                                               vals64 = (const val64_string *)hfinfo->strings;
                                        } else {
                                                range = (const range_string *)hfinfo->strings;
                                        }
@@ -6233,6 +6210,16 @@ proto_registrar_dump_values(void)
                                        vi++;
                                }
                        }
+                       else if (vals64) {
+                               vi = 0;
+                               while (vals64[vi].strptr) {
+                                       printf("V64\t%s\t%" G_GINT64_MODIFIER "u\t%s\n",
+                                               hfinfo->abbrev,
+                                               vals64[vi].value,
+                                               vals64[vi].strptr);
+                                       vi++;
+                               }
+                       }
 
                        /* print range strings? */
                        else if (range) {
@@ -6329,7 +6316,7 @@ proto_registrar_dump_fields(void)
                         * *maximum* length is 2 bytes, and be used
                         * for all lengths.)
                         */
-                       if (hfinfo->same_name_prev != NULL)
+                       if (hfinfo->same_name_prev_id != -1)
                                continue;
 
                        PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
@@ -6417,13 +6404,6 @@ hfinfo_numeric_format(const header_field_info *hfinfo)
 {
        const char *format = NULL;
 
-       /* Pick the proper format string */
-       if (hfinfo->type == FT_FRAMENUM) {
-               /*
-                * Frame numbers are always displayed in decimal.
-                */
-               format = "%s == %u";
-       } else {
                /* Get the underlying BASE_ value */
                switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
                        case BASE_DEC:
@@ -6431,21 +6411,9 @@ hfinfo_numeric_format(const header_field_info *hfinfo)
                        case BASE_OCT: /* I'm lazy */
                        case BASE_CUSTOM:
                                switch (hfinfo->type) {
-                                       case FT_UINT8:
-                                       case FT_UINT16:
-                                       case FT_UINT24:
-                                       case FT_UINT32:
-                                               format = "%s == %u";
-                                               break;
                                        case FT_UINT64:
                                                format = "%s == %" G_GINT64_MODIFIER "u";
                                                break;
-                                       case FT_INT8:
-                                       case FT_INT16:
-                                       case FT_INT24:
-                                       case FT_INT32:
-                                               format = "%s == %d";
-                                               break;
                                        case FT_INT64:
                                                format = "%s == %" G_GINT64_MODIFIER "d";
                                                break;
@@ -6457,22 +6425,6 @@ hfinfo_numeric_format(const header_field_info *hfinfo)
                        case BASE_HEX:
                        case BASE_HEX_DEC:
                                switch (hfinfo->type) {
-                                       case FT_UINT8:
-                                       case FT_INT8:
-                                               format = "%s == 0x%02x";
-                                               break;
-                                       case FT_UINT16:
-                                       case FT_INT16:
-                                               format = "%s == 0x%04x";
-                                               break;
-                                       case FT_UINT24:
-                                       case FT_INT24:
-                                               format = "%s == 0x%06x";
-                                               break;
-                                       case FT_UINT32:
-                                       case FT_INT32:
-                                               format = "%s == 0x%08x";
-                                               break;
                                        case FT_UINT64:
                                        case FT_INT64:
                                                format = "%s == 0x%016" G_GINT64_MODIFIER "x";
@@ -6486,86 +6438,6 @@ hfinfo_numeric_format(const header_field_info *hfinfo)
                                DISSECTOR_ASSERT_NOT_REACHED();
                                ;
                }
-       }
-       return format;
-}
-
-static const char *
-hfinfo_numeric_value_format(const header_field_info *hfinfo)
-{
-       const char *format = NULL;
-
-       /* Pick the proper format string */
-       if (hfinfo->type == FT_FRAMENUM) {
-               /*
-                * Frame numbers are always displayed in decimal.
-                */
-               format = "%u";
-       } else {
-               /* Get the underlying BASE_ value */
-               switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
-                       case BASE_NONE:
-                       case BASE_DEC:
-                       case BASE_DEC_HEX:
-                       case BASE_OCT: /* I'm lazy */
-                       case BASE_CUSTOM:
-                               switch (hfinfo->type) {
-                                       case FT_UINT8:
-                                       case FT_UINT16:
-                                       case FT_UINT24:
-                                       case FT_UINT32:
-                                               format = "%u";
-                                               break;
-                                       case FT_UINT64:
-                                               format = "%" G_GINT64_MODIFIER "u";
-                                               break;
-                                       case FT_INT8:
-                                       case FT_INT16:
-                                       case FT_INT24:
-                                       case FT_INT32:
-                                               format = "%d";
-                                               break;
-                                       case FT_INT64:
-                                               format = "%" G_GINT64_MODIFIER "d";
-                                               break;
-                                       default:
-                                               DISSECTOR_ASSERT_NOT_REACHED();
-                                               ;
-                               }
-                               break;
-                       case BASE_HEX:
-                       case BASE_HEX_DEC:
-                               switch (hfinfo->type) {
-                                       case FT_UINT8:
-                                       case FT_INT8:
-                                               format = "0x%02x";
-                                               break;
-                                       case FT_UINT16:
-                                       case FT_INT16:
-                                               format = "0x%04x";
-                                               break;
-                                       case FT_UINT24:
-                                       case FT_INT24:
-                                               format = "0x%06x";
-                                               break;
-                                       case FT_UINT32:
-                                       case FT_INT32:
-                                               format = "0x%08x";
-                                               break;
-                                       case FT_UINT64:
-                                       case FT_INT64:
-                                               format = "0x%016" G_GINT64_MODIFIER "x";
-                                               break;
-                                       default:
-                                               DISSECTOR_ASSERT_NOT_REACHED();
-                                               ;
-                               }
-                               break;
-                       default:
-                               DISSECTOR_ASSERT_NOT_REACHED();
-                               ;
-               }
-       }
        return format;
 }
 
@@ -6585,7 +6457,6 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
        int                abbrev_len;
        char              *ptr;
        int                buf_len;
-       const char        *format;
        int                dfilter_len, i;
        gint               start, length, length_remaining;
        guint8             c;
@@ -6659,34 +6530,29 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
                case FT_UINT16:
                case FT_UINT24:
                case FT_UINT32:
-                       if (filter != NULL) {
-                               format = hfinfo_numeric_format(hfinfo);
-                               if (is_signed_num) {
-                                       *filter = ep_strdup_printf(format,
-                                                  hfinfo->abbrev,
-                                                  fvalue_get_sinteger(&finfo->value));
-                               } else {
-                                       *filter = ep_strdup_printf(format,
-                                                  hfinfo->abbrev,
-                                                          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));
+                               guint32 number;
+
+                               char buf[32];
+                               const char *out;
+
+                               if (is_signed_num)
+                                       number = fvalue_get_sinteger(&finfo->value);
+                               else
+                                       number = fvalue_get_uinteger(&finfo->value);
+
+                               out = hfinfo_numeric_value_format(hfinfo, buf, number);
+
+                               *filter = ep_strdup_printf("%s == %s", hfinfo->abbrev, out);
                        }
                        break;
 
                case FT_INT64:
                case FT_UINT64:
                        if (filter != NULL) {
-                               format = hfinfo_numeric_format(hfinfo);
+                               const char *format = hfinfo_numeric_format(hfinfo);
+
                                *filter = ep_strdup_printf(format,
                                        hfinfo->abbrev,
                                        fvalue_get_integer64(&finfo->value));
@@ -6893,7 +6759,7 @@ proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
                        fields++;
                        continue;
                }
-               tmpval = (value & hf->bitmask) >> hf->bitshift;
+               tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
 
                switch (hf->type) {
                case FT_INT8:
@@ -7086,15 +6952,27 @@ proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
 }
 
 proto_item *
-proto_tree_add_bits_item(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
+proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
                         const guint bit_offset, const gint no_of_bits,
                         const guint encoding)
 {
        header_field_info *hfinfo;
+       gint              octet_length;
+       gint              octet_offset;
+
+       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
+
+       octet_length = (no_of_bits + 7) >> 3;
+       octet_offset = bit_offset >> 3;
+       test_length(hfinfo, tree, tvb, octet_offset, octet_length, encoding);
 
-       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hfinfo);
+       /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
+        * but only after doing a bunch more work (which we can, in the common
+        * case, shortcut here).
+        */
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, encoding);
+       return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
 }
 
 /*
@@ -7104,7 +6982,7 @@ proto_tree_add_bits_item(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
  */
 
 static proto_item *
-_proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
+_proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
                            const guint bit_offset, const gint no_of_bits,
                            guint64 *return_value, const guint encoding)
 {
@@ -7121,7 +6999,7 @@ _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb
        const true_false_string *tfstring;
 
        /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
-       PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
+       PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
 
        if (hf_field->bitmask != 0) {
                REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val"
@@ -7138,10 +7016,7 @@ _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb
         * 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++;
+       length = (tot_no_bits + 7) >> 3;
 
        if (no_of_bits < 65) {
                value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
@@ -7170,7 +7045,7 @@ _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb
        }
 
        /* Coast clear. Try and fake it */
-       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
 
        bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
 
@@ -7180,7 +7055,7 @@ _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb
                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,
+               return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, (guint32)value,
                        "%s = %s: %s",
                        bf_str, hf_field->name,
                        (guint32)value ? tfstring->true_string : tfstring->false_string);
@@ -7190,7 +7065,7 @@ _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb
        case FT_UINT16:
        case FT_UINT24:
        case FT_UINT32:
-               pi = proto_tree_add_uint(tree, hf_index, tvb, offset, length, (guint32)value);
+               pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
                fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
                break;
 
@@ -7198,18 +7073,18 @@ _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb
        case FT_INT16:
        case FT_INT24:
        case FT_INT32:
-               pi = proto_tree_add_int(tree, hf_index, tvb, offset, length, (gint32)value);
+               pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (gint32)value);
                fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
                break;
 
        case FT_UINT64:
-               pi = proto_tree_add_uint64(tree, hf_index, tvb, offset, length, value);
-               fill_label_uint64(PITEM_FINFO(pi), lbl_str);
+               pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
+               fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
                break;
 
        case FT_INT64:
-               pi = proto_tree_add_int64(tree, hf_index, tvb, offset, length, (gint64)value);
-               fill_label_int64(PITEM_FINFO(pi), lbl_str);
+               pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (gint64)value);
+               fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
                break;
 
        default:
@@ -7223,7 +7098,7 @@ _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb
 }
 
 proto_item *
-proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
+proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
                                       const guint bit_offset, const crumb_spec_t *crumb_spec,
                                       guint64 *return_value)
 {
@@ -7244,7 +7119,7 @@ proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hf_index, tvb
        const true_false_string *tfstring;
 
        /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
-       PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
+       PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
 
        if (hf_field->bitmask != 0) {
                REPORT_DISSECTOR_BUG(ep_strdup_printf(
@@ -7314,7 +7189,7 @@ proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hf_index, tvb
        }
 
        /* Coast clear. Try and fake it */
-       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
 
        /* initialise the format string */
        bf_str    = (char *)ep_alloc(256);
@@ -7341,7 +7216,7 @@ proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hf_index, tvb
                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,
+               return proto_tree_add_boolean_format(tree, hfindex,
                                                     tvb, octet_offset, octet_length, (guint32)value,
                                                     "%s = %s: %s",
                                                     bf_str, hf_field->name,
@@ -7352,7 +7227,7 @@ proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hf_index, tvb
        case FT_UINT16:
        case FT_UINT24:
        case FT_UINT32:
-               pi = proto_tree_add_uint(tree, hf_index, tvb, octet_offset, octet_length, (guint32)value);
+               pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
                fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
                break;
 
@@ -7360,18 +7235,18 @@ proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hf_index, tvb
        case FT_INT16:
        case FT_INT24:
        case FT_INT32:
-               pi = proto_tree_add_int(tree, hf_index, tvb, octet_offset, octet_length, (gint32)value);
+               pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (gint32)value);
                fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
                break;
 
        case FT_UINT64:
-               pi = proto_tree_add_uint64(tree, hf_index, tvb, octet_offset, octet_length, value);
-               fill_label_uint64(PITEM_FINFO(pi), lbl_str);
+               pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
+               fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
                break;
 
        case FT_INT64:
-               pi = proto_tree_add_int64(tree, hf_index, tvb, octet_offset, octet_length, (gint64)value);
-               fill_label_int64(PITEM_FINFO(pi), lbl_str);
+               pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (gint64)value);
+               fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
                break;
 
        default:
@@ -7384,12 +7259,12 @@ proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hf_index, tvb
 }
 
 void
-proto_tree_add_split_bits_crumb(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const guint bit_offset,
+proto_tree_add_split_bits_crumb(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const guint bit_offset,
                                const crumb_spec_t *crumb_spec, guint16 crumb_index)
 {
-       header_field_info *hf_info;
+       header_field_info *hfinfo;
 
-       PROTO_REGISTRAR_GET_NTH(hf_index, hf_info);
+       PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
        proto_tree_add_text(tree, tvb,
                            bit_offset >> 3,
                            ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
@@ -7400,17 +7275,17 @@ proto_tree_add_split_bits_crumb(proto_tree *tree, const int hf_index, tvbuff_t *
                                                              crumb_spec[crumb_index].crumb_bit_length,
                                                              ENC_BIG_ENDIAN)),
                            crumb_index,
-                           hf_info->name);
+                           hfinfo->name);
 }
 
 proto_item *
-proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
+proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
                            const guint bit_offset, const gint no_of_bits,
                            guint64 *return_value, const guint encoding)
 {
        proto_item *item;
 
-       if ((item = _proto_tree_add_bits_ret_val(tree, hf_index, tvb,
+       if ((item = _proto_tree_add_bits_ret_val(tree, hfindex, tvb,
                                                 bit_offset, no_of_bits,
                                                 return_value, encoding))) {
                FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
@@ -7420,7 +7295,7 @@ proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
 }
 
 static proto_item *
-_proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
+_proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
                                 tvbuff_t *tvb, const guint bit_offset,
                                 const gint no_of_bits, void *value_ptr,
                                 gchar *value_str)
@@ -7433,7 +7308,7 @@ _proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
        header_field_info *hf_field;
 
        /* 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);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
 
        if (hf_field->bitmask != 0) {
                REPORT_DISSECTOR_BUG(ep_strdup_printf(
@@ -7477,7 +7352,7 @@ _proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
         */
        switch (hf_field->type) {
        case FT_BOOLEAN:
-               return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
+               return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
                                                     "%s: %s", str, value_str);
                break;
 
@@ -7485,12 +7360,12 @@ _proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
        case FT_UINT16:
        case FT_UINT24:
        case FT_UINT32:
-               return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
+               return proto_tree_add_uint_format(tree, hfindex, 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,
+               return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(guint64 *)value_ptr,
                                                    "%s: %s", str, value_str);
                break;
 
@@ -7498,17 +7373,17 @@ _proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
        case FT_INT16:
        case FT_INT24:
        case FT_INT32:
-               return proto_tree_add_int_format(tree, hf_index, tvb, offset, length, *(gint32 *)value_ptr,
+               return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(gint32 *)value_ptr,
                                                 "%s: %s", str, value_str);
                break;
 
        case FT_INT64:
-               return proto_tree_add_int64_format(tree, hf_index, tvb, offset, length, *(gint64 *)value_ptr,
+               return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(gint64 *)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,
+               return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
                                                   "%s: %s", str, value_str);
                break;
 
@@ -7520,14 +7395,14 @@ _proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
 }
 
 static proto_item *
-proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
+proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
                                 tvbuff_t *tvb, const guint bit_offset,
                                 const gint no_of_bits, void *value_ptr,
                                 gchar *value_str)
 {
        proto_item *item;
 
-       if ((item = _proto_tree_add_bits_format_value(tree, hf_index,
+       if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
                                                      tvb, bit_offset, no_of_bits,
                                                      value_ptr, value_str))) {
                FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
@@ -7542,7 +7417,7 @@ proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
        va_end(ap);
 
 proto_item *
-proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hf_index,
+proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
                                      tvbuff_t *tvb, const guint bit_offset,
                                      const gint no_of_bits, guint32 value,
                                      const char *format, ...)
@@ -7551,7 +7426,7 @@ proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hf_index,
        gchar  *dst;
        header_field_info *hf_field;
 
-       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
 
        switch (hf_field->type) {
                case FT_UINT8:
@@ -7568,11 +7443,11 @@ proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hf_index,
 
        CREATE_VALUE_STRING(dst, format, ap);
 
-       return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
+       return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
 }
 
 proto_item *
-proto_tree_add_float_bits_format_value(proto_tree *tree, const int hf_index,
+proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
                                       tvbuff_t *tvb, const guint bit_offset,
                                       const gint no_of_bits, float value,
                                       const char *format, ...)
@@ -7581,17 +7456,17 @@ proto_tree_add_float_bits_format_value(proto_tree *tree, const int hf_index,
        gchar  *dst;
        header_field_info *hf_field;
 
-       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, 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);
+       return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
 }
 
 proto_item *
-proto_tree_add_int_bits_format_value(proto_tree *tree, const int hf_index,
+proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
                                     tvbuff_t *tvb, const guint bit_offset,
                                     const gint no_of_bits, gint32 value,
                                     const char *format, ...)
@@ -7600,7 +7475,7 @@ proto_tree_add_int_bits_format_value(proto_tree *tree, const int hf_index,
        gchar  *dst;
        header_field_info *hf_field;
 
-       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
 
        switch (hf_field->type) {
                case FT_INT8:
@@ -7617,11 +7492,11 @@ proto_tree_add_int_bits_format_value(proto_tree *tree, const int hf_index,
 
        CREATE_VALUE_STRING(dst, format, ap);
 
-       return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
+       return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
 }
 
 proto_item *
-proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hf_index,
+proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
                                         tvbuff_t *tvb, const guint bit_offset,
                                         const gint no_of_bits, guint32 value,
                                         const char *format, ...)
@@ -7630,13 +7505,13 @@ proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hf_index,
        gchar  *dst;
        header_field_info *hf_field;
 
-       TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, 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);
+       return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
 }
 
 guchar
@@ -7645,6 +7520,24 @@ proto_check_field_name(const gchar *field_name)
        return wrs_check_charset(fld_abbrev_chars, field_name);
 }
 
+gboolean
+tree_expanded(int tree_type)
+{
+       g_assert(tree_type >= 0 && tree_type < num_tree_types);
+       return tree_is_expanded[tree_type >> 5] & (1 << (tree_type & 31));
+}
+
+void
+tree_expanded_set(int tree_type, gboolean value)
+{
+       g_assert(tree_type >= 0 && tree_type < num_tree_types);
+
+       if (value)
+               tree_is_expanded[tree_type >> 5] |= (1 << (tree_type & 31));
+       else
+               tree_is_expanded[tree_type >> 5] &= ~(1 << (tree_type & 31));
+}
+
 /*
  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
  *