Merge branch 'master' of nicira.dyndns.org:/srv/git/openflow
[sliver-openvswitch.git] / lib / util.c
1 /* Copyright (C) 2007 Board of Trustees, Leland Stanford Jr. University.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21
22 #include "util.h"
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 const char *program_name;
29
30 static void
31 out_of_memory(void) 
32 {
33     fatal(0, "virtual memory exhausted");
34 }
35
36 void *
37 xcalloc(size_t count, size_t size) 
38 {
39     void *p = count && size ? calloc(count, size) : malloc(1);
40     if (p == NULL) {
41         out_of_memory();
42     }
43     return p;
44 }
45
46 void *
47 xmalloc(size_t size) 
48 {
49     void *p = malloc(size ? size : 1);
50     if (p == NULL) {
51         out_of_memory();
52     }
53     return p;
54 }
55
56 void *
57 xrealloc(void *p, size_t size) 
58 {
59     p = realloc(p, size ? size : 1);
60     if (p == NULL) {
61         out_of_memory();
62     }
63     return p;
64 }
65
66 char *
67 xstrdup(const char *s_) 
68 {
69     size_t size = strlen(s_) + 1;
70     char *s = xmalloc(size);
71     memcpy(s, s_, size);
72     return s;
73 }
74
75 char *
76 xasprintf(const char *format, ...)
77 {
78     va_list args;
79     size_t needed;
80     char *s;
81
82     va_start(args, format);
83     needed = vsnprintf(NULL, 0, format, args);
84     va_end(args);
85
86     s = xmalloc(needed + 1);
87
88     va_start(args, format);
89     vsnprintf(s, needed + 1, format, args);
90     va_end(args);
91
92     return s;
93 }
94
95 void fatal(int err_no, const char *format, ...)
96 {
97     va_list args;
98
99     fprintf(stderr, "%s: ", program_name);
100     va_start(args, format);
101     vfprintf(stderr, format, args);
102     va_end(args);
103     if (err_no != 0)
104         fprintf(stderr, " (%s)", strerror(err_no));
105     putc('\n', stderr);
106
107     exit(EXIT_FAILURE);
108 }
109
110 void error(int err_no, const char *format, ...)
111 {
112     va_list args;
113
114     fprintf(stderr, "%s: ", program_name);
115     va_start(args, format);
116     vfprintf(stderr, format, args);
117     va_end(args);
118     if (err_no != 0)
119         fprintf(stderr, " (%s)", strerror(err_no));
120     putc('\n', stderr);
121 }
122
123 void debug(int err_no, const char *format, ...)
124 {
125     va_list args;
126
127     fprintf(stderr, "%s: ", program_name);
128     va_start(args, format);
129     vfprintf(stderr, format, args);
130     va_end(args);
131     if (err_no != 0)
132         fprintf(stderr, " (%s)", strerror(err_no));
133     putc('\n', stderr);
134 }
135
136 /* Sets program_name based on 'argv0'.  Should be called at the beginning of
137  * main(), as "set_program_name(argv[0]);".  */
138 void set_program_name(const char *argv0)
139 {
140     const char *slash = strrchr(argv0, '/');
141     program_name = slash ? slash + 1 : argv0;
142 }
143
144 /* Writes the 'size' bytes in 'buf' to 'stream' as hex bytes arranged 16 per
145  * line.  Numeric offsets are also included, starting at 'ofs' for the first
146  * byte in 'buf'.  If 'ascii' is true then the corresponding ASCII characters
147  * are also rendered alongside. */
148 void
149 hex_dump(FILE *stream, const void *buf_, size_t size,
150          uintptr_t ofs, bool ascii)
151 {
152   const uint8_t *buf = buf_;
153   const size_t per_line = 16; /* Maximum bytes per line. */
154
155   while (size > 0)
156     {
157       size_t start, end, n;
158       size_t i;
159
160       /* Number of bytes on this line. */
161       start = ofs % per_line;
162       end = per_line;
163       if (end - start > size)
164         end = start + size;
165       n = end - start;
166
167       /* Print line. */
168       fprintf(stream, "%08jx  ", (uintmax_t) ROUND_DOWN(ofs, per_line));
169       for (i = 0; i < start; i++)
170         fprintf(stream, "   ");
171       for (; i < end; i++)
172         fprintf(stream, "%02hhx%c",
173                 buf[i - start], i == per_line / 2 - 1? '-' : ' ');
174       if (ascii)
175         {
176           for (; i < per_line; i++)
177             fprintf(stream, "   ");
178           fprintf(stream, "|");
179           for (i = 0; i < start; i++)
180             fprintf(stream, " ");
181           for (; i < end; i++) {
182               int c = buf[i - start];
183               putc(c >= 32 && c < 127 ? c : '.', stream);
184           }
185           for (; i < per_line; i++)
186             fprintf(stream, " ");
187           fprintf(stream, "|");
188         }
189       fprintf(stream, "\n");
190
191       ofs += n;
192       buf += n;
193       size -= n;
194     }
195 }