qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

printf.c (2972B)


      1 /*
      2  * Copyright (C) 2015 Virtual Open Systems SAS
      3  * Author: Alexander Spyridakis <a.spyridakis@virtualopensystems.com>
      4  *
      5  * printf based on implementation by Kevin Wolf <kwolf@redhat.com>
      6  *
      7  * This program is free software; you can redistribute it and/or modify
      8  * it under the terms of the GNU General Public License version 2 as
      9  * published by the Free Software Foundation.
     10  *
     11  * SPDX-License-Identifier: GPL-2.0-only
     12  */
     13 
     14 #include "minilib.h"
     15 
     16 typedef __builtin_va_list   va_list;
     17 #define va_start(ap, X)     __builtin_va_start(ap, X)
     18 #define va_arg(ap, type)    __builtin_va_arg(ap, type)
     19 #define va_end(ap)          __builtin_va_end(ap)
     20 
     21 static void print_str(char *s)
     22 {
     23     while (*s) {
     24         __sys_outc(*s++);
     25     }
     26 }
     27 
     28 static void print_num(unsigned long long value, int base)
     29 {
     30     char digits[] = "0123456789abcdef";
     31     char buf[32];
     32     int i = sizeof(buf) - 2, j;
     33 
     34     /* Set the buffer to 0. See problem of before. */
     35     for (j = 0; j < 32; j++) {
     36         buf[j] = 0;
     37     }
     38 
     39     do {
     40         buf[i--] = digits[value % base];
     41         value /= base;
     42     } while (value);
     43 
     44     print_str(&buf[i + 1]);
     45 }
     46 
     47 void ml_printf(const char *fmt, ...)
     48 {
     49     va_list ap;
     50     char *str;
     51     int base;
     52     int has_long;
     53     int alt_form;
     54     unsigned long long val;
     55 
     56     va_start(ap, fmt);
     57 
     58     for (; *fmt; fmt++) {
     59         if (*fmt != '%') {
     60             __sys_outc(*fmt);
     61             continue;
     62         }
     63         fmt++;
     64 
     65         if (*fmt == '#') {
     66             fmt++;
     67             alt_form = 1;
     68         } else {
     69             alt_form = 0;
     70         }
     71 
     72         if (*fmt == 'l') {
     73             fmt++;
     74             if (*fmt == 'l') {
     75                 fmt++;
     76                 has_long = 2;
     77             } else {
     78                 has_long = 1;
     79             }
     80         } else {
     81             has_long = 0;
     82         }
     83 
     84         switch (*fmt) {
     85         case 'x':
     86         case 'p':
     87             base = 16;
     88             goto convert_number;
     89         case 'd':
     90         case 'i':
     91         case 'u':
     92             base = 10;
     93             goto convert_number;
     94         case 'o':
     95             base = 8;
     96             goto convert_number;
     97 
     98         convert_number:
     99             switch (has_long) {
    100             case 0:
    101                 val = va_arg(ap, unsigned int);
    102                 break;
    103             case 1:
    104                 val = va_arg(ap, unsigned long);
    105                 break;
    106             case 2:
    107                 val = va_arg(ap, unsigned long long);
    108                 break;
    109             }
    110 
    111             if (alt_form && base == 16) {
    112                 print_str("0x");
    113             }
    114 
    115             print_num(val, base);
    116             break;
    117 
    118         case 's':
    119             str = va_arg(ap, char*);
    120             print_str(str);
    121             break;
    122         case 'c':
    123             __sys_outc(va_arg(ap, int));
    124             break;
    125         case '%':
    126             __sys_outc(*fmt);
    127             break;
    128         default:
    129             __sys_outc('%');
    130             __sys_outc(*fmt);
    131             break;
    132         }
    133     }
    134 
    135     va_end(ap);
    136 }