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