19b50d902SRodney W. Grimes /*- 29b50d902SRodney W. Grimes * Copyright (c) 1993 39b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 49b50d902SRodney W. Grimes * 59b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 69b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 79b50d902SRodney W. Grimes * are met: 89b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 99b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 109b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 129b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 139b50d902SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 149b50d902SRodney W. Grimes * must display the following acknowledgement: 159b50d902SRodney W. Grimes * This product includes software developed by the University of 169b50d902SRodney W. Grimes * California, Berkeley and its contributors. 179b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 189b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 199b50d902SRodney W. Grimes * without specific prior written permission. 209b50d902SRodney W. Grimes * 219b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 229b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 239b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 249b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 259b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 269b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 279b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 289b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 299b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 309b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 319b50d902SRodney W. Grimes * SUCH DAMAGE. 329b50d902SRodney W. Grimes */ 339b50d902SRodney W. Grimes 349b50d902SRodney W. Grimes #ifndef lint 357bd7ad50SPhilippe Charnier static const char copyright[] = 369b50d902SRodney W. Grimes "@(#) Copyright (c) 1993\n\ 379b50d902SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 389b50d902SRodney W. Grimes #endif /* not lint */ 399b50d902SRodney W. Grimes 409b50d902SRodney W. Grimes #ifndef lint 417bd7ad50SPhilippe Charnier #if 0 429b50d902SRodney W. Grimes static char sccsid[] = "@(#)jot.c 8.1 (Berkeley) 6/6/93"; 437bd7ad50SPhilippe Charnier #endif 44cf0def93SJuli Mallett #endif 45cf0def93SJuli Mallett #include <sys/cdefs.h> 46cf0def93SJuli Mallett __FBSDID("$FreeBSD$"); 479b50d902SRodney W. Grimes 489b50d902SRodney W. Grimes /* 499b50d902SRodney W. Grimes * jot - print sequential or random data 509b50d902SRodney W. Grimes * 519b50d902SRodney W. Grimes * Author: John Kunze, Office of Comp. Affairs, UCB 529b50d902SRodney W. Grimes */ 539b50d902SRodney W. Grimes 549b50d902SRodney W. Grimes #include <ctype.h> 557bd7ad50SPhilippe Charnier #include <err.h> 569b50d902SRodney W. Grimes #include <limits.h> 579b50d902SRodney W. Grimes #include <stdio.h> 580ad736e6SMike Barcroft #include <stdint.h> 599b50d902SRodney W. Grimes #include <stdlib.h> 609b50d902SRodney W. Grimes #include <string.h> 619b50d902SRodney W. Grimes #include <time.h> 629d288406SAndrey A. Chernov #include <unistd.h> 639b50d902SRodney W. Grimes 649b50d902SRodney W. Grimes #define REPS_DEF 100 659b50d902SRodney W. Grimes #define BEGIN_DEF 1 669b50d902SRodney W. Grimes #define ENDER_DEF 100 679b50d902SRodney W. Grimes #define STEP_DEF 1 689b50d902SRodney W. Grimes 69afe53a49SDiomidis Spinellis #define HAVE_STEP 1 70afe53a49SDiomidis Spinellis #define HAVE_ENDER 2 71afe53a49SDiomidis Spinellis #define HAVE_BEGIN 4 72afe53a49SDiomidis Spinellis #define HAVE_REPS 8 73afe53a49SDiomidis Spinellis 7415ba0427SDima Dorfman #define is_default(s) (strcmp((s), "-") == 0) 759b50d902SRodney W. Grimes 769b50d902SRodney W. Grimes double begin; 779b50d902SRodney W. Grimes double ender; 789b50d902SRodney W. Grimes double s; 799b50d902SRodney W. Grimes long reps; 809b50d902SRodney W. Grimes int randomize; 819b50d902SRodney W. Grimes int infinity; 829b50d902SRodney W. Grimes int boring; 839b50d902SRodney W. Grimes int prec; 845249bd84SSheldon Hearn int longdata; 858db8a33bSSheldon Hearn int intdata; 869b50d902SRodney W. Grimes int chardata; 878db8a33bSSheldon Hearn int nosign; 889b50d902SRodney W. Grimes int nofinalnl; 89edd7b267SDima Dorfman const char *sepstring = "\n"; 909b50d902SRodney W. Grimes char format[BUFSIZ]; 919b50d902SRodney W. Grimes 92f1bb2cd2SWarner Losh void getformat(void); 93f1bb2cd2SWarner Losh int getprec(char *); 94f1bb2cd2SWarner Losh int putdata(double, long); 95f1bb2cd2SWarner Losh static void usage(void); 969b50d902SRodney W. Grimes 979b50d902SRodney W. Grimes int 98cf0def93SJuli Mallett main(int argc, char **argv) 999b50d902SRodney W. Grimes { 1009b50d902SRodney W. Grimes double xd, yd; 1019b50d902SRodney W. Grimes long id; 10215ba0427SDima Dorfman double *x = &xd; 10315ba0427SDima Dorfman double *y = &yd; 10415ba0427SDima Dorfman long *i = &id; 10515ba0427SDima Dorfman unsigned int mask = 0; 10615ba0427SDima Dorfman int n = 0; 10715ba0427SDima Dorfman int ch; 1089b50d902SRodney W. Grimes 10915ba0427SDima Dorfman while ((ch = getopt(argc, argv, "rb:w:cs:np:")) != -1) 110cf0def93SJuli Mallett switch (ch) { 1119b50d902SRodney W. Grimes case 'r': 1129b50d902SRodney W. Grimes randomize = 1; 1139b50d902SRodney W. Grimes break; 1149b50d902SRodney W. Grimes case 'c': 1159b50d902SRodney W. Grimes chardata = 1; 1169b50d902SRodney W. Grimes break; 1179b50d902SRodney W. Grimes case 'n': 1189b50d902SRodney W. Grimes nofinalnl = 1; 1199b50d902SRodney W. Grimes break; 1209b50d902SRodney W. Grimes case 'b': 1219b50d902SRodney W. Grimes boring = 1; 12215ba0427SDima Dorfman /* FALLTHROUGH */ 1239b50d902SRodney W. Grimes case 'w': 12415ba0427SDima Dorfman if (strlcpy(format, optarg, sizeof(format)) >= 12515ba0427SDima Dorfman sizeof(format)) 12615ba0427SDima Dorfman errx(1, "-%c word too long", ch); 1279b50d902SRodney W. Grimes break; 1289b50d902SRodney W. Grimes case 's': 12915ba0427SDima Dorfman sepstring = optarg; 1309b50d902SRodney W. Grimes break; 1319b50d902SRodney W. Grimes case 'p': 13215ba0427SDima Dorfman prec = atoi(optarg); 1339b50d902SRodney W. Grimes if (prec <= 0) 1347bd7ad50SPhilippe Charnier errx(1, "bad precision value"); 1359b50d902SRodney W. Grimes break; 1369b50d902SRodney W. Grimes default: 1377bd7ad50SPhilippe Charnier usage(); 1389b50d902SRodney W. Grimes } 13915ba0427SDima Dorfman argc -= optind; 14015ba0427SDima Dorfman argv += optind; 1419b50d902SRodney W. Grimes 14215ba0427SDima Dorfman switch (argc) { /* examine args right to left, falling thru cases */ 1439b50d902SRodney W. Grimes case 4: 14415ba0427SDima Dorfman if (!is_default(argv[3])) { 14515ba0427SDima Dorfman if (!sscanf(argv[3], "%lf", &s)) 14615ba0427SDima Dorfman errx(1, "bad s value: %s", argv[3]); 147afe53a49SDiomidis Spinellis mask |= HAVE_STEP; 1489b50d902SRodney W. Grimes } 149afe53a49SDiomidis Spinellis /* FALLTHROUGH */ 1509b50d902SRodney W. Grimes case 3: 15115ba0427SDima Dorfman if (!is_default(argv[2])) { 15215ba0427SDima Dorfman if (!sscanf(argv[2], "%lf", &ender)) 15315ba0427SDima Dorfman ender = argv[2][strlen(argv[2])-1]; 154afe53a49SDiomidis Spinellis mask |= HAVE_ENDER; 1559b50d902SRodney W. Grimes if (!prec) 15615ba0427SDima Dorfman n = getprec(argv[2]); 1579b50d902SRodney W. Grimes } 158afe53a49SDiomidis Spinellis /* FALLTHROUGH */ 1599b50d902SRodney W. Grimes case 2: 16015ba0427SDima Dorfman if (!is_default(argv[1])) { 16115ba0427SDima Dorfman if (!sscanf(argv[1], "%lf", &begin)) 16215ba0427SDima Dorfman begin = argv[1][strlen(argv[1])-1]; 163afe53a49SDiomidis Spinellis mask |= HAVE_BEGIN; 1649b50d902SRodney W. Grimes if (!prec) 16515ba0427SDima Dorfman prec = getprec(argv[1]); 1669b50d902SRodney W. Grimes if (n > prec) /* maximum precision */ 1679b50d902SRodney W. Grimes prec = n; 1689b50d902SRodney W. Grimes } 169afe53a49SDiomidis Spinellis /* FALLTHROUGH */ 1709b50d902SRodney W. Grimes case 1: 17115ba0427SDima Dorfman if (!is_default(argv[0])) { 17215ba0427SDima Dorfman if (!sscanf(argv[0], "%ld", &reps)) 17315ba0427SDima Dorfman errx(1, "bad reps value: %s", argv[0]); 174afe53a49SDiomidis Spinellis mask |= HAVE_REPS; 1759b50d902SRodney W. Grimes } 1769b50d902SRodney W. Grimes break; 1779b50d902SRodney W. Grimes case 0: 1787bd7ad50SPhilippe Charnier usage(); 1799b50d902SRodney W. Grimes default: 18015ba0427SDima Dorfman errx(1, "too many arguments. What do you mean by %s?", 18115ba0427SDima Dorfman argv[4]); 1829b50d902SRodney W. Grimes } 1839b50d902SRodney W. Grimes getformat(); 1849b50d902SRodney W. Grimes while (mask) /* 4 bit mask has 1's where last 4 args were given */ 1859b50d902SRodney W. Grimes switch (mask) { /* fill in the 0's by default or computation */ 186afe53a49SDiomidis Spinellis case HAVE_STEP: 1879b50d902SRodney W. Grimes reps = REPS_DEF; 188afe53a49SDiomidis Spinellis mask = HAVE_REPS | HAVE_STEP; 1899b50d902SRodney W. Grimes break; 190afe53a49SDiomidis Spinellis case HAVE_ENDER: 1919b50d902SRodney W. Grimes reps = REPS_DEF; 192afe53a49SDiomidis Spinellis mask = HAVE_REPS | HAVE_ENDER; 1939b50d902SRodney W. Grimes break; 194afe53a49SDiomidis Spinellis case HAVE_ENDER | HAVE_STEP: 1959b50d902SRodney W. Grimes reps = REPS_DEF; 196afe53a49SDiomidis Spinellis mask = HAVE_REPS | HAVE_ENDER | HAVE_STEP; 1979b50d902SRodney W. Grimes break; 198afe53a49SDiomidis Spinellis case HAVE_BEGIN: 1999b50d902SRodney W. Grimes reps = REPS_DEF; 200afe53a49SDiomidis Spinellis mask = HAVE_REPS | HAVE_BEGIN; 2019b50d902SRodney W. Grimes break; 202afe53a49SDiomidis Spinellis case HAVE_BEGIN | HAVE_STEP: 2039b50d902SRodney W. Grimes reps = REPS_DEF; 204afe53a49SDiomidis Spinellis mask = HAVE_REPS | HAVE_BEGIN | HAVE_STEP; 2059b50d902SRodney W. Grimes break; 206afe53a49SDiomidis Spinellis case HAVE_BEGIN | HAVE_ENDER: 2079b50d902SRodney W. Grimes reps = REPS_DEF; 208afe53a49SDiomidis Spinellis mask = HAVE_REPS | HAVE_BEGIN | HAVE_ENDER; 2099b50d902SRodney W. Grimes break; 210afe53a49SDiomidis Spinellis case HAVE_BEGIN | HAVE_ENDER | HAVE_STEP: 2119b50d902SRodney W. Grimes if (randomize) { 2129b50d902SRodney W. Grimes reps = REPS_DEF; 2139b50d902SRodney W. Grimes mask = 0; 2149b50d902SRodney W. Grimes break; 2159b50d902SRodney W. Grimes } 2169b50d902SRodney W. Grimes if (s == 0.0) { 2179b50d902SRodney W. Grimes reps = 0; 2189b50d902SRodney W. Grimes mask = 0; 2199b50d902SRodney W. Grimes break; 2209b50d902SRodney W. Grimes } 2219b50d902SRodney W. Grimes reps = (ender - begin + s) / s; 2229b50d902SRodney W. Grimes if (reps <= 0) 2237bd7ad50SPhilippe Charnier errx(1, "impossible stepsize"); 2249b50d902SRodney W. Grimes mask = 0; 2259b50d902SRodney W. Grimes break; 226afe53a49SDiomidis Spinellis case HAVE_REPS: 2279b50d902SRodney W. Grimes begin = BEGIN_DEF; 228afe53a49SDiomidis Spinellis mask = HAVE_REPS | HAVE_BEGIN; 2299b50d902SRodney W. Grimes break; 230afe53a49SDiomidis Spinellis case HAVE_REPS | HAVE_STEP: 2319b50d902SRodney W. Grimes begin = BEGIN_DEF; 232afe53a49SDiomidis Spinellis mask = HAVE_REPS | HAVE_BEGIN | HAVE_STEP; 2339b50d902SRodney W. Grimes break; 234afe53a49SDiomidis Spinellis case HAVE_REPS | HAVE_ENDER: 23515ba0427SDima Dorfman s = (randomize ? time(NULL) : STEP_DEF); 236afe53a49SDiomidis Spinellis mask = HAVE_REPS | HAVE_ENDER | HAVE_STEP; 2379b50d902SRodney W. Grimes break; 238afe53a49SDiomidis Spinellis case HAVE_REPS | HAVE_ENDER | HAVE_STEP: 2399b50d902SRodney W. Grimes if (randomize) 2409b50d902SRodney W. Grimes begin = BEGIN_DEF; 2419b50d902SRodney W. Grimes else if (reps == 0) 2427bd7ad50SPhilippe Charnier errx(1, "must specify begin if reps == 0"); 2439b50d902SRodney W. Grimes begin = ender - reps * s + s; 2449b50d902SRodney W. Grimes mask = 0; 2459b50d902SRodney W. Grimes break; 246afe53a49SDiomidis Spinellis case HAVE_REPS | HAVE_BEGIN: 2475790155eSAndrey A. Chernov s = (randomize ? -1.0 : STEP_DEF); 248afe53a49SDiomidis Spinellis mask = HAVE_REPS | HAVE_BEGIN | HAVE_STEP; 2499b50d902SRodney W. Grimes break; 250afe53a49SDiomidis Spinellis case HAVE_REPS | HAVE_BEGIN | HAVE_STEP: 2519b50d902SRodney W. Grimes if (randomize) 2529b50d902SRodney W. Grimes ender = ENDER_DEF; 2539b50d902SRodney W. Grimes else 2549b50d902SRodney W. Grimes ender = begin + reps * s - s; 2559b50d902SRodney W. Grimes mask = 0; 2569b50d902SRodney W. Grimes break; 257afe53a49SDiomidis Spinellis case HAVE_REPS | HAVE_BEGIN | HAVE_ENDER: 2589b50d902SRodney W. Grimes if (randomize) 2595790155eSAndrey A. Chernov s = -1.0; 2609b50d902SRodney W. Grimes else if (reps == 0) 2617bd7ad50SPhilippe Charnier errx(1, "infinite sequences cannot be bounded"); 2629b50d902SRodney W. Grimes else if (reps == 1) 2639b50d902SRodney W. Grimes s = 0.0; 2649b50d902SRodney W. Grimes else 2659b50d902SRodney W. Grimes s = (ender - begin) / (reps - 1); 2669b50d902SRodney W. Grimes mask = 0; 2679b50d902SRodney W. Grimes break; 268afe53a49SDiomidis Spinellis case HAVE_REPS | HAVE_BEGIN | HAVE_ENDER | HAVE_STEP: 269afe53a49SDiomidis Spinellis /* if reps given and implied, */ 2709b50d902SRodney W. Grimes if (!randomize && s != 0.0) { 2719b50d902SRodney W. Grimes long t = (ender - begin + s) / s; 2729b50d902SRodney W. Grimes if (t <= 0) 2737bd7ad50SPhilippe Charnier errx(1, "impossible stepsize"); 2749b50d902SRodney W. Grimes if (t < reps) /* take lesser */ 2759b50d902SRodney W. Grimes reps = t; 2769b50d902SRodney W. Grimes } 2779b50d902SRodney W. Grimes mask = 0; 2789b50d902SRodney W. Grimes break; 2799b50d902SRodney W. Grimes default: 2807bd7ad50SPhilippe Charnier errx(1, "bad mask"); 2819b50d902SRodney W. Grimes } 2829b50d902SRodney W. Grimes if (reps == 0) 2839b50d902SRodney W. Grimes infinity = 1; 28415ba0427SDima Dorfman if (randomize) { 28515ba0427SDima Dorfman *x = (ender - begin) * (ender > begin ? 1 : -1); 28615ba0427SDima Dorfman for (*i = 1; *i <= reps || infinity; (*i)++) { 287bbc7056bSDavid Schultz *y = arc4random() / ((double)UINT32_MAX + 1); 28815ba0427SDima Dorfman if (putdata(*y * *x + begin, reps - *i)) 28915ba0427SDima Dorfman errx(1, "range error in conversion"); 29015ba0427SDima Dorfman } 29115ba0427SDima Dorfman } else 29215ba0427SDima Dorfman for (*i = 1, *x = begin; *i <= reps || infinity; (*i)++, *x += s) 29315ba0427SDima Dorfman if (putdata(*x, reps - *i)) 29415ba0427SDima Dorfman errx(1, "range error in conversion"); 29515ba0427SDima Dorfman if (!nofinalnl) 29615ba0427SDima Dorfman putchar('\n'); 29715ba0427SDima Dorfman exit(0); 2989b50d902SRodney W. Grimes } 2999b50d902SRodney W. Grimes 3005249bd84SSheldon Hearn int 301cf0def93SJuli Mallett putdata(double x, long int notlast) 3029b50d902SRodney W. Grimes { 3039b50d902SRodney W. Grimes 3045249bd84SSheldon Hearn if (boring) 305612740bdSKris Kennaway printf("%s", format); 3065249bd84SSheldon Hearn else if (longdata && nosign) { 3075249bd84SSheldon Hearn if (x <= (double)ULONG_MAX && x >= (double)0) 3088db8a33bSSheldon Hearn printf(format, (unsigned long)x); 3095249bd84SSheldon Hearn else 3105249bd84SSheldon Hearn return (1); 3115249bd84SSheldon Hearn } else if (longdata) { 3125249bd84SSheldon Hearn if (x <= (double)LONG_MAX && x >= (double)LONG_MIN) 3138db8a33bSSheldon Hearn printf(format, (long)x); 3145249bd84SSheldon Hearn else 3155249bd84SSheldon Hearn return (1); 3165249bd84SSheldon Hearn } else if (chardata || (intdata && !nosign)) { 3175249bd84SSheldon Hearn if (x <= (double)INT_MAX && x >= (double)INT_MIN) 3185249bd84SSheldon Hearn printf(format, (int)x); 3195249bd84SSheldon Hearn else 3205249bd84SSheldon Hearn return (1); 3215249bd84SSheldon Hearn } else if (intdata) { 3225249bd84SSheldon Hearn if (x <= (double)UINT_MAX && x >= (double)0) 3235249bd84SSheldon Hearn printf(format, (unsigned int)x); 3245249bd84SSheldon Hearn else 3255249bd84SSheldon Hearn return (1); 3265249bd84SSheldon Hearn 3275249bd84SSheldon Hearn } else 3289b50d902SRodney W. Grimes printf(format, x); 3299b50d902SRodney W. Grimes if (notlast != 0) 3309b50d902SRodney W. Grimes fputs(sepstring, stdout); 3315249bd84SSheldon Hearn 3325249bd84SSheldon Hearn return (0); 3339b50d902SRodney W. Grimes } 3349b50d902SRodney W. Grimes 3357bd7ad50SPhilippe Charnier static void 336cf0def93SJuli Mallett usage(void) 3379b50d902SRodney W. Grimes { 3387bd7ad50SPhilippe Charnier fprintf(stderr, "%s\n%s\n", 3397bd7ad50SPhilippe Charnier "usage: jot [-cnr] [-b word] [-w word] [-s string] [-p precision]", 3407bd7ad50SPhilippe Charnier " [reps [begin [end [s]]]]"); 3419b50d902SRodney W. Grimes exit(1); 3429b50d902SRodney W. Grimes } 3439b50d902SRodney W. Grimes 3449b50d902SRodney W. Grimes int 345cf0def93SJuli Mallett getprec(char *str) 3469b50d902SRodney W. Grimes { 34715ba0427SDima Dorfman char *p; 34815ba0427SDima Dorfman char *q; 3499b50d902SRodney W. Grimes 350edd7b267SDima Dorfman for (p = str; *p; p++) 3519b50d902SRodney W. Grimes if (*p == '.') 3529b50d902SRodney W. Grimes break; 3539b50d902SRodney W. Grimes if (!*p) 3549b50d902SRodney W. Grimes return (0); 3559b50d902SRodney W. Grimes for (q = ++p; *p; p++) 356911a3ff9STim J. Robbins if (!isdigit((unsigned char)*p)) 3579b50d902SRodney W. Grimes break; 3589b50d902SRodney W. Grimes return (p - q); 3599b50d902SRodney W. Grimes } 3609b50d902SRodney W. Grimes 3619b50d902SRodney W. Grimes void 362cf0def93SJuli Mallett getformat(void) 3639b50d902SRodney W. Grimes { 364edd7b267SDima Dorfman char *p, *p2; 3655249bd84SSheldon Hearn int dot, hash, space, sign, numbers = 0; 36615ba0427SDima Dorfman size_t sz; 3679b50d902SRodney W. Grimes 3689b50d902SRodney W. Grimes if (boring) /* no need to bother */ 3699b50d902SRodney W. Grimes return; 3709b50d902SRodney W. Grimes for (p = format; *p; p++) /* look for '%' */ 3719b50d902SRodney W. Grimes if (*p == '%' && *(p+1) != '%') /* leave %% alone */ 3729b50d902SRodney W. Grimes break; 37315ba0427SDima Dorfman sz = sizeof(format) - strlen(format) - 1; 37415ba0427SDima Dorfman if (!*p && !chardata) { 37515ba0427SDima Dorfman if (snprintf(p, sz, "%%.%df", prec) >= (int)sz) 37615ba0427SDima Dorfman errx(1, "-w word too long"); 37715ba0427SDima Dorfman } else if (!*p && chardata) { 37815ba0427SDima Dorfman if (strlcpy(p, "%c", sz) >= sz) 37915ba0427SDima Dorfman errx(1, "-w word too long"); 3808db8a33bSSheldon Hearn intdata = 1; 38115ba0427SDima Dorfman } else if (!*(p+1)) { 38215ba0427SDima Dorfman if (sz <= 0) 38315ba0427SDima Dorfman errx(1, "-w word too long"); 3849b50d902SRodney W. Grimes strcat(format, "%"); /* cannot end in single '%' */ 38515ba0427SDima Dorfman } else { 3868db8a33bSSheldon Hearn /* 3878db8a33bSSheldon Hearn * Allow conversion format specifiers of the form 3888db8a33bSSheldon Hearn * %[#][ ][{+,-}][0-9]*[.[0-9]*]? where ? must be one of 3898db8a33bSSheldon Hearn * [l]{d,i,o,u,x} or {f,e,g,E,G,d,o,x,D,O,U,X,c,u} 3908db8a33bSSheldon Hearn */ 391edd7b267SDima Dorfman p2 = p++; 3928db8a33bSSheldon Hearn dot = hash = space = sign = numbers = 0; 393911a3ff9STim J. Robbins while (!isalpha((unsigned char)*p)) { 394911a3ff9STim J. Robbins if (isdigit((unsigned char)*p)) { 3958db8a33bSSheldon Hearn numbers++; 3969b50d902SRodney W. Grimes p++; 3978db8a33bSSheldon Hearn } else if ((*p == '#' && !(numbers|dot|sign|space| 3988db8a33bSSheldon Hearn hash++)) || 3998db8a33bSSheldon Hearn (*p == ' ' && !(numbers|dot|space++)) || 4008db8a33bSSheldon Hearn ((*p == '+' || *p == '-') && !(numbers|dot|sign++)) 4018db8a33bSSheldon Hearn || (*p == '.' && !(dot++))) 4028db8a33bSSheldon Hearn p++; 4038db8a33bSSheldon Hearn else 4045249bd84SSheldon Hearn goto fmt_broken; 4055249bd84SSheldon Hearn } 4065249bd84SSheldon Hearn if (*p == 'l') { 4075249bd84SSheldon Hearn longdata = 1; 4085249bd84SSheldon Hearn if (*++p == 'l') { 4095249bd84SSheldon Hearn if (p[1] != '\0') 4105249bd84SSheldon Hearn p++; 4115249bd84SSheldon Hearn goto fmt_broken; 4125249bd84SSheldon Hearn } 4138db8a33bSSheldon Hearn } 4149b50d902SRodney W. Grimes switch (*p) { 4158db8a33bSSheldon Hearn case 'o': case 'u': case 'x': case 'X': 4168db8a33bSSheldon Hearn intdata = nosign = 1; 4179b50d902SRodney W. Grimes break; 4188db8a33bSSheldon Hearn case 'd': case 'i': 4198db8a33bSSheldon Hearn intdata = 1; 4208db8a33bSSheldon Hearn break; 4218db8a33bSSheldon Hearn case 'D': 4225249bd84SSheldon Hearn if (!longdata) { 4238db8a33bSSheldon Hearn intdata = 1; 4248db8a33bSSheldon Hearn break; 4258db8a33bSSheldon Hearn } 4268db8a33bSSheldon Hearn case 'O': case 'U': 4275249bd84SSheldon Hearn if (!longdata) { 4288db8a33bSSheldon Hearn intdata = nosign = 1; 4298db8a33bSSheldon Hearn break; 4308db8a33bSSheldon Hearn } 4318db8a33bSSheldon Hearn case 'c': 4325249bd84SSheldon Hearn if (!(intdata | longdata)) { 4338db8a33bSSheldon Hearn chardata = 1; 4348db8a33bSSheldon Hearn break; 4358db8a33bSSheldon Hearn } 4365249bd84SSheldon Hearn case 'h': case 'n': case 'p': case 'q': case 's': case 'L': 4378db8a33bSSheldon Hearn case '$': case '*': 4385249bd84SSheldon Hearn goto fmt_broken; 4398db8a33bSSheldon Hearn case 'f': case 'e': case 'g': case 'E': case 'G': 4405249bd84SSheldon Hearn if (!longdata) 4418db8a33bSSheldon Hearn break; 4428db8a33bSSheldon Hearn /* FALLTHROUGH */ 4439b50d902SRodney W. Grimes default: 4445249bd84SSheldon Hearn fmt_broken: 4458db8a33bSSheldon Hearn *++p = '\0'; 446edd7b267SDima Dorfman errx(1, "illegal or unsupported format '%s'", p2); 4478db8a33bSSheldon Hearn /* NOTREACHED */ 4488db8a33bSSheldon Hearn } 4498db8a33bSSheldon Hearn while (*++p) 4508db8a33bSSheldon Hearn if (*p == '%' && *(p+1) && *(p+1) != '%') 4518db8a33bSSheldon Hearn errx(1, "too many conversions"); 4528db8a33bSSheldon Hearn else if (*p == '%' && *(p+1) == '%') 4538db8a33bSSheldon Hearn p++; 4548db8a33bSSheldon Hearn else if (*p == '%' && !*(p+1)) { 4558db8a33bSSheldon Hearn strcat(format, "%"); 4569b50d902SRodney W. Grimes break; 4579b50d902SRodney W. Grimes } 4589b50d902SRodney W. Grimes } 4599b50d902SRodney W. Grimes } 460