00001 #if ever
00002 static char sccsid[] = "@(#)printf.c (U of Maryland) FLB 6-Jan-1987";
00003 static char RCSid[] = "@(#)$Header: /opt/proj/minix/cvsroot/src/commands/simple/printf.c,v 1.1.1.1 2005/04/21 14:55:31 beng Exp $";
00004 #endif
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #define EX_OK 0
00041 #define EX_USAGE 1
00042
00043 int ctrl(char *s);
00044
00045 #define atoi(a) strtoul((a), NULL, 0)
00046
00047
00048
00049 int main(int argc, char *argv[])
00050 {
00051 register char *cp, *conv_spec, **argp, **ep;
00052 char *ctor(int x);
00053
00054 if (argc < 2) {
00055 fprintf(stderr,
00056 "printf: Usage: printf <format-string> [ arg1 . . . ]\n");
00057 exit(EX_USAGE);
00058 }
00059
00060 argp = &argv[2];
00061 ep = &argv[argc];
00062
00063 ctrl(argv[1]);
00064
00065
00066
00067 for (cp = argv[1]; *cp; cp++) {
00068 register int dynamic_count;
00069
00070
00071 while (*cp && *cp != '%') {
00072 putchar(*cp++);
00073 }
00074
00075 if (!*cp)
00076 break;
00077
00078 dynamic_count = 0;
00079 conv_spec = cp++;
00080
00081 for (;*cp; cp++) {
00082 char conv_buf[BUFSIZ];
00083 register int conv_len;
00084
00085 switch (*cp) {
00086 case '.': case '0': case '1': case '2': case '3':
00087 case '4': case '5': case '6': case '7': case '8':
00088 case '9':
00089 continue;
00090
00091 case '*':
00092 dynamic_count++;
00093 continue;
00094
00095 case 's':
00096 if (&argp[dynamic_count] >= ep) {
00097 fprintf(stderr,
00098 "printf: Not enough args for format.\n"
00099 );
00100 exit(EX_USAGE);
00101 }
00102
00103 (void) strncpy(conv_buf, conv_spec,
00104 conv_len = cp - conv_spec + 1);
00105 conv_buf[conv_len] = '\0';
00106
00107 switch (dynamic_count) {
00108 case 0:
00109 ctrl(*argp);
00110 printf(conv_buf, *argp++);
00111 break;
00112
00113 case 1:
00114 {
00115 register int a1;
00116
00117 a1 = atoi(*argp++);
00118 ctrl(*argp);
00119 printf(conv_buf, a1, *argp++);
00120 }
00121 break;
00122
00123 case 2:
00124 {
00125 register int a1, a2;
00126
00127 a1 = atoi(*argp++);
00128 a2 = atoi(*argp++);
00129 ctrl(*argp);
00130 printf(conv_buf, a1, a2, *argp++);
00131 }
00132 break;
00133
00134 }
00135 goto out;
00136
00137 case 'c':
00138 if (&argp[dynamic_count] >= ep) {
00139 fprintf(stderr,
00140 "printf: Not enough args for format.\n"
00141 );
00142 exit(EX_USAGE);
00143 }
00144
00145 (void) strncpy(conv_buf, conv_spec,
00146 conv_len = cp - conv_spec + 1);
00147 conv_buf[conv_len] = '\0';
00148
00149 switch (dynamic_count) {
00150 case 0:
00151 ctrl(*argp);
00152 printf(conv_buf, **argp++);
00153 break;
00154
00155 case 1:
00156 {
00157 register int a1;
00158
00159 a1 = atoi(*argp++);
00160 ctrl(*argp);
00161 printf(conv_buf, a1, **argp++);
00162 }
00163 break;
00164
00165 case 2:
00166 {
00167 register int a1, a2;
00168
00169 a1 = atoi(*argp++);
00170 a2 = atoi(*argp++);
00171 ctrl(*argp);
00172 printf(conv_buf, a1, a2, **argp++);
00173 }
00174 break;
00175 }
00176 goto out;
00177
00178 case 'd':
00179 case 'o':
00180 case 'x':
00181 case 'X':
00182 case 'u':
00183 if (&argp[dynamic_count] >= ep) {
00184 fprintf(stderr,
00185 "printf: Not enough args for format.\n"
00186 );
00187 exit(EX_USAGE);
00188 }
00189
00190 (void) strncpy(conv_buf, conv_spec,
00191 conv_len = cp - conv_spec + 1);
00192 conv_buf[conv_len] = '\0';
00193
00194 switch (dynamic_count) {
00195 case 0:
00196 printf(conv_buf, atoi(*argp++));
00197 break;
00198
00199 case 1:
00200 {
00201 register int a1;
00202
00203 a1 = atoi(*argp++);
00204 printf(conv_buf, a1, atoi(*argp++));
00205 }
00206 break;
00207
00208 case 2:
00209 {
00210 register int a1, a2;
00211
00212 a1 = atoi(*argp++);
00213 a2 = atoi(*argp++);
00214 printf(conv_buf, a1, a2, atoi(*argp++));
00215 }
00216 break;
00217
00218 }
00219 goto out;
00220
00221 case 'f':
00222 case 'e':
00223 case 'g':
00224 if (&argp[dynamic_count] >= ep) {
00225 fprintf(stderr,
00226 "printf: Not enough args for format.\n"
00227 );
00228 exit(EX_USAGE);
00229 }
00230
00231 (void) strncpy(conv_buf, conv_spec,
00232 conv_len = cp - conv_spec + 1);
00233 conv_buf[conv_len] = '\0';
00234
00235 switch (dynamic_count) {
00236 case 0:
00237 printf(conv_buf, atof(*argp++));
00238 break;
00239
00240 case 1:
00241 {
00242 register int a1;
00243
00244 a1 = atoi(*argp++);
00245 printf(conv_buf, a1, atof(*argp++));
00246 }
00247 break;
00248
00249 case 2:
00250 {
00251 register int a1, a2;
00252
00253 a1 = atoi(*argp++);
00254 a2 = atoi(*argp++);
00255 printf(conv_buf, a1, a2, atof(*argp++));
00256 }
00257 break;
00258
00259 }
00260 goto out;
00261
00262 case 'r':
00263 if (&argp[dynamic_count] >= ep) {
00264 fprintf(stderr,
00265 "printf: Not enough args for format.\n"
00266 );
00267 exit(EX_USAGE);
00268 }
00269
00270 (void) strncpy(conv_buf, conv_spec,
00271 conv_len = cp - conv_spec + 1);
00272 conv_buf[conv_len] = '\0';
00273 conv_buf[conv_len - 1] = 's';
00274
00275 switch (dynamic_count) {
00276 case 0:
00277 printf(conv_buf,
00278 ctor(atoi(*argp++)));
00279 break;
00280
00281 case 1:
00282 {
00283 register int a1;
00284
00285 a1 = atoi(*argp++);
00286 printf(conv_buf, a1,
00287 ctor(atoi(*argp++)));
00288 }
00289 break;
00290
00291 case 2:
00292 {
00293 register int a1, a2;
00294
00295 a1 = atoi(*argp++);
00296 a2 = atoi(*argp++);
00297 printf(conv_buf, a1, a2,
00298 ctor(atoi(*argp++)));
00299 }
00300 break;
00301
00302 }
00303 goto out;
00304
00305 case '%':
00306 putchar('%');
00307 break;
00308
00309 default:
00310
00311 continue;
00312 }
00313 }
00314 out: ;
00315 }
00316
00317 exit(EX_OK);
00318 }
00319
00320
00321
00322
00323
00324 int ctrl(char *s)
00325 {
00326 register char *op;
00327 static int val;
00328
00329 for (op = s; *s; s++)
00330 if (*s == '\\')
00331 switch (*++s) {
00332 case '\0':
00333 goto out;
00334
00335 case '\\':
00336 *op++ = '\\';
00337 break;
00338
00339 case 'n':
00340 *op++ = '\n';
00341 break;
00342
00343 case 't':
00344 *op++ = '\t';
00345 break;
00346
00347 case 'r':
00348 *op++ = '\r';
00349 break;
00350
00351 case 'f':
00352 *op++ = '\f';
00353 break;
00354
00355 case 'b':
00356 *op++ = '\b';
00357 break;
00358
00359 case 'v':
00360 *op++ = '\13';
00361 break;
00362
00363 case 'a':
00364 *op++ = '\7';
00365 break;
00366
00367 case '0': case '1': case '2': case '3':
00368 case '4': case '5': case '6': case '7':
00369 {
00370 register int digits;
00371
00372 val = 0;
00373 (void) sscanf(s, "%3o", &val);
00374 *op++ = val;
00375 for (digits = 3; s[1] &&
00376 strchr("01234567", s[1])
00377 && --digits > 0;
00378 s++);
00379 }
00380 break;
00381
00382 case 'x':
00383 case 'X':
00384 s++;
00385 {
00386 register int digits;
00387
00388 val = 0;
00389 (void) sscanf(s, "%3x", &val);
00390 *op++ = val;
00391 for (digits = 3; *s && s[1] &&
00392 strchr("0123456789abcdefABCDEF",
00393 s[1])
00394 && --digits > 0;
00395 s++);
00396 }
00397 break;
00398
00399 }
00400 else
00401 *op++ = *s;
00402
00403 out:
00404
00405 *op = '\0';
00406 }
00407
00408
00409
00410
00411
00412 struct roman {
00413 unsigned r_mag;
00414 char r_units, r_fives;
00415 } roman[] = {
00416 { 1000, 'M', '\0', },
00417 { 100, 'C', 'D', },
00418 { 10, 'X', 'L', },
00419 { 1, 'I', 'V', },
00420 };
00421
00422 char *ctor(int x)
00423 {
00424 register struct roman *mp;
00425 static char buf[BUFSIZ];
00426 register char *cp = buf;
00427
00428
00429
00430 if (x < 0) {
00431 *cp++ = '-';
00432 x = -x;
00433 }
00434
00435 for (mp = roman; x; mp++) {
00436 register unsigned units;
00437
00438 units = x / mp->r_mag;
00439 x = x % mp->r_mag;
00440
00441 if (cp > &buf[BUFSIZ-2])
00442 return "???";
00443
00444 if (units == 9 && mp > roman) {
00445 *cp++ = mp->r_units;
00446 *cp++ = mp[-1].r_units;
00447 }
00448 else if (units == 4 && mp->r_fives) {
00449
00450 *cp++ = mp->r_units;
00451 *cp++ = mp->r_fives;
00452 }
00453 else {
00454 if (units >= 5 && mp->r_fives) {
00455 *cp++ = mp->r_fives;
00456 units -= 5;
00457 }
00458 while (units--) {
00459 *cp++ = mp->r_units;
00460 if (cp > &buf[BUFSIZ-5])
00461 return "???";
00462 }
00463 }
00464 }
00465
00466 *cp = '\0';
00467
00468 return buf;
00469 }
00470
00471