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

Defined functions

_p_dconv defined in line 245; used 2 times
_p_emit defined in line 317; used 1 times

Defined variables

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

Defined macros

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