Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added sprintf implementation from FreeBSD
[palacios.git] / palacios / src / palacios / vmm_sprintf.c
1 /*
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 /* 
21  * Ported from FreeBSD
22  */
23
24 /*-
25  * Copyright (c) 1986, 1988, 1991, 1993
26  *      The Regents of the University of California.  All rights reserved.
27  * (c) UNIX System Laboratories, Inc.
28  * All or some portions of this file are derived from material licensed
29  * to the University of California by American Telephone and Telegraph
30  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
31  * the permission of UNIX System Laboratories, Inc.
32  *
33  * Redistribution and use in source and binary forms, with or without
34  * modification, are permitted provided that the following conditions
35  * are met:
36  * 1. Redistributions of source code must retain the above copyright
37  *    notice, this list of conditions and the following disclaimer.
38  * 2. Redistributions in binary form must reproduce the above copyright
39  *    notice, this list of conditions and the following disclaimer in the
40  *    documentation and/or other materials provided with the distribution.
41  * 4. Neither the name of the University nor the names of its contributors
42  *    may be used to endorse or promote products derived from this software
43  *    without specific prior written permission.
44  *
45  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55  * SUCH DAMAGE.
56  *
57  *      @(#)subr_prf.c  8.3 (Berkeley) 1/21/94
58  */
59
60
61 #include <stdarg.h> // err.....
62
63 #include <palacios/vmm.h>
64 #include <palacios/vmm_types.h>
65 #include <palacios/vmm_string.h>
66 #include <palacios/vmm_sprintf.h>
67
68
69 #define NEED_SPRINTF 1
70 #define NEED_SNPRINTF 1
71 #define NEED_VSPRINTF 1
72 #define NEED_VSNPRINTF 1
73 #define NEED_VSNRPRINTF 1
74
75
76 typedef addr_t ptrdiff_t;     /* ptr1 - ptr2 */
77
78 /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
79 #define MAXNBUF (sizeof(uint64_t) + 1)
80
81
82 /* convert a hex value to it's ascii representation */
83 static char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
84
85 #define hex2ascii(hex)  (hex2ascii_data[hex])
86
87
88 struct snprintf_arg {
89         char    *str;
90         size_t  remain;
91 };
92
93
94 static char * ksprintn(char * nbuf, uint64_t num, int base, int *len, int upper);
95 static void snprintf_func(int ch, void * arg);
96 static int kvprintf(char const * fmt, void (*func)(int, void *), void * arg, int radix, va_list ap);
97
98
99 #if NEED_SPRINTF
100 /*
101  * Scaled down version of sprintf(3).
102  */
103 int sprintf(char * buf, const char * cfmt, ...) {
104     int retval;
105     va_list ap;
106     
107     va_start(ap, cfmt);
108     retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
109     buf[retval] = '\0';
110     va_end(ap);
111     return (retval);
112 }
113 #endif 
114
115
116 #if NEED_VSPRINTF
117 /*
118  * Scaled down version of vsprintf(3).
119  */
120 int vsprintf(char * buf, const char * cfmt, va_list ap) {
121     int retval;
122
123     retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
124     buf[retval] = '\0';
125     return (retval);
126 }
127 #endif
128
129
130 #if NEED_SNPRINTF
131 /*
132  * Scaled down version of snprintf(3).
133  */
134 int snprintf(char * str, size_t size, const char * format, ...) {
135     int retval;
136     va_list ap;
137
138     va_start(ap, format);
139     retval = vsnprintf(str, size, format, ap);
140     va_end(ap);
141     return(retval);
142 }
143 #endif
144
145
146 #if NEED_VSNPRINTF 
147 /*
148  * Scaled down version of vsnprintf(3).
149  */
150 int vsnprintf(char * str, size_t size, const char * format, va_list ap) {
151     struct snprintf_arg info;
152     int retval;
153
154     info.str = str;
155     info.remain = size;
156     retval = kvprintf(format, snprintf_func, &info, 10, ap);
157     if (info.remain >= 1) {
158         *info.str++ = '\0';
159     }
160     return (retval);
161 }
162 #endif 
163
164
165 #if NEED_VSNRPRINTF
166 /*
167  * Kernel version which takes radix argument vsnprintf(3).
168  */
169 int vsnrprintf(char * str, size_t size, int radix, const char * format, va_list ap) {
170     struct snprintf_arg info;
171     int retval;
172
173     info.str = str;
174     info.remain = size;
175     retval = kvprintf(format, snprintf_func, &info, radix, ap);
176     if (info.remain >= 1) {
177         *info.str++ = '\0';
178     }
179     return (retval);
180 }
181 #endif
182
183
184 static void
185 snprintf_func(int ch, void *arg)
186 {
187         struct snprintf_arg *const info = arg;
188
189         if (info->remain >= 2) {
190                 *info->str++ = ch;
191                 info->remain--;
192         }
193 }
194
195 /*
196  * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
197  * order; return an optional length and a pointer to the last character
198  * written in the buffer (i.e., the first character of the string).
199  * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
200  */
201 static char *
202 ksprintn(char *nbuf, uint64_t num, int base, int *lenp, int upper)
203 {
204         char *p, c;
205
206         p = nbuf;
207         *p = '\0';
208         do {
209                 c = hex2ascii(num % base);
210                 *++p = upper ? toupper(c) : c;
211         } while (num /= base);
212         if (lenp)
213                 *lenp = p - nbuf;
214         return (p);
215 }
216
217 /*
218  * Scaled down version of printf(3).
219  *
220  * Two additional formats:
221  *
222  * The format %b is supported to decode error registers.
223  * Its usage is:
224  *
225  *      printf("reg=%b\n", regval, "<base><arg>*");
226  *
227  * where <base> is the output base expressed as a control character, e.g.
228  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
229  * the first of which gives the bit number to be inspected (origin 1), and
230  * the next characters (up to a control character, i.e. a character <= 32),
231  * give the name of the register.  Thus:
232  *
233  *      kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
234  *
235  * would produce output:
236  *
237  *      reg=3<BITTWO,BITONE>
238  *
239  * XXX:  %D  -- Hexdump, takes pointer and separator string:
240  *              ("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
241  *              ("%*D", len, ptr, " " -> XX XX XX XX ...
242  */
243 static int
244 kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
245 {
246 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
247         char nbuf[MAXNBUF];
248         char *d;
249         const char *p, *percent, *q;
250         uchar_t *up;
251         int ch, n;
252         uint64_t num;
253         int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
254         int cflag, hflag, jflag, tflag, zflag;
255         int dwidth, upper;
256         char padc;
257         int stop = 0, retval = 0;
258
259         num = 0;
260         if (!func)
261                 d = (char *) arg;
262         else
263                 d = NULL;
264
265         if (fmt == NULL)
266                 fmt = "(fmt null)\n";
267
268         if (radix < 2 || radix > 36)
269                 radix = 10;
270
271         for (;;) {
272                 padc = ' ';
273                 width = 0;
274                 while ((ch = (uchar_t)*fmt++) != '%' || stop) {
275                         if (ch == '\0')
276                                 return (retval);
277                         PCHAR(ch);
278                 }
279                 percent = fmt - 1;
280                 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
281                 sign = 0; dot = 0; dwidth = 0; upper = 0;
282                 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
283 reswitch:       switch (ch = (uchar_t)*fmt++) {
284                 case '.':
285                         dot = 1;
286                         goto reswitch;
287                 case '#':
288                         sharpflag = 1;
289                         goto reswitch;
290                 case '+':
291                         sign = 1;
292                         goto reswitch;
293                 case '-':
294                         ladjust = 1;
295                         goto reswitch;
296                 case '%':
297                         PCHAR(ch);
298                         break;
299                 case '*':
300                         if (!dot) {
301                                 width = va_arg(ap, int);
302                                 if (width < 0) {
303                                         ladjust = !ladjust;
304                                         width = -width;
305                                 }
306                         } else {
307                                 dwidth = va_arg(ap, int);
308                         }
309                         goto reswitch;
310                 case '0':
311                         if (!dot) {
312                                 padc = '0';
313                                 goto reswitch;
314                         }
315                 case '1': case '2': case '3': case '4':
316                 case '5': case '6': case '7': case '8': case '9':
317                                 for (n = 0;; ++fmt) {
318                                         n = n * 10 + ch - '0';
319                                         ch = *fmt;
320                                         if (ch < '0' || ch > '9')
321                                                 break;
322                                 }
323                         if (dot)
324                                 dwidth = n;
325                         else
326                                 width = n;
327                         goto reswitch;
328                 case 'b':
329                         num = (uint_t)va_arg(ap, int);
330                         p = va_arg(ap, char *);
331                         for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
332                                 PCHAR(*q--);
333
334                         if (num == 0)
335                                 break;
336
337                         for (tmp = 0; *p;) {
338                                 n = *p++;
339                                 if (num & (1 << (n - 1))) {
340                                         PCHAR(tmp ? ',' : '<');
341                                         for (; (n = *p) > ' '; ++p)
342                                                 PCHAR(n);
343                                         tmp = 1;
344                                 } else
345                                         for (; *p > ' '; ++p)
346                                                 continue;
347                         }
348                         if (tmp)
349                                 PCHAR('>');
350                         break;
351                 case 'c':
352                         PCHAR(va_arg(ap, int));
353                         break;
354                 case 'D':
355                         up = va_arg(ap, uchar_t *);
356                         p = va_arg(ap, char *);
357                         if (!width)
358                                 width = 16;
359                         while(width--) {
360                                 PCHAR(hex2ascii(*up >> 4));
361                                 PCHAR(hex2ascii(*up & 0x0f));
362                                 up++;
363                                 if (width)
364                                         for (q=p;*q;q++)
365                                                 PCHAR(*q);
366                         }
367                         break;
368                 case 'd':
369                 case 'i':
370                         base = 10;
371                         sign = 1;
372                         goto handle_sign;
373                 case 'h':
374                         if (hflag) {
375                                 hflag = 0;
376                                 cflag = 1;
377                         } else
378                                 hflag = 1;
379                         goto reswitch;
380                 case 'j':
381                         jflag = 1;
382                         goto reswitch;
383                 case 'l':
384                         if (lflag) {
385                                 lflag = 0;
386                                 qflag = 1;
387                         } else {
388                                 lflag = 1;
389                         }
390                         goto reswitch;
391                 case 'n':
392                         if (jflag)
393                                 *(va_arg(ap, sint64_t *)) = retval;
394                         else if (qflag)
395                                 *(va_arg(ap, sint64_t *)) = retval;
396                         else if (lflag)
397                                 *(va_arg(ap, long *)) = retval;
398                         else if (zflag)
399                                 *(va_arg(ap, size_t *)) = retval;
400                         else if (hflag)
401                                 *(va_arg(ap, short *)) = retval;
402                         else if (cflag)
403                                 *(va_arg(ap, char *)) = retval;
404                         else
405                                 *(va_arg(ap, int *)) = retval;
406                         break;
407                 case 'o':
408                         base = 8;
409                         goto handle_nosign;
410                 case 'p':
411                         base = 16;
412                         sharpflag = (width == 0);
413                         sign = 0;
414                         num = (addr_t)va_arg(ap, void *);
415                         goto number;
416                 case 'q':
417                         qflag = 1;
418                         goto reswitch;
419                 case 'r':
420                         base = radix;
421                         if (sign)
422                                 goto handle_sign;
423                         goto handle_nosign;
424                 case 's':
425                         p = va_arg(ap, char *);
426                         if (p == NULL)
427                                 p = "(null)";
428                         if (!dot)
429                                 n = strlen (p);
430                         else
431                                 for (n = 0; n < dwidth && p[n]; n++)
432                                         continue;
433
434                         width -= n;
435
436                         if (!ladjust && width > 0)
437                                 while (width--)
438                                         PCHAR(padc);
439                         while (n--)
440                                 PCHAR(*p++);
441                         if (ladjust && width > 0)
442                                 while (width--)
443                                         PCHAR(padc);
444                         break;
445                 case 't':
446                         tflag = 1;
447                         goto reswitch;
448                 case 'u':
449                         base = 10;
450                         goto handle_nosign;
451                 case 'X':
452                         upper = 1;
453                 case 'x':
454                         base = 16;
455                         goto handle_nosign;
456                 case 'y':
457                         base = 16;
458                         sign = 1;
459                         goto handle_sign;
460                 case 'z':
461                         zflag = 1;
462                         goto reswitch;
463 handle_nosign:
464                         sign = 0;
465                         if (jflag)
466                                 num = va_arg(ap, addr_t);
467                         else if (qflag)
468                                 num = va_arg(ap, uint64_t);
469                         else if (tflag)
470                                 num = va_arg(ap, ptrdiff_t);
471                         else if (lflag)
472                                 num = va_arg(ap, ulong_t);
473                         else if (zflag)
474                                 num = va_arg(ap, size_t);
475                         else if (hflag)
476                                 num = (ushort_t)va_arg(ap, int);
477                         else if (cflag)
478                                 num = (uchar_t)va_arg(ap, int);
479                         else
480                                 num = va_arg(ap, uint_t);
481                         goto number;
482 handle_sign:
483                         if (jflag)
484                                 num = va_arg(ap, sint64_t);
485                         else if (qflag)
486                                 num = va_arg(ap, sint64_t);
487                         else if (tflag)
488                                 num = va_arg(ap, ptrdiff_t);
489                         else if (lflag)
490                                 num = va_arg(ap, long);
491                         else if (zflag)
492                                 num = va_arg(ap, ssize_t);
493                         else if (hflag)
494                                 num = (short)va_arg(ap, int);
495                         else if (cflag)
496                                 num = (char)va_arg(ap, int);
497                         else
498                                 num = va_arg(ap, int);
499 number:
500                         if (sign && (sint64_t)num < 0) {
501                                 neg = 1;
502                                 num = -(sint64_t)num;
503                         }
504                         p = ksprintn(nbuf, num, base, &tmp, upper);
505                         if (sharpflag && num != 0) {
506                                 if (base == 8)
507                                         tmp++;
508                                 else if (base == 16)
509                                         tmp += 2;
510                         }
511                         if (neg)
512                                 tmp++;
513
514                         if (!ladjust && padc != '0' && width
515                             && (width -= tmp) > 0)
516                                 while (width--)
517                                         PCHAR(padc);
518                         if (neg)
519                                 PCHAR('-');
520                         if (sharpflag && num != 0) {
521                                 if (base == 8) {
522                                         PCHAR('0');
523                                 } else if (base == 16) {
524                                         PCHAR('0');
525                                         PCHAR('x');
526                                 }
527                         }
528                         if (!ladjust && width && (width -= tmp) > 0)
529                                 while (width--)
530                                         PCHAR(padc);
531
532                         while (*p)
533                                 PCHAR(*p--);
534
535                         if (ladjust && width && (width -= tmp) > 0)
536                                 while (width--)
537                                         PCHAR(padc);
538
539                         break;
540                 default:
541                         while (percent < fmt)
542                                 PCHAR(*percent++);
543                         /*
544                          * Since we ignore an formatting argument it is no 
545                          * longer safe to obey the remaining formatting
546                          * arguments as the arguments will no longer match
547                          * the format specs.
548                          */
549                         stop = 1;
550                         break;
551                 }
552         }
553 #undef PCHAR
554 }
555
556
557 #define HD_COLUMN_MASK  0xff
558 #define HD_DELIM_MASK   0xff00
559 #define HD_OMIT_COUNT   (1 << 16)
560 #define HD_OMIT_HEX     (1 << 17)
561 #define HD_OMIT_CHARS   (1 << 18)
562
563
564 void
565 v3_hexdump(const void *ptr, int length, const char *hdr, int flags)
566 {
567         int i, j, k;
568         int cols;
569         const unsigned char *cp;
570         char delim;
571
572         if ((flags & HD_DELIM_MASK) != 0)
573                 delim = (flags & HD_DELIM_MASK) >> 8;
574         else
575                 delim = ' ';
576
577         if ((flags & HD_COLUMN_MASK) != 0)
578                 cols = flags & HD_COLUMN_MASK;
579         else
580                 cols = 16;
581
582         cp = ptr;
583         for (i = 0; i < length; i+= cols) {
584                 if (hdr != NULL)
585                         PrintDebug("%s", hdr);
586
587                 if ((flags & HD_OMIT_COUNT) == 0)
588                         PrintDebug("%04x  ", i);
589
590                 if ((flags & HD_OMIT_HEX) == 0) {
591                         for (j = 0; j < cols; j++) {
592                                 k = i + j;
593                                 if (k < length)
594                                         PrintDebug("%c%02x", delim, cp[k]);
595                                 else
596                                         PrintDebug("   ");
597                         }
598                 }
599
600                 if ((flags & HD_OMIT_CHARS) == 0) {
601                         PrintDebug("  |");
602                         for (j = 0; j < cols; j++) {
603                                 k = i + j;
604                                 if (k >= length)
605                                         PrintDebug(" ");
606                                 else if (cp[k] >= ' ' && cp[k] <= '~')
607                                         PrintDebug("%c", cp[k]);
608                                 else
609                                         PrintDebug(".");
610                         }
611                         PrintDebug("|");
612                 }
613                 PrintDebug("\n");
614         }
615 }
616