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