|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.