home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / RECIO110.ZIP / TESTCH.C < prev    next >
C/C++ Source or Header  |  1994-03-28  |  10KB  |  304 lines

  1. /* testch.c - tests int, double, char and string char delimited functions */
  2. /* recio version 1.10, release March 28, 1994 */
  3. /* Copyright (C) 1994 William Pierpoint */
  4.  
  5. #include <ctype.h>
  6. #include <errno.h>
  7. #include <limits.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11.  
  12. #include "recio.h"
  13.  
  14. /* errors normally to stderr; but for test, stdout */
  15. #define errout  stdout
  16.  
  17. /* clip value v between lower l and upper u bounds */
  18. #define range(l, v, u)  (min(max((l),(v)),(u)))
  19.  
  20. /****************************************************************************
  21. Dynamic string copy function, kludged for use with recio.  This 
  22. function is not part of recio nor was rseterr() designed to work 
  23. with it, but you get the idea. 
  24. Obligation: free dst when finished with it.
  25. *****************************************************************************/
  26. char *                  /* return dst                                       */
  27.     scopys(             /* copy string dynamically                          */
  28.         char *dst,      /* destination string pointer                       */
  29.         char *src)      /* source string pointer                            */
  30. /****************************************************************************/
  31. {                       
  32.   size_t dlen;          /* strlen of dst */
  33.   size_t slen;          /* strlen of src */
  34.   int errnum;           /* error number */
  35.  
  36.   /* if null src pointer */
  37.   if (!src) {
  38.     rseterr(NULL, EINVAL);
  39.     dst = NULL;
  40.     goto done;
  41.   }
  42.   
  43.   if (dst) {
  44.     dlen = strlen(dst);
  45.     slen = strlen(src);
  46.     if (dlen < slen) {
  47.       do {
  48.         dst = (char *) realloc(dst, slen+1);
  49.         if (!dst) {
  50.           errnum = rseterr(NULL, ENOMEM);
  51.           if (errnum) goto done;
  52.         }
  53.       } while (!dst);
  54.     }
  55.     strcpy(dst, src);
  56.   } else {
  57.      do {
  58.        dst = strdup(src);
  59.        if (!dst) {
  60.          errnum = rseterr(NULL, ENOMEM);
  61.          if (errnum) goto done;
  62.        }
  63.      } while (!dst);
  64.    }
  65. done:
  66.   return dst;
  67. }
  68.  
  69. /****************************************************************************/
  70. void                         /* returns nothing                             */
  71.     rdaterrmsg(              /* print data error message                    */
  72.         REC *rp,             /* record pointer                              */
  73.         int errnum)          /* error number                                */
  74. /****************************************************************************/
  75. {
  76.   switch (errnum) {
  77.   case R_ERANGE:   /* data out of range */
  78.     fprintf(errout, "DATA ERROR reading %s at record %lu and field %d: "
  79.      "data value out of range\n", rnames(rp), rrecno(rp), rfldno(rp));
  80.     break;
  81.   case R_EINVDAT:  /* invalid data */
  82.     fprintf(errout, "DATA ERROR reading %s at record %lu and field %d: "
  83.      "invalid data\n", rnames(rp), rrecno(rp), rfldno(rp));
  84.     break;
  85.   case R_EMISDAT:  /* missing data */
  86.     fprintf(errout, "DATA ERROR reading %s at record %lu and field %d: "
  87.      "data missing\n", rnames(rp), rrecno(rp), rfldno(rp));
  88.     break;
  89.   }
  90. }
  91.  
  92. /****************************************************************************/
  93. void                         /* returns nothing                             */
  94.     rerrfn(                  /* recio callback error function               */
  95.         REC *rp)             /* record pointer                              */
  96. /****************************************************************************/
  97. {
  98.   int errnum;       /* error number */
  99.   char strbuf[33];  /* string buffer for ltoa and sprintf */
  100.  
  101.   if (risvalid(rp)) {
  102.   
  103.     /* reof flag set */
  104.     if (reof(rp)) { 
  105.       fprintf(errout, "ERROR reading %s: "
  106.        "tried to read past end of file\n", rnames(rp));
  107.     
  108.     /* rerror flag set */
  109.     } else {
  110.  
  111.       /* determine cause of error */
  112.       errnum = rerror(rp);
  113.       switch (errnum) {
  114.  
  115.       /* data errors */
  116.       case R_ERANGE:   /* data out of range */
  117.       case R_EINVDAT:  /* invalid data */
  118.       case R_EMISDAT:  /* missing data */
  119.         rdaterrmsg(rp, errnum);
  120.           
  121.         /* determine context */
  122.         switch (rcxtno(rp)) {
  123.         case RECIN:
  124.           
  125.           /* determine field */
  126.           switch (rfldno(rp)) {
  127.           case 1:  /* the integer field */
  128.             switch (errnum) {
  129.             case R_EMISDAT:
  130.               fprintf(errout, "...substituting zero\n");
  131.               rsetfldstr(rp, "0");
  132.               break;
  133.             case R_EINVDAT:
  134.             case R_ERANGE:
  135.               fprintf(errout, "...substituting best guess\n");
  136.               rsetfldstr(rp, ltoa(
  137.                (int) range(INT_MIN, strtol(rflds(rp), NULL, 10), INT_MAX), 
  138.                strbuf, 10));
  139.               break;
  140.             }
  141.             break;
  142.           
  143.           case 2:  /* the double field */
  144.             switch (errnum) {
  145.             case R_EMISDAT:
  146.               fprintf(errout, "...substituting zero\n");
  147.               rsetfldstr(rp, "0");
  148.               break;
  149.             case R_EINVDAT:
  150.             case R_ERANGE:
  151.               fprintf(errout, "...substituting best guess\n");
  152.               sprintf(strbuf, "%g", strtod(rflds(rp), NULL));
  153.               rsetfldstr(rp, strbuf);
  154.               break;
  155.             }
  156.             break;
  157.           
  158.           case 3: /* the character field */
  159.             switch (errnum) {
  160.             case R_EMISDAT:
  161.               fprintf(errout, "...substituting the letter N\n");
  162.               rsetfldstr(rp, "N");
  163.               break;
  164.             case R_EINVDAT:
  165.               fprintf(errout, "...substituting best guess\n");
  166.               strbuf[0] = strtoc(rflds(rp), NULL);
  167.               strbuf[1] = '\0';
  168.               rsetfldstr(rp, strbuf);
  169.               break;
  170.             }
  171.             break;
  172.  
  173.           case 4: /* the string field */
  174.             switch (errnum) {
  175.             case R_EMISDAT:
  176.               fprintf(errout, "...substituting empty field\n");
  177.               rsetfldstr(rp, "");
  178.               break;
  179.             }
  180.             break;
  181.  
  182.           default: /* all other fields */
  183.             break;
  184.           }
  185.           break;
  186.         
  187.         default:  /* programming error - missing context number */
  188.           fprintf (errout, "FATAL ERROR in %s: missing context number\n", 
  189.            rnames(rp));
  190.           abort();
  191.           break;
  192.         }
  193.         break;
  194.         
  195.       /* non-fatal errors */
  196.       case R_ENOREG:
  197.         fprintf(errout, "WARNING: function atexit failed\n");
  198.         rclearerr(rp);
  199.         break;
  200.  
  201.       /* fatal errors (R_EINVAL, R_ENOMEM) */
  202.       case R_EINVAL:
  203.         fprintf(errout, "FATAL ERROR reading FILE %s: invalid argument", 
  204.          rnames(rp));
  205.         abort();
  206.         break;
  207.       case R_ENOMEM:
  208.         fprintf(errout, "FATAL ERROR reading FILE %s: out of memory", 
  209.          rnames(rp));
  210.         abort();
  211.         break;
  212.       default:
  213.         fprintf(errout, "FATAL ERROR reading FILE %s: unknown error", 
  214.          rnames(rp));
  215.         abort();
  216.         break;
  217.       }
  218.     }
  219.   
  220.   /* invalid record pointer */
  221.   } else {
  222.     switch (errno) {
  223.  
  224.     /* non-fatal errors */
  225.     case EACCES:
  226.     case EMFILE:
  227.       fprintf(errout, "WARNING: %s\n", strerror(errno));
  228.       break;
  229.  
  230.     /* fatal errors (EINVAL, ENOMEM) */
  231.     default:
  232.       fprintf(errout, "FATAL ERROR: %s\n", strerror(errno));
  233.       abort();
  234.       break;
  235.     }
  236.     errno = 0;
  237.   }
  238. }
  239.  
  240. /****************************************************************************
  241. main
  242. *****************************************************************************/
  243. #include <io.h>
  244.  
  245. int main()
  246. {
  247.   int fldint;                   /* integer field */
  248.   double flddbl;                /* double field */
  249.   int fldch;                    /* character field */
  250.   char *fldstr = NULL;          /* string field */
  251.   int hstdin = fileno(stdin);   /* handle to stdin */
  252.   
  253.   /* install error function */
  254.   rseterrfn(rerrfn);
  255.   
  256.   /* set field and text delimiters */
  257.   rsetfldch(recin, ',');
  258.   rsettxtch(recin, '"');
  259.   
  260.   /* if input not redirected */
  261.   if (isatty(hstdin)) {
  262.     /* print instructions */
  263.     puts("RECIO v 1.10 TESTCH Copyright (C) 1994 William Pierpoint");
  264.     puts("Tests integer, double, character, and string character "
  265.      "delimited functions.");
  266.     puts("It reads four fields, separated by commas, from the console.");
  267.     puts("Example:");
  268.     puts("   1, 3.14 ,  Y, \"Hello, World!\"\n");
  269.     puts("Press Ctrl-Z followed by the Enter key to exit program.");
  270.     puts("You may begin now.\n");
  271.   }
  272.   
  273.   /* loop through input */
  274.   while (rgetrec(recin)) {
  275.  
  276.     /* if input redirected, echo record contents */
  277.     if (!isatty(hstdin)) puts(rrecs(recin));
  278.  
  279.     /* parse record */
  280.     fldint = rgeti(recin);
  281.     flddbl = rgetd(recin);
  282.     fldch  = rgetc(recin);
  283.     fldstr = scopys(fldstr, rgets(recin));
  284.     
  285.     /* print results */
  286.     printf("\n");
  287.     printf("  Integer field: %d\n", fldint);
  288.     printf("   Double field: %g\n", flddbl);
  289.     printf("Character field: %c\n", fldch);
  290.     printf("   String field: %s\n\n", fldstr);
  291.   }
  292.   
  293.   /* free string fields */
  294.   free (fldstr);
  295.   
  296.   /* check stream for error */
  297.   if (rerror(recin)) { 
  298.     fprintf(errout, "ERROR reading %s ended on error: %s", 
  299.      rnames(recin), strerror(rerror(recin)));
  300.     exit (EXIT_FAILURE);
  301.   }
  302.   return EXIT_SUCCESS;
  303. }
  304.