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.


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