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.


b48e6575d8bbd3e2e35d45851cb4275feff02f3d
[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 0
70 #define NEED_SNPRINTF 0
71 #define NEED_VSPRINTF 0
72 #define NEED_VSNPRINTF 0
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 snprintf_func(int ch, void *arg) {
185         struct snprintf_arg *const info = arg;
186
187         if (info->remain >= 2) {
188                 *info->str++ = ch;
189                 info->remain--;
190         }
191 }
192
193 /*
194  * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
195  * order; return an optional length and a pointer to the last character
196  * written in the buffer (i.e., the first character of the string).
197  * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
198  */
199 static char * ksprintn(char *nbuf, uint64_t num, int base, int *lenp, int upper) {
200         char *p, c;
201
202         p = nbuf;
203         *p = '\0';
204         do {
205                 c = hex2ascii(num % base);
206                 *++p = upper ? toupper(c) : c;
207         } while (num /= base);
208         if (lenp)
209                 *lenp = p - nbuf;
210         return (p);
211 }
212
213 /*
214  * Scaled down version of printf(3).
215  *
216  * Two additional formats:
217  *
218  * The format %b is supported to decode error registers.
219  * Its usage is:
220  *
221  *      printf("reg=%b\n", regval, "<base><arg>*");
222  *
223  * where <base> is the output base expressed as a control character, e.g.
224  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
225  * the first of which gives the bit number to be inspected (origin 1), and
226  * the next characters (up to a control character, i.e. a character <= 32),
227  * give the name of the register.  Thus:
228  *
229  *      kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
230  *
231  * would produce output:
232  *
233  *      reg=3<BITTWO,BITONE>
234  *
235  * XXX:  %D  -- Hexdump, takes pointer and separator string:
236  *              ("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
237  *              ("%*D", len, ptr, " " -> XX XX XX XX ...
238  */
239 static int
240 kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
241 {
242 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
243         char nbuf[MAXNBUF];
244         char *d;
245         const char *p, *percent, *q;
246         uchar_t *up;
247         int ch, n;
248         uint64_t num;
249         int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
250         int cflag, hflag, jflag, tflag, zflag;
251         int dwidth, upper;
252         char padc;
253         int stop = 0, retval = 0;
254
255         num = 0;
256         if (!func)
257                 d = (char *) arg;
258         else
259                 d = NULL;
260
261         if (fmt == NULL)
262                 fmt = "(fmt null)\n";
263
264         if (radix < 2 || radix > 36)
265                 radix = 10;
266
267         for (;;) {
268                 padc = ' ';
269                 width = 0;
270                 while ((ch = (uchar_t)*fmt++) != '%' || stop) {
271                         if (ch == '\0')
272                                 return (retval);
273                         PCHAR(ch);
274                 }
275                 percent = fmt - 1;
276                 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
277                 sign = 0; dot = 0; dwidth = 0; upper = 0;
278                 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
279 reswitch:       switch (ch = (uchar_t)*fmt++) {
280                 case '.':
281                         dot = 1;
282                         goto reswitch;
283                 case '#':
284                         sharpflag = 1;
285                         goto reswitch;
286                 case '+':
287                         sign = 1;
288                         goto reswitch;
289                 case '-':
290                         ladjust = 1;
291                         goto reswitch;
292                 case '%':
293                         PCHAR(ch);
294                         break;
295                 case '*':
296                         if (!dot) {
297                                 width = va_arg(ap, int);
298                                 if (width < 0) {
299                                         ladjust = !ladjust;
300                                         width = -width;
301                                 }
302                         } else {
303                                 dwidth = va_arg(ap, int);
304                         }
305                         goto reswitch;
306                 case '0':
307                         if (!dot) {
308                                 padc = '0';
309                                 goto reswitch;
310                         }
311                 case '1': case '2': case '3': case '4':
312                 case '5': case '6': case '7': case '8': case '9':
313                                 for (n = 0;; ++fmt) {
314                                         n = n * 10 + ch - '0';
315                                         ch = *fmt;
316                                         if (ch < '0' || ch > '9')
317                                                 break;
318                                 }
319                         if (dot)
320                                 dwidth = n;
321                         else
322                                 width = n;
323                         goto reswitch;
324                 case 'b':
325                         num = (uint_t)va_arg(ap, int);
326                         p = va_arg(ap, char *);
327                         for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
328                                 PCHAR(*q--);
329
330                         if (num == 0)
331                                 break;
332
333                         for (tmp = 0; *p;) {
334                                 n = *p++;
335                                 if (num & (1 << (n - 1))) {
336                                         PCHAR(tmp ? ',' : '<');
337                                         for (; (n = *p) > ' '; ++p)
338                                                 PCHAR(n);
339                                         tmp = 1;
340                                 } else
341                                         for (; *p > ' '; ++p)
342                                                 continue;
343                         }
344                         if (tmp)
345                                 PCHAR('>');
346                         break;
347                 case 'c':
348                         PCHAR(va_arg(ap, int));
349                         break;
350                 case 'D':
351                         up = va_arg(ap, uchar_t *);
352                         p = va_arg(ap, char *);
353                         if (!width)
354                                 width = 16;
355                         while(width--) {
356                                 PCHAR(hex2ascii(*up >> 4));
357                                 PCHAR(hex2ascii(*up & 0x0f));
358                                 up++;
359                                 if (width)
360                                         for (q=p;*q;q++)
361                                                 PCHAR(*q);
362                         }
363                         break;
364                 case 'd':
365                 case 'i':
366                         base = 10;
367                         sign = 1;
368                         goto handle_sign;
369                 case 'h':
370                         if (hflag) {
371                                 hflag = 0;
372                                 cflag = 1;
373                         } else
374                                 hflag = 1;
375                         goto reswitch;
376                 case 'j':
377                         jflag = 1;
378                         goto reswitch;
379                 case 'l':
380                         if (lflag) {
381                                 lflag = 0;
382                                 qflag = 1;
383                         } else {
384                                 lflag = 1;
385                         }
386                         goto reswitch;
387                 case 'n':
388                         if (jflag)
389                                 *(va_arg(ap, sint64_t *)) = retval;
390                         else if (qflag)
391                                 *(va_arg(ap, sint64_t *)) = retval;
392                         else if (lflag)
393                                 *(va_arg(ap, long *)) = retval;
394                         else if (zflag)
395                                 *(va_arg(ap, size_t *)) = retval;
396                         else if (hflag)
397                                 *(va_arg(ap, short *)) = retval;
398                         else if (cflag)
399                                 *(va_arg(ap, char *)) = retval;
400                         else
401                                 *(va_arg(ap, int *)) = retval;
402                         break;
403                 case 'o':
404                         base = 8;
405                         goto handle_nosign;
406                 case 'p':
407                         base = 16;
408                         sharpflag = (width == 0);
409                         sign = 0;
410                         num = (addr_t)va_arg(ap, void *);
411                         goto number;
412                 case 'q':
413                         qflag = 1;
414                         goto reswitch;
415                 case 'r':
416                         base = radix;
417                         if (sign)
418                                 goto handle_sign;
419                         goto handle_nosign;
420                 case 's':
421                         p = va_arg(ap, char *);
422                         if (p == NULL)
423                                 p = "(null)";
424                         if (!dot)
425                                 n = strlen (p);
426                         else
427                                 for (n = 0; n < dwidth && p[n]; n++)
428                                         continue;
429
430                         width -= n;
431
432                         if (!ladjust && width > 0)
433                                 while (width--)
434                                         PCHAR(padc);
435                         while (n--)
436                                 PCHAR(*p++);
437                         if (ladjust && width > 0)
438                                 while (width--)
439                                         PCHAR(padc);
440                         break;
441                 case 't':
442                         tflag = 1;
443                         goto reswitch;
444                 case 'u':
445                         base = 10;
446                         goto handle_nosign;
447                 case 'X':
448                         upper = 1;
449                 case 'x':
450                         base = 16;
451                         goto handle_nosign;
452                 case 'y':
453                         base = 16;
454                         sign = 1;
455                         goto handle_sign;
456                 case 'z':
457                         zflag = 1;
458                         goto reswitch;
459 handle_nosign:
460                         sign = 0;
461                         if (jflag)
462                                 num = va_arg(ap, addr_t);
463                         else if (qflag)
464                                 num = va_arg(ap, uint64_t);
465                         else if (tflag)
466                                 num = va_arg(ap, ptrdiff_t);
467                         else if (lflag)
468                                 num = va_arg(ap, ulong_t);
469                         else if (zflag)
470                                 num = va_arg(ap, size_t);
471                         else if (hflag)
472                                 num = (ushort_t)va_arg(ap, int);
473                         else if (cflag)
474                                 num = (uchar_t)va_arg(ap, int);
475                         else
476                                 num = va_arg(ap, uint_t);
477                         goto number;
478 handle_sign:
479                         if (jflag)
480                                 num = va_arg(ap, sint64_t);
481                         else if (qflag)
482                                 num = va_arg(ap, sint64_t);
483                         else if (tflag)
484                                 num = va_arg(ap, ptrdiff_t);
485                         else if (lflag)
486                                 num = va_arg(ap, long);
487                         else if (zflag)
488                                 num = va_arg(ap, ssize_t);
489                         else if (hflag)
490                                 num = (short)va_arg(ap, int);
491                         else if (cflag)
492                                 num = (char)va_arg(ap, int);
493                         else
494                                 num = va_arg(ap, int);
495 number:
496                         if (sign && (sint64_t)num < 0) {
497                                 neg = 1;
498                                 num = -(sint64_t)num;
499                         }
500                         p = ksprintn(nbuf, num, base, &tmp, upper);
501                         if (sharpflag && num != 0) {
502                                 if (base == 8)
503                                         tmp++;
504                                 else if (base == 16)
505                                         tmp += 2;
506                         }
507                         if (neg)
508                                 tmp++;
509
510                         if (!ladjust && padc != '0' && width
511                             && (width -= tmp) > 0)
512                                 while (width--)
513                                         PCHAR(padc);
514                         if (neg)
515                                 PCHAR('-');
516                         if (sharpflag && num != 0) {
517                                 if (base == 8) {
518                                         PCHAR('0');
519                                 } else if (base == 16) {
520                                         PCHAR('0');
521                                         PCHAR('x');
522                                 }
523                         }
524                         if (!ladjust && width && (width -= tmp) > 0)
525                                 while (width--)
526                                         PCHAR(padc);
527
528                         while (*p)
529                                 PCHAR(*p--);
530
531                         if (ladjust && width && (width -= tmp) > 0)
532                                 while (width--)
533                                         PCHAR(padc);
534
535                         break;
536                 default:
537                         while (percent < fmt)
538                                 PCHAR(*percent++);
539                         /*
540                          * Since we ignore an formatting argument it is no 
541                          * longer safe to obey the remaining formatting
542                          * arguments as the arguments will no longer match
543                          * the format specs.
544                          */
545                         stop = 1;
546                         break;
547                 }
548         }
549 #undef PCHAR
550 }
551
552
553
554
555 void v3_hexdump(const void * ptr, int length, const char * hdr, int flags) {
556     int i, j, k;
557     int cols;
558     const unsigned char *cp;
559     char delim;
560     
561     if ((flags & HD_DELIM_MASK) != 0)
562         delim = (flags & HD_DELIM_MASK) >> 8;
563     else
564         delim = ' ';
565
566     if ((flags & HD_COLUMN_MASK) != 0)
567         cols = flags & HD_COLUMN_MASK;
568     else
569         cols = 16;
570
571     cp = ptr;
572     for (i = 0; i < length; i+= cols) {
573         if (hdr != NULL)
574             PrintDebug("%s", hdr);
575
576         if ((flags & HD_OMIT_COUNT) == 0)
577             PrintDebug("%04x  ", i);
578
579         if ((flags & HD_OMIT_HEX) == 0) {
580             for (j = 0; j < cols; j++) {
581                 k = i + j;
582                 if (k < length)
583                     PrintDebug("%c%02x", delim, cp[k]);
584                 else
585                     PrintDebug("   ");
586             }
587         }
588
589         if ((flags & HD_OMIT_CHARS) == 0) {
590             PrintDebug("  |");
591             for (j = 0; j < cols; j++) {
592                 k = i + j;
593                 if (k >= length)
594                     PrintDebug(" ");
595                 else if (cp[k] >= ' ' && cp[k] <= '~')
596                     PrintDebug("%c", cp[k]);
597                 else
598                     PrintDebug(".");
599             }
600             PrintDebug("|");
601         }
602         PrintDebug("\n");
603     }
604 }
605