Use octet_to_hex() in another place.
[metze/wireshark/wip.git] / epan / to_str.c
index 4555b0d64b47951effdff2e0f96e6a1388edeef8..36bf7b5b320e956ba35a582de34f7f6319d14aa6 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>                /* needed for <netinet/in.h> */
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>       /* needed for <arpa/inet.h> on some platforms */
-#endif
-
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>                /* needed to define AF_ values on UNIX */
-#endif
+#include "config.h"
 
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>          /* needed to define AF_ values on Windows */
-#endif
-
-#ifdef NEED_INET_V6DEFS_H
-# include "inet_v6defs.h"
-#endif
-
-#include "to_str.h"
-#include "value_string.h"
-#include "addr_resolv.h"
-#include "pint.h"
-#include "atalk-utils.h"
-#include "sna-utils.h"
-#include "osi-utils.h"
-#include <epan/dissectors/packet-mtp3.h>
 #include <stdio.h>
+#include <string.h>
 #include <time.h>
+#include <glib.h>
+
 #include "emem.h"
+#include "proto.h"
+#include "to_str.h"
+#include "strutil.h"
 
 /*
  * If a user _does_ pass in a too-small buffer, this is probably
  */
 #define BUF_TOO_SMALL_ERR "[Buffer too small]"
 
-/* Routine to convert a sequence of bytes to a hex string, one byte/two hex
- * digits at at a time, with a specified punctuation character between
- * the bytes.
- *
- * If punct is '\0', no punctuation is applied (and thus
- * the resulting string is (len-1) bytes shorter)
- */
-gchar *
-bytestring_to_str(const guint8 *ad, guint32 len, char punct) {
-  gchar *buf;
-  gchar        *p;
-  int          i = (int) len - 1;
-  guint32      octet;
-  size_t       buflen;
+static inline char
+octet_to_hex(guint8 oct)
+{
   /* At least one version of Apple's C compiler/linker is buggy, causing
      a complaint from the linker about the "literal C string section"
      not ending with '\0' if we initialize a 16-element "char" array with
@@ -97,62 +55,213 @@ bytestring_to_str(const guint8 *ad, guint32 len, char punct) {
       { '0', '1', '2', '3', '4', '5', '6', '7',
         '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
 
+  return hex_digits[oct & 0xF];
+}
+
+static inline char *
+byte_to_hex(char *out, guint32 dword) {
+  *out++ = octet_to_hex(dword >> 4);
+  *out++ = octet_to_hex(dword);
+  return out;
+}
+
+char *
+word_to_hex(char *out, guint16 word) {
+  out = byte_to_hex(out, word >> 8);
+  out = byte_to_hex(out, word);
+  return out;
+}
+
+char *
+word_to_hex_npad(char *out, guint16 word) {
+       if (word >= 0x1000)
+               *out++ = octet_to_hex(word >> 12);
+       if (word >= 0x0100)
+               *out++ = octet_to_hex(word >> 8);
+       if (word >= 0x0010)
+               *out++ = octet_to_hex(word >> 4);
+       *out++ = octet_to_hex(word);
+       return out;
+}
+
+char *
+dword_to_hex(char *out, guint32 dword) {
+  out = byte_to_hex(out, dword >> 24);
+  out = byte_to_hex(out, dword >> 16);
+  out = byte_to_hex(out, dword >>  8);
+  out = byte_to_hex(out, dword);
+  return out;
+}
+
+char *
+dword_to_hex_punct(char *out, guint32 dword, char punct) {
+  out = byte_to_hex(out, dword >> 24);
+  *out++ = punct;
+  out = byte_to_hex(out, dword >> 16);
+  *out++ = punct;
+  out = byte_to_hex(out, dword >>  8);
+  *out++ = punct;
+  out = byte_to_hex(out, dword);
+  return out;
+}
+
+/*
+ * This does *not* null-terminate the string.  It returns a pointer
+ * to the position in the string following the last character it
+ * puts there, so that the caller can either put the null terminator
+ * in or can append more stuff to the buffer.
+ *
+ * There needs to be at least len * 2 bytes left in the buffer.
+ */
+char *
+bytes_to_hexstr(char *out, const guint8 *ad, guint32 len) {
+  guint32 i;
+
+  if (!ad)
+    REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr()");
+
+  for (i = 0; i < len; i++)
+    out = byte_to_hex(out, ad[i]);
+  return out;
+}
+
+/*
+ * This does *not* null-terminate the string.  It returns a pointer
+ * to the position in the string following the last character it
+ * puts there, so that the caller can either put the null terminator
+ * in or can append more stuff to the buffer.
+ *
+ * There needs to be at least len * 3 - 1 bytes left in the buffer.
+ */
+char *
+bytes_to_hexstr_punct(char *out, const guint8 *ad, guint32 len, char punct) {
+  guint32 i;
+
+  if (!ad)
+    REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr_punct()");
+
+  out = byte_to_hex(out, ad[0]);
+  for (i = 1; i < len; i++) {
+    *out++ = punct;
+    out = byte_to_hex(out, ad[i]);
+  }
+  return out;
+}
+
+/* Routine to convert a sequence of bytes to a hex string, one byte/two hex
+ * digits at at a time, with a specified punctuation character between
+ * the bytes.
+ *
+ * If punct is '\0', no punctuation is applied (and thus
+ * the resulting string is (len-1) bytes shorter)
+ */
+const gchar *
+bytestring_to_str(const guint8 *ad, const guint32 len, const char punct) {
+  gchar *buf;
+  size_t       buflen;
+
+  if (!ad)
+    REPORT_DISSECTOR_BUG("Null pointer passed to bytestring_to_str()");
+
+  /* XXX, Old code was using int as iterator... Why len is guint32 anyway?! (darkjames) */
+  if ( ((int) len) < 0)
+     return "";
+
+  if (!len)
+     return "";
+
   if (punct)
     buflen=len*3;
   else
     buflen=len*2 + 1;
 
-  if (buflen < 3 || i < 0) {
-    return "";
-  }
+  buf=(gchar *)ep_alloc(buflen);
 
-  buf=ep_alloc(buflen);
-  p = &buf[buflen - 1];
-  *p = '\0';
-  for (;;) {
-    octet = ad[i];
-    *--p = hex_digits[octet&0xF];
-    octet >>= 4;
-    *--p = hex_digits[octet&0xF];
-    if (i <= 0)
-      break;
-    if (punct)
-      *--p = punct;
-    i--;
-  }
-  return p;
+  if (punct)
+    bytes_to_hexstr_punct(buf, ad, len, punct);
+  else
+    bytes_to_hexstr(buf, ad, len);
+
+  buf[buflen-1] = '\0';
+  return buf;
 }
 
-/* Wrapper for the most common case of asking
- * for a string using a colon as the hex-digit separator.
- */
-/* XXX FIXME
-remove this one later when every call has been converted to address_to_str()
-*/
+/* Max string length for displaying byte string.  */
+#define        MAX_BYTE_STR_LEN        48
+
 gchar *
-ether_to_str(const guint8 *ad)
-{
-       return bytestring_to_str(ad, 6, ':');
+bytes_to_str(const guint8 *bd, int bd_len) {
+  gchar *cur;
+  gchar *cur_ptr;
+  int truncated = 0;
+
+  if (!bd)
+    REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_str()");
+
+  cur=(gchar *)ep_alloc(MAX_BYTE_STR_LEN+3+1);
+  if (bd_len <= 0) { cur[0] = '\0'; return cur; }
+
+  if (bd_len > MAX_BYTE_STR_LEN/2) {   /* bd_len > 24 */
+    truncated = 1;
+    bd_len = MAX_BYTE_STR_LEN/2;
+  }
+
+  cur_ptr = bytes_to_hexstr(cur, bd, bd_len);  /* max MAX_BYTE_STR_LEN bytes */
+
+  if (truncated)
+    cur_ptr = g_stpcpy(cur_ptr, "...");                /* 3 bytes */
+
+  *cur_ptr = '\0';                             /* 1 byte */
+  return cur;
 }
 
-/*
- This function is very fast and this function is called a lot.
- XXX update the address_to_str stuff to use this function.
-*/
+/* Turn an array of bytes into a string showing the bytes in hex with
+ * punct as a bytes separator.
+ */
 gchar *
-ip_to_str(const guint8 *ad) {
-  gchar *buf;
+bytes_to_str_punct(const guint8 *bd, int bd_len, gchar punct) {
+  gchar *cur;
+  gchar *cur_ptr;
+  int truncated = 0;
 
-  buf=ep_alloc(MAX_IP_STR_LEN);
-  ip_to_str_buf(ad, buf, MAX_IP_STR_LEN);
-  return buf;
+  if (!punct)
+    return bytes_to_str(bd, bd_len);
+
+  cur=(gchar *)ep_alloc(MAX_BYTE_STR_LEN+3+1);
+  if (bd_len <= 0) { cur[0] = '\0'; return cur; }
+
+  if (bd_len > MAX_BYTE_STR_LEN/3) {   /* bd_len > 16 */
+   truncated = 1;
+   bd_len = MAX_BYTE_STR_LEN/3;
+  }
+
+  cur_ptr = bytes_to_hexstr_punct(cur, bd, bd_len, punct); /* max MAX_BYTE_STR_LEN-1 bytes */
+
+  if (truncated) {
+    *cur_ptr++ = punct;                                /* 1 byte */
+    cur_ptr    = g_stpcpy(cur_ptr, "...");     /* 3 bytes */
+  }
+
+  *cur_ptr = '\0';
+  return cur;
 }
 
-/*
- This function is very fast and this function is called a lot.
- XXX update the address_to_str stuff to use this function.
-*/
-static const char * const fast_strings[] = {
+static int
+guint32_to_str_buf_len(const guint32 u) {
+    if (u >= 1000000000)return 10;
+    if (u >= 100000000) return 9;
+    if (u >= 10000000) return 8;
+    if (u >= 1000000)  return 7;
+    if (u >= 100000)   return 6;
+    if (u >= 10000)    return 5;
+    if (u >= 1000)     return 4;
+    if (u >= 100)      return 3;
+    if (u >= 10)       return 2;
+
+    return 1;
+}
+
+static const char fast_strings[][4] = {
 "0", "1", "2", "3", "4", "5", "6", "7",
 "8", "9", "10", "11", "12", "13", "14", "15",
 "16", "17", "18", "19", "20", "21", "22", "23",
@@ -186,158 +295,33 @@ static const char * const fast_strings[] = {
 "240", "241", "242", "243", "244", "245", "246", "247",
 "248", "249", "250", "251", "252", "253", "254", "255"
 };
-void
-ip_to_str_buf(const guint8 *ad, gchar *buf, int buf_len)
-{
-       register gchar const *p;
-       register gchar *b=buf;
 
-       if (buf_len < MAX_IP_STR_LEN) {
-               g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR );                 /* Let the unexpected value alert user */
-               return;
-       }
-
-       p=fast_strings[*ad++];
-       do {
-               *b++=*p;
-               p++;
-       } while(*p);
-       *b++='.';
-
-       p=fast_strings[*ad++];
-       do {
-               *b++=*p;
-               p++;
-       } while(*p);
-       *b++='.';
-
-       p=fast_strings[*ad++];
-       do {
-               *b++=*p;
-               p++;
-       } while(*p);
-       *b++='.';
-
-       p=fast_strings[*ad];
-       do {
-               *b++=*p;
-               p++;
-       } while(*p);
-       *b=0;
-}
-
-
-/* XXX FIXME
-remove this one later when every call has been converted to address_to_str()
-*/
-gchar *
-ip6_to_str(const struct e_in6_addr *ad) {
-#ifndef INET6_ADDRSTRLEN
-#define INET6_ADDRSTRLEN 46
-#endif
-  static gchar *str;
-
-  str=ep_alloc(INET6_ADDRSTRLEN+1);
-
-  ip6_to_str_buf(ad, str);
-  return str;
-}
+char *uint_to_str_back(char *ptr, guint32 value);
 
 void
-ip6_to_str_buf(const struct e_in6_addr *ad, gchar *buf)
-{
-  inet_ntop(AF_INET6, (const guchar*)ad, buf, INET6_ADDRSTRLEN);
-}
-
-gchar*
-ipx_addr_to_str(guint32 net, const guint8 *ad)
-{
-       gchar   *buf;
-       char    *name;
-
-       buf=ep_alloc(8+1+MAXNAMELEN+1); /* 8 digits, 1 period, NAME, 1 null */
-       name = get_ether_name_if_known(ad);
-
-       if (name) {
-               g_snprintf(buf, 8+1+MAXNAMELEN+1, "%s.%s", get_ipxnet_name(net), name);
-       }
-       else {
-               g_snprintf(buf, 8+1+MAXNAMELEN+1, "%s.%s", get_ipxnet_name(net),
-                   bytestring_to_str(ad, 6, '\0'));
-       }
-       return buf;
-}
+guint32_to_str_buf(guint32 u, gchar *buf, int buf_len) {
+  int str_len = guint32_to_str_buf_len(u)+1;
 
-gchar*
-ipxnet_to_string(const guint8 *ad)
-{
-       guint32 addr = pntohl(ad);
-       return ipxnet_to_str_punct(addr, ' ');
-}
+  gchar *bp = &buf[str_len];
 
-gchar *
-ipxnet_to_str_punct(const guint32 ad, char punct)
-{
-  gchar        *buf;
-  gchar        *p;
-  int          i;
-  guint32      octet;
-  /* At least one version of Apple's C compiler/linker is buggy, causing
-     a complaint from the linker about the "literal C string section"
-     not ending with '\0' if we initialize a 16-element "char" array with
-     a 16-character string, the fact that initializing such an array with
-     such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
-     '\0' byte in the string nonwithstanding. */
-  static const gchar hex_digits[16] =
-      { '0', '1', '2', '3', '4', '5', '6', '7',
-        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-  static const guint32  octet_mask[4] =
-         { 0xff000000 , 0x00ff0000, 0x0000ff00, 0x000000ff };
-
-  buf=ep_alloc(12);
-  p = &buf[12];
-  *--p = '\0';
-  i = 3;
-  for (;;) {
-    octet = (ad & octet_mask[i]) >> ((3 - i) * 8);
-    *--p = hex_digits[octet&0xF];
-    octet >>= 4;
-    *--p = hex_digits[octet&0xF];
-    if (i == 0)
-      break;
-    if (punct)
-      *--p = punct;
-    i--;
+  if (buf_len < str_len) {
+    g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len);        /* Let the unexpected value alert user */
+    return;
   }
-  return p;
-}
 
-gchar *
-vines_addr_to_str(const guint8 *addrp)
-{
-  gchar        *buf;
+  *--bp = '\0';
 
-  buf=ep_alloc(214);
-
-  vines_addr_to_str_buf(addrp, buf, 214);
-  return buf;
+  uint_to_str_back(bp, u);
 }
 
-void
-vines_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
-{
-  g_snprintf(buf, buf_len, "%08x.%04x", pntohl(&addrp[0]), pntohs(&addrp[4]));
-}
+gchar *
+guint32_to_str(const guint32 u) {
+  int str_len = 16; /* guint32_to_str_buf_len(u)+1; */
 
+  gchar *bp = (gchar *)ep_alloc(str_len);
+  guint32_to_str_buf(u, bp, str_len);
 
-void
-usb_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
-{
-  if(pletohl(&addrp[0])==0xffffffff){
-    g_snprintf(buf, buf_len, "host");
-  } else {
-    g_snprintf(buf, buf_len, "%d.%d", pletohl(&addrp[0]), pletohl(&addrp[4]));
-  }
+  return bp;
 }
 
 #define        PLURALIZE(n)    (((n) > 1) ? "s" : "")
@@ -346,7 +330,8 @@ usb_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
 /*
  * Maximum length of a string showing days/hours/minutes/seconds.
  * (Does not include the terminating '\0'.)
- * Includes space for a '-' sign for any negative compunents.
+ * Includes space for a '-' sign for any negative components.
+ * -12345 days, 12 hours, 12 minutes, 12.123 seconds
  */
 #define TIME_SECS_LEN  (10+1+4+2+2+5+2+2+7+2+2+7+4)
 
@@ -359,101 +344,155 @@ usb_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
  * If time is negative, add a '-' to all non-null components.
  */
 static void
-time_secs_to_str_buf(gint32 time, guint32 frac, gboolean is_nsecs,
-                          gchar *buf, int buf_len)
+time_secs_to_str_buf(gint32 time_val, const guint32 frac, const gboolean is_nsecs,
+                          emem_strbuf_t *buf)
 {
-  static gchar *p;
   int hours, mins, secs;
   const gchar *msign = "";
   gboolean do_comma = FALSE;
 
-  if(time<0){
-    time= -time;
-    msign="-";
+  if(time_val == G_MININT32) { /* That Which Shall Not Be Negated */
+    ep_strbuf_append_printf(buf, "Unable to cope with time value %d", time_val);
+    return;
   }
 
-  if(time<0){  /* We've overflowed. */
-    g_snprintf(buf, buf_len, "Unable to cope with time value %d", time);
-    return;
+  if(time_val < 0){
+    time_val = -time_val;
+    msign = "-";
   }
 
-  secs = time % 60;
-  time /= 60;
-  mins = time % 60;
-  time /= 60;
-  hours = time % 24;
-  time /= 24;
+  secs = time_val % 60;
+  time_val /= 60;
+  mins = time_val % 60;
+  time_val /= 60;
+  hours = time_val % 24;
+  time_val /= 24;
 
-  /* This would probably be cleaner if we used GStrings instead. */
-  p = buf;
-  if (time != 0) {
-    p += g_snprintf(p, buf_len, "%s%u day%s", time?msign:"", time, PLURALIZE(time));
+  if (time_val != 0) {
+    ep_strbuf_append_printf(buf, "%s%u day%s", msign, time_val, PLURALIZE(time_val));
     do_comma = TRUE;
+    msign="";
   }
   if (hours != 0) {
-    p += g_snprintf(p, buf_len-(p-buf), "%s%s%u hour%s", COMMA(do_comma), hours?msign:"", hours, PLURALIZE(hours));
+    ep_strbuf_append_printf(buf, "%s%s%u hour%s", COMMA(do_comma), msign, hours, PLURALIZE(hours));
     do_comma = TRUE;
+    msign="";
   }
   if (mins != 0) {
-    p += g_snprintf(p, buf_len-(p-buf), "%s%s%u minute%s", COMMA(do_comma), mins?msign:"", mins, PLURALIZE(mins));
+    ep_strbuf_append_printf(buf, "%s%s%u minute%s", COMMA(do_comma), msign, mins, PLURALIZE(mins));
     do_comma = TRUE;
+    msign="";
   }
   if (secs != 0 || frac != 0) {
     if (frac != 0) {
       if (is_nsecs)
-        p += g_snprintf(p, buf_len-(p-buf), "%s%s%u.%09u seconds", COMMA(do_comma), msign, secs, frac);
+        ep_strbuf_append_printf(buf, "%s%s%u.%09u seconds", COMMA(do_comma), msign, secs, frac);
       else
-        p += g_snprintf(p, buf_len-(p-buf), "%s%s%u.%03u seconds", COMMA(do_comma), msign, secs, frac);
+        ep_strbuf_append_printf(buf, "%s%s%u.%03u seconds", COMMA(do_comma), msign, secs, frac);
     } else
-      p += g_snprintf(p, buf_len-(p-buf), "%s%s%u second%s", COMMA(do_comma), msign, secs, PLURALIZE(secs));
+      ep_strbuf_append_printf(buf, "%s%s%u second%s", COMMA(do_comma), msign, secs, PLURALIZE(secs));
   }
 }
 
 gchar *
-time_secs_to_str(gint32 time)
+time_secs_to_str(const gint32 time_val)
 {
-  gchar *buf;
+  emem_strbuf_t *buf;
 
-  buf=ep_alloc(TIME_SECS_LEN+1);
+  buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
 
-  if (time == 0) {
-    g_snprintf(buf, TIME_SECS_LEN+1, "0 time");
-    return buf;
+  if (time_val == 0) {
+    ep_strbuf_append(buf, "0 seconds");
+    return buf->str;
   }
 
-  time_secs_to_str_buf(time, 0, FALSE, buf, TIME_SECS_LEN+1);
-  return buf;
+  time_secs_to_str_buf(time_val, 0, FALSE, buf);
+  return buf->str;
+}
+
+static void
+time_secs_to_str_buf_unsigned(guint32 time_val, const guint32 frac, const gboolean is_nsecs,
+                        emem_strbuf_t *buf)
+{
+  int hours, mins, secs;
+  gboolean do_comma = FALSE;
+
+  secs = time_val % 60;
+  time_val /= 60;
+  mins = time_val % 60;
+  time_val /= 60;
+  hours = time_val % 24;
+  time_val /= 24;
+
+  if (time_val != 0) {
+    ep_strbuf_append_printf(buf, "%u day%s", time_val, PLURALIZE(time_val));
+    do_comma = TRUE;
+  }
+  if (hours != 0) {
+    ep_strbuf_append_printf(buf, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
+    do_comma = TRUE;
+  }
+  if (mins != 0) {
+    ep_strbuf_append_printf(buf, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
+    do_comma = TRUE;
+  }
+  if (secs != 0 || frac != 0) {
+    if (frac != 0) {
+      if (is_nsecs)
+        ep_strbuf_append_printf(buf, "%s%u.%09u seconds", COMMA(do_comma), secs, frac);
+      else
+        ep_strbuf_append_printf(buf, "%s%u.%03u seconds", COMMA(do_comma), secs, frac);
+    } else
+      ep_strbuf_append_printf(buf, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
+  }
 }
 
 gchar *
-time_msecs_to_str(gint32 time)
+time_secs_to_str_unsigned(const guint32 time_val)
 {
-  gchar *buf;
+  emem_strbuf_t *buf;
+
+  buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
+
+  if (time_val == 0) {
+    ep_strbuf_append(buf, "0 seconds");
+    return buf->str;
+  }
+
+  time_secs_to_str_buf_unsigned(time_val, 0, FALSE, buf);
+  return buf->str;
+}
+
+
+gchar *
+time_msecs_to_str(gint32 time_val)
+{
+  emem_strbuf_t *buf;
   int msecs;
 
-  buf=ep_alloc(TIME_SECS_LEN+1+3+1);
+  buf=ep_strbuf_sized_new(TIME_SECS_LEN+1+3+1, TIME_SECS_LEN+1+3+1);
 
-  if (time == 0) {
-    g_snprintf(buf, TIME_SECS_LEN+1+3+1, "0 time");
-    return buf;
+  if (time_val == 0) {
+    ep_strbuf_append(buf, "0 seconds");
+    return buf->str;
   }
 
-  if(time<0){
+  if(time_val<0){
     /* oops we got passed a negative time */
-    time= -time;
-    msecs = time % 1000;
-    time /= 1000;
-    time= -time;
+    time_val= -time_val;
+    msecs = time_val % 1000;
+    time_val /= 1000;
+    time_val= -time_val;
   } else {
-    msecs = time % 1000;
-    time /= 1000;
+    msecs = time_val % 1000;
+    time_val /= 1000;
   }
 
-  time_secs_to_str_buf(time, msecs, FALSE, buf, TIME_SECS_LEN+1+3+1);
-  return buf;
+  time_secs_to_str_buf(time_val, msecs, FALSE, buf);
+  return buf->str;
 }
 
-static const char *mon_names[12] = {
+static const char mon_names[12][4] = {
        "Jan",
        "Feb",
        "Mar",
@@ -468,16 +507,65 @@ static const char *mon_names[12] = {
        "Dec"
 };
 
+static const gchar *get_zonename(struct tm *tmp) {
+#if defined(HAVE_TM_ZONE)
+       return tmp->tm_zone;
+#else
+       if ((tmp->tm_isdst != 0) && (tmp->tm_isdst != 1)) {
+               return "???";
+       }
+# if defined(HAVE_TZNAME)
+       return tzname[tmp->tm_isdst];
+
+# elif defined(_WIN32)
+       /* Windows C Runtime:                                                 */
+       /*   _tzname is encoded using the "system default ansi code page"     */
+       /*     ("which is not necessarily the same as the C library locale"). */
+       /*     So: _tzname must be converted to UTF8 before use.              */
+       /*   Alternative: use Windows GetTimeZoneInformation() to get the     */
+        /*     timezone name in UTF16 and convert same to UTF8.               */
+       /*   XXX: the result is that the timezone name will be based upon the */
+       /*    system code page (iow: the charset of the system).              */
+       /*    Since Wireshark is not internationalized, it would seem more    */
+       /*    correct to show the timezone name in English, no matter what    */
+        /*    the system code page, but I don't how to do that (or if it's    */
+        /*    really even possible).                                          */
+        /*    In any case converting to UTF8 presumably at least keeps GTK    */
+        /*    happy. (A bug was reported wherein Wireshark crashed in GDK     */
+        /*    on a "Japanese version of Windows XP" when trying to copy       */
+        /*    the date/time string (containing a copy of _tz_name) to the     */
+        /*    clipboard).                                                     */
+
+       {
+               static char *ws_tzname[2] = {NULL, NULL};
+
+               /* The g_malloc'd value returned from g_locale_to_utf8() is   */
+               /*  cached for all further use so there's no need to ever     */
+               /*  g_free() that value.                                      */
+               if (ws_tzname[tmp->tm_isdst] == NULL) {
+                       ws_tzname[tmp->tm_isdst] = g_locale_to_utf8(_tzname[tmp->tm_isdst], -1, NULL, NULL, NULL);
+                       if (ws_tzname[tmp->tm_isdst] == NULL) {
+                               ws_tzname[tmp->tm_isdst] = "???";
+                       }
+               }
+               return ws_tzname[tmp->tm_isdst];
+       }
+# else
+       return tmp->tm_isdst ? "?DT" : "?ST";
+
+# endif
+#endif
+}
+
 gchar *
-abs_time_to_str(nstime_t *abs_time)
+abs_time_to_str(const nstime_t *abs_time, const absolute_time_display_e fmt,
+   gboolean show_zone)
 {
-        struct tm *tmp;
-        gchar *buf;
-
-        buf=ep_alloc(3+1+2+2+4+1+2+1+2+1+2+1+9+1);
+        struct tm *tmp = NULL;
+        const char *zonename = "???";
+        gchar *buf = NULL;
 
-        
-#ifdef _MSC_VER
+#if (defined _WIN32) && (_MSC_VER < 1500)
         /* calling localtime() on MSVC 2005 with huge values causes it to crash */
         /* XXX - find the exact value that still does work */
         /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
@@ -485,95 +573,206 @@ abs_time_to_str(nstime_t *abs_time)
             tmp = NULL;
         } else
 #endif
-        tmp = localtime(&abs_time->secs);
+        switch (fmt) {
+
+        case ABSOLUTE_TIME_UTC:
+        case ABSOLUTE_TIME_DOY_UTC:
+                tmp = gmtime(&abs_time->secs);
+                zonename = "UTC";
+                break;
+
+       case ABSOLUTE_TIME_LOCAL:
+                tmp = localtime(&abs_time->secs);
+                if (tmp) {
+                       zonename = get_zonename(tmp);
+                }
+                break;
+        }
         if (tmp) {
-               g_snprintf(buf, 3+1+2+2+4+1+2+1+2+1+2+1+9+1,
-                   "%s %2d, %d %02d:%02d:%02d.%09ld",
-                   mon_names[tmp->tm_mon],
-                   tmp->tm_mday,
-                   tmp->tm_year + 1900,
-                   tmp->tm_hour,
-                   tmp->tm_min,
-                   tmp->tm_sec,
-                   (long)abs_time->nsecs);
+                switch (fmt) {
+
+                case ABSOLUTE_TIME_DOY_UTC:
+                       if (show_zone) {
+                               buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d.%09ld %s",
+                                   tmp->tm_year + 1900,
+                                   tmp->tm_yday + 1,
+                                   tmp->tm_hour,
+                                   tmp->tm_min,
+                                   tmp->tm_sec,
+                                   (long)abs_time->nsecs,
+                                   zonename);
+                        } else {
+                               buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d.%09ld",
+                                   tmp->tm_year + 1900,
+                                   tmp->tm_yday + 1,
+                                   tmp->tm_hour,
+                                   tmp->tm_min,
+                                   tmp->tm_sec,
+                                   (long)abs_time->nsecs);
+                        }
+                        break;
+
+                case ABSOLUTE_TIME_UTC:
+                case ABSOLUTE_TIME_LOCAL:
+                       if (show_zone) {
+                               buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d.%09ld %s",
+                                   mon_names[tmp->tm_mon],
+                                   tmp->tm_mday,
+                                   tmp->tm_year + 1900,
+                                   tmp->tm_hour,
+                                   tmp->tm_min,
+                                   tmp->tm_sec,
+                                   (long)abs_time->nsecs,
+                                   zonename);
+                       } else {
+                               buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d.%09ld",
+                                   mon_names[tmp->tm_mon],
+                                   tmp->tm_mday,
+                                   tmp->tm_year + 1900,
+                                   tmp->tm_hour,
+                                   tmp->tm_min,
+                                   tmp->tm_sec,
+                                   (long)abs_time->nsecs);
+                       }
+                        break;
+                }
         } else
-               strncpy(buf, "Not representable", 3+1+2+2+4+1+2+1+2+1+2+1+9+1);
+                buf = ep_strdup("Not representable");
         return buf;
 }
 
 gchar *
-abs_time_secs_to_str(time_t abs_time)
+abs_time_secs_to_str(const time_t abs_time, const absolute_time_display_e fmt,
+    gboolean show_zone)
 {
-        struct tm *tmp;
-        gchar *buf;
-
-       buf=ep_alloc(3+1+2+2+4+1+2+1+2+1+2+1);
+        struct tm *tmp = NULL;
+        const char *zonename = "???";
+        gchar *buf = NULL;
 
-        tmp = localtime(&abs_time);
+#if (defined _WIN32) && (_MSC_VER < 1500)
+        /* calling localtime() on MSVC 2005 with huge values causes it to crash */
+        /* XXX - find the exact value that still does work */
+        /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
+        if(abs_time > 2000000000) {
+            tmp = NULL;
+        } else
+#endif
+        switch (fmt) {
+
+        case ABSOLUTE_TIME_UTC:
+        case ABSOLUTE_TIME_DOY_UTC:
+                tmp = gmtime(&abs_time);
+                zonename = "UTC";
+                break;
+
+       case ABSOLUTE_TIME_LOCAL:
+                tmp = localtime(&abs_time);
+                if (tmp) {
+                       zonename = get_zonename(tmp);
+                }
+                break;
+        }
         if (tmp) {
-               g_snprintf(buf, 3+1+2+2+4+1+2+1+2+1+2+1,
-                   "%s %2d, %d %02d:%02d:%02d",
-                   mon_names[tmp->tm_mon],
-                   tmp->tm_mday,
-                   tmp->tm_year + 1900,
-                   tmp->tm_hour,
-                   tmp->tm_min,
-                   tmp->tm_sec);
+                switch (fmt) {
+
+                case ABSOLUTE_TIME_DOY_UTC:
+                       if (show_zone) {
+                               buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d %s",
+                                   tmp->tm_year + 1900,
+                                   tmp->tm_yday + 1,
+                                   tmp->tm_hour,
+                                   tmp->tm_min,
+                                   tmp->tm_sec,
+                                   zonename);
+                       } else {
+                               buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d",
+                                   tmp->tm_year + 1900,
+                                   tmp->tm_yday + 1,
+                                   tmp->tm_hour,
+                                   tmp->tm_min,
+                                   tmp->tm_sec);
+                       }
+                        break;
+
+                case ABSOLUTE_TIME_UTC:
+                case ABSOLUTE_TIME_LOCAL:
+                       if (show_zone) {
+                               buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d %s",
+                                   mon_names[tmp->tm_mon],
+                                   tmp->tm_mday,
+                                   tmp->tm_year + 1900,
+                                   tmp->tm_hour,
+                                   tmp->tm_min,
+                                   tmp->tm_sec,
+                                   zonename);
+                        } else {
+                               buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d",
+                                   mon_names[tmp->tm_mon],
+                                   tmp->tm_mday,
+                                   tmp->tm_year + 1900,
+                                   tmp->tm_hour,
+                                   tmp->tm_min,
+                                   tmp->tm_sec);
+                        }
+                        break;
+                }
         } else
-               strncpy(buf, "Not representable", 3+1+2+2+4+1+2+1+2+1+2+1);
+                buf = ep_strdup("Not representable");
         return buf;
 }
 
 void
-display_signed_time(gchar *buf, int buflen, gint32 sec, gint32 frac,
-    time_res_t units)
+display_signed_time(gchar *buf, int buflen, const gint32 sec, gint32 frac,
+    const to_str_time_res_t units)
 {
-       const char *sign;
-
        /* If the fractional part of the time stamp is negative,
           print its absolute value and, if the seconds part isn't
           (the seconds part should be zero in that case), stick
           a "-" in front of the entire time stamp. */
-       sign = "";
        if (frac < 0) {
                frac = -frac;
-               if (sec >= 0)
-                       sign = "-";
+               if (sec >= 0) {
+                       if (buflen < 1) {
+                         return;
+                       }
+                       buf[0] = '-';
+                       buf++;
+                       buflen--;
+               }
        }
        switch (units) {
 
-       case SECS:
-               g_snprintf(buf, buflen, "%s%d", sign, sec);
+       case TO_STR_TIME_RES_T_SECS:
+               g_snprintf(buf, buflen, "%d", sec);
                break;
 
-       case DSECS:
-               g_snprintf(buf, buflen, "%s%d.%01d", sign, sec, frac);
+       case TO_STR_TIME_RES_T_DSECS:
+               g_snprintf(buf, buflen, "%d.%01d", sec, frac);
                break;
 
-       case CSECS:
-               g_snprintf(buf, buflen, "%s%d.%02d", sign, sec, frac);
+       case TO_STR_TIME_RES_T_CSECS:
+               g_snprintf(buf, buflen, "%d.%02d", sec, frac);
                break;
 
-       case MSECS:
-               g_snprintf(buf, buflen, "%s%d.%03d", sign, sec, frac);
+       case TO_STR_TIME_RES_T_MSECS:
+               g_snprintf(buf, buflen, "%d.%03d", sec, frac);
                break;
 
-       case USECS:
-               g_snprintf(buf, buflen, "%s%d.%06d", sign, sec, frac);
+       case TO_STR_TIME_RES_T_USECS:
+               g_snprintf(buf, buflen, "%d.%06d", sec, frac);
                break;
 
-       case NSECS:
-               g_snprintf(buf, buflen, "%s%d.%09d", sign, sec, frac);
+       case TO_STR_TIME_RES_T_NSECS:
+               g_snprintf(buf, buflen, "%d.%09d", sec, frac);
                break;
        }
 }
 
 
 void
-display_epoch_time(gchar *buf, int buflen, time_t sec, gint32 frac,
-    time_res_t units)
+display_epoch_time(gchar *buf, int buflen, const time_t sec, gint32 frac,
+    const to_str_time_res_t units)
 {
-       const char *sign;
        double elapsed_secs;
 
        elapsed_secs = difftime(sec,(time_t)0);
@@ -584,36 +783,41 @@ display_epoch_time(gchar *buf, int buflen, time_t sec, gint32 frac,
           print its absolute value and, if the seconds part isn't
           (the seconds part should be zero in that case), stick
           a "-" in front of the entire time stamp. */
-       sign = "";
        if (frac < 0) {
                frac = -frac;
-               if (elapsed_secs >= 0)
-                       sign = "-";
+               if (elapsed_secs >= 0) {
+                       if (buflen < 1) {
+                         return;
+                       }
+                       buf[0] = '-';
+                       buf++;
+                       buflen--;
+               }
        }
        switch (units) {
 
-       case SECS:
-               g_snprintf(buf, buflen, "%s%0.0f", sign, elapsed_secs);
+       case TO_STR_TIME_RES_T_SECS:
+               g_snprintf(buf, buflen, "%0.0f", elapsed_secs);
                break;
 
-       case DSECS:
-               g_snprintf(buf, buflen, "%s%0.0f.%01d", sign, elapsed_secs, frac);
+       case TO_STR_TIME_RES_T_DSECS:
+               g_snprintf(buf, buflen, "%0.0f.%01d", elapsed_secs, frac);
                break;
 
-       case CSECS:
-               g_snprintf(buf, buflen, "%s%0.0f.%02d", sign, elapsed_secs, frac);
+       case TO_STR_TIME_RES_T_CSECS:
+               g_snprintf(buf, buflen, "%0.0f.%02d", elapsed_secs, frac);
                break;
 
-       case MSECS:
-               g_snprintf(buf, buflen, "%s%0.0f.%03d", sign, elapsed_secs, frac);
+       case TO_STR_TIME_RES_T_MSECS:
+               g_snprintf(buf, buflen, "%0.0f.%03d", elapsed_secs, frac);
                break;
 
-       case USECS:
-               g_snprintf(buf, buflen, "%s%0.0f.%06d", sign, elapsed_secs, frac);
+       case TO_STR_TIME_RES_T_USECS:
+               g_snprintf(buf, buflen, "%0.0f.%06d", elapsed_secs, frac);
                break;
 
-       case NSECS:
-               g_snprintf(buf, buflen, "%s%0.0f.%09d", sign, elapsed_secs, frac);
+       case TO_STR_TIME_RES_T_NSECS:
+               g_snprintf(buf, buflen, "%0.0f.%09d", elapsed_secs, frac);
                break;
        }
 }
@@ -622,42 +826,38 @@ display_epoch_time(gchar *buf, int buflen, time_t sec, gint32 frac,
  * Display a relative time as days/hours/minutes/seconds.
  */
 gchar *
-rel_time_to_str(nstime_t *rel_time)
+rel_time_to_str(const nstime_t *rel_time)
 {
-       gchar *buf;
-       char *p;
-       const char *sign;
-       gint32 time;
+       emem_strbuf_t *buf;
+       gint32 time_val;
        gint32 nsec;
 
-       buf=ep_alloc(1+TIME_SECS_LEN+1+6+1);
-       p = buf;
+       buf=ep_strbuf_sized_new(1+TIME_SECS_LEN+1+6+1, 1+TIME_SECS_LEN+1+6+1);
 
        /* If the nanoseconds part of the time stamp is negative,
           print its absolute value and, if the seconds part isn't
           (the seconds part should be zero in that case), stick
           a "-" in front of the entire time stamp. */
-       sign = "";
-       time = (gint) rel_time->secs;
+       time_val = (gint) rel_time->secs;
        nsec = rel_time->nsecs;
-       if (time == 0 && nsec == 0) {
-               g_snprintf(buf, 1+TIME_SECS_LEN+1+6+1, "0.000000000 seconds");
-               return buf;
+       if (time_val == 0 && nsec == 0) {
+               ep_strbuf_append(buf, "0.000000000 seconds");
+               return buf->str;
        }
        if (nsec < 0) {
                nsec = -nsec;
-               *p++ = '-';
+               ep_strbuf_append_c(buf, '-');
 
                /*
                 * We assume here that "rel_time->secs" is negative
                 * or zero; if it's not, the time stamp is bogus,
                 * with a positive seconds and negative microseconds.
                 */
-               time = (gint) -rel_time->secs;
+               time_val = (gint) -rel_time->secs;
        }
 
-       time_secs_to_str_buf(time, nsec, TRUE, p, 1+TIME_SECS_LEN+1+6+1);
-       return buf;
+       time_secs_to_str_buf(time_val, nsec, TRUE, buf);
+       return buf->str;
 }
 
 #define REL_TIME_SECS_LEN      (1+10+1+9+1)
@@ -666,88 +866,83 @@ rel_time_to_str(nstime_t *rel_time)
  * Display a relative time as seconds.
  */
 gchar *
-rel_time_to_secs_str(nstime_t *rel_time)
+rel_time_to_secs_str(const nstime_t *rel_time)
 {
         gchar *buf;
 
-       buf=ep_alloc(REL_TIME_SECS_LEN);
+       buf=(gchar *)ep_alloc(REL_TIME_SECS_LEN);
 
         display_signed_time(buf, REL_TIME_SECS_LEN, (gint32) rel_time->secs,
-            rel_time->nsecs, NSECS);
+            rel_time->nsecs, TO_STR_TIME_RES_T_NSECS);
         return buf;
 }
 
+/*
+ * Generates a string representing the bits in a bitfield at "bit_offset" from an 8 bit boundary
+ * with the length in bits of no_of_bits based on value.
+ * Ex: ..xx x...
+ */
 
-/* XXX FIXME
-remove this one later when every call has been converted to address_to_str()
-*/
-gchar *
-fc_to_str(const guint8 *ad)
+char *
+decode_bits_in_field(const guint bit_offset, const gint no_of_bits, const guint64 value)
 {
-    return bytestring_to_str (ad, 3, '.');
-}
-
-/* FC Network Header Network Address Authority Identifiers */
+       guint64 mask = 0,tmp;
+       char *str;
+       int bit, str_p = 0;
+       int i;
+
+       mask = 1;
+       mask = mask << (no_of_bits-1);
+
+       /* Prepare the string, 256 pos for the bits and zero termination, + 64 for the spaces */
+       str=(char *)ep_alloc0(256+64);
+       for(bit=0;bit<((int)(bit_offset&0x07));bit++){
+               if(bit&&(!(bit%4))){
+                       str[str_p] = ' ';
+                       str_p++;
+               }
+               str[str_p] = '.';
+               str_p++;
+       }
 
-#define FC_NH_NAA_IEEE         1       /* IEEE 802.1a */
-#define FC_NH_NAA_IEEE_E       2       /* IEEE Exteneded */
-#define FC_NH_NAA_LOCAL                3
-#define FC_NH_NAA_IP           4       /* 32-bit IP address */
-#define FC_NH_NAA_IEEE_R       5       /* IEEE Registered */
-#define FC_NH_NAA_IEEE_R_E     6       /* IEEE Registered Exteneded */
-/* according to FC-PH 3 draft these are now reclaimed and reserved */
-#define FC_NH_NAA_CCITT_INDV   12      /* CCITT 60 bit individual address */
-#define FC_NH_NAA_CCITT_GRP    14      /* CCITT 60 bit group address */
+       /* read the bits for the int */
+       for(i=0;i<no_of_bits;i++){
+               if(bit&&(!(bit%4))){
+                       str[str_p] = ' ';
+                       str_p++;
+               }
+               if(bit&&(!(bit%8))){
+                       str[str_p] = ' ';
+                       str_p++;
+               }
+               bit++;
+               tmp = value & mask;
+               if(tmp != 0){
+                       str[str_p] = '1';
+                       str_p++;
+               } else {
+                       str[str_p] = '0';
+                       str_p++;
+               }
+               mask = mask>>1;
+       }
 
-gchar *
-fcwwn_to_str (const guint8 *ad)
-{
-    int fmt;
-    guint8 oui[6];
-    gchar *ethstr;
-
-    if (ad == NULL) return NULL;
-
-    ethstr=ep_alloc(512);
-
-    fmt = (ad[0] & 0xF0) >> 4;
-
-    switch (fmt) {
-
-    case FC_NH_NAA_IEEE:
-    case FC_NH_NAA_IEEE_E:
-        memcpy (oui, &ad[2], 6);
-        g_snprintf (ethstr, 512, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", ad[0],
-                 ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7],
-                 get_manuf_name (oui));
-        break;
-
-    case FC_NH_NAA_IEEE_R:
-        oui[0] = ((ad[0] & 0x0F) << 4) | ((ad[1] & 0xF0) >> 4);
-        oui[1] = ((ad[1] & 0x0F) << 4) | ((ad[2] & 0xF0) >> 4);
-        oui[2] = ((ad[2] & 0x0F) << 4) | ((ad[3] & 0xF0) >> 4);
-        oui[3] = ((ad[3] & 0x0F) << 4) | ((ad[4] & 0xF0) >> 4);
-        oui[4] = ((ad[4] & 0x0F) << 4) | ((ad[5] & 0xF0) >> 4);
-        oui[5] = ((ad[5] & 0x0F) << 4) | ((ad[6] & 0xF0) >> 4);
-
-        g_snprintf (ethstr, 512, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", ad[0],
-                 ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7],
-                 get_manuf_name (oui));
-        break;
-
-    default:
-        g_snprintf (ethstr, 512, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", ad[0],
-                 ad[1], ad[2], ad[3], ad[4], ad[5], ad[6], ad[7]);
-        break;
-    }
-    return (ethstr);
+       for(;bit%8;bit++){
+               if(bit&&(!(bit%4))){
+                       str[str_p] = ' ';
+                       str_p++;
+               }
+               str[str_p] = '.';
+               str_p++;
+       }
+       return str;
 }
 
 /* Generate, into "buf", a string showing the bits of a bitfield.
    Return a pointer to the character after that string. */
 /*XXX this needs a buf_len check */
 char *
-other_decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
+other_decode_bitfield_value(char *buf, const guint32 val, const guint32 mask, const int width)
 {
   int i;
   guint32 bit;
@@ -779,7 +974,7 @@ other_decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
 }
 
 char *
-decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
+decode_bitfield_value(char *buf, const guint32 val, const guint32 mask, const int width)
 {
   char *p;
 
@@ -790,15 +985,15 @@ decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
 }
 
 /* Generate a string describing a Boolean bitfield (a one-bit field that
-   says something is either true of false). */
+   says something is either true or false). */
 const char *
-decode_boolean_bitfield(guint32 val, guint32 mask, int width,
+decode_boolean_bitfield(const guint32 val, const guint32 mask, const int width,
     const char *truedesc, const char *falsedesc)
 {
   char *buf;
   char *p;
 
-  buf=ep_alloc(1025); /* is this a bit overkill? */
+  buf=(char *)ep_alloc(1025); /* is this a bit overkill? */
   p = decode_bitfield_value(buf, val, mask, width);
   if (val & mask)
     strcpy(p, truedesc);
@@ -810,206 +1005,186 @@ decode_boolean_bitfield(guint32 val, guint32 mask, int width,
 /* Generate a string describing a numeric bitfield (an N-bit field whose
    value is just a number). */
 const char *
-decode_numeric_bitfield(guint32 val, guint32 mask, int width,
+decode_numeric_bitfield(const guint32 val, const guint32 mask, const int width,
     const char *fmt)
 {
   char *buf;
   char *p;
   int shift = 0;
 
-  buf=ep_alloc(1025); /* isnt this a bit overkill? */
+  buf=(char *)ep_alloc(1025); /* isnt this a bit overkill? */
   /* Compute the number of bits we have to shift the bitfield right
      to extract its value. */
   while ((mask & (1<<shift)) == 0)
     shift++;
 
   p = decode_bitfield_value(buf, val, mask, width);
-  g_snprintf(p, 1025-(p-buf), fmt, (val & mask) >> shift);
+  g_snprintf(p, (gulong) (1025-(p-buf)), fmt, (val & mask) >> shift);
   return buf;
 }
 
-
-/*XXX FIXME the code below may be called very very frequently in the future.
-  optimize it for speed and get rid of the slow sprintfs */
-/* XXX - perhaps we should have individual address types register
-   a table of routines to do operations such as address-to-name translation,
-   address-to-string translation, and the like, and have this call them,
-   and also have an address-to-string-with-a-name routine */
-/* XXX - use this, and that future address-to-string-with-a-name routine,
-   in "col_set_addr()"; it might also be useful to have address types
-   export the names of the source and destination address fields, so
-   that "col_set_addr()" need know nothing whatsoever about particular
-   address types */
-/* convert an address struct into a printable string */
-gchar*
-address_to_str(const address *addr)
+/*
+ This function is very fast and this function is called a lot.
+ XXX update the ep_address_to_str stuff to use this function.
+*/
+void
+ip_to_str_buf(const guint8 *ad, gchar *buf, const int buf_len)
 {
-  gchar *str;
+       register gchar const *p;
+       register gchar *b=buf;
 
-  str=ep_alloc(MAX_ADDR_STR_LEN);
-  address_to_str_buf(addr, str, MAX_ADDR_STR_LEN);
-  return str;
-}
+       if (buf_len < MAX_IP_STR_LEN) {
+               g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR );                 /* Let the unexpected value alert user */
+               return;
+       }
 
-void
-address_to_str_buf(const address *addr, gchar *buf, int buf_len)
-{
-  const guint8 *addrdata;
-  const char *addrstr;
-  struct atalk_ddp_addr ddp_addr;
+       p=fast_strings[*ad++];
+       do {
+               *b++=*p;
+               p++;
+       } while(*p);
+       *b++='.';
 
-  if (!buf)
-    return;
+       p=fast_strings[*ad++];
+       do {
+               *b++=*p;
+               p++;
+       } while(*p);
+       *b++='.';
 
-  switch(addr->type){
-  case AT_NONE:
-    g_snprintf(buf, buf_len, "%s", "");
-    break;
-  case AT_ETHER:
-    addrdata = addr->data;
-    g_snprintf(buf, buf_len, "%02x:%02x:%02x:%02x:%02x:%02x", addrdata[0], addrdata[1], addrdata[2], addrdata[3], addrdata[4], addrdata[5]);
-    break;
-  case AT_IPv4:
-    ip_to_str_buf(addr->data, buf, buf_len);
-    break;
-  case AT_IPv6:
-    if ( inet_ntop(AF_INET6, addr->data, buf, buf_len) == NULL ) /* Returns NULL if no space and does not touch buf */
-       g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR );                 /* Let the unexpected value alert user */
-    break;
-  case AT_IPX:
-    addrdata = addr->data;
-    g_snprintf(buf, buf_len, "%02x%02x%02x%02x.%02x%02x%02x%02x%02x%02x", addrdata[0], addrdata[1], addrdata[2], addrdata[3], addrdata[4], addrdata[5], addrdata[6], addrdata[7], addrdata[8], addrdata[9]);
-    break;
-  case AT_SNA:
-    sna_fid_to_str_buf(addr, buf, buf_len);
-    break;
-  case AT_ATALK:
-    memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
-    atalk_addr_to_str_buf(&ddp_addr, buf, buf_len);
-    break;
-  case AT_VINES:
-    vines_addr_to_str_buf(addr->data, buf, buf_len);
-    break;
-  case AT_USB:
-    usb_addr_to_str_buf(addr->data, buf, buf_len);
-    break;
-  case AT_OSI:
-    print_nsap_net_buf(addr->data, addr->len, buf, buf_len);
-    break;
-  case AT_ARCNET:
-    addrdata = addr->data;
-    g_snprintf(buf, buf_len, "0x%02X", addrdata[0]);
-    break;
-  case AT_FC:
-    addrdata = addr->data;
-    g_snprintf(buf, buf_len, "%02x.%02x.%02x", addrdata[0], addrdata[1], addrdata[2]);
-    break;
-  case AT_SS7PC:
-    mtp3_addr_to_str_buf((const mtp3_addr_pc_t *)addr->data, buf, buf_len);
-    break;
-  case AT_STRINGZ:
-    addrstr = addr->data;
-    g_snprintf(buf, buf_len, "%s", addrstr);
-    break;
-  case AT_EUI64:
-    addrdata = addr->data;
-    g_snprintf(buf, buf_len, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
-            addrdata[0], addrdata[1], addrdata[2], addrdata[3],
-            addrdata[4], addrdata[5], addrdata[6], addrdata[7]);
-    break;
-  case AT_URI: {
-    int copy_len = addr->len < (buf_len - 1) ? addr->len : (buf_len - 1);
-    memcpy(buf, addr->data, copy_len );
-    buf[copy_len] = '\0';
-    }
-    break;
-  case AT_TIPC:
-    tipc_addr_to_str_buf(addr->data, buf, buf_len);
-    break;
-  default:
-    g_assert_not_reached();
-  }
+       p=fast_strings[*ad++];
+       do {
+               *b++=*p;
+               p++;
+       } while(*p);
+       *b++='.';
+
+       p=fast_strings[*ad];
+       do {
+               *b++=*p;
+               p++;
+       } while(*p);
+       *b=0;
 }
 
-gchar* oid_to_str(const guint8 *oid, gint oid_len) {
+gchar* guid_to_str(const e_guid_t *guid) {
   gchar *buf;
 
-  buf=ep_alloc(MAX_OID_STR_LEN);
-  return oid_to_str_buf(oid, oid_len, buf, MAX_OID_STR_LEN);
+  buf=(gchar *)ep_alloc(GUID_STR_LEN);
+  return guid_to_str_buf(guid, buf, GUID_STR_LEN);
 }
 
-#define OID_STR_LIMIT (1 + 10 + 4 + 1) /* "." + 10 digits + ".>>>" + '\0' */
-gchar* oid_to_str_buf(const guint8 *oid, gint oid_len, gchar *buf, int buf_len) {
-  gint i;
-  guint8 byte;
-  guint32 subid0, subid;
-  gboolean is_first;
-  gchar *bufp;
+gchar* guid_to_str_buf(const e_guid_t *guid, gchar *buf, int buf_len) {
+  char *tempptr = buf;
 
-  bufp = buf; subid = 0; is_first = TRUE;
-  for (i=0; i<oid_len; i++){
-    byte = oid[i];
-    if ((bufp - buf) > (buf_len - OID_STR_LIMIT)) {
-      bufp += g_snprintf(bufp, buf_len-(bufp-buf), ".>>>");
-      break;
-    }
-    subid <<= 7;
-    subid |= byte & 0x7F;
-    if (byte & 0x80) {
-      continue;
-    }
-    if (is_first) {
-      subid0 = 0;
-      if (subid >= 40) { subid0++; subid-=40; }
-      if (subid >= 40) { subid0++; subid-=40; }
-      bufp += g_snprintf(bufp, buf_len-(bufp-buf), "%u.%u", subid0, subid);
-      is_first = FALSE;
-    } else {
-      bufp += g_snprintf(bufp, buf_len-(bufp-buf), ".%u", subid);
-    }
-    subid = 0;
+  if (buf_len < GUID_STR_LEN) {
+     g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len);/* Let the unexpected value alert user */
+     return buf;
   }
-  *bufp = '\0';
 
+  /* 37 bytes */
+  tempptr    = dword_to_hex(tempptr, guid->data1);             /*  8 bytes */
+  *tempptr++ = '-';                                            /*  1 byte */
+  tempptr    = word_to_hex(tempptr, guid->data2);              /*  4 bytes */
+  *tempptr++ = '-';                                            /*  1 byte */
+  tempptr    = word_to_hex(tempptr, guid->data3);              /*  4 bytes */
+  *tempptr++ = '-';                                            /*  1 byte */
+  tempptr    = bytes_to_hexstr(tempptr, &guid->data4[0], 2);   /*  4 bytes */
+  *tempptr++ = '-';                                            /*  1 byte */
+  tempptr    = bytes_to_hexstr(tempptr, &guid->data4[2], 6);   /* 12 bytes */
+
+  *tempptr   = '\0';
   return buf;
 }
 
-gchar* guid_to_str(const e_guid_t *guid) {
-  gchar *buf;
+const gchar* port_type_to_str (port_type type) {
+       switch (type) {
+               case PT_NONE:           return "NONE";
+               case PT_SCTP:           return "SCTP";
+               case PT_TCP:            return "TCP";
+               case PT_UDP:            return "UDP";
+               case PT_DCCP:           return "DCCP";
+               case PT_IPX:            return "IPX";
+               case PT_NCP:            return "NCP";
+               case PT_EXCHG:          return "FC EXCHG";
+               case PT_DDP:            return "DDP";
+               case PT_SBCCS:          return "FICON SBCCS";
+               case PT_IDP:            return "IDP";
+               case PT_TIPC:           return "TIPC";
+               case PT_USB:            return "USB";
+               case PT_I2C:            return "I2C";
+               case PT_IBQP:           return "IBQP";
+               case PT_BLUETOOTH:      return "BLUETOOTH";
+               default:                        return "[Unknown]";
+       }
+}
 
-  buf=ep_alloc(GUID_STR_LEN);
-  return guid_to_str_buf(guid, buf, GUID_STR_LEN);
+char *
+oct_to_str_back(char *ptr, guint32 value)
+{
+       while (value) {
+               *(--ptr) = '0' + (value & 0x7);
+               value >>= 3;
+       }
+
+       *(--ptr) = '0';
+       return ptr;
 }
 
-gchar* guid_to_str_buf(const e_guid_t *guid, gchar *buf, int buf_len) {
-  g_snprintf(buf, buf_len, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-          guid->data1, guid->data2, guid->data3,
-          guid->data4[0], guid->data4[1], guid->data4[2], guid->data4[3], guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]);
-  return buf;
+char *
+hex_to_str_back(char *ptr, int pad, guint32 value)
+{
+       do {
+               *(--ptr) = octet_to_hex(value);
+               value >>= 4;
+               pad--;
+       } while (value);
+
+       /* pad */
+       while (pad > 0) {
+               *(--ptr) = '0';
+               pad--;
+       }
+
+       *(--ptr) = 'x';
+       *(--ptr) = '0';
+
+       return ptr;
 }
 
-void
-tipc_addr_to_str_buf( const guint8 *data, gchar *buf, int buf_len){
-       guint8 zone;
-       guint16 subnetwork;
-       guint16 processor;
-       guint32 tipc_address;
+char *
+uint_to_str_back(char *ptr, guint32 value)
+{
+       char const *p;
 
-       tipc_address = data[0];
-       tipc_address = (tipc_address << 8) ^ data[1];
-       tipc_address = (tipc_address << 8) ^ data[2];
-       tipc_address = (tipc_address << 8) ^ data[3];
+       /* special case */
+       if (value == 0)
+               *(--ptr) = '0';
 
-       processor = tipc_address & 0x0fff;
+       while (value >= 10) {
+               p = fast_strings[100 + (value % 100)];
 
-       tipc_address = tipc_address >> 12;
-       subnetwork = tipc_address & 0x0fff;
+               value /= 100;
 
-       tipc_address = tipc_address >> 12;
-       zone = tipc_address & 0xff;
+               *(--ptr) = p[2];
+               *(--ptr) = p[1];
+       }
+
+       if (value)
+               *(--ptr) = (value) | '0';
 
-       g_snprintf(buf,buf_len,"%u.%u.%u",zone,subnetwork,processor);
+       return ptr;
+}
 
+char *
+int_to_str_back(char *ptr, gint32 value)
+{
+       if (value < 0) {
+               ptr = uint_to_str_back(ptr, -value);
+               *(--ptr) = '-';
+       } else
+               ptr = uint_to_str_back(ptr, value);
 
+       return ptr;
 }