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.


6403007848ff5ce3cd79fc1b68a4579246122538
[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
70
71 typedef addr_t ptrdiff_t;     /* ptr1 - ptr2 */
72
73 /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
74 #define MAXNBUF (sizeof(uint64_t) + 1)
75
76
77 /* convert a hex value to it's ascii representation */
78 static char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
79
80 #define hex2ascii(hex)  (hex2ascii_data[hex])
81
82
83 struct snprintf_arg {
84     char        *str;
85     size_t      remain;
86 };
87
88
89
90 #if defined(V3_CONFIG_BUILT_IN_STDIO) &&                      \
91     ( defined(V3_CONFIG_BUILT_IN_SPRINTF) ||          \
92       defined(V3_CONFIG_BUILT_IN_SNPRINTF) ||         \
93       defined(V3_CONFIG_BUILT_IN_VSPRINTF) ||         \
94       defined(V3_CONFIG_BUILT_IN_VSNRPRINTF ))
95
96 static char * ksprintn(char * nbuf, uint64_t num, int base, int *len, int upper);
97 static void snprintf_func(int ch, void * arg);
98 static int kvprintf(char const * fmt, void (*func)(int, void *), void * arg, int radix, va_list ap);
99
100
101 #ifdef V3_CONFIG_BUILT_IN_SPRINTF
102 /*
103  * Scaled down version of sprintf(3).
104  */
105 int sprintf(char * buf, const char * cfmt, ...) {
106     int retval;
107     va_list ap;
108     
109     va_start(ap, cfmt);
110     retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
111     buf[retval] = '\0';
112     va_end(ap);
113     return (retval);
114 }
115 #endif 
116
117
118 #ifdef V3_CONFIG_BUILT_IN_VSPRINTF
119 /*
120  * Scaled down version of vsprintf(3).
121  */
122 int vsprintf(char * buf, const char * cfmt, va_list ap) {
123     int retval;
124
125     retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
126     buf[retval] = '\0';
127     return (retval);
128 }
129 #endif
130
131
132 #ifdef V3_CONFIG_BUILT_IN_SNPRINTF
133 /*
134  * Scaled down version of snprintf(3).
135  */
136 int snprintf(char * str, size_t size, const char * format, ...) {
137     int retval;
138     va_list ap;
139
140     va_start(ap, format);
141     retval = vsnprintf(str, size, format, ap);
142     va_end(ap);
143     return(retval);
144 }
145 #endif
146
147
148
149 /*
150  * Scaled down version of vsnprintf(3).
151  */
152 int vsnprintf(char * str, size_t size, const char * format, va_list ap) {
153     struct snprintf_arg info;
154     int retval;
155
156     info.str = str;
157     info.remain = size;
158     retval = kvprintf(format, snprintf_func, &info, 10, ap);
159     if (info.remain >= 1) {
160         *info.str++ = '\0';
161     }
162     return (retval);
163 }
164
165
166
167 #ifdef V3_CONFIG_BUILT_IN_VSNRPRINTF
168 /*
169  * Kernel version which takes radix argument vsnprintf(3).
170  */
171 int vsnrprintf(char * str, size_t size, int radix, const char * format, va_list ap) {
172     struct snprintf_arg info;
173     int retval;
174
175     info.str = str;
176     info.remain = size;
177     retval = kvprintf(format, snprintf_func, &info, radix, ap);
178     if (info.remain >= 1) {
179         *info.str++ = '\0';
180     }
181     return (retval);
182 }
183 #endif
184
185
186 static void snprintf_func(int ch, void *arg) {
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 * ksprintn(char *nbuf, uint64_t num, int base, int *lenp, int upper) {
202         char *p, c;
203
204         p = nbuf;
205         *p = '\0';
206         do {
207                 c = hex2ascii(num % base);
208                 *++p = upper ? toupper(c) : c;
209         } while (num /= base);
210         if (lenp)
211                 *lenp = p - nbuf;
212         return (p);
213 }
214
215 /*
216  * Scaled down version of printf(3).
217  *
218  * Two additional formats:
219  *
220  * The format %b is supported to decode error registers.
221  * Its usage is:
222  *
223  *      printf("reg=%b\n", regval, "<base><arg>*");
224  *
225  * where <base> is the output base expressed as a control character, e.g.
226  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
227  * the first of which gives the bit number to be inspected (origin 1), and
228  * the next characters (up to a control character, i.e. a character <= 32),
229  * give the name of the register.  Thus:
230  *
231  *      kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
232  *
233  * would produce output:
234  *
235  *      reg=3<BITTWO,BITONE>
236  *
237  * XXX:  %D  -- Hexdump, takes pointer and separator string:
238  *              ("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
239  *              ("%*D", len, ptr, " " -> XX XX XX XX ...
240  */
241 static int
242 kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
243 {
244 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
245         char nbuf[MAXNBUF];
246         char *d;
247         const char *p, *percent, *q;
248         uchar_t *up;
249         int ch, n;
250         uint64_t num;
251         int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
252         int cflag, hflag, jflag, tflag, zflag;
253         int dwidth, upper;
254         char padc;
255         int stop = 0, retval = 0;
256
257         num = 0;
258         if (!func)
259                 d = (char *) arg;
260         else
261                 d = NULL;
262
263         if (fmt == NULL)
264                 fmt = "(fmt null)\n";
265
266         if (radix < 2 || radix > 36)
267                 radix = 10;
268
269         for (;;) {
270                 padc = ' ';
271                 width = 0;
272                 while ((ch = (uchar_t)*fmt++) != '%' || stop) {
273                         if (ch == '\0')
274                                 return (retval);
275                         PCHAR(ch);
276                 }
277                 percent = fmt - 1;
278                 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
279                 sign = 0; dot = 0; dwidth = 0; upper = 0;
280                 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
281 reswitch:       switch (ch = (uchar_t)*fmt++) {
282                 case '.':
283                         dot = 1;
284                         goto reswitch;
285                 case '#':
286                         sharpflag = 1;
287                         goto reswitch;
288                 case '+':
289                         sign = 1;
290                         goto reswitch;
291                 case '-':
292                         ladjust = 1;
293                         goto reswitch;
294                 case '%':
295                         PCHAR(ch);
296                         break;
297                 case '*':
298                         if (!dot) {
299                                 width = va_arg(ap, int);
300                                 if (width < 0) {
301                                         ladjust = !ladjust;
302                                         width = -width;
303                                 }
304                         } else {
305                                 dwidth = va_arg(ap, int);
306                         }
307                         goto reswitch;
308                 case '0':
309                         if (!dot) {
310                                 padc = '0';
311                                 goto reswitch;
312                         }
313                 case '1': case '2': case '3': case '4':
314                 case '5': case '6': case '7': case '8': case '9':
315                                 for (n = 0;; ++fmt) {
316                                         n = n * 10 + ch - '0';
317                                         ch = *fmt;
318                                         if (ch < '0' || ch > '9')
319                                                 break;
320                                 }
321                         if (dot)
322                                 dwidth = n;
323                         else
324                                 width = n;
325                         goto reswitch;
326                 case 'b':
327                         num = (uint_t)va_arg(ap, int);
328                         p = va_arg(ap, char *);
329                         for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
330                                 PCHAR(*q--);
331
332                         if (num == 0)
333                                 break;
334
335                         for (tmp = 0; *p;) {
336                                 n = *p++;
337                                 if (num & (1 << (n - 1))) {
338                                         PCHAR(tmp ? ',' : '<');
339                                         for (; (n = *p) > ' '; ++p)
340                                                 PCHAR(n);
341                                         tmp = 1;
342                                 } else
343                                         for (; *p > ' '; ++p)
344                                                 continue;
345                         }
346                         if (tmp)
347                                 PCHAR('>');
348                         break;
349                 case 'c':
350                         PCHAR(va_arg(ap, int));
351                         break;
352                 case 'D':
353                         up = va_arg(ap, uchar_t *);
354                         p = va_arg(ap, char *);
355                         if (!width)
356                                 width = 16;
357                         while(width--) {
358                                 PCHAR(hex2ascii(*up >> 4));
359                                 PCHAR(hex2ascii(*up & 0x0f));
360                                 up++;
361                                 if (width)
362                                         for (q=p;*q;q++)
363                                                 PCHAR(*q);
364                         }
365                         break;
366                 case 'd':
367                 case 'i':
368                         base = 10;
369                         sign = 1;
370                         goto handle_sign;
371                 case 'h':
372                         if (hflag) {
373                                 hflag = 0;
374                                 cflag = 1;
375                         } else
376                                 hflag = 1;
377                         goto reswitch;
378                 case 'j':
379                         jflag = 1;
380                         goto reswitch;
381                 case 'l':
382                         if (lflag) {
383                                 lflag = 0;
384                                 qflag = 1;
385                         } else {
386                                 lflag = 1;
387                         }
388                         goto reswitch;
389                 case 'n':
390                         if (jflag)
391                                 *(va_arg(ap, sint64_t *)) = retval;
392                         else if (qflag)
393                                 *(va_arg(ap, sint64_t *)) = retval;
394                         else if (lflag)
395                                 *(va_arg(ap, long *)) = retval;
396                         else if (zflag)
397                                 *(va_arg(ap, size_t *)) = retval;
398                         else if (hflag)
399                                 *(va_arg(ap, short *)) = retval;
400                         else if (cflag)
401                                 *(va_arg(ap, char *)) = retval;
402                         else
403                                 *(va_arg(ap, int *)) = retval;
404                         break;
405                 case 'o':
406                         base = 8;
407                         goto handle_nosign;
408                 case 'p':
409                         base = 16;
410                         sharpflag = (width == 0);
411                         sign = 0;
412                         num = (addr_t)va_arg(ap, void *);
413                         goto number;
414                 case 'q':
415                         qflag = 1;
416                         goto reswitch;
417                 case 'r':
418                         base = radix;
419                         if (sign)
420                                 goto handle_sign;
421                         goto handle_nosign;
422                 case 's':
423                         p = va_arg(ap, char *);
424                         if (p == NULL)
425                                 p = "(null)";
426                         if (!dot)
427                                 n = strlen (p);
428                         else
429                                 for (n = 0; n < dwidth && p[n]; n++)
430                                         continue;
431
432                         width -= n;
433
434                         if (!ladjust && width > 0)
435                                 while (width--)
436                                         PCHAR(padc);
437                         while (n--)
438                                 PCHAR(*p++);
439                         if (ladjust && width > 0)
440                                 while (width--)
441                                         PCHAR(padc);
442                         break;
443                 case 't':
444                         tflag = 1;
445                         goto reswitch;
446                 case 'u':
447                         base = 10;
448                         goto handle_nosign;
449                 case 'X':
450                         upper = 1;
451                 case 'x':
452                         base = 16;
453                         goto handle_nosign;
454                 case 'y':
455                         base = 16;
456                         sign = 1;
457                         goto handle_sign;
458                 case 'z':
459                         zflag = 1;
460                         goto reswitch;
461 handle_nosign:
462                         sign = 0;
463                         if (jflag)
464                                 num = va_arg(ap, addr_t);
465                         else if (qflag)
466                                 num = va_arg(ap, uint64_t);
467                         else if (tflag)
468                                 num = va_arg(ap, ptrdiff_t);
469                         else if (lflag)
470                                 num = va_arg(ap, ulong_t);
471                         else if (zflag)
472                                 num = va_arg(ap, size_t);
473                         else if (hflag)
474                                 num = (ushort_t)va_arg(ap, int);
475                         else if (cflag)
476                                 num = (uchar_t)va_arg(ap, int);
477                         else
478                                 num = va_arg(ap, uint_t);
479                         goto number;
480 handle_sign:
481                         if (jflag)
482                                 num = va_arg(ap, sint64_t);
483                         else if (qflag)
484                                 num = va_arg(ap, sint64_t);
485                         else if (tflag)
486                                 num = va_arg(ap, ptrdiff_t);
487                         else if (lflag)
488                                 num = va_arg(ap, long);
489                         else if (zflag)
490                                 num = va_arg(ap, ssize_t);
491                         else if (hflag)
492                                 num = (short)va_arg(ap, int);
493                         else if (cflag)
494                                 num = (char)va_arg(ap, int);
495                         else
496                                 num = va_arg(ap, int);
497 number:
498                         if (sign && (sint64_t)num < 0) {
499                                 neg = 1;
500                                 num = -(sint64_t)num;
501                         }
502                         p = ksprintn(nbuf, num, base, &tmp, upper);
503                         if (sharpflag && num != 0) {
504                                 if (base == 8)
505                                         tmp++;
506                                 else if (base == 16)
507                                         tmp += 2;
508                         }
509                         if (neg)
510                                 tmp++;
511
512                         if (!ladjust && padc != '0' && width
513                             && (width -= tmp) > 0)
514                                 while (width--)
515                                         PCHAR(padc);
516                         if (neg)
517                                 PCHAR('-');
518                         if (sharpflag && num != 0) {
519                                 if (base == 8) {
520                                         PCHAR('0');
521                                 } else if (base == 16) {
522                                         PCHAR('0');
523                                         PCHAR('x');
524                                 }
525                         }
526                         if (!ladjust && width && (width -= tmp) > 0)
527                                 while (width--)
528                                         PCHAR(padc);
529
530                         while (*p)
531                                 PCHAR(*p--);
532
533                         if (ladjust && width && (width -= tmp) > 0)
534                                 while (width--)
535                                         PCHAR(padc);
536
537                         break;
538                 default:
539                         while (percent < fmt)
540                                 PCHAR(*percent++);
541                         /*
542                          * Since we ignore an formatting argument it is no 
543                          * longer safe to obey the remaining formatting
544                          * arguments as the arguments will no longer match
545                          * the format specs.
546                          */
547                         stop = 1;
548                         break;
549                 }
550         }
551 #undef PCHAR
552 }
553
554
555 #endif // V3_CONFIG_BUILT_IN_STDIO
556
557
558
559 void v3_hexdump(const void * ptr, int length, const char * hdr, int flags) {
560     int i, j, k;
561     int cols;
562     const unsigned char *cp;
563     char delim;
564     
565     if ((flags & HD_DELIM_MASK) != 0)
566         delim = (flags & HD_DELIM_MASK) >> 8;
567     else
568         delim = ' ';
569
570     if ((flags & HD_COLUMN_MASK) != 0)
571         cols = flags & HD_COLUMN_MASK;
572     else
573         cols = 16;
574
575     cp = ptr;
576     for (i = 0; i < length; i+= cols) {
577         if (hdr != NULL)
578             V3_Print("%s", hdr);
579
580         if ((flags & HD_OMIT_COUNT) == 0)
581             V3_Print("%04x  ", i);
582
583         if ((flags & HD_OMIT_HEX) == 0) {
584             for (j = 0; j < cols; j++) {
585                 k = i + j;
586                 if (k < length)
587                     V3_Print("%c%02x", delim, cp[k]);
588                 else
589                     V3_Print("   ");
590             }
591         }
592
593         if ((flags & HD_OMIT_CHARS) == 0) {
594             V3_Print("  |");
595             for (j = 0; j < cols; j++) {
596                 k = i + j;
597                 if (k >= length)
598                     V3_Print(" ");
599                 else if (cp[k] >= ' ' && cp[k] <= '~')
600                     V3_Print("%c", cp[k]);
601                 else
602                     V3_Print(".");
603             }
604             V3_Print("|");
605         }
606         V3_Print("\n");
607     }
608 }
609