doprnt.c

Go to the documentation of this file.
00001 /*
00002  * doprnt.c - print formatted output
00003  */
00004 /* $Header: /opt/proj/minix/cvsroot/src/lib/stdio/doprnt.c,v 1.1.1.1 2005/04/21 14:56:34 beng Exp $ */
00005 
00006 #include        <ctype.h>
00007 #include        <stdio.h>
00008 #include        <stdarg.h>
00009 #include        <string.h>
00010 #include        "loc_incl.h"
00011 
00012 /* gnum() is used to get the width and precision fields of a format. */
00013 static const char *
00014 gnum(register const char *f, int *ip, va_list *app)
00015 {
00016         register int    i, c;
00017 
00018         if (*f == '*') {
00019                 *ip = va_arg((*app), int);
00020                 f++;
00021         } else {
00022                 i = 0;
00023                 while ((c = *f - '0') >= 0 && c <= 9) {
00024                         i = i*10 + c;
00025                         f++;
00026                 }
00027                 *ip = i;
00028         }
00029         return f;
00030 }
00031 
00032 #if     _EM_WSIZE == _EM_PSIZE
00033 #define set_pointer(flags)                              /* nothing */
00034 #elif   _EM_LSIZE == _EM_PSIZE
00035 #define set_pointer(flags)      (flags |= FL_LONG)
00036 #else
00037 #error garbage pointer size
00038 #define set_pointer(flags)              /* compilation might continue */
00039 #endif
00040 
00041 /* print an ordinal number */
00042 static char *
00043 o_print(va_list *ap, int flags, char *s, char c, int precision, int is_signed)
00044 {
00045         long signed_val;
00046         unsigned long unsigned_val;
00047         char *old_s = s;
00048         int base;
00049 
00050         switch (flags & (FL_SHORT | FL_LONG)) {
00051         case FL_SHORT:
00052                 if (is_signed) {
00053                         signed_val = (short) va_arg(*ap, int);
00054                 } else {
00055                         unsigned_val = (unsigned short) va_arg(*ap, unsigned);
00056                 }
00057                 break;
00058         case FL_LONG:
00059                 if (is_signed) {
00060                         signed_val = va_arg(*ap, long);
00061                 } else {
00062                         unsigned_val = va_arg(*ap, unsigned long);
00063                 }
00064                 break;
00065         default:
00066                 if (is_signed) {
00067                         signed_val = va_arg(*ap, int);
00068                 } else {
00069                         unsigned_val = va_arg(*ap, unsigned int);
00070                 }
00071                 break;
00072         }
00073 
00074         if (is_signed) {
00075                 if (signed_val < 0) {
00076                         *s++ = '-';
00077                         signed_val = -signed_val;
00078                 } else if (flags & FL_SIGN) *s++ = '+';
00079                 else if (flags & FL_SPACE) *s++ = ' ';
00080                 unsigned_val = signed_val;
00081         }
00082         if ((flags & FL_ALT) && (c == 'o')) *s++ = '0';
00083         if (!unsigned_val) {
00084                  if (!precision)
00085                         return s;
00086         } else if (((flags & FL_ALT) && (c == 'x' || c == 'X'))
00087                     || c == 'p') {
00088                 *s++ = '0';
00089                 *s++ = (c == 'X' ? 'X' : 'x');
00090         }
00091 
00092         switch (c) {
00093         case 'b':       base = 2;       break;
00094         case 'o':       base = 8;       break;
00095         case 'd':
00096         case 'i':
00097         case 'u':       base = 10;      break;
00098         case 'x':
00099         case 'X':
00100         case 'p':       base = 16;      break;
00101         }
00102 
00103         s = _i_compute(unsigned_val, base, s, precision);
00104 
00105         if (c == 'X')
00106                 while (old_s != s) {
00107                         *old_s = toupper(*old_s);
00108                         old_s++;
00109                 }
00110 
00111         return s;
00112 }
00113 
00114 int
00115 _doprnt(register const char *fmt, va_list ap, FILE *stream)
00116 {
00117         register char   *s;
00118         register int    j;
00119         int             i, c, width, precision, zfill, flags, between_fill;
00120         int             nrchars=0;
00121         const char      *oldfmt;
00122         char            *s1, buf[1025];
00123 
00124         while (c = *fmt++) {
00125                 if (c != '%') {
00126 #ifdef  CPM
00127                         if (c == '\n') {
00128                                 if (putc('\r', stream) == EOF)
00129                                         return nrchars ? -nrchars : -1;
00130                                 nrchars++;
00131                         }
00132 #endif
00133                         if (putc(c, stream) == EOF)
00134                                 return nrchars ? -nrchars : -1;
00135                         nrchars++;
00136                         continue;
00137                 }
00138                 flags = 0;
00139                 do {
00140                         switch(*fmt) {
00141                         case '-':       flags |= FL_LJUST;      break;
00142                         case '+':       flags |= FL_SIGN;       break;
00143                         case ' ':       flags |= FL_SPACE;      break;
00144                         case '#':       flags |= FL_ALT;        break;
00145                         case '0':       flags |= FL_ZEROFILL;   break;
00146                         default:        flags |= FL_NOMORE;     continue;
00147                         }
00148                         fmt++;
00149                 } while(!(flags & FL_NOMORE));
00150 
00151                 oldfmt = fmt;
00152                 fmt = gnum(fmt, &width, &ap);
00153                 if (fmt != oldfmt) flags |= FL_WIDTHSPEC;
00154 
00155                 if (*fmt == '.') {
00156                         fmt++; oldfmt = fmt;
00157                         fmt = gnum(fmt, &precision, &ap);
00158                         if (precision >= 0) flags |= FL_PRECSPEC;
00159                 }
00160 
00161                 if ((flags & FL_WIDTHSPEC) && width < 0) {
00162                         width = -width;
00163                         flags |= FL_LJUST;
00164                 }
00165                 if (!(flags & FL_WIDTHSPEC)) width = 0;
00166 
00167                 if (flags & FL_SIGN) flags &= ~FL_SPACE;
00168 
00169                 if (flags & FL_LJUST) flags &= ~FL_ZEROFILL;
00170 
00171 
00172                 s = s1 = buf;
00173 
00174                 switch (*fmt) {
00175                 case 'h':       flags |= FL_SHORT; fmt++; break;
00176                 case 'l':       flags |= FL_LONG; fmt++; break;
00177                 case 'L':       flags |= FL_LONGDOUBLE; fmt++; break;
00178                 }
00179 
00180                 switch (c = *fmt++) {
00181                 default:
00182 #ifdef  CPM
00183                         if (c == '\n') {
00184                                 if (putc('\r', stream) == EOF)
00185                                         return nrchars ? -nrchars : -1;
00186                                 nrchars++;
00187                         }
00188 #endif
00189                         if (putc(c, stream) == EOF)
00190                                 return nrchars ? -nrchars : -1;
00191                         nrchars++;
00192                         continue;
00193                 case 'n':
00194                         if (flags & FL_SHORT)
00195                                 *va_arg(ap, short *) = (short) nrchars;
00196                         else if (flags & FL_LONG)
00197                                 *va_arg(ap, long *) = (long) nrchars;
00198                         else
00199                                 *va_arg(ap, int *) = (int) nrchars;
00200                         continue;
00201                 case 's':
00202                         s1 = va_arg(ap, char *);
00203                         if (s1 == NULL)
00204                                 s1 = "(null)";
00205                         s = s1;
00206                         while (precision || !(flags & FL_PRECSPEC)) {
00207                                 if (*s == '\0')
00208                                         break;
00209                                 s++;
00210                                 precision--;
00211                         }
00212                         break;
00213                 case 'p':
00214                         set_pointer(flags);
00215                         /* fallthrough */
00216                 case 'b':
00217                 case 'o':
00218                 case 'u':
00219                 case 'x':
00220                 case 'X':
00221                         if (!(flags & FL_PRECSPEC)) precision = 1;
00222                         else if (c != 'p') flags &= ~FL_ZEROFILL;
00223                         s = o_print(&ap, flags, s, c, precision, 0);
00224                         break;
00225                 case 'd':
00226                 case 'i':
00227                         flags |= FL_SIGNEDCONV;
00228                         if (!(flags & FL_PRECSPEC)) precision = 1;
00229                         else flags &= ~FL_ZEROFILL;
00230                         s = o_print(&ap, flags, s, c, precision, 1);
00231                         break;
00232                 case 'c':
00233                         *s++ = va_arg(ap, int);
00234                         break;
00235 #ifndef NOFLOAT
00236                 case 'G':
00237                 case 'g':
00238                         if ((flags & FL_PRECSPEC) && (precision == 0))
00239                                 precision = 1;
00240                 case 'f':
00241                 case 'E':
00242                 case 'e':
00243                         if (!(flags & FL_PRECSPEC)) 
00244                                 precision = 6;
00245 
00246                         if (precision >= sizeof(buf))
00247                                 precision = sizeof(buf) - 1;
00248 
00249                         flags |= FL_SIGNEDCONV;
00250                         s = _f_print(&ap, flags, s, c, precision);
00251                         break;
00252 #endif  /* NOFLOAT */
00253                 case 'r':
00254                         ap = va_arg(ap, va_list);
00255                         fmt = va_arg(ap, char *);
00256                         continue;
00257                 }
00258                 zfill = ' ';
00259                 if (flags & FL_ZEROFILL) zfill = '0';
00260                 j = s - s1;
00261 
00262                 /* between_fill is true under the following conditions:
00263                  * 1- the fill character is '0'
00264                  * and
00265                  * 2a- the number is of the form 0x... or 0X...
00266                  * or
00267                  * 2b- the number contains a sign or space
00268                  */
00269                 between_fill = 0;
00270                 if ((flags & FL_ZEROFILL)
00271                     && (((c == 'x' || c == 'X') && (flags & FL_ALT))
00272                         || (c == 'p')
00273                         || ((flags & FL_SIGNEDCONV)
00274                             && ( *s1 == '+' || *s1 == '-' || *s1 == ' '))))
00275                         between_fill++;
00276 
00277                 if ((i = width - j) > 0)
00278                         if (!(flags & FL_LJUST)) {      /* right justify */
00279                                 nrchars += i;
00280                                 if (between_fill) {
00281                                     if (flags & FL_SIGNEDCONV) {
00282                                         j--; nrchars++;
00283                                         if (putc(*s1++, stream) == EOF)
00284                                                 return nrchars ? -nrchars : -1;
00285                                     } else {
00286                                         j -= 2; nrchars += 2;
00287                                         if ((putc(*s1++, stream) == EOF)
00288                                             || (putc(*s1++, stream) == EOF))
00289                                                 return nrchars ? -nrchars : -1;
00290                                     }
00291                                 }
00292                                 do {
00293                                         if (putc(zfill, stream) == EOF)
00294                                                 return nrchars ? -nrchars : -1;
00295                                 } while (--i);
00296                         }
00297 
00298                 nrchars += j;
00299                 while (--j >= 0) {
00300                         if (putc(*s1++, stream) == EOF)
00301                                 return nrchars ? -nrchars : -1;
00302                 }
00303 
00304                 if (i > 0) nrchars += i;
00305                 while (--i >= 0)
00306                         if (putc(zfill, stream) == EOF)
00307                                 return nrchars ? -nrchars : -1;
00308         }
00309         return nrchars;
00310 }

Generated on Fri Apr 14 22:57:27 2006 for minix by  doxygen 1.4.6