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