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

Defined functions

_p_dconv defined in line 237; used 2 times
_p_emit defined in line 309; used 1 times

Defined variables

fill defined in line 20; used 7 times
printf_id defined in line 2; never used
sccsid defined in line 4; never used
sign defined in line 20; used 7 times
width defined in line 20; used 12 times

Defined macros

BIG defined in line 17; used 2 times
MAXDIGS defined in line 18; used 3 times
MAXINT defined in line 16; used 2 times
MAXOCT defined in line 15; used 2 times
Last modified: 1981-07-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 938
Valid CSS Valid XHTML 1.0 Strict