Include <sys/time.h> as well as <time.h> in "column-utils.c" and
[obnox/wireshark/wip.git] / epan / to_str.c
1 /* to_str.h
2  * Routines  for utilities to convert various other types to strings.
3  *
4  * $Id: to_str.c,v 1.4 2001/04/02 02:30:06 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #ifdef NEED_SNPRINTF_H
35 # include "snprintf.h"
36 #endif
37
38 #ifdef HAVE_NETINET_IN_H
39 # include <netinet/in.h>
40 #endif
41
42 #ifdef HAVE_ARPA_INET_H
43 #include <arpa/inet.h>
44 #endif
45
46 #ifdef HAVE_SYS_SOCKET_H
47 #include <sys/socket.h>
48 #endif
49
50 #ifdef NEED_INET_V6DEFS_H
51 # include "inet_v6defs.h"
52 #endif
53
54 #ifdef HAVE_SYS_TIME_H
55 # include <sys/time.h>
56 #endif
57
58 #include "to_str.h"
59 #include "resolv.h"
60 #include "pint.h"
61 #include <stdio.h>
62 #include <time.h>
63
64
65 /* Wrapper for the most common case of asking
66  * for a string using a colon as the hex-digit separator.
67  */
68
69 gchar *
70 ether_to_str(const guint8 *ad)
71 {
72         return ether_to_str_punct(ad, ':');
73 }
74
75 /* Places char punct in the string as the hex-digit separator.
76  * If punct is '\0', no punctuation is applied (and thus
77  * the resulting string is 5 bytes shorter)
78  */
79 gchar *
80 ether_to_str_punct(const guint8 *ad, char punct) {
81   static gchar  str[3][18];
82   static gchar *cur;
83   gchar        *p;
84   int          i;
85   guint32      octet;
86   static const gchar hex_digits[16] = "0123456789abcdef";
87
88   if (cur == &str[0][0]) {
89     cur = &str[1][0];
90   } else if (cur == &str[1][0]) {  
91     cur = &str[2][0];
92   } else {  
93     cur = &str[0][0];
94   }
95   p = &cur[18];
96   *--p = '\0';
97   i = 5;
98   for (;;) {
99     octet = ad[i];
100     *--p = hex_digits[octet&0xF];
101     octet >>= 4;
102     *--p = hex_digits[octet&0xF];
103     if (i == 0)
104       break;
105     if (punct)
106       *--p = punct;
107     i--;
108   }
109   return p;
110 }
111
112 gchar *
113 ip_to_str(const guint8 *ad) {
114   static gchar  str[3][16];
115   static gchar *cur;
116
117   if (cur == &str[0][0]) {
118     cur = &str[1][0];
119   } else if (cur == &str[1][0]) {  
120     cur = &str[2][0];
121   } else {  
122     cur = &str[0][0];
123   }
124   ip_to_str_buf(ad, cur);
125   return cur;
126 }
127
128 void
129 ip_to_str_buf(const guint8 *ad, gchar *buf)
130 {
131   gchar        *p;
132   int           i;
133   guint32       octet;
134   guint32       digit;
135   gboolean      saw_nonzero;
136
137   p = buf;
138   i = 0;
139   for (;;) {
140     saw_nonzero = FALSE;
141     octet = ad[i];
142     digit = octet/100;
143     if (digit != 0) {
144       *p++ = digit + '0';
145       saw_nonzero = TRUE;
146     }
147     octet %= 100;
148     digit = octet/10;
149     if (saw_nonzero || digit != 0)
150       *p++ = digit + '0';
151     digit = octet%10;
152     *p++ = digit + '0';
153     if (i == 3)
154       break;
155     *p++ = '.';
156     i++;
157   }
158   *p = '\0';
159 }
160
161 gchar *
162 ip6_to_str(struct e_in6_addr *ad) {
163 #ifndef INET6_ADDRSTRLEN
164 #define INET6_ADDRSTRLEN 46
165 #endif
166   static gchar buf[INET6_ADDRSTRLEN];
167
168   inet_ntop(AF_INET6, (u_char*)ad, (gchar*)buf, sizeof(buf));
169   return buf;
170 }
171
172 gchar*
173 ipx_addr_to_str(guint32 net, const guint8 *ad)
174 {
175         static gchar    str[3][8+1+MAXNAMELEN+1]; /* 8 digits, 1 period, NAME, 1 null */
176         static gchar    *cur;
177         char            *name;
178
179         if (cur == &str[0][0]) {
180                 cur = &str[1][0];
181         } else if (cur == &str[1][0]) {
182                 cur = &str[2][0];
183         } else {
184                 cur = &str[0][0];
185         }
186
187         name = get_ether_name_if_known(ad);
188
189         if (name) {
190                 sprintf(cur, "%s.%s", get_ipxnet_name(net), name);
191         }
192         else {
193                 sprintf(cur, "%s.%s", get_ipxnet_name(net), ether_to_str_punct(ad, '\0'));
194         }
195         return cur;
196 }
197
198 gchar*
199 ipxnet_to_string(const guint8 *ad)
200 {
201         guint32 addr = pntohl(ad);
202         return ipxnet_to_str_punct(addr, ' ');
203 }
204
205 gchar *
206 ipxnet_to_str_punct(const guint32 ad, char punct)
207 {
208   static gchar  str[3][12];
209   static gchar *cur;
210   gchar        *p;
211   int          i;
212   guint32      octet;
213   static const gchar hex_digits[16] = "0123456789ABCDEF";
214   static const guint32  octet_mask[4] =
215           { 0xff000000 , 0x00ff0000, 0x0000ff00, 0x000000ff };
216
217   if (cur == &str[0][0]) {
218     cur = &str[1][0];
219   } else if (cur == &str[1][0]) {  
220     cur = &str[2][0];
221   } else {  
222     cur = &str[0][0];
223   }
224   p = &cur[12];
225   *--p = '\0';
226   i = 3;
227   for (;;) {
228     octet = (ad & octet_mask[i]) >> ((3 - i) * 8);
229     *--p = hex_digits[octet&0xF];
230     octet >>= 4;
231     *--p = hex_digits[octet&0xF];
232     if (i == 0)
233       break;
234     if (punct)
235       *--p = punct;
236     i--;
237   }
238   return p;
239 }
240
241 gchar *
242 vines_addr_to_str(const guint8 *addrp)
243 {
244   static gchar  str[3][214];
245   static gchar  *cur;
246
247   if (cur == &str[0][0]) {
248     cur = &str[1][0];
249   } else if (cur == &str[1][0]) {
250     cur = &str[2][0];
251   } else {
252     cur = &str[0][0];
253   }
254
255   sprintf(cur, "%08x.%04x", pntohl(&addrp[0]), pntohs(&addrp[4]));
256   return cur;
257 }
258
259 #define PLURALIZE(n)    (((n) > 1) ? "s" : "")
260 #define COMMA(do_it)    ((do_it) ? ", " : "")
261
262 gchar *
263 time_secs_to_str(guint32 time)
264 {
265   static gchar  str[3][8+1+4+2+2+5+2+2+7+2+2+7+1];
266   static gchar *cur, *p;
267   int hours, mins, secs;
268   int do_comma;
269
270   if (cur == &str[0][0]) {
271     cur = &str[1][0];
272   } else if (cur == &str[1][0]) {  
273     cur = &str[2][0];
274   } else {  
275     cur = &str[0][0];
276   }
277
278   if (time == 0) {
279     sprintf(cur, "0 time");
280     return cur;
281   }
282
283   secs = time % 60;
284   time /= 60;
285   mins = time % 60;
286   time /= 60;
287   hours = time % 24;
288   time /= 24;
289
290   p = cur;
291   if (time != 0) {
292     sprintf(p, "%u day%s", time, PLURALIZE(time));
293     p += strlen(p);
294     do_comma = 1;
295   } else
296     do_comma = 0;
297   if (hours != 0) {
298     sprintf(p, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
299     p += strlen(p);
300     do_comma = 1;
301   } else
302     do_comma = 0;
303   if (mins != 0) {
304     sprintf(p, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
305     p += strlen(p);
306     do_comma = 1;
307   } else
308     do_comma = 0;
309   if (secs != 0)
310     sprintf(p, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
311   return cur;
312 }
313
314 static const char *mon_names[12] = {
315         "Jan",
316         "Feb",
317         "Mar",
318         "Apr",
319         "May",
320         "Jun",
321         "Jul",
322         "Aug",
323         "Sep",
324         "Oct",
325         "Nov",
326         "Dec"
327 };
328
329 gchar *
330 abs_time_to_str(struct timeval *abs_time)
331 {
332         struct tm *tmp;
333         static gchar *cur;
334         static char str[3][3+1+2+2+4+1+2+1+2+1+2+1+4+1 + 5 /* extra */];
335
336         if (cur == &str[0][0]) {
337                 cur = &str[1][0];
338         } else if (cur == &str[1][0]) {
339                 cur = &str[2][0];
340         } else {
341                 cur = &str[0][0];
342         }
343
344         tmp = localtime(&abs_time->tv_sec);
345         sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%04ld",
346             mon_names[tmp->tm_mon],
347             tmp->tm_mday,
348             tmp->tm_year + 1900,
349             tmp->tm_hour,
350             tmp->tm_min,
351             tmp->tm_sec,
352             (long)abs_time->tv_usec/100);
353
354         return cur;
355 }
356
357 #define REL_TIME_LEN    (1+10+1+6+1)
358
359 void
360 display_signed_time(gchar *buf, int buflen, gint32 sec, gint32 usec)
361 {
362         char *sign;
363
364         /* If the microseconds part of the time stamp is negative,
365            print its absolute value and, if the seconds part isn't
366            (the seconds part should be zero in that case), stick
367            a "-" in front of the entire time stamp. */
368         sign = "";
369         if (usec < 0) {
370                 usec = -usec;
371                 if (sec >= 0)
372                         sign = "-";
373         }
374         snprintf(buf, buflen, "%s%d.%06d", sign, sec, usec);
375 }
376
377 gchar *
378 rel_time_to_str(struct timeval *rel_time)
379 {
380         static gchar *cur;
381         static char str[3][REL_TIME_LEN];
382
383         if (cur == &str[0][0]) {
384                 cur = &str[1][0];
385         } else if (cur == &str[1][0]) {
386                 cur = &str[2][0];
387         } else {
388                 cur = &str[0][0];
389         }
390
391         display_signed_time(cur, REL_TIME_LEN, rel_time->tv_sec,
392             rel_time->tv_usec);
393         return cur;
394 }
395
396 /* Generate, into "buf", a string showing the bits of a bitfield.
397    Return a pointer to the character after that string. */
398 char *
399 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
400 {
401   int i;
402   guint32 bit;
403   char *p;
404
405   i = 0;
406   p = buf;
407   bit = 1 << (width - 1);
408   for (;;) {
409     if (mask & bit) {
410       /* This bit is part of the field.  Show its value. */
411       if (val & bit)
412         *p++ = '1';
413       else
414         *p++ = '0';
415     } else {
416       /* This bit is not part of the field. */
417       *p++ = '.';
418     }
419     bit >>= 1;
420     i++;
421     if (i >= width)
422       break;
423     if (i % 4 == 0)
424       *p++ = ' ';
425   }
426   strcpy(p, " = ");
427   p += 3;
428   return p;
429 }
430
431 /* Generate a string describing a Boolean bitfield (a one-bit field that
432    says something is either true of false). */
433 const char *
434 decode_boolean_bitfield(guint32 val, guint32 mask, int width,
435     const char *truedesc, const char *falsedesc)
436 {
437   static char buf[1025];
438   char *p;
439
440   p = decode_bitfield_value(buf, val, mask, width);
441   if (val & mask)
442     strcpy(p, truedesc);
443   else
444     strcpy(p, falsedesc);
445   return buf;
446 }
447
448 /* Generate a string describing a numeric bitfield (an N-bit field whose
449    value is just a number). */
450 const char *
451 decode_numeric_bitfield(guint32 val, guint32 mask, int width,
452     const char *fmt)
453 {
454   static char buf[1025];
455   char *p;
456   int shift = 0;
457
458   /* Compute the number of bits we have to shift the bitfield right
459      to extract its value. */
460   while ((mask & (1<<shift)) == 0)
461     shift++;
462
463   p = decode_bitfield_value(buf, val, mask, width);
464   sprintf(p, fmt, (val & mask) >> shift);
465   return buf;
466 }
467
468
469