Annotation of src/games/number/number.c, Revision 1.5
1.5 ! lukem 1: /* $NetBSD: number.c,v 1.4 1997/01/07 12:16:57 tls Exp $ */
1.3 cgd 2:
1.1 cgd 3: /*
1.3 cgd 4: * Copyright (c) 1988, 1993, 1994
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
1.5 ! lukem 36: #include <sys/cdefs.h>
1.1 cgd 37: #ifndef lint
1.5 ! lukem 38: __COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\n\
! 39: The Regents of the University of California. All rights reserved.\n");
1.1 cgd 40: #endif /* not lint */
41:
42: #ifndef lint
1.3 cgd 43: #if 0
1.4 tls 44: static char sccsid[] = "@(#)number.c 8.3 (Berkeley) 5/4/95";
1.3 cgd 45: #else
1.5 ! lukem 46: __RCSID("$NetBSD$");
1.3 cgd 47: #endif
1.1 cgd 48: #endif /* not lint */
49:
1.3 cgd 50: #include <sys/types.h>
51:
52: #include <ctype.h>
1.4 tls 53: #include <err.h>
1.1 cgd 54: #include <stdio.h>
1.3 cgd 55: #include <stdlib.h>
56: #include <string.h>
1.4 tls 57: #include <unistd.h>
1.1 cgd 58:
1.3 cgd 59: #define MAXNUM 65 /* Biggest number we handle. */
1.1 cgd 60:
61: static char *name1[] = {
62: "", "one", "two", "three",
63: "four", "five", "six", "seven",
64: "eight", "nine", "ten", "eleven",
65: "twelve", "thirteen", "fourteen", "fifteen",
66: "sixteen", "seventeen", "eighteen", "nineteen",
67: },
68: *name2[] = {
69: "", "ten", "twenty", "thirty",
70: "forty", "fifty", "sixty", "seventy",
71: "eighty", "ninety",
72: },
73: *name3[] = {
74: "hundred", "thousand", "million", "billion",
75: "trillion", "quadrillion", "quintillion", "sextillion",
76: "septillion", "octillion", "nonillion", "decillion",
77: "undecillion", "duodecillion", "tredecillion", "quattuordecillion",
78: "quindecillion", "sexdecillion",
79: "septendecillion", "octodecillion",
80: "novemdecillion", "vigintillion",
81: };
82:
1.3 cgd 83: void convert __P((char *));
1.5 ! lukem 84: int main __P((int, char *[]));
1.3 cgd 85: int number __P((char *, int));
86: void pfract __P((int));
87: void toobig __P((void));
88: int unit __P((int, char *));
89: void usage __P((void));
90:
91: int lflag;
92:
93: int
94: main(argc, argv)
95: int argc;
96: char *argv[];
97: {
98: int ch, first;
99: char line[256];
100:
101: lflag = 0;
1.5 ! lukem 102: while ((ch = getopt(argc, argv, "l")) != -1)
1.3 cgd 103: switch (ch) {
104: case 'l':
105: lflag = 1;
106: break;
107: case '?':
108: default:
109: usage();
110: }
111: argc -= optind;
112: argv += optind;
113:
114: if (*argv == NULL)
115: for (first = 1;
116: fgets(line, sizeof(line), stdin) != NULL; first = 0) {
117: if (strchr(line, '\n') == NULL)
118: errx(1, "line too long.");
119: if (!first)
120: (void)printf("...\n");
121: convert(line);
1.1 cgd 122: }
123: else
1.3 cgd 124: for (first = 1; *argv != NULL; first = 0, ++argv) {
125: if (!first)
126: (void)printf("...\n");
127: convert(*argv);
1.1 cgd 128: }
129: exit(0);
130: }
131:
1.3 cgd 132: void
1.1 cgd 133: convert(line)
1.3 cgd 134: char *line;
1.1 cgd 135: {
1.5 ! lukem 136: int flen, len, rval;
! 137: char *p, *fraction;
1.3 cgd 138:
1.5 ! lukem 139: flen = 0;
1.3 cgd 140: fraction = NULL;
141: for (p = line; *p != '\0' && *p != '\n'; ++p) {
142: if (isblank(*p)) {
143: if (p == line) {
144: ++line;
145: continue;
146: }
147: goto badnum;
148: }
149: if (isdigit(*p))
150: continue;
151: switch (*p) {
152: case '.':
153: if (fraction != NULL)
154: goto badnum;
155: fraction = p + 1;
156: *p = '\0';
157: break;
158: case '-':
159: if (p == line)
1.1 cgd 160: break;
1.3 cgd 161: /* FALLTHROUGH */
162: default:
163: badnum: errx(1, "illegal number: %s", line);
164: break;
165: }
166: }
167: *p = '\0';
168:
169: if ((len = strlen(line)) > MAXNUM ||
1.5 ! lukem 170: (fraction != NULL && (flen = strlen(fraction)) > MAXNUM))
1.3 cgd 171: errx(1, "number too large, max %d digits.", MAXNUM);
172:
1.1 cgd 173: if (*line == '-') {
1.3 cgd 174: (void)printf("minus%s", lflag ? " " : "\n");
1.1 cgd 175: ++line;
176: }
1.3 cgd 177:
178: rval = len > 0 ? unit(len, line) : 0;
179: if (fraction != NULL && flen != 0)
180: for (p = fraction; *p != '\0'; ++p)
181: if (*p != '0') {
182: if (rval)
183: (void)printf("%sand%s",
184: lflag ? " " : "",
185: lflag ? " " : "\n");
186: if (unit(flen, fraction)) {
187: if (lflag)
188: (void)printf(" ");
189: pfract(flen);
190: rval = 1;
1.1 cgd 191: }
192: break;
193: }
1.3 cgd 194: if (!rval)
195: (void)printf("zero%s", lflag ? "" : ".\n");
196: if (lflag)
197: (void)printf("\n");
1.1 cgd 198: }
199:
1.3 cgd 200: int
201: unit(len, p)
1.5 ! lukem 202: int len;
! 203: char *p;
1.1 cgd 204: {
1.5 ! lukem 205: int off, rval;
1.1 cgd 206:
1.3 cgd 207: rval = 0;
1.1 cgd 208: if (len > 3) {
209: if (len % 3) {
210: off = len % 3;
211: len -= off;
1.3 cgd 212: if (number(p, off)) {
213: rval = 1;
214: (void)printf(" %s%s",
215: name3[len / 3], lflag ? " " : ".\n");
1.1 cgd 216: }
1.3 cgd 217: p += off;
1.1 cgd 218: }
1.3 cgd 219: for (; len > 3; p += 3) {
1.1 cgd 220: len -= 3;
1.3 cgd 221: if (number(p, 3)) {
222: rval = 1;
223: (void)printf(" %s%s",
224: name3[len / 3], lflag ? " " : ".\n");
1.1 cgd 225: }
226: }
227: }
1.3 cgd 228: if (number(p, len)) {
229: if (!lflag)
230: (void)printf(".\n");
231: rval = 1;
1.1 cgd 232: }
1.3 cgd 233: return (rval);
1.1 cgd 234: }
235:
1.3 cgd 236: int
237: number(p, len)
1.5 ! lukem 238: char *p;
1.3 cgd 239: int len;
1.1 cgd 240: {
1.5 ! lukem 241: int val, rval;
1.1 cgd 242:
1.3 cgd 243: rval = 0;
244: switch (len) {
1.1 cgd 245: case 3:
1.3 cgd 246: if (*p != '0') {
247: rval = 1;
248: (void)printf("%s hundred", name1[*p - '0']);
1.1 cgd 249: }
1.3 cgd 250: ++p;
251: /* FALLTHROUGH */
1.1 cgd 252: case 2:
1.3 cgd 253: val = (p[1] - '0') + (p[0] - '0') * 10;
1.1 cgd 254: if (val) {
1.3 cgd 255: if (rval)
256: (void)printf(" ");
1.1 cgd 257: if (val < 20)
1.3 cgd 258: (void)printf("%s", name1[val]);
1.1 cgd 259: else {
1.3 cgd 260: (void)printf("%s", name2[val / 10]);
1.1 cgd 261: if (val % 10)
1.3 cgd 262: (void)printf("-%s", name1[val % 10]);
1.1 cgd 263: }
1.3 cgd 264: rval = 1;
1.1 cgd 265: }
266: break;
267: case 1:
1.3 cgd 268: if (*p != '0') {
269: rval = 1;
270: (void)printf("%s", name1[*p - '0']);
1.1 cgd 271: }
272: }
1.3 cgd 273: return (rval);
1.1 cgd 274: }
275:
1.3 cgd 276: void
1.1 cgd 277: pfract(len)
1.3 cgd 278: int len;
1.1 cgd 279: {
1.3 cgd 280: static char *pref[] = { "", "ten-", "hundred-" };
1.1 cgd 281:
282: switch(len) {
283: case 1:
1.3 cgd 284: (void)printf("tenths.\n");
1.1 cgd 285: break;
286: case 2:
1.3 cgd 287: (void)printf("hundredths.\n");
1.1 cgd 288: break;
289: default:
1.3 cgd 290: (void)printf("%s%sths.\n", pref[len % 3], name3[len / 3]);
291: break;
1.1 cgd 292: }
293: }
294:
1.3 cgd 295: void
296: usage()
1.1 cgd 297: {
1.3 cgd 298: (void)fprintf(stderr, "usage: number [# ...]\n");
299: exit(1);
1.1 cgd 300: }
CVSweb <webmaster@jp.NetBSD.org>