# 2.11BSD#431 - /usr/src/usr.bin/printf/printf.c

##### Functions

    main              X
    progprintf        X

##### Macros

    EOF               X
    PF                X
    main              X
    warnx             X

       1: /*
       2:  * Copyright (c) 1989, 1993
       3:  *	The Regents of the University of California.  All rights reserved.
       4:  *
       5:  * Redistribution and use in source and binary forms, with or without
       6:  * modification, are permitted provided that the following conditions
       7:  * are met:
       8:  * 1. Redistributions of source code must retain the above copyright
       9:  *    notice, this list of conditions and the following disclaimer.
      10:  * 2. Redistributions in binary form must reproduce the above copyright
      11:  *    notice, this list of conditions and the following disclaimer in the
      12:  *    documentation and/or other materials provided with the distribution.
      13:  * 3. All advertising materials mentioning features or use of this software
      14:  *    must display the following acknowledgement:
      15:  *	This product includes software developed by the University of
      16:  *	California, Berkeley and its contributors.
      17:  * 4. Neither the name of the University nor the names of its contributors
      18:  *    may be used to endorse or promote products derived from this software
      19:  *    without specific prior written permission.
      20:  *
      21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31:  * SUCH DAMAGE.
      32:  */
      33:
      34: #if !defined(BUILTIN) && !defined(SHELL) && !defined(lint) && defined(DOSCCS)
      35: static char copyright[] =
      36: "@(#) Copyright (c) 1989, 1993\n\
      37: 	The Regents of the University of California.  All rights reserved.\n";
      38:
      39: static char sccsid[] = "@(#)printf.c	8.1 (Berkeley) 7/20/93";
      40: #endif /* not lint */
      41:
      42: #include <sys/types.h>
      43:
      44: #include <errno.h>
      45: #ifdef SHELL
      46: #define EOF -1
      47: #else
      48: #include <stdio.h>
      49: #endif
      50: #include <string.h>
      51:
      52: extern  double  atof();
      53: extern  long    strtol();
      54: extern  int errno;
      55:
      56: /*
      57:  * XXX
      58:  * This *has* to go away.  TK.
      59:  */
      60: #ifdef SHELL
      61: #define main printfcmd
      62: #define warnx(a, b, c) {                        \
      63:     char buf[64];                           \
      64:     (void)sprintf(buf, sizeof(buf), a, b, c);           \
      65:     error(buf);                         \
      66: }
      67: #include "../../bin/sh/bltin/bltin.h"
      68: #endif
      69:
      70: #define PF(f, func) { \
      71:     if (fieldwidth) \
      72:         if (precision) \
      73:             (void)printf(f, fieldwidth, precision, func); \
      74:         else \
      75:             (void)printf(f, fieldwidth, func); \
      76:     else if (precision) \
      77:         (void)printf(f, precision, func); \
      78:     else \
      79:         (void)printf(f, func); \
      80: }
      81:
      82: static int   asciicode();
      83: static void  escape();
      84: static int   getchr();
      85: static double    getdouble();
      86: static int   getint();
      87: static int   getlong();
      88: static char *getstr();
      89: static char *mklong();
      90: static void  usage();
      91:
      92: static char **gargv;
      93:
      94: int
      95: #ifdef BUILTIN
      96: progprintf(argc, argv)
      97: #else
      98: main(argc, argv)
      99: #endif
     100:     int argc;
     101:     char *argv[];
     102: {
     103:     extern int optind;
     104:     static char *skip1, *skip2;
     105:     int ch, end, fieldwidth, precision;
     106:     char convch, nextch, *format, *start;
     107:     register char *fmt;
     108:
     109:     while ((ch = getopt(argc, argv, "")) != EOF)
     110:         switch (ch) {
     111:         case '?':
     112:         default:
     113:             usage();
     114:             return (1);
     115:         }
     116:     argc -= optind;
     117:     argv += optind;
     118:
     119:     if (argc < 1) {
     120:         usage();
     121:         return (1);
     122:     }
     123:
     124:     /*
     125: 	 * Basic algorithm is to scan the format string for conversion
     126: 	 * specifications -- once one is found, find out if the field
     127: 	 * width or precision is a '*'; if it is, gather up value.  Note,
     128: 	 * format strings are reused as necessary to use up the provided
     129: 	 * arguments, arguments of zero/null string are provided to use
     130: 	 * up the format string.
     131: 	 */
     132:     skip1 = "#-+ 0";
     133:     skip2 = "*0123456789";
     134:
     135:     escape(fmt = format = *argv);       /* backslash interpretation */
     136:     gargv = ++argv;
     137:     for (;;) {
     138:         end = 0;
     139:         /* find next format specification */
     140: next:       for (start = fmt;; ++fmt) {
     141:             if (!*fmt) {
     142:                 /* avoid infinite loop */
     143:                 if (end == 1) {
     144:                     warnx("missing format character",
     145:                         NULL, NULL);
     146:                     return (1);
     147:                 }
     148:                 end = 1;
     149:                 if (fmt > start)
     150:                     (void)printf("%s", start);
     151:                 if (!*gargv)
     152:                     return (0);
     153:                 fmt = format;
     154:                 goto next;
     155:             }
     156:             /* %% prints a % */
     157:             if (*fmt == '%') {
     158:                 if (*++fmt != '%')
     159:                     break;
     160:                 *fmt++ = '\0';
     161:                 (void)printf("%s", start);
     162:                 goto next;
     163:             }
     164:         }
     165:
     166:         /* skip to field width */
     167:         for (; strchr(skip1, *fmt); ++fmt);
     168:         if (*fmt == '*') {
     169:             if (getint(&fieldwidth))
     170:                 return (1);
     171:         } else
     172:             fieldwidth = 0;
     173:
     174:         /* skip to possible '.', get following precision */
     175:         for (; strchr(skip2, *fmt); ++fmt);
     176:         if (*fmt == '.')
     177:             ++fmt;
     178:         if (*fmt == '*') {
     179:             if (getint(&precision))
     180:                 return (1);
     181:         } else
     182:             precision = 0;
     183:
     184:         /* skip to conversion char */
     185:         for (; strchr(skip2, *fmt); ++fmt);
     186:         if (!*fmt) {
     187:             warnx("missing format character", NULL, NULL);
     188:             return (1);
     189:         }
     190:
     191:         convch = *fmt;
     192:         nextch = *++fmt;
     193:         *fmt = '\0';
     194:         switch(convch) {
     195:         case 'c': {
     196:             char p;
     197:
     198:             p = getchr();
     199:             PF(start, p);
     200:             break;
     201:         }
     202:         case 's': {
     203:             char *p;
     204:
     205:             p = getstr();
     206:             PF(start, p);
     207:             break;
     208:         }
     209:         case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': {
     210:             long p;
     211:             char *f;
     212:
     213:             if ((f = mklong(start, convch)) == NULL)
     214:                 return (1);
     215:             if (getlong(&p))
     216:                 return (1);
     217:             PF(f, p);
     218:             break;
     219:         }
     220:         case 'e': case 'E': case 'f': case 'g': case 'G': {
     221:             double p;
     222:
     223:             p = getdouble();
     224:             PF(start, p);
     225:             break;
     226:         }
     227:         default:
     228:             warnx("illegal format character", NULL, NULL);
     229:             return (1);
     230:         }
     231:         *fmt = nextch;
     232:     }
     233:     /* NOTREACHED */
     234: }
     235:
     236: static char *
     237: mklong(str, ch)
     238:     register char *str;
     239:     int ch;
     240: {
     241:     static char copy[64];
     242:     register int len;
     243:
     244:     if (ch == 'X')      /* XXX */
     245:         ch = 'x';
     246:     len = strlen(str) + 2;
     247:     bcopy(str, copy, len - 3);
     248:     copy[len - 3] = 'l';
     249:     copy[len - 2] = ch;
     250:     copy[len - 1] = '\0';
     251:     return (copy);
     252: }
     253:
     254: static void
     255: escape(fmt)
     256:     register char *fmt;
     257: {
     258:     register char *store;
     259:     register int value;
     260:     int c;
     261:
     262:     for (store = fmt; c = *fmt; ++fmt, ++store) {
     263:         if (c != '\\') {
     264:             *store = c;
     265:             continue;
     266:         }
     267:         switch (*++fmt) {
     268:         case '\0':      /* EOS, user error */
     269:             *store = '\\';
     270:             *++store = '\0';
     271:             return;
     272:         case '\\':      /* backslash */
     273:         case '\'':      /* single quote */
     274:             *store = *fmt;
     275:             break;
     276:         case 'a':       /* bell/alert */
     277:             *store = '\7';
     278:             break;
     279:         case 'b':       /* backspace */
     280:             *store = '\b';
     281:             break;
     282:         case 'f':       /* form-feed */
     283:             *store = '\f';
     284:             break;
     285:         case 'n':       /* newline */
     286:             *store = '\n';
     287:             break;
     288:         case 'r':       /* carriage-return */
     289:             *store = '\r';
     290:             break;
     291:         case 't':       /* horizontal tab */
     292:             *store = '\t';
     293:             break;
     294:         case 'v':       /* vertical tab */
     295:             *store = '\13';
     296:             break;
     297:                     /* octal constant */
     298:         case '0': case '1': case '2': case '3':
     299:         case '4': case '5': case '6': case '7':
     300:             for (c = 3, value = 0;
     301:                 c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) {
     302:                 value <<= 3;
     303:                 value += *fmt - '0';
     304:             }
     305:             --fmt;
     306:             *store = value;
     307:             break;
     308:         default:
     309:             *store = *fmt;
     310:             break;
     311:         }
     312:     }
     313:     *store = '\0';
     314: }
     315:
     316: static int
     317: getchr()
     318: {
     319:     if (!*gargv)
     320:         return ('\0');
     321:     return ((int)**gargv++);
     322: }
     323:
     324: static char *
     325: getstr()
     326: {
     327:     if (!*gargv)
     328:         return ("");
     329:     return (*gargv++);
     330: }
     331:
     332: static char *Number = "+-.0123456789";
     333: static int
     334: getint(ip)
     335:     int *ip;
     336: {
     337:     long val;
     338:
     339:     if (getlong(&val))
     340:         return (1);
     341:     if (val > 65535) {
     342:         warnx("%s: %s", *gargv, strerror(ERANGE));
     343:         return (1);
     344:     }
     345:     *ip = val;
     346:     return (0);
     347: }
     348:
     349: static int
     350: getlong(lp)
     351:     register long *lp;
     352: {
     353:     long val;
     354:     char *ep;
     355:
     356:     if (!*gargv) {
     357:         *lp = 0;
     358:         return (0);
     359:     }
     360:     if (strchr(Number, **gargv)) {
     361:         errno = 0;
     362:         val = strtol(*gargv, &ep, 0);
     363:         if (*ep != '\0') {
     364:             warnx("%s: illegal number", *gargv, NULL);
     365:             return (1);
     366:         }
     367:         if (errno == ERANGE)
     368:             if (val == 2147483647L) {
     369:                 warnx("%s: %s", *gargv, strerror(ERANGE));
     370:                 return (1);
     371:             }
     372:             if (val == (-2147483647L-1)) {
     373:                 warnx("%s: %s", *gargv, strerror(ERANGE));
     374:                 return (1);
     375:             }
     376:
     377:         *lp = val;
     378:         ++gargv;
     379:         return (0);
     380:     }
     381:     *lp =  (long)asciicode();
     382:     return (0);
     383: }
     384:
     385: static double
     386: getdouble()
     387: {
     388:     if (!*gargv)
     389:         return ((double)0);
     390:     if (strchr(Number, **gargv))
     391:         return (atof(*gargv++));
     392:     return ((double)asciicode());
     393: }
     394:
     395: static int
     396: asciicode()
     397: {
     398:     register int ch;
     399:
     400:     ch = **gargv;
     401:     if (ch == '\'' || ch == '"')
     402:         ch = (*gargv)[1];
     403:     ++gargv;
     404:     return (ch);
     405: }
     406:
     407: static void
     408: usage()
     409: {
     410:     (void)fprintf(stderr, "usage: printf format [arg ...]\n");
     411: }

#### Defined functions

asciicode defined in line 395; used 3 times

- in line 82, 381, 392

escape defined in line 254; used 2 times

- in line 83, 135

getchr defined in line 316; used 2 times

- in line 84, 198

getdouble defined in line 385; used 2 times

- in line 85, 223

getint defined in line 333; used 3 times

- in line 86, 169, 179

getlong defined in line 349; used 3 times

- in line 87, 215, 339

getstr defined in line 324; used 2 times

- in line 88, 205

main defined in line 94; never used
mklong defined in line 236; used 2 times

- in line 89, 213

progprintf defined in line 94; never used
usage defined in line 407; used 3 times

- in line 90, 113, 120

#### Defined variables

Number defined in line 332; used 2 times

- in line 360, 390

copyright defined in line 35; never used
gargv defined in line 92; used 20 times

- in line 136, 151, 319-321(2), 327-329(2), 342, 356-378(7), 388-391(3), 400-403(3)

sccsid defined in line 39; never used

#### Defined macros

EOF defined in line 46; used 1 times

- in line 109

PF defined in line 70; used 4 times

- in line 199, 206, 217, 224

main defined in line 61; never used
warnx defined in line 62; used 7 times

- in line 144, 187, 228, 342, 364-373(3)

Last modified: 1995-04-03 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1323 |