9os

Experimental kernel using plan9 ideas for embedded device
git clone git://git.simple-cc.org/9os
Log | Files | Refs | README | LICENSE

doprnt.c (2102B)


      1 #include <errno.h>
      2 #include <stdarg.h>
      3 #include <stddef.h>
      4 #include <string.h>
      5 
      6 #include <libk.h>
      7 
      8 #include "stream.h"
      9 
     10 static void
     11 printc(Stream *sp, int c)
     12 {
     13 	if (sp->base) {
     14 		if (sp->cnt < sp->len)
     15 			sp->base[sp->cnt++] = c;
     16 	} else {
     17 		putch(c);
     18 		sp->cnt++;
     19 	}
     20 }
     21 
     22 static void
     23 printn(Stream *sp, long long n, int base, int sign, int fill)
     24 {
     25 	int first, d;
     26 	unsigned long long div;
     27 	const static char digits[] = "0123456789ABCDEF";
     28 
     29 	switch (base) {
     30 	case 8:
     31 		div = 01000000000000000000000u;
     32 		break;
     33 	case 10:
     34 		div = 10000000000000000000u;
     35 		break;
     36 	case 16:
     37 	default:
     38 		div = 0x1000000000000000u;
     39 		break;
     40 	}
     41 
     42 	if (sign && n < 0) {
     43 		n = -n;
     44 		printc(sp, '-');
     45 	}
     46 
     47 	for (first = 1; div > 0; div /= base) {
     48 		d = n / div;
     49 		if (d == 0 && first && div != 1 && !fill)
     50 			continue;
     51 		n -= d * div;
     52 		printc(sp, digits[d]);
     53 		first = 0;
     54 	}
     55 }
     56 
     57 static long long
     58 getnum(va_list *va, int size)
     59 {
     60 	switch (size) {
     61 	case 0:
     62 		return va_arg(*va, int);
     63 	case 1:
     64 		return va_arg(*va, long);
     65 	case 2:
     66 		return va_arg(*va, long long);
     67 	case 3:
     68 		return (long long) va_arg(*va, void *);
     69 	case 4:
     70 	default:
     71 		return va_arg(*va, size_t);
     72 	}
     73 }
     74 
     75 void
     76 doprnt(Stream *sp, const char *fmt, va_list va)
     77 {
     78 	char c;
     79 	va_list va2;
     80 	int fill, base, sign, size;
     81 	char *s;
     82 
     83 	va_copy(va2, va);
     84 	while (( c = *fmt++) != '\0') {
     85 		if (c != '%') {
     86 			printc(sp, c);
     87 			continue;
     88 		}
     89 
     90 		fill = size = sign = 0;
     91 flags:
     92 		switch (c = *fmt++) {
     93 		case '0':
     94 			fill = 1;
     95 			goto flags;
     96 		case 'l':
     97 			size++;
     98 			goto flags;
     99 		case 'z':
    100 			size = 4;
    101 			goto flags;
    102 		case 'o':
    103 			base = 8;
    104 			goto print_number;
    105 		case 'd':
    106 			sign = 1;
    107 		case 'u':
    108 			base = 10;
    109 			goto print_number;
    110 		case 'p':
    111 			size = 3;
    112 			fill = 1;
    113 		case 'X':
    114 		case 'x':
    115 			base = 16;
    116 		print_number:
    117 			printn(sp, getnum(&va2, size), base, sign, fill);
    118 			break;
    119 		case 'e':
    120 			s = strerror(errno);
    121 			goto printout;
    122 		case 's':
    123 			s = va_arg(va2, char *);
    124 		printout:
    125 			while (*s)
    126 				printc(sp, *s++);
    127 			break;
    128 		case 'c':
    129 			c = va_arg(va2, int);
    130 		case '%':
    131 			printc(sp, c);
    132 			break;
    133 		case '\0':
    134 			goto out_loop;
    135 		}
    136 	}
    137 
    138 out_loop:
    139 	va_end(va2);
    140 }