home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * PFMT.C
- *
- * (c)Copyright 1990, Matthew Dillon, All Rights Reserved
- *
- * func format same as fwrite: func(buf, 1, n, desc)
- */
-
- #include <stdarg.h>
- #include <stdio.h>
-
- #define F_SPAC 1
- #define F_PLUS 2
- #define F_MINUS 4
- #define F_HASH 8
- #define F_ZERO 16
-
- #define F_SHORT 32
- #define F_LONG 64
- #define F_DLONG 128
-
- int
- _pfmt(ctl, va, func, desc)
- char *ctl;
- va_list va;
- int (*func)();
- void *desc;
- {
- char *base = ctl;
- char c;
- int error = 0;
- int bytes = 0;
- short flags;
- short i1, i2;
-
- for (;;) {
- while (*ctl && *ctl != '%')
- ++ctl;
- if (ctl != base) {
- error = (*func)(base, 1, ctl - base, desc);
- if (error > 0)
- bytes += error;
- }
- if (*ctl++ == 0)
- return(0);
- c = *ctl;
- if (c == '%') {
- base = ctl++;
- continue;
- }
-
- /*
- * %[flags][val[.val]]c
- */
-
- flags = 0;
- for (;; c = *++ctl) {
- if (c == '-') {
- flags |= F_MINUS;
- continue;
- }
- if (c == '+') {
- flags |= F_PLUS;
- continue;
- }
- if (c == ' ') {
- flags |= F_SPAC;
- continue;
- }
- if (c == '#') {
- flags |= F_HASH;
- continue;
- }
- if (c == '0') {
- flags |= F_ZERO;
- continue;
- }
- break;
- }
- if (c == '*') {
- c = *++ctl;
- i1 = va_arg(va, int);
- } else if (c >= '0' && c <= '9') {
- i1 = 0;
- while (c >= '0' && c <= '9') {
- i1 = i1 * 10 + (c - '0');
- c = *++ctl;
- }
- } else {
- i1 = -1;
- }
- i2 = -1;
- if (c == '.') {
- c = *++ctl;
- if (c == '*') {
- c = *++ctl;
- i2 = va_arg(va, int);
- } else {
- i2 = 0;
- while (c >= '0' && c <= '9') {
- i2 = i2 * 10 + (c - '0');
- c = *++ctl;
- }
- }
- }
- if (i1 > 4096 || i2 > 4096) /* bad for business! */
- continue;
- for (;;) {
- if (c == 'h') {
- c = *++ctl;
- flags |= F_SHORT; /* only if sizeof(int) != 4 */
- continue;
- }
- if (c == 'l') {
- c = *++ctl;
- flags |= F_LONG;
- continue;
- }
- if (c == 'L') {
- c = *++ctl;
- flags |= F_DLONG;
- continue;
- }
- break;
- }
- error = _pfmtone(c, &va, func, desc, flags, i1, i2);
- if (error > 0)
- bytes += error;
-
- if (error != -2) {
- base = ++ctl;
- }
- }
- if (error < 0)
- return(error);
- return(bytes); /* # bytes written */
- }
-
- int
- _pfmtone(c, pva, func, desc, flags, i1, i2)
- char c;
- va_list *pva;
- int (*func)();
- void *desc;
- short flags;
- int i1, i2;
- {
- va_list va = *pva;
- int len = 0;
- int error = 0;
- int bytes = 0;
- char buf[32];
- char *ptr = buf;
-
- switch(c) {
- case 'c':
- c = va_arg(va, int);
- ptr = &c;
- len = 1;
- break;
- case 'd':
- case 'u':
- {
- short neg = 0;
- unsigned long v = va_arg(va, unsigned long);
-
- ptr = buf + sizeof(buf);
- if (c != 'u' && (long)v < 0) {
- v = -v;
- neg = 1;
- }
- do {
- *--ptr = v % 10 + '0';
- v = v / 10;
- } while (v);
- if (neg)
- *--ptr = '-';
- len = buf + sizeof(buf) - ptr;
- }
- break;
- case 'e':
- case 'E':
- case 'f':
- case 'g':
- case 'G':
- case 'i':
- case 'n':
- break;
- case 'o':
- {
- short neg = 0;
- unsigned long v = va_arg(va, unsigned long);
-
- ptr = buf + sizeof(buf);
- if (c != 'u' && (long)v < 0) {
- v = -v;
- neg = 1;
- }
- do {
- *--ptr = (v & 7) + '0';
- v = v >> 3;
- } while (v);
- if (neg)
- *--ptr = '-';
- len = buf + sizeof(buf) - ptr;
- }
- break;
- case 'p':
- break;
- case 's':
- ptr = va_arg(va, char *);
- len = strlen(ptr);
- break;
- case 'x':
- case 'X':
- {
- unsigned long v = va_arg(va, unsigned long);
- static char IToHC[17] = { "0123456789ABCDEF" };
-
- ptr = buf + sizeof(buf);
- do {
- *--ptr = IToHC[v & 0x0F];
- v = v >> 4;
- } while (v);
- len = buf + sizeof(buf) - ptr;
- }
- break;
- default:
- return(-2); /* unknown conversion specifier */
- }
-
- if (i2 < 0)
- i2 = len;
- if (i2 < len)
- len = i2;
- if (i1 < len)
- i1 = len;
-
- if (i1 > len && !(flags & F_MINUS)) { /* pre-pad */
- int n = i1 - len;
- int r;
- char tmp[64];
-
- r = sizeof(tmp);
- if (n < r)
- r = n;
-
- if (flags & F_ZERO) {
- _slow_bset(tmp, r, '0');
- } else {
- _slow_bset(tmp, r, ' ');
- }
- while (n) {
- error = (*func)(tmp, 1, r, desc);
- if (error > 0)
- bytes += error;
- n -= r;
- if (n < sizeof(tmp))
- r = n;
- }
- }
- if (len > 0) {
- error = (*func)(ptr, 1, len, desc);
- if (error > 0)
- bytes += error;
- }
-
- if (i1 > len && (flags & F_MINUS)) { /* pos-pad */
- int n = i1 - len;
- int r;
- char tmp[64];
-
- r = sizeof(tmp);
- if (n < r)
- r = n;
-
- _slow_bset(tmp, r, ' ');
-
- while (n) {
- error = (*func)(tmp, 1, r, desc);
- if (error > 0)
- bytes += error;
- n -= r;
- if (n < sizeof(tmp))
- r = n;
- }
- }
-
- *pva = va;
- if (error < 0)
- return(error);
- return(bytes);
- }
-
-
-