home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / utils.zip / add.c next >
C/C++ Source or Header  |  2002-05-05  |  6KB  |  258 lines

  1. /* Adding machine */
  2.  
  3. /*
  4.   Author:
  5.    Frank da Cruz, Columbia University, August 1988
  6.    fdc@columbia.edu
  7.    Please send any changes back to the author.
  8.  
  9.   To build
  10.    make "CFLAGS=xxx" add
  11.    where xxx is:
  12.      POSIX for POSIX (tcsetattr())
  13.      ATTSV for AT&T System V (ioctl())
  14.    if CFLAGS omitted, BSD is used (stty())
  15.  
  16.   Copyright (C) 1988-2002,
  17.   Trustees of Columbia University in the City of New York.
  18. */
  19. #include <stdio.h>
  20. #include <ctype.h>
  21.  
  22. #ifdef POSIX
  23. #include <termios.h>
  24. static struct termios ccold, ccraw;
  25. #else
  26. #ifdef ATTSV
  27. #include <termio.h>
  28. static struct termio ccold, ccraw;
  29. #else
  30. #include <sgtty.h>
  31. static struct sgttyb ccold, ccraw;
  32. #endif /* ATTSV */
  33. #endif /* POSIX */
  34.  
  35. float a, s;
  36. int i, k, n, tt, in_num, got_num, in_comment;
  37. char buf[100], c;
  38. char sav[100] = { '\0' };
  39. char comment[100], *cp;
  40. char *hlp[] = {
  41. " ",
  42. "Adding machine.  Type numbers to be added, may include decimal point.",
  43. "Enter number with carriage return.  You can edit numbers with Delete",
  44. "or Ctrl-U.  You can also enter the following single-character commands,",
  45. "which act immediately (no CR):",
  46. " ",
  47. " q - quit (and print, total if any)",
  48. " c - clear",
  49. " r - repeat previous entry",
  50. " s - print subtotal (don't clear total)",
  51. " a - print average (don't clear)",
  52. " t - print total (and clear)",
  53. " ",
  54. "And, if you have a column of numbers in a file, you can 'add < filename'.",
  55. ""
  56. };
  57.  
  58. xx(c) char c; {
  59.     *cp++ = c;
  60.     if (tt) putchar(c);
  61. }
  62.  
  63. main () {
  64.  
  65.     tt = isatty(0);            /* Input from real terminal? */
  66.  
  67.     if (tt) { /* If real terminal put in rawmode for no echo */
  68. #ifdef POSIX                /* The POSIX way... */
  69.         tcgetattr(0,&ccold);
  70.     ccraw = ccold;
  71.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  72.         tcsetattr(0,TCSADRAIN,&ccraw);
  73. #else
  74. #ifdef ATTSV
  75.         tcgetattr(0,&cold);        /* The System V way... */
  76.     ccraw = ccold;
  77.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  78.     ioctl(0,TCSATAW,&ccraw);
  79. #else
  80.     gtty(0,&ccold);            /* The V7 / BSD way... */
  81.     ccraw = ccold;
  82.     ccraw.sg_flags |= (RAW);
  83.     ccraw.sg_flags &= ~(ECHO|CRMOD);
  84.     stty(0,&ccraw);
  85. #endif /* ATTSV */
  86. #endif /* POSIX */
  87.     fprintf(stderr,"add...\r\n? for help\r\n"); /* Greet */
  88.     }
  89.     i = 0;                /* i is number buffer pointer */
  90.     in_comment = 0;            /* in comment */
  91.     in_num = 0;                /* in number */
  92.     got_num = 0;            /* got number */
  93.     cp = comment;            /* comment buffer */
  94.     *cp = '\0';                /* zero it */
  95.     while (1) {
  96.     c = getchar();            /* Get a char */
  97.     if (c == EOF) doexit(0);
  98.     c &= 0177;
  99.     switch (c) {
  100.       case '?':            /* Give help */
  101.         if (in_comment) xx(c);
  102.         else if (tt) {
  103.         for ( k = 0; *hlp[k] ; k++ )
  104.           fprintf(stderr, "%s\r\n", hlp[k]);
  105.         fprintf(stderr,"%s",buf);
  106.         }
  107.         break;
  108.           case 'a':            /* Average */
  109.           case 'A':
  110.         if (in_comment) xx(c);
  111.         else if (in_num == 1) {
  112.         fprintf(stderr,"\07");
  113.         break;
  114.         }
  115.             else if (n == 0) fprintf(stderr,"(nothing to average)\r\n");
  116.         else
  117.           fprintf(stderr,"%10.2f = average (for %d)\r\n",(s / (float)n),n);
  118.         break;
  119.       case 'c':            /* Clear */
  120.       case 'C':
  121.         if (in_comment) xx(c);
  122.         else if (in_num == 1) {
  123.         fprintf(stderr,"\07");
  124.         break;
  125.         } else {
  126.         s = 0.0;
  127.         n = 0;
  128.         fprintf(stderr,"    (clear)\r\n");
  129.         }
  130.         sav[0] = '\0';
  131.         break;
  132.       case 't':            /* Total & clear */
  133.       case 'T':
  134.         if (in_comment) xx(c);
  135.         else if (in_num == 1) {
  136.         fprintf(stderr,"\07");
  137.         break;
  138.         } else {
  139.         fprintf(stderr,"%10.2f = total (for %d)\r\n",s,n);
  140.         fprintf(stderr,"    (clear)\r\n");
  141.         s = 0.0, n = 0;
  142.         }
  143.         sav[0] = '\0';
  144.         break;
  145.       case 's':            /* Subtotal */
  146.       case 'S':
  147.         if (in_comment) xx(c);
  148.         else if (in_num == 1) {
  149.         fprintf(stderr,"\07");
  150.         break;
  151.         } else fprintf(stderr,"%10.2f = subtotal (for %d)\r\n",s,n);
  152.         break;
  153.       case 'r':            /* Re-enter previous number */
  154.       case 'R':
  155.         if (in_comment) xx(c);
  156.         else if (in_num == 1) {
  157.         fprintf(stderr,"\07");
  158.         break;
  159.         }
  160.         strcpy(buf,sav);
  161.         printf(buf);
  162.         i = strlen(buf);
  163.         sav[0] = '\0';
  164.         break;
  165.       case 'q':            /* Quit */
  166.       case 'Q':
  167.         if (in_comment) {
  168.         xx(c);
  169.         } else if (in_num == 1) {
  170.         fprintf(stderr,"\07");
  171.         break;
  172.         } else doexit(0);
  173.         break;
  174.           case 127:            /* Delete, backspace */
  175.           case '\010':            /* Erase prev character */
  176.         if (i > 0) {
  177.         i--;
  178.         fprintf(stderr,"\010 \010");
  179.         }
  180.         else fprintf(stderr,"\07");
  181.         break;
  182.           case '\025':            /* Ctrl-U or Ctrl-W */
  183.           case '\027':            /* Erase current number */
  184.             i = 0;
  185.         buf[0] = '\0';
  186.         fprintf(stderr,"\r                \r");
  187.             break;
  188.           case '\r':            /* Enter the number */
  189.           case '\n':
  190.         buf[i] = '\0';
  191.         if (tt) fprintf(stderr,"\r                \r");
  192.         if ((sscanf(buf, "%f", &a) != 1) && (i > 0)) {
  193.           fprintf(stderr,"%s - bad number\r\n",buf);
  194.         } else if (i > 0) {
  195.           s += a, n++;
  196.           if (tt) fprintf(stderr,"%10.2f %s\r\n",a,comment);
  197.           sprintf(sav,"%10.2f",a);
  198.           a = 0;
  199.         }
  200.         i = 0;
  201.         in_num = 0;
  202.         got_num = 0;
  203.         buf[0] = '\0';
  204.         in_comment = 0;
  205.         cp = comment;
  206.         *cp = '\0';
  207.         break;
  208.       case ' ':                /* Blanks */
  209.         if (in_num) {
  210.         in_num = 0;
  211.         got_num = 1;
  212.         in_comment = 1;
  213.         xx(c);
  214.         } else if (in_comment) xx(c);
  215.         break;
  216.       case '0':                /* A digit, or period, or minus */
  217.       case '1':
  218.       case '2':
  219.       case '3':
  220.       case '4':
  221.       case '5':
  222.       case '6':
  223.       case '7':
  224.       case '8':
  225.       case '9':
  226.       case '.':
  227.       case '-':
  228.     if (in_comment) xx(c);
  229.     else {
  230.         in_num = 1;
  231.         if (tt) fputc(c,stderr);
  232.         buf[i++] = c;
  233.     }
  234.     break;
  235.       default:                /* Beep on anything else */
  236.     if (in_comment) xx(c);
  237.     else fprintf(stderr,"\07");
  238.     break;
  239.         }
  240.     }
  241. }
  242.  
  243. doexit(p) int p; {            /* Restore tty on exit */
  244.     if (s != 0.0)
  245.       fprintf(stderr,"%10.2f = total (for %d)\r\n",s,n);
  246.     if (tt)
  247. #ifdef POSIX
  248.       tcsetattr(0,TCSADRAIN,&ccold);
  249. #else
  250. #ifdef ATTSV
  251.     ioctl(0,TCSETAW,&ccold);
  252. #else
  253.       stty(0,&ccold);
  254. #endif /* ATTSV */
  255. #endif /* POSIX */
  256.     exit(p);
  257. }
  258.