/* -------------------------------------------------------------------- */ /* */ /* */ /* */ /* Copyright (C) 2000 Angelo Masci */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* */ /* You can contact the author at this e-mail address: */ /* */ /* angelo@styx.demon.co.uk */ /* */ /* -------------------------------------------------------------------- $Id$ -------------------------------------------------------------------- */ #include #include "common.h" #include "format.h" /* -------------------------------------------------------------------- */ #define FALSE 0 #define TRUE (!FALSE) #define NWIDTH 64 /* Current maximum width limit for numbers */ /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ int format(int (* copyfunc)(void *, char *, int), void (* flushfunc)(void *), void *cfarg, char *fmt, va_list args) { int res, written, n; char *ptr, *optr, buf[NWIDTH]; int width; char c; int signed_flag, long_flag; int int_val; unsigned int uint_val; long long_val; unsigned long ulong_val; written = 0; while (*fmt) { ptr = fmt; while ((*fmt) && (*fmt != '%')) { fmt++; } n = fmt - ptr; if (n) { res = (*copyfunc)(cfarg, ptr, n); if (res != n) { goto finish; } written += res; } signed_flag = TRUE; long_flag = FALSE; if (*fmt == '%') { fmt++; width = 0; while ((*fmt >= '0') && (*fmt <= '9')) { width *= 10; width += (*fmt - '0'); fmt++; } if (*fmt == 'l') { long_flag = TRUE; fmt++; } switch (*fmt) { case 'c': c = (char)(va_arg(args, int)); res = (*copyfunc)(cfarg, &c, 1); if (res != 1) { goto finish; } written += res; break; case 's': ptr = (char *)(va_arg(args, int)); optr = ptr; n = 0; while(*ptr++) { n++; } /* -------------------- */ /* Output Left Padding */ if (width > n) { width -= n; while (width--) { res = (*copyfunc)(cfarg, " ", 1); if (res != 1) { goto finish; } } written += res; } /* -------------------- */ /* Output String */ res = (*copyfunc)(cfarg, optr, n); if (res != n) { goto finish; } /* -------------------- */ /* Output Right Padding */ /* Unfinished --- */ written += res; break; /* %[0-9]*d int */ /* %[0-9]*u unsigned int */ /* %[0-9]*ld long int */ /* %[0-9]*lu unsigned long int */ case 'u': signed_flag = FALSE; case 'd': optr = &buf[NWIDTH]; if (long_flag) { if (signed_flag) { long_val = va_arg(args, long); do { *--optr = '0' + (long_val % 10); long_val = long_val / 10; } while (long_val); } else { ulong_val = (unsigned long)va_arg(args, long); do { *--optr = '0' + (ulong_val % 10); ulong_val = ulong_val / 10; } while (ulong_val); } } else { if (signed_flag) { int_val = va_arg(args, int); do { *--optr = '0' + (int_val % 10); int_val = int_val / 10; } while (int_val); } else { uint_val = (unsigned int)va_arg(args, int); do { *--optr = '0' + (uint_val % 10); uint_val = uint_val / 10; } while (uint_val); } } /* -------------------- */ /* Output Left Padding */ if (width > (&buf[NWIDTH] - optr)) { width -= (&buf[NWIDTH] - optr); while (width--) { res = (*copyfunc)(cfarg, " ", 1); if (res != 1) { goto finish; } } written += res; } /* -------------------- */ /* Output Value */ res = (*copyfunc)(cfarg, optr, (&buf[NWIDTH] - optr)); if (res != (&buf[NWIDTH] - optr)) { goto finish; } written += res; /* -------------------- */ /* Output Right Padding */ /* Unfinished --- */ break; case '%': res = (*copyfunc)(cfarg, "%", 1); if (res != 1) { goto finish; } written += res; break; default: break; } fmt++; } } res = (*copyfunc)(cfarg, "", 1); if (res != 1) { goto finish; } finish: written += res; if (flushfunc != NULL) { (*flushfunc)(cfarg); } return written; }