1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #if !defined(lint) && defined(DOSCCS)
   8: static char *sccsid = "@(#)printf.c	7.3 (Berkeley) 6/7/85";
   9: 
  10: /* The pwb version this is based on */
  11: static char *printf_id = "@(#) printf.c:2.2 6/5/79";
  12: #endif
  13: 
  14: #include "varargs.h"
  15: /*
  16:  * This version of printf is compatible with the Version 7 C
  17:  * printf. The differences are only minor except that this
  18:  * printf assumes it is to print through putchar. Version 7
  19:  * printf is more general (and is much larger) and includes
  20:  * provisions for floating point.
  21:  */
  22: 
  23: 
  24: #define MAXOCT  11  /* Maximum octal digits in a long */
  25: #define MAXINT  32767   /* largest normal length positive integer */
  26: #define BIG 1000000000  /* largest power of 10 less than an unsigned long */
  27: #define MAXDIGS 10  /* number of digits in BIG */
  28: 
  29: static int width, sign, fill;
  30: 
  31: char *_p_dconv();
  32: 
  33: printf(va_alist)
  34:     va_dcl
  35: {
  36:     va_list ap;
  37:     register char *fmt;
  38:     char fcode;
  39:     int prec;
  40:     int length,mask1,nbits,n;
  41:     long int mask2, num;
  42:     register char *bptr;
  43:     char *ptr;
  44:     char buf[134];
  45: 
  46:     va_start(ap);
  47:     fmt = va_arg(ap,char *);
  48:     for (;;) {
  49:         /* process format string first */
  50:         while ((fcode = *fmt++)!='%') {
  51:             /* ordinary (non-%) character */
  52:             if (fcode=='\0')
  53:                 return;
  54:             putchar(fcode);
  55:         }
  56:         /* length modifier: -1 for h, 1 for l, 0 for none */
  57:         length = 0;
  58:         /* check for a leading - sign */
  59:         sign = 0;
  60:         if (*fmt == '-') {
  61:             sign++;
  62:             fmt++;
  63:         }
  64:         /* a '0' may follow the - sign */
  65:         /* this is the requested fill character */
  66:         fill = 1;
  67:         if (*fmt == '0') {
  68:             fill--;
  69:             fmt++;
  70:         }
  71: 
  72:         /* Now comes a digit string which may be a '*' */
  73:         if (*fmt == '*') {
  74:             width = va_arg(ap, int);
  75:             if (width < 0) {
  76:                 width = -width;
  77:                 sign = !sign;
  78:             }
  79:             fmt++;
  80:         }
  81:         else {
  82:             width = 0;
  83:             while (*fmt>='0' && *fmt<='9')
  84:                 width = width * 10 + (*fmt++ - '0');
  85:         }
  86: 
  87:         /* maybe a decimal point followed by more digits (or '*') */
  88:         if (*fmt=='.') {
  89:             if (*++fmt == '*') {
  90:                 prec = va_arg(ap, int);
  91:                 fmt++;
  92:             }
  93:             else {
  94:                 prec = 0;
  95:                 while (*fmt>='0' && *fmt<='9')
  96:                     prec = prec * 10 + (*fmt++ - '0');
  97:             }
  98:         }
  99:         else
 100:             prec = -1;
 101: 
 102:         /*
 103: 		 * At this point, "sign" is nonzero if there was
 104: 		 * a sign, "fill" is 0 if there was a leading
 105: 		 * zero and 1 otherwise, "width" and "prec"
 106: 		 * contain numbers corresponding to the digit
 107: 		 * strings before and after the decimal point,
 108: 		 * respectively, and "fmt" addresses the next
 109: 		 * character after the whole mess. If there was
 110: 		 * no decimal point, "prec" will be -1.
 111: 		 */
 112:         switch (*fmt) {
 113:             case 'L':
 114:             case 'l':
 115:                 length = 2;
 116:                 /* no break!! */
 117:             case 'h':
 118:             case 'H':
 119:                 length--;
 120:                 fmt++;
 121:                 break;
 122:         }
 123: 
 124:         /*
 125: 		 * At exit from the following switch, we will
 126: 		 * emit the characters starting at "bptr" and
 127: 		 * ending at "ptr"-1, unless fcode is '\0'.
 128: 		 */
 129:         switch (fcode = *fmt++) {
 130:             /* process characters and strings first */
 131:             case 'c':
 132:                 buf[0] = va_arg(ap, int);
 133:                 ptr = bptr = &buf[0];
 134:                 if (buf[0] != '\0')
 135:                     ptr++;
 136:                 break;
 137:             case 's':
 138:                 bptr = va_arg(ap,char *);
 139:                 if (bptr==0)
 140:                     bptr = "(null pointer)";
 141:                 if (prec < 0)
 142:                     prec = MAXINT;
 143:                 for (n=0; *bptr++ && n < prec; n++) ;
 144:                 ptr = --bptr;
 145:                 bptr -= n;
 146:                 break;
 147:             case 'O':
 148:                 length = 1;
 149:                 fcode = 'o';
 150:                 /* no break */
 151:             case 'o':
 152:             case 'X':
 153:             case 'x':
 154:                 if (length > 0)
 155:                     num = va_arg(ap,long);
 156:                 else
 157:                     num = (unsigned)va_arg(ap,int);
 158:                 if (fcode=='o') {
 159:                     mask1 = 0x7;
 160:                     mask2 = 0x1fffffffL;
 161:                     nbits = 3;
 162:                 }
 163:                 else {
 164:                     mask1 = 0xf;
 165:                     mask2 = 0x0fffffffL;
 166:                     nbits = 4;
 167:                 }
 168:                 n = (num!=0);
 169:                 bptr = buf + MAXOCT + 3;
 170:                 /* shift and mask for speed */
 171:                 do
 172:                     if (((int) num & mask1) < 10)
 173:                     *--bptr = ((int) num & mask1) + 060;
 174:                     else
 175:                     *--bptr = ((int) num & mask1) + 0127;
 176:                 while (num = (num >> nbits) & mask2);
 177: 
 178:                 if (fcode=='o') {
 179:                     if (n)
 180:                         *--bptr = '0';
 181:                 }
 182:                 else
 183:                     if (!sign && fill <= 0) {
 184:                         putchar('0');
 185:                         putchar(fcode);
 186:                         width -= 2;
 187:                     }
 188:                     else {
 189:                         *--bptr = fcode;
 190:                         *--bptr = '0';
 191:                     }
 192:                 ptr = buf + MAXOCT + 3;
 193:                 break;
 194:             case 'D':
 195:             case 'U':
 196:             case 'I':
 197:                 length = 1;
 198:                 fcode = fcode + 'a' - 'A';
 199:                 /* no break */
 200:             case 'd':
 201:             case 'i':
 202:             case 'u':
 203:                 if (length > 0)
 204:                     num = va_arg(ap,long);
 205:                 else {
 206:                     n = va_arg(ap,int);
 207:                     if (fcode=='u')
 208:                         num = (unsigned) n;
 209:                     else
 210:                         num = (long) n;
 211:                 }
 212:                 if (n = (fcode != 'u' && num < 0))
 213:                     num = -num;
 214:                 /* now convert to digits */
 215:                 bptr = _p_dconv(num, buf);
 216:                 if (n)
 217:                     *--bptr = '-';
 218:                 if (fill == 0)
 219:                     fill = -1;
 220:                 ptr = buf + MAXDIGS + 1;
 221:                 break;
 222:             default:
 223:                 /* not a control character,
 224: 				 * print it.
 225: 				 */
 226:                 ptr = bptr = &fcode;
 227:                 ptr++;
 228:                 break;
 229:             }
 230:             if (fcode != '\0')
 231:                 _p_emit(bptr,ptr);
 232:     }
 233:     va_end(ap);
 234: }
 235: 
 236: /* _p_dconv converts the unsigned long integer "value" to
 237:  * printable decimal and places it in "buffer", right-justified.
 238:  * The value returned is the address of the first non-zero character,
 239:  * or the address of the last character if all are zero.
 240:  * The result is NOT null terminated, and is MAXDIGS characters long,
 241:  * starting at buffer[1] (to allow for insertion of a sign).
 242:  *
 243:  * This program assumes it is running on 2's complement machine
 244:  * with reasonable overflow treatment.
 245:  */
 246: char *
 247: _p_dconv(value, buffer)
 248:     long value;
 249:     char *buffer;
 250: {
 251:     register char *bp;
 252:     register int svalue;
 253:     int n;
 254:     long lval;
 255: 
 256:     bp = buffer;
 257: 
 258:     /* zero is a special case */
 259:     if (value == 0) {
 260:         bp += MAXDIGS;
 261:         *bp = '0';
 262:         return(bp);
 263:     }
 264: 
 265:     /* develop the leading digit of the value in "n" */
 266:     n = 0;
 267:     while (value < 0) {
 268:         value -= BIG;   /* will eventually underflow */
 269:         n++;
 270:     }
 271:     while ((lval = value - BIG) >= 0) {
 272:         value = lval;
 273:         n++;
 274:     }
 275: 
 276:     /* stash it in buffer[1] to allow for a sign */
 277:     bp[1] = n + '0';
 278:     /*
 279: 	 * Now develop the rest of the digits. Since speed counts here,
 280: 	 * we do it in two loops. The first gets "value" down until it
 281: 	 * is no larger than MAXINT. The second one uses integer divides
 282: 	 * rather than long divides to speed it up.
 283: 	 */
 284:     bp += MAXDIGS + 1;
 285:     while (value > MAXINT) {
 286:         *--bp = (int)(value % 10) + '0';
 287:         value /= 10;
 288:     }
 289: 
 290:     /* cannot lose precision */
 291:     svalue = value;
 292:     while (svalue > 0) {
 293:         *--bp = (svalue % 10) + '0';
 294:         svalue /= 10;
 295:     }
 296: 
 297:     /* fill in intermediate zeroes if needed */
 298:     if (buffer[1] != '0') {
 299:         while (bp > buffer + 2)
 300:             *--bp = '0';
 301:         --bp;
 302:     }
 303:     return(bp);
 304: }
 305: 
 306: /*
 307:  * This program sends string "s" to putchar. The character after
 308:  * the end of "s" is given by "send". This allows the size of the
 309:  * field to be computed; it is stored in "alen". "width" contains the
 310:  * user specified length. If width<alen, the width will be taken to
 311:  * be alen. "sign" is zero if the string is to be right-justified
 312:  * in the field, nonzero if it is to be left-justified. "fill" is
 313:  * 0 if the string is to be padded with '0', positive if it is to be
 314:  * padded with ' ', and negative if an initial '-' should appear before
 315:  * any padding in right-justification (to avoid printing "-3" as
 316:  * "000-3" where "-0003" was intended).
 317:  */
 318: _p_emit(s, send)
 319:     register char *s;
 320:     char *send;
 321: {
 322:     char cfill;
 323:     register int alen;
 324:     int npad;
 325: 
 326:     alen = send - s;
 327:     if (alen > width)
 328:         width = alen;
 329:     cfill = fill>0? ' ': '0';
 330: 
 331:     /* we may want to print a leading '-' before anything */
 332:     if (*s == '-' && fill < 0) {
 333:         putchar(*s++);
 334:         alen--;
 335:         width--;
 336:     }
 337:     npad = width - alen;
 338: 
 339:     /* emit any leading pad characters */
 340:     if (!sign)
 341:         while (--npad >= 0)
 342:             putchar(cfill);
 343: 
 344:     /* emit the string itself */
 345:     while (--alen >= 0)
 346:         putchar(*s++);
 347: 
 348:     /* emit trailing pad characters */
 349:     if (sign)
 350:         while (--npad >= 0)
 351:             putchar(cfill);
 352: }

Defined functions

_p_dconv defined in line 246; used 2 times
_p_emit defined in line 318; used 1 times

Defined variables

fill defined in line 29; used 7 times
printf_id defined in line 11; never used
sccsid defined in line 8; never used
sign defined in line 29; used 7 times
width defined in line 29; used 12 times

Defined macros

BIG defined in line 26; used 2 times
MAXDIGS defined in line 27; used 3 times
MAXINT defined in line 25; used 2 times
MAXOCT defined in line 24; used 2 times
Last modified: 1991-09-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3397
Valid CSS Valid XHTML 1.0 Strict