"Fossies" - the Fresh Open Source Software Archive

Member "schily-2021-09-18/calc/calc.c" (20 Aug 2021, 9659 Bytes) of package /linux/privat/schily-2021-09-18.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* @(#)calc.c   1.27 21/08/20 Copyright 1985-2021 J. Schilling */
    2 #include <schily/mconfig.h>
    3 #ifndef lint
    4 static  UConst char sccsid[] =
    5     "@(#)calc.c 1.27 21/08/20 Copyright 1985-2021 J. Schilling";
    6 #endif
    7 /*
    8  *  Simples Taschenrechnerprogramm
    9  *
   10  *  Copyright (c) 1985-2021 J. Schilling
   11  */
   12 /*
   13  * The contents of this file are subject to the terms of the
   14  * Common Development and Distribution License, Version 1.0 only
   15  * (the "License").  You may not use this file except in compliance
   16  * with the License.
   17  *
   18  * See the file CDDL.Schily.txt in this distribution for details.
   19  * A copy of the CDDL is also available via the Internet at
   20  * http://www.opensource.org/licenses/cddl1.txt
   21  *
   22  * When distributing Covered Code, include this CDDL HEADER in each
   23  * file and include the License file CDDL.Schily.txt from this distribution.
   24  */
   25 
   26 #include <schily/stdio.h>
   27 #include <schily/stdlib.h>
   28 #include <schily/utypes.h>
   29 #include <schily/standard.h>
   30 #define GT_COMERR       /* #define comerr gtcomerr */
   31 #define GT_ERROR        /* #define error gterror   */
   32 #include <schily/schily.h>
   33 #ifdef  FERR_DEBUG
   34 #include <schily/termios.h>
   35 #endif
   36 #include <schily/nlsdefs.h>
   37 
   38 #define LLEN    100
   39 
   40 #define LSHIFT  1000
   41 #define RSHIFT  1001
   42 
   43 LOCAL   void    usage   __PR((int));
   44 EXPORT  int main    __PR((int, char **));
   45 LOCAL   void    prdig   __PR((int));
   46 LOCAL   void    prlldig __PR((Llong));
   47 LOCAL   void    kommentar __PR((void));
   48 LOCAL   int xbreakline __PR((char *, char *, char **, int));
   49 
   50 LOCAL void
   51 usage(exitcode)
   52     int exitcode;
   53 {
   54     error("Usage: calc [options]\n");
   55     error("Options:\n");
   56     error(" -help   Print this help.\n");
   57     error(" -version Print version number.\n");
   58     kommentar();
   59     exit(exitcode);
   60     /* NOTREACHED */
   61 }
   62 
   63 EXPORT int
   64 main(ac, av)
   65     int ac;
   66     char    **av;
   67 {
   68     int cac;
   69     char    * const* cav;
   70     BOOL    help = FALSE;
   71     BOOL    prversion = FALSE;
   72     char    eingabe[LLEN+1];
   73     char    *argumente[8];
   74     int i;
   75     int op = 0;
   76     char    *opstr;
   77     Llong   arg1;
   78     Llong   arg2;
   79     Llong   ergebnis;
   80     Llong   rest = (Llong)0;
   81     int iarg1;
   82     int iarg2;
   83     int iergebnis;
   84     int irest = 0;
   85 
   86     save_args(ac, av);
   87 
   88     (void) setlocale(LC_ALL, "");
   89 
   90 #ifdef  USE_NLS
   91 #if !defined(TEXT_DOMAIN)   /* Should be defined by cc -D */
   92 #define TEXT_DOMAIN "calc"  /* Use this only if it weren't */
   93 #endif
   94     { char  *dir;
   95     dir = searchfileinpath("share/locale", F_OK,
   96                     SIP_ANY_FILE|SIP_NO_PATH, NULL);
   97     if (dir)
   98         (void) bindtextdomain(TEXT_DOMAIN, dir);
   99     else
  100 #if defined(PROTOTYPES) && defined(INS_BASE)
  101     (void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
  102 #else
  103     (void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
  104 #endif
  105     (void) textdomain(TEXT_DOMAIN);
  106     }
  107 #endif  /* USE_NLS */
  108 
  109     cac = --ac;
  110     cav = ++av;
  111     if (getallargs(&cac, &cav, "help,version", &help, &prversion) < 0) {
  112         errmsgno(EX_BAD, "Bad Option %s.\n", cav[0]);
  113         usage(EX_BAD);
  114     }
  115     if (help)
  116         usage(0);
  117     if (prversion) {
  118         gtprintf("Calc release %s %s (%s-%s-%s) Copyright (C) 1985, 89-91, 1996, 2000-2021 %s\n",
  119                 "1.27", "2021/08/20",
  120                 HOST_CPU, HOST_VENDOR, HOST_OS,
  121                 _("Jörg Schilling"));
  122         exit(0);
  123     }
  124 
  125     putchar('?'); flush();
  126     while (getline(eingabe, LLEN) >= 0 && !streql(eingabe, "quit")) {
  127 
  128         opstr = eingabe;
  129         while (*opstr == ' ' || *opstr == '\t')
  130             opstr++;
  131 
  132         /*
  133          * optional Kommentarausgabe
  134          */
  135         if (streql(opstr, "help")) {
  136             kommentar();
  137             putchar('?'); flush();
  138             continue;
  139         }
  140 
  141         /*
  142          * Test des Formats und der Argumente
  143          */
  144         i = xbreakline(opstr, " \t", argumente, 5);
  145         if (*argumente[i-1] == '\0')
  146             i--;
  147         switch (i) {
  148 
  149         case 1:
  150             if (*astoll(argumente[0], &ergebnis) != '\0') {
  151                 gtprintf("'%s' ist keine Zahl!\n?", argumente[0]);
  152                 continue;
  153             }
  154             iergebnis   = (int)ergebnis;
  155             goto print;
  156         case 2:
  157             op = *argumente[0];
  158             if (op != '!' && op != '~') {
  159                 gtprintf("Unzulässiger Operator für: ");
  160                 gtprintf("'op argument1'\n?");
  161                 continue;
  162             }
  163             if (*astoll(argumente[1], &arg1) != '\0') {
  164                 gtprintf("'%s' ist keine Zahl!\n?", argumente[1]);
  165                 continue;
  166             }
  167             break;
  168         case 3:
  169             if (*astoll(argumente[0], &arg1) != '\0') {
  170                 gtprintf("'%s' ist keine Zahl!\n?", argumente[0]);
  171                 continue;
  172             }
  173             if (*astoll(argumente[2], &arg2) != '\0') {
  174                 gtprintf("'%s' ist keine Zahl!\n?", argumente[2]);
  175                 continue;
  176             }
  177             break;
  178 
  179         default:
  180             gtprintf("Die Eingabe hat nicht das richtige Format: ");
  181             gtprintf("'argument1 op argument2'\n?");
  182             continue;
  183         }
  184 
  185         /*
  186          * Test der Operationssymbole
  187          */
  188         op = 0;
  189         opstr = argumente[1];
  190         if (i == 2)
  191             opstr = argumente[0];
  192 
  193         if (streql(opstr, "<<")) {
  194             op = LSHIFT;
  195         } else if (streql(opstr, ">>")) {
  196             op = RSHIFT;
  197         } else if (opstr[1] != '\0') {
  198             gtprintf("Operationssymbole sind einstellig. Falsche Eingabe!\n?");
  199             continue;
  200         } else if (!op) {
  201             op = *opstr;
  202         }
  203 
  204         i = 0;
  205         iergebnis   = (int)ergebnis;
  206         iarg1       = (int)arg1;
  207         iarg2       = (int)arg2;
  208 
  209         switch (op) {
  210 
  211         case '+':
  212             ergebnis = arg1 + arg2;
  213             iergebnis = iarg1 + iarg2;
  214             break;
  215         case '-':
  216             ergebnis = arg1 - arg2;
  217             iergebnis = iarg1 - iarg2;
  218             break;
  219         case '*':
  220             ergebnis = arg1 * arg2;
  221             iergebnis = iarg1 * iarg2;
  222             break;
  223         case LSHIFT:
  224             ergebnis = (Ullong)arg1 << arg2;
  225             iergebnis = (unsigned)iarg1 << iarg2;
  226             break;
  227         case RSHIFT:
  228             ergebnis = (Ullong)arg1 >> arg2;
  229             iergebnis = (unsigned)iarg1 >> iarg2;
  230             break;
  231         case '^':
  232             ergebnis = arg1 ^ arg2;
  233             iergebnis = iarg1 ^ iarg2;
  234             break;
  235         case '&':
  236             ergebnis = arg1 & arg2;
  237             iergebnis = iarg1 & iarg2;
  238             break;
  239         case '|':
  240             ergebnis = arg1 | arg2;
  241             iergebnis = iarg1 | iarg2;
  242             break;
  243         case '!':
  244             ergebnis = !arg1;
  245             iergebnis = !iarg1;
  246             break;
  247         case '~':
  248             ergebnis = ~arg1;
  249             iergebnis = ~iarg1;
  250             break;
  251         case '%':
  252         case '/': if (arg2 == 0) {
  253                 gtprintf("Division durch Null ist unzulaessig.\n?");
  254                 i = 1;
  255                 break;
  256             } else {
  257                 /*
  258                  * 9223372036854775808 /  322122547200
  259                  * liefert eine Integer(32) Division durch 0
  260                  */
  261                 ergebnis = arg1 / arg2;
  262                 rest = arg1 % arg2;
  263                 if (iarg2 == 0) {
  264                     /*
  265                      * Alle unteren 32 Bit sind 0
  266                      * Division durch Null verhindern.
  267                      */
  268                     iergebnis = irest = 0;
  269                 } else {
  270                     iergebnis = iarg1 / iarg2;
  271                     irest = iarg1 % iarg2;
  272                 }
  273 
  274                 if (op == '%') {
  275                     ergebnis = rest;
  276                     iergebnis = irest;
  277                 }
  278                 break;
  279             }
  280 
  281         default:
  282             gtprintf("Unzulaessiger Operator!\n?");
  283             i = 1;
  284             break;
  285         }
  286         if (i == 1)
  287             continue;
  288 
  289 print:
  290         /*
  291          * Ausgabe
  292          */
  293         prdig(iergebnis);
  294         if (op == '/') {
  295             gtprintf("\nRest (dezimal): %d\n", irest);
  296             prdig(irest);
  297         }
  298         putchar('\n');
  299 
  300         prlldig(ergebnis);
  301         if (op == '/') {
  302             gtprintf("\nRest (dezimal): %lld\n", rest);
  303             prlldig(rest);
  304         }
  305         putchar('\n');
  306 
  307         putchar('?'); flush();
  308     }
  309     if (ferror(stdin)) {
  310 #ifdef  FERR_DEBUG
  311         pid_t   pgrp;
  312         ioctl(STDIN_FILENO, TIOCGPGRP, (char *)&pgrp);
  313         errmsg("Read error on stdin. pid %ld pgrp %ld tty pgrp %ld\n",
  314             (long)getpid(), (long)getpgid(0), (long)pgrp);
  315 #else
  316         errmsg("Read error on stdin.\n");
  317 #endif
  318     }
  319     return (0);
  320 }
  321 
  322 LOCAL void
  323 prdig(n)
  324     int n;
  325 {
  326     register int    i;
  327 
  328     printf(" = %d   %u   0%o   0x%x\n = ", n, n, n, n);
  329     if (n < 0)
  330         putchar('1');
  331     else
  332         putchar('0');
  333     for (i = 1; i <= 31; i++) {
  334         /*
  335          * New compilers like to make left shifting signed vars illegal
  336          */
  337         n = (int)(((unsigned int)n) << 1);
  338         if (n < 0)
  339             putchar('1');
  340         else
  341             putchar('0');
  342         if (i%4 == 3)
  343             putchar(' ');
  344     }
  345 }
  346 
  347 LOCAL void
  348 prlldig(n)
  349     Llong   n;
  350 {
  351     register int    i;
  352 
  353     printf(" = %lld   %llu   0%llo   0x%llx\n = ", n, n, n, n);
  354     if (n < 0)
  355         putchar('1');
  356     else
  357         putchar('0');
  358     for (i = 1; i <= 63; i++) {
  359         /*
  360          * New compilers like to make left shifting signed vars illegal
  361          */
  362         n = (Llong)(((ULlong)n) << 1);
  363         if (n < 0)
  364             putchar('1');
  365         else
  366             putchar('0');
  367         if (i%4 == 3)
  368             putchar(' ');
  369     }
  370 }
  371 
  372 LOCAL void
  373 kommentar()
  374 {
  375     error("                    Taschenrechnerprogramm\n");
  376     error("                    ======================\n");
  377     error("Das Programm wird verlassen durch die Eingabe: 'QUIT'\n");
  378     error("Es kann jeweils eine binäre Operation aus {+,-,*,/,%%,<<,>>,^,&,|}\n");
  379     error("oder eine unäre Operation aus {~,!} ausgeführt werden. Eine einzelne\n");
  380     error("Zahl wird wie eine unäre Operation behandelt. Als Eingabe sind nur\n");
  381     error("integer-Werte zugelassen, aber es ist egal, ob sie dezimal, oktal\n");
  382     error("oder hexadezimal kodiert sind; auch verschiedene Kodierungen in einer\n");
  383     error("Rechnung sind zulässig. Die Ausgabe erfolgt dezimal, oktal,\n");
  384     error("hexadezimal und binär in zwei Darstellungen: 32 Bit sowie 64 Bit.\n");
  385     error("'/' liefert zusätzlich den Rest (dezimal) bei ganzzahliger Division.\n");
  386     error("\n");
  387     error("***************************************************************\n");
  388     error("* Die Eingabe muss folgendes Format haben:                    *\n");
  389     error("*          'argument1 op argument2'  oder                     *\n");
  390     error("*          'op argument'             oder                     *\n");
  391     error("*          'argument'                                         *\n");
  392     error("***************************************************************\n");
  393 }
  394 
  395 /*--------------------------------------------------------------------------*/
  396 #include <schily/string.h>
  397 
  398 LOCAL int
  399 xbreakline(buf, delim, array, len)
  400         char    *buf;
  401     register char   *delim;
  402     register char   *array[];
  403     register int    len;
  404 {
  405     register char   *bp = buf;
  406     register char   *dp;
  407     register int    i;
  408     register int    found;
  409 
  410     for (i = 0, found = 1; i < len; i++) {
  411         for (dp = bp; *dp != '\0' && strchr(delim, *dp) == NULL; dp++)
  412             ;
  413 
  414         array[i] = bp;
  415         if (*dp != '\0' && strchr(delim, *dp) != NULL) {
  416             *dp++ = '\0';
  417             found++;
  418         }
  419         while (*dp != '\0' && strchr(delim, *dp) != NULL)
  420             dp++;
  421         bp = dp;
  422     }
  423     if (found > len)
  424         found = len;
  425     return (found);
  426 }