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
main(argc,argv)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
convert(line)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
unit(len,p)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
number(p,len)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
pfract(len)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
usage()262 usage()
263 {
264 (void)fprintf(stderr, "usage: number [# ...]\n");
265 exit(1);
266 }
267