Annotation of 43BSDReno/usr.bin/printf/printf.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1989 The Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted
        !             6:  * provided that: (1) source distributions retain this entire copyright
        !             7:  * notice and comment, and (2) distributions including binaries display
        !             8:  * the following acknowledgement:  ``This product includes software
        !             9:  * developed by the University of California, Berkeley and its contributors''
        !            10:  * in the documentation or other materials provided with the distribution
        !            11:  * and in all advertising materials mentioning features or use of this
        !            12:  * software. Neither the name of the University nor the names of its
        !            13:  * contributors may be used to endorse or promote products derived
        !            14:  * from this software without specific prior written permission.
        !            15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            18:  */
        !            19: 
        !            20: #ifndef lint
        !            21: char copyright[] =
        !            22: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
        !            23:  All rights reserved.\n";
        !            24: #endif /* not lint */
        !            25: 
        !            26: #ifndef lint
        !            27: static char sccsid[] = "@(#)printf.c   5.9 (Berkeley) 6/1/90";
        !            28: #endif /* not lint */
        !            29: 
        !            30: #include <sys/types.h>
        !            31: #include <stdio.h>
        !            32: 
        !            33: #define PF(f, func) { \
        !            34:        if (fieldwidth) \
        !            35:                if (precision) \
        !            36:                        (void)printf(f, fieldwidth, precision, func); \
        !            37:                else \
        !            38:                        (void)printf(f, fieldwidth, func); \
        !            39:        else if (precision) \
        !            40:                (void)printf(f, precision, func); \
        !            41:        else \
        !            42:                (void)printf(f, func); \
        !            43: }
        !            44: 
        !            45: char **gargv;
        !            46: 
        !            47: main(argc, argv)
        !            48:        int argc;
        !            49:        char **argv;
        !            50: {
        !            51:        static char *skip1, *skip2;
        !            52:        register char *format, *fmt, *start;
        !            53:        register int end, fieldwidth, precision;
        !            54:        char convch, nextch, *getstr(), *index(), *mklong();
        !            55:        double getdouble();
        !            56:        long getlong();
        !            57: 
        !            58:        if (argc < 2) {
        !            59:                fprintf(stderr, "usage: printf format [arg ...]\n");
        !            60:                exit(1);
        !            61:        }
        !            62: 
        !            63:        /*
        !            64:         * Basic algorithm is to scan the format string for conversion
        !            65:         * specifications -- once one is found, find out if the field
        !            66:         * width or precision is a '*'; if it is, gather up value.  Note,
        !            67:         * format strings are reused as necessary to use up the provided
        !            68:         * arguments, arguments of zero/null string are provided to use
        !            69:         * up the format string.
        !            70:         */
        !            71:        skip1 = "#-+ 0";
        !            72:        skip2 = "*0123456789";
        !            73: 
        !            74:        escape(fmt = format = *++argv);         /* backslash interpretation */
        !            75:        gargv = ++argv;
        !            76:        for (;;) {
        !            77:                end = 0;
        !            78:                /* find next format specification */
        !            79: next:          for (start = fmt;; ++fmt) {
        !            80:                        if (!*fmt) {
        !            81:                                /* avoid infinite loop */
        !            82:                                if (end == 1) {
        !            83:                                        fprintf(stderr,
        !            84:                                            "printf: missing format character.\n");
        !            85:                                        exit(1);
        !            86:                                }
        !            87:                                end = 1;
        !            88:                                if (fmt > start)
        !            89:                                        (void)printf("%s", start);
        !            90:                                if (!*gargv)
        !            91:                                        exit(0);
        !            92:                                fmt = format;
        !            93:                                goto next;
        !            94:                        }
        !            95:                        /* %% prints a % */
        !            96:                        if (*fmt == '%') {
        !            97:                                if (*++fmt != '%')
        !            98:                                        break;
        !            99:                                *fmt++ = '\0';
        !           100:                                (void)printf("%s", start);
        !           101:                                goto next;
        !           102:                        }
        !           103:                }
        !           104: 
        !           105:                /* skip to field width */
        !           106:                for (; index(skip1, *fmt); ++fmt);
        !           107:                fieldwidth = *fmt == '*' ? getint() : 0;
        !           108: 
        !           109:                /* skip to possible '.', get following precision */
        !           110:                for (; index(skip2, *fmt); ++fmt);
        !           111:                if (*fmt == '.')
        !           112:                        ++fmt;
        !           113:                precision = *fmt == '*' ? getint() : 0;
        !           114: 
        !           115:                /* skip to conversion char */
        !           116:                for (; index(skip2, *fmt); ++fmt);
        !           117:                if (!*fmt) {
        !           118:                        fprintf(stderr, "printf: missing format character.\n");
        !           119:                        exit(1);
        !           120:                }
        !           121: 
        !           122:                convch = *fmt;
        !           123:                nextch = *++fmt;
        !           124:                *fmt = '\0';
        !           125:                switch(convch) {
        !           126:                case 'c': {
        !           127:                        char p = getchr();
        !           128:                        PF(start, p);
        !           129:                        break;
        !           130:                }
        !           131:                case 's': {
        !           132:                        char *p = getstr();
        !           133:                        PF(start, p);
        !           134:                        break;
        !           135:                }
        !           136:                case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': {
        !           137:                        char *f = mklong(start, convch);
        !           138:                        long p = getlong();
        !           139:                        PF(f, p);
        !           140:                        break;
        !           141:                }
        !           142:                case 'e': case 'E': case 'f': case 'g': case 'G': {
        !           143:                        double p = getdouble();
        !           144:                        PF(start, p);
        !           145:                        break;
        !           146:                }
        !           147:                default:
        !           148:                        fprintf(stderr, "printf: illegal format character.\n");
        !           149:                        exit(1);
        !           150:                }
        !           151:                *fmt = nextch;
        !           152:        }
        !           153:        /* NOTREACHED */
        !           154: }
        !           155: 
        !           156: char *
        !           157: mklong(str, ch)
        !           158:        char *str, ch;
        !           159: {
        !           160:        int len;
        !           161:        char *copy, *malloc();
        !           162: 
        !           163:        len = strlen(str) + 2;
        !           164:        if (!(copy = malloc((u_int)len))) {     /* never freed; XXX */
        !           165:                fprintf(stderr, "printf: out of memory.\n");
        !           166:                exit(1);
        !           167:        }
        !           168:        bcopy(str, copy, len - 3);
        !           169:        copy[len - 3] = 'l';
        !           170:        copy[len - 2] = ch;
        !           171:        copy[len - 1] = '\0';
        !           172:        return(copy);
        !           173: }
        !           174: 
        !           175: escape(fmt)
        !           176:        register char *fmt;
        !           177: {
        !           178:        register char *store;
        !           179:        register int value, c;
        !           180: 
        !           181:        for (store = fmt; c = *fmt; ++fmt, ++store) {
        !           182:                if (c != '\\') {
        !           183:                        *store = c;
        !           184:                        continue;
        !           185:                }
        !           186:                switch (*++fmt) {
        !           187:                case '\0':              /* EOS, user error */
        !           188:                        *store = '\\';
        !           189:                        *++store = '\0';
        !           190:                        return;
        !           191:                case '\\':              /* backslash */
        !           192:                case '\'':              /* single quote */
        !           193:                        *store = *fmt;
        !           194:                        break;
        !           195:                case 'a':               /* bell/alert */
        !           196:                        *store = '\7';
        !           197:                        break;
        !           198:                case 'b':               /* backspace */
        !           199:                        *store = '\b';
        !           200:                        break;
        !           201:                case 'f':               /* form-feed */
        !           202:                        *store = '\f';
        !           203:                        break;
        !           204:                case 'n':               /* newline */
        !           205:                        *store = '\n';
        !           206:                        break;
        !           207:                case 'r':               /* carriage-return */
        !           208:                        *store = '\r';
        !           209:                        break;
        !           210:                case 't':               /* horizontal tab */
        !           211:                        *store = '\t';
        !           212:                        break;
        !           213:                case 'v':               /* vertical tab */
        !           214:                        *store = '\13';
        !           215:                        break;
        !           216:                                        /* octal constant */
        !           217:                case '0': case '1': case '2': case '3':
        !           218:                case '4': case '5': case '6': case '7':
        !           219:                        for (c = 3, value = 0;
        !           220:                            c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) {
        !           221:                                value <<= 3;
        !           222:                                value += *fmt - '0';
        !           223:                        }
        !           224:                        --fmt;
        !           225:                        *store = value;
        !           226:                        break;
        !           227:                default:
        !           228:                        *store = *fmt;
        !           229:                        break;
        !           230:                }
        !           231:        }
        !           232:        *store = '\0';
        !           233: }
        !           234: 
        !           235: getchr()
        !           236: {
        !           237:        if (!*gargv)
        !           238:                return((int)'\0');
        !           239:        return((int)**gargv++);
        !           240: }
        !           241: 
        !           242: char *
        !           243: getstr()
        !           244: {
        !           245:        if (!*gargv)
        !           246:                return("");
        !           247:        return(*gargv++);
        !           248: }
        !           249: 
        !           250: static char *number = "+-.0123456789";
        !           251: getint()
        !           252: {
        !           253:        if (!*gargv)
        !           254:                return(0);
        !           255:        if (index(number, **gargv))
        !           256:                return(atoi(*gargv++));
        !           257:        return(asciicode());
        !           258: }
        !           259: 
        !           260: long
        !           261: getlong()
        !           262: {
        !           263:        long atol();
        !           264: 
        !           265:        if (!*gargv)
        !           266:                return((long)0);
        !           267:        if (index(number, **gargv))
        !           268:                return(strtol(*gargv++, (char **)NULL, 0));
        !           269:        return((long)asciicode());
        !           270: }
        !           271: 
        !           272: double
        !           273: getdouble()
        !           274: {
        !           275:        double atof();
        !           276: 
        !           277:        if (!*gargv)
        !           278:                return((double)0);
        !           279:        if (index(number, **gargv))
        !           280:                return(atof(*gargv++));
        !           281:        return((double)asciicode());
        !           282: }
        !           283: 
        !           284: asciicode()
        !           285: {
        !           286:        register char ch;
        !           287: 
        !           288:        ch = **gargv;
        !           289:        if (ch == '\'' || ch == '"')
        !           290:                ch = (*gargv)[1];
        !           291:        ++gargv;
        !           292:        return(ch);
        !           293: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.