# 2.11BSD#431 - /usr/src/ucb/ex/printf.c

##### Functions

    _p_dconv          X
    _p_emit           X
    printf            X

##### Macros

    BIG               X
    MAXDIGS           X
    MAXINT            X
    MAXOCT            X

       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

- in line 31, 215

_p_emit defined in line 318; used 1 times

- in line 231

printf defined in line 33; used 44 times

- in /usr/src/ucb/ex/ex.c line 193
- in /usr/src/ucb/ex/ex_cmds.c line 675, 816
- in /usr/src/ucb/ex/ex_cmds2.c line 102
- in /usr/src/ucb/ex/ex_cmdsub.c line 96-99(2), 567
- in /usr/src/ucb/ex/ex_get.c line 140
- in /usr/src/ucb/ex/ex_io.c line 101-113(5), 328, 404, 589-591(2), 650, 832-844(6)
- in /usr/src/ucb/ex/ex_put.c line 129, 825
- in /usr/src/ucb/ex/ex_re.c line 529-531(2)
- in /usr/src/ucb/ex/ex_set.c line 223-232(3)
- in /usr/src/ucb/ex/ex_subr.c line 254-256(2), 367, 450
- in /usr/src/ucb/ex/ex_temp.c line 405, 438
- in /usr/src/ucb/ex/ex_unix.c line 101, 195, 226
- in /usr/src/ucb/ex/ex_vadj.c line 1071
- in /usr/src/ucb/ex/ex_vget.c line 327-331(2)
- in /usr/src/ucb/ex/ex_vops2.c line 273

#### Defined variables

fill defined in line 29; used 7 times

- in line 66-68(2), 183, 218-219(2), 329-332(2)

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

- in line 59-61(2), 77(2), 183, 340, 349

width defined in line 29; used 12 times

- in line 74-76(4), 82-84(3), 186, 327-328(2), 335-337(2)

#### Defined macros

BIG defined in line 26; used 2 times

- in line 268-271(2)

MAXDIGS defined in line 27; used 3 times

- in line 220, 260, 284

MAXINT defined in line 25; used 2 times

- in line 142, 285

MAXOCT defined in line 24; used 2 times

- in line 169, 192

Last modified: 1991-09-08 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1469 |