1 /* 2 * Copyright (c) 1988, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char copyright[] = 10 "@(#) Copyright (c) 1988, 1993, 1994\n\ 11 The Regents of the University of California. All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)number.c 8.2 (Berkeley) 03/31/94"; 16 #endif /* not lint */ 17 18 #include <sys/types.h> 19 20 #include <ctype.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <err.h> 25 26 #define MAXNUM 65 /* Biggest number we handle. */ 27 28 static char *name1[] = { 29 "", "one", "two", "three", 30 "four", "five", "six", "seven", 31 "eight", "nine", "ten", "eleven", 32 "twelve", "thirteen", "fourteen", "fifteen", 33 "sixteen", "seventeen", "eighteen", "nineteen", 34 }, 35 *name2[] = { 36 "", "ten", "twenty", "thirty", 37 "forty", "fifty", "sixty", "seventy", 38 "eighty", "ninety", 39 }, 40 *name3[] = { 41 "hundred", "thousand", "million", "billion", 42 "trillion", "quadrillion", "quintillion", "sextillion", 43 "septillion", "octillion", "nonillion", "decillion", 44 "undecillion", "duodecillion", "tredecillion", "quattuordecillion", 45 "quindecillion", "sexdecillion", 46 "septendecillion", "octodecillion", 47 "novemdecillion", "vigintillion", 48 }; 49 50 void convert __P((char *)); 51 int number __P((char *, int)); 52 void pfract __P((int)); 53 void toobig __P((void)); 54 int unit __P((int, char *)); 55 void usage __P((void)); 56 57 int lflag; 58 59 int 60 main(argc, argv) 61 int argc; 62 char *argv[]; 63 { 64 int ch, first; 65 char line[256]; 66 67 lflag = 0; 68 while ((ch = getopt(argc, argv, "l")) != EOF) 69 switch (ch) { 70 case 'l': 71 lflag = 1; 72 break; 73 case '?': 74 default: 75 usage(); 76 } 77 argc -= optind; 78 argv += optind; 79 80 if (*argv == NULL) 81 for (first = 1; 82 fgets(line, sizeof(line), stdin) != NULL; first = 0) { 83 if (strchr(line, '\n') == NULL) 84 errx(1, "line too long."); 85 if (!first) 86 (void)printf("...\n"); 87 convert(line); 88 } 89 else 90 for (first = 1; *argv != NULL; first = 0, ++argv) { 91 if (!first) 92 (void)printf("...\n"); 93 convert(*argv); 94 } 95 exit(0); 96 } 97 98 void 99 convert(line) 100 char *line; 101 { 102 register flen, len, rval; 103 register char *p, *fraction; 104 105 fraction = NULL; 106 for (p = line; *p != '\0' && *p != '\n'; ++p) { 107 if (isblank(*p)) { 108 if (p == line) { 109 ++line; 110 continue; 111 } 112 goto badnum; 113 } 114 if (isdigit(*p)) 115 continue; 116 switch (*p) { 117 case '.': 118 if (fraction != NULL) 119 goto badnum; 120 fraction = p + 1; 121 *p = '\0'; 122 break; 123 case '-': 124 if (p == line) 125 break; 126 /* FALLTHROUGH */ 127 default: 128 badnum: errx(1, "illegal number: %s", line); 129 break; 130 } 131 } 132 *p = '\0'; 133 134 if ((len = strlen(line)) > MAXNUM || 135 fraction != NULL && (flen = strlen(fraction)) > MAXNUM) 136 errx(1, "number too large, max %d digits.", MAXNUM); 137 138 if (*line == '-') { 139 (void)printf("minus%s", lflag ? " " : "\n"); 140 ++line; 141 } 142 143 rval = len > 0 ? unit(len, line) : 0; 144 if (fraction != NULL && flen != 0) 145 for (p = fraction; *p != '\0'; ++p) 146 if (*p != '0') { 147 if (rval) 148 (void)printf("%sand%s", 149 lflag ? " " : "", 150 lflag ? " " : "\n"); 151 if (unit(flen, fraction)) { 152 if (lflag) 153 (void)printf(" "); 154 pfract(flen); 155 rval = 1; 156 } 157 break; 158 } 159 if (!rval) 160 (void)printf("zero%s", lflag ? "" : ".\n"); 161 if (lflag) 162 (void)printf("\n"); 163 } 164 165 int 166 unit(len, p) 167 register int len; 168 register char *p; 169 { 170 register int off, rval; 171 172 rval = 0; 173 if (len > 3) { 174 if (len % 3) { 175 off = len % 3; 176 len -= off; 177 if (number(p, off)) { 178 rval = 1; 179 (void)printf(" %s%s", 180 name3[len / 3], lflag ? " " : ".\n"); 181 } 182 p += off; 183 } 184 for (; len > 3; p += 3) { 185 len -= 3; 186 if (number(p, 3)) { 187 rval = 1; 188 (void)printf(" %s%s", 189 name3[len / 3], lflag ? " " : ".\n"); 190 } 191 } 192 } 193 if (number(p, len)) { 194 if (!lflag) 195 (void)printf(".\n"); 196 rval = 1; 197 } 198 return (rval); 199 } 200 201 int 202 number(p, len) 203 register char *p; 204 int len; 205 { 206 register int val, rval; 207 208 rval = 0; 209 switch (len) { 210 case 3: 211 if (*p != '0') { 212 rval = 1; 213 (void)printf("%s hundred", name1[*p - '0']); 214 } 215 ++p; 216 /* FALLTHROUGH */ 217 case 2: 218 val = (p[1] - '0') + (p[0] - '0') * 10; 219 if (val) { 220 if (rval) 221 (void)printf(" "); 222 if (val < 20) 223 (void)printf("%s", name1[val]); 224 else { 225 (void)printf("%s", name2[val / 10]); 226 if (val % 10) 227 (void)printf("-%s", name1[val % 10]); 228 } 229 rval = 1; 230 } 231 break; 232 case 1: 233 if (*p != '0') { 234 rval = 1; 235 (void)printf("%s", name1[*p - '0']); 236 } 237 } 238 return (rval); 239 } 240 241 void 242 pfract(len) 243 int len; 244 { 245 static char *pref[] = { "", "ten-", "hundred-" }; 246 247 switch(len) { 248 case 1: 249 (void)printf("tenths.\n"); 250 break; 251 case 2: 252 (void)printf("hundredths.\n"); 253 break; 254 default: 255 (void)printf("%s%sths.\n", pref[len % 3], name3[len / 3]); 256 break; 257 } 258 } 259 260 void 261 usage() 262 { 263 (void)fprintf(stderr, "usage: number [# ...]\n"); 264 exit(1); 265 } 266