ANSIfication; bug report 4.3BSD/bin/223
[unix-history] / usr / src / games / number / number.c
CommitLineData
3ce5f7e7 1/*
44d8b20d
KB
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
f4f66d2c
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
3ce5f7e7 16 */
e9b5e6c3 17
3ce5f7e7 18#ifndef lint
44d8b20d
KB
19char copyright[] =
20"@(#) Copyright (c) 1988 Regents of the University of California.\n\
21 All rights reserved.\n";
22#endif /* not lint */
23
24#ifndef lint
f4f66d2c 25static char sccsid[] = "@(#)number.c 4.5 (Berkeley) %G%";
44d8b20d 26#endif /* not lint */
b2a69b00
KB
27
28#include <stdio.h>
3ce5f7e7
KB
29#include <ctype.h>
30
31#define YES 1
32#define NO 0
33#define EOS '\0'
34#define MAXNUM 65 /* biggest number we handle */
35
36static char *name1[] = {
37 "", "one", "two", "three",
38 "four", "five", "six", "seven",
39 "eight", "nine", "ten", "eleven",
40 "twelve", "thirteen", "fourteen", "fifteen",
41 "sixteen", "seventeen", "eighteen", "nineteen",
42},
43 *name2[] = {
44 "", "ten", "twenty", "thirty",
45 "forty", "fifty", "sixty", "seventy",
46 "eighty", "ninety",
47},
48 *name3[] = {
49 "hundred", "thousand", "million", "billion",
50 "trillion", "quadrillion", "quintillion", "sextillion",
51 "septillion", "octillion", "nonillion", "decillion",
52 "undecillion", "duodecillion", "tredecillion", "quattuordecillion",
53 "quindecillion", "sexdecillion",
54 "septendecillion", "octodecillion",
55 "novemdecillion", "vigintillion",
e9b5e6c3 56};
e9b5e6c3 57
3ce5f7e7
KB
58main(argc,argv)
59 int argc;
60 char **argv;
61{
62 register int cnt;
63 char line[MAXNUM * 2 + 2]; /* MAXNUM '.' MAXNUM '\0' */
e9b5e6c3 64
3ce5f7e7
KB
65 if (argc > 1)
66 for (cnt = 1;cnt < argc;++cnt) {
67 convert(argv[cnt]);
68 puts("...");
e9b5e6c3 69 }
3ce5f7e7
KB
70 else
71 while (fgets(line,sizeof(line),stdin)) {
72 convert(line);
73 puts("...");
e9b5e6c3 74 }
3ce5f7e7 75 exit(0);
e9b5e6c3
KM
76}
77
3ce5f7e7
KB
78static
79convert(line)
80 char *line;
e9b5e6c3 81{
3ce5f7e7
KB
82 register int len,
83 ret;
84 register char *C,
85 *fraction;
86
87 for (fraction = NULL, C = line;*C && *C != '\n';++C)
88 if (!isdigit(*C))
89 switch(*C) {
90 case '-':
91 if (C != line)
92 usage(NO);
93 break;
94 case '.':
95 if (!fraction) {
96 fraction = C + 1;
97 *C = EOS;
98 break;
99 }
100 default:
101 usage(NO);
102 }
103 *C = EOS;
104 if (*line == '-') {
105 puts("minus");
106 ++line;
e9b5e6c3 107 }
3ce5f7e7
KB
108 ret = NO;
109 if (len = strlen(line)) {
110 if (len > MAXNUM)
111 usage(YES);
112 ret = unit(len,line);
e9b5e6c3 113 }
3ce5f7e7
KB
114 if (fraction && (len = strlen(fraction))) {
115 if (len > MAXNUM)
116 usage(YES);
117 for (C = fraction;*C;++C)
118 if (*C != '0') {
119 if (ret)
120 puts("and");
121 if (unit(len,fraction)) {
122 ++ret;
123 pfract(len);
124 }
125 break;
126 }
e9b5e6c3 127 }
3ce5f7e7
KB
128 if (!ret)
129 puts("zero.");
e9b5e6c3
KM
130}
131
3ce5f7e7
KB
132static
133unit(len,C)
134 register int len;
135 register char *C;
e9b5e6c3 136{
3ce5f7e7
KB
137 register int off,
138 ret;
139
140 ret = NO;
141 if (len > 3) {
142 if (len % 3) {
143 off = len % 3;
144 len -= off;
145 if (number(C,off)) {
146 ret = YES;
147 printf(" %s.\n",name3[len / 3]);
148 }
149 C += off;
150 }
151 for (;len > 3;C += 3) {
152 len -= 3;
153 if (number(C,3)) {
154 ret = YES;
155 printf(" %s.\n",name3[len / 3]);
156 }
157 }
158 }
159 if (number(C,len)) {
160 puts(".");
161 ret = YES;
162 }
163 return(ret);
e9b5e6c3
KM
164}
165
3ce5f7e7
KB
166static
167number(C,len)
168 register char *C;
169 int len;
e9b5e6c3 170{
3ce5f7e7
KB
171 register int val,
172 ret;
173
174 ret = 0;
175 switch(len) {
176 case 3:
177 if (*C != '0') {
178 ++ret;
179 printf("%s hundred",name1[*C - '0']);
180 }
181 ++C;
182 /*FALLTHROUGH*/
183 case 2:
184 val = (C[1] - '0') + (C[0] - '0') * 10;
185 if (val) {
186 if (ret++)
187 putchar(' ');
188 if (val < 20)
189 fputs(name1[val],stdout);
190 else {
191 fputs(name2[val / 10],stdout);
192 if (val % 10)
193 printf("-%s",name1[val % 10]);
194 }
195 }
196 break;
197 case 1:
198 if (*C != '0') {
199 ++ret;
200 fputs(name1[*C - '0'],stdout);
201 }
202 }
203 return(ret);
e9b5e6c3
KM
204}
205
3ce5f7e7
KB
206static
207pfract(len)
208 register int len;
e9b5e6c3 209{
3ce5f7e7
KB
210 static char *pref[] = { "", "ten-", "hundred-" };
211
212 switch(len) {
213 case 1:
214 puts("tenths.");
215 break;
216 case 2:
217 puts("hundredths.");
218 break;
219 default:
220 printf("%s%sths.\n",pref[len % 3],name3[len / 3]);
221 }
e9b5e6c3
KM
222}
223
3ce5f7e7
KB
224static
225usage(toobig)
226 int toobig;
e9b5e6c3 227{
3ce5f7e7
KB
228 if (toobig)
229 fprintf(stderr,"number: number too large, max %d digits.\n",MAXNUM);
230 fputs("usage: number # ...\n",stderr);
231 exit(-1);
e9b5e6c3 232}