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.


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