(linenum→info "unix/slp.c:2238")

bsd-games/2.17/number/number.c

    1: /*      $NetBSD: number.c,v 1.10 2004/11/05 21:30:32 dsl Exp $       */
    2: 
    3: /*
    4:  * Copyright (c) 1988, 1993, 1994
    5:  *      The Regents of the University of California.  All rights reserved.
    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. Neither the name of the University nor the names of its contributors
   16:  *    may be used to endorse or promote products derived from this software
   17:  *    without specific prior written permission.
   18:  *
   19:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29:  * SUCH DAMAGE.
   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 /* not lint */
   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 /* not lint */
   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              /* Biggest number we handle. */
   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:         /* Revoke setgid privileges */
   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:                         /* FALLTHROUGH */
  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:                 /* FALLTHROUGH */
  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: }
Syntax (Markdown)