"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. For more information about "calc.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes reports: 2021-08-14_vs_2021-09-18 or 2021-07-29_vs_2021-09-18.

    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 }