]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - number/number.c
Add RCS identifiers.
[bsdgames-darwin.git] / number / number.c
1 /*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 char copyright[] =
36 "@(#) Copyright (c) 1988 Regents of the University of California.\n\
37 All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 /*static char sccsid[] = "from: @(#)number.c 5.1 (Berkeley) 2/28/91";*/
42 static char rcsid[] = "$Id: number.c,v 1.2 1993/08/01 18:53:19 mycroft Exp $";
43 #endif /* not lint */
44
45 #include <stdio.h>
46 #include <ctype.h>
47
48 #define YES 1
49 #define NO 0
50 #define EOS '\0'
51 #define MAXNUM 65 /* biggest number we handle */
52
53 static char *name1[] = {
54 "", "one", "two", "three",
55 "four", "five", "six", "seven",
56 "eight", "nine", "ten", "eleven",
57 "twelve", "thirteen", "fourteen", "fifteen",
58 "sixteen", "seventeen", "eighteen", "nineteen",
59 },
60 *name2[] = {
61 "", "ten", "twenty", "thirty",
62 "forty", "fifty", "sixty", "seventy",
63 "eighty", "ninety",
64 },
65 *name3[] = {
66 "hundred", "thousand", "million", "billion",
67 "trillion", "quadrillion", "quintillion", "sextillion",
68 "septillion", "octillion", "nonillion", "decillion",
69 "undecillion", "duodecillion", "tredecillion", "quattuordecillion",
70 "quindecillion", "sexdecillion",
71 "septendecillion", "octodecillion",
72 "novemdecillion", "vigintillion",
73 };
74
75 main(argc,argv)
76 int argc;
77 char **argv;
78 {
79 register int cnt;
80 char line[MAXNUM * 2 + 2]; /* MAXNUM '.' MAXNUM '\0' */
81
82 if (argc > 1)
83 for (cnt = 1;cnt < argc;++cnt) {
84 convert(argv[cnt]);
85 puts("...");
86 }
87 else
88 while (fgets(line,sizeof(line),stdin)) {
89 convert(line);
90 puts("...");
91 }
92 exit(0);
93 }
94
95 convert(line)
96 char *line;
97 {
98 register int len,
99 ret;
100 register char *C,
101 *fraction;
102
103 for (fraction = NULL, C = line;*C && *C != '\n';++C)
104 if (!isdigit(*C))
105 switch(*C) {
106 case '-':
107 if (C != line)
108 usage(NO);
109 break;
110 case '.':
111 if (!fraction) {
112 fraction = C + 1;
113 *C = EOS;
114 break;
115 }
116 default:
117 usage(NO);
118 }
119 *C = EOS;
120 if (*line == '-') {
121 puts("minus");
122 ++line;
123 }
124 ret = NO;
125 if (len = strlen(line)) {
126 if (len > MAXNUM)
127 usage(YES);
128 ret = unit(len,line);
129 }
130 if (fraction && (len = strlen(fraction))) {
131 if (len > MAXNUM)
132 usage(YES);
133 for (C = fraction;*C;++C)
134 if (*C != '0') {
135 if (ret)
136 puts("and");
137 if (unit(len,fraction)) {
138 ++ret;
139 pfract(len);
140 }
141 break;
142 }
143 }
144 if (!ret)
145 puts("zero.");
146 }
147
148 unit(len,C)
149 register int len;
150 register char *C;
151 {
152 register int off,
153 ret;
154
155 ret = NO;
156 if (len > 3) {
157 if (len % 3) {
158 off = len % 3;
159 len -= off;
160 if (number(C,off)) {
161 ret = YES;
162 printf(" %s.\n",name3[len / 3]);
163 }
164 C += off;
165 }
166 for (;len > 3;C += 3) {
167 len -= 3;
168 if (number(C,3)) {
169 ret = YES;
170 printf(" %s.\n",name3[len / 3]);
171 }
172 }
173 }
174 if (number(C,len)) {
175 puts(".");
176 ret = YES;
177 }
178 return(ret);
179 }
180
181 number(C,len)
182 register char *C;
183 int len;
184 {
185 register int val,
186 ret;
187
188 ret = 0;
189 switch(len) {
190 case 3:
191 if (*C != '0') {
192 ++ret;
193 printf("%s hundred",name1[*C - '0']);
194 }
195 ++C;
196 /*FALLTHROUGH*/
197 case 2:
198 val = (C[1] - '0') + (C[0] - '0') * 10;
199 if (val) {
200 if (ret++)
201 putchar(' ');
202 if (val < 20)
203 fputs(name1[val],stdout);
204 else {
205 fputs(name2[val / 10],stdout);
206 if (val % 10)
207 printf("-%s",name1[val % 10]);
208 }
209 }
210 break;
211 case 1:
212 if (*C != '0') {
213 ++ret;
214 fputs(name1[*C - '0'],stdout);
215 }
216 }
217 return(ret);
218 }
219
220 pfract(len)
221 register int len;
222 {
223 static char *pref[] = { "", "ten-", "hundred-" };
224
225 switch(len) {
226 case 1:
227 puts("tenths.");
228 break;
229 case 2:
230 puts("hundredths.");
231 break;
232 default:
233 printf("%s%sths.\n",pref[len % 3],name3[len / 3]);
234 }
235 }
236
237 usage(toobig)
238 int toobig;
239 {
240 if (toobig)
241 fprintf(stderr,"number: number too large, max %d digits.\n",MAXNUM);
242 fputs("usage: number # ...\n",stderr);
243 exit(-1);
244 }