/* *----------------------------------------------------------------------------- * * stdio.c -- * * Minimal implementation of ISO C's stdio.h. * *----------------------------------------------------------------------------- */ /* FIXME: this file is a mess */ #include void process_format (char *buffer, int *p, int buflen, char *fmt, int *k) { } enum size { BYTE = -2, SHORT, INT, LONG, LONGLONG }; long long divs10(long long n) { long long q, r; n = n + (n>>63 & 9); q = (n >> 1) + (n >> 2); q = q + (q >> 4); q = q + (q >> 8); q = q + (q >> 16); q = q >> 3; r = n - q*10; return q + ((r + 6) >> 4); } #define insert(c) ({ buffer[p] = (c); \ p++; \ if (p >= buflen) { \ buflen *= 2; \ buffer = realloc (buffer, buflen + 1); \ } }) /* *----------------------------------------------------------------------------- * * printf -- * * Light version of the real printf. Current format characters * recognized are: * * c * s * d * x * % * *----------------------------------------------------------------------------- */ int printf (char *fmt, ...) { char *buffer; int buflen, k, p, b; int width; /* field width: 0 = unlimited */ int zero_pad; /* pad left with zeros: 0 = no, 1 = yes */ int align; /* 0 = right, 1 = left */ enum size size; /* 0 = normal, 1 = l, 2 = ll, -1 = h, -2 = hh */ #define TBUFLEN 64 char tbuf[TBUFLEN]; int tbp; char byte; short short_int; long long_int; long long longlong_int; char *pint = NULL; long long allint = 0; int nintbytes = 0; char fmt_char; va_list ap; va_start (ap, fmt); buflen = 2 * strlen (fmt); buffer = malloc (buflen + 1); buffer[buflen] = '\0'; p = 0; for (k = 0; k < strlen (fmt); k++) { width = 0; /* field width: 0 = unlimited */ zero_pad = 0; /* pad left with zeros: 0 = no, 1 = yes */ align = 0; /* 0 = right, 1 = left */ size = INT; tbp = TBUFLEN - 1; if (fmt[k] != '%') { insert (fmt[k]); continue; } /* skip past initial % */ k++; /* %% */ if (fmt[k] == '%') { insert ('%'); continue; } if (fmt[k] == '-') { align = 1; k++; } if (fmt[k] == '0') { zero_pad = 1; k++; } while (fmt[k] >= '0' && fmt[k] <= '9') { width = 10 * width + (fmt[k] - '0'); k++; } if (fmt[k] == '\0') { break; } if (fmt[k] == 'h') { size--; k++; } if (fmt[k] == 'h') { size--; k++; } if (fmt[k] == 'l') { size++; k++; } if (fmt[k] == 'l') { size++; k++; } /* use fmt_char to be able to do format substitutions */ fmt_char = fmt[k]; /* %p becomes 0x%08x */ if (fmt_char == 'p') { fmt_char = 'x'; size = LONG; width = 8; zero_pad = 1; insert ('0'); insert ('x'); } /* %s */ if (fmt_char == 's') { char *arg = va_arg (ap, char *); /* copy string left justified */ if (width > strlen (arg) && align) { for (b = 0; b < strlen (arg); b++) { insert (arg[b]); } } /* pad with spaces as needed */ if (width > strlen (arg)) { int pad; for (pad = 0; pad < width - strlen (arg); pad++) { insert (' '); } } /* right justified, copy string */ if (!align) { for (b = 0; b < strlen (arg); b++) { insert (arg[b]); } } } /* %c */ if (fmt_char == 'c') { char c = (char)va_arg (ap, int); insert (c); } /* %d, %x */ if (fmt_char == 'x' || fmt_char == 'd') { switch (size) { case BYTE: byte = (char)va_arg (ap, int); pint = &byte; allint = (long long)byte; nintbytes = 1; break; case SHORT: short_int = (short)va_arg (ap, int); pint = (char *)&short_int; allint = (long long)short_int; nintbytes = 2; break; case INT: case LONG: long_int = va_arg (ap, long); pint = (char *)&long_int; allint = (long long)long_int; nintbytes = 4; break; case LONGLONG: longlong_int = va_arg (ap, long); pint = (char *)&longlong_int; allint = longlong_int; nintbytes = 8; break; } tbp = TBUFLEN; /* x */ if (fmt_char == 'x') { char hex[] = "0123456789abcdef"; for (b = 0; b < nintbytes; b++) { tbp--; tbuf[tbp] = hex[*(pint+b) & 0xf]; tbp--; tbuf[tbp] = hex[(*(pint+b) >> 4) & 0xf]; } } /* d */ if (fmt_char == 'd') { long long d10q; while (allint) { tbp--; d10q = divs10 (allint); tbuf[tbp] = (char)('0' + (allint - 10*d10q)); allint = d10q; } } /* get rid of leading zeros */ while (tbuf[tbp] == '0' && tbp < TBUFLEN - 1) { tbp++; } /* pad value if requested */ if (!align) { for (b = 0; b < width - (TBUFLEN - tbp); b++) { insert (zero_pad ? '0' : ' '); } } /* copy the formatted number */ for (b = tbp; b < TBUFLEN; b++) { insert (tbuf[b]); } /* left justify if requested (and there's room) */ if (align && width > (TBUFLEN - tbp)) { for (b = 0; b < width - (TBUFLEN - tbp); b++) { insert (' '); } } /* end of %x or %d */ } } insert ('\0'); print_str (buffer); free (buffer); va_end (ap); return 0; }