home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / recio213.zip / rgett.c < prev    next >
C/C++ Source or Header  |  1995-09-05  |  16KB  |  401 lines

  1. /*****************************************************************************
  2.    MODULE: rgett.c
  3.   PURPOSE: recio character delimited time input functions
  4. COPYRIGHT: (C) 1994-1995, William Pierpoint
  5.  COMPILER: Borland C Version 3.1
  6.        OS: MSDOS Version 6.2
  7.   VERSION: 2.13
  8.   RELEASE: September 4, 1995
  9. *****************************************************************************/
  10.  
  11. #include <ctype.h>
  12. #include <errno.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <time.h>
  17.  
  18. #include "recio.h"
  19.  
  20. extern int _risready(REC *rp, int mode);
  21. extern char *_rfldstr(REC *rp, size_t len);
  22. extern char *_rerrs(REC *rp, int errnum);
  23.  
  24. #define rtmfmt(rp) ((rp)->r_tmfmt)
  25.  
  26. int _rgett_c_warno;        /* warning number */
  27. int _recbegyr = RECBEGYR;  /* year time format %y begins */
  28.  
  29. /****************************************************************************/
  30. static int                   /* return number of digits read                */
  31.     istrncpy(                /* copy up to n digits from src to dst         */
  32.               char *dst,     /* destination string                          */
  33.         const char *src,     /* source string                               */
  34.                 int n)       /* number of digits to copy                    */
  35. /****************************************************************************/
  36. {
  37.     int i;
  38.     
  39.     /* copy up to n digits */
  40.     for (i=0; i < n; i++) {
  41.         if (isdigit(*src)) {
  42.             *dst++ = *src++;
  43.         } else {
  44.             break;
  45.         }
  46.     }
  47.     /* append string terminator */
  48.     *dst = '\0';
  49.     return i;
  50. }
  51.  
  52. /****************************************************************************/
  53. void                         /* returns nothing                             */
  54.     rsetbegyr(               /* sets beginning year for time format %y      */
  55.         int year)            /* beginning year                              */
  56. /****************************************************************************/
  57. {
  58.      _recbegyr = year;
  59. }
  60.  
  61. /****************************************************************************/
  62. void                         /* returns nothing                             */
  63.     _tminit(                 /* initialize a tm struct                      */
  64.         struct tm *t)        /* tm struct                                   */
  65. /****************************************************************************/
  66. {
  67.     t->tm_sec = 0;
  68.     t->tm_min = 0;
  69.     t->tm_hour = 0;
  70.     t->tm_mday = 1;
  71.     t->tm_mon = 0;
  72.     t->tm_year = 70;
  73.     t->tm_isdst = -1;
  74. }
  75.  
  76. /****************************************************************************/
  77. struct tm                    /* return tm                                   */
  78.     timetotm(                /* convert time_t to struct tm                 */
  79.         time_t time)         /* source time                                 */
  80. /****************************************************************************/
  81. {
  82.     struct tm t;
  83.     
  84.     if (time == (time_t)-1) _tminit(&t);
  85.     else memcpy(&t, localtime(&time), sizeof(struct tm));
  86.     return t;
  87. }
  88.  
  89. /****************************************************************************/
  90. time_t                       /* return time (-1=error)                      */
  91.     tmtotime(                /* convert struct tm to time_t                 */
  92.         struct tm t)         /* broken-down time source                     */
  93. /****************************************************************************/
  94. {
  95.     time_t time;             /* return time (-1 = error)    */
  96.     
  97.     /* note: see section 3.5 of design.txt for mktime range */
  98.     time = mktime(&t);
  99.     if (time == (time_t) -1) errno = ERANGE;
  100.     return time;
  101. }
  102.  
  103. /****************************************************************************/
  104. time_t                       /* return time (-1=error)                      */
  105.     sftotime(                /* convert formated string to time_t           */
  106.         const char *s,       /* source string with time data                */
  107.         const char *fmt)     /* time format                                 */
  108. /****************************************************************************/
  109. {
  110.     time_t time=(time_t) -1; /* return time (-1=error) */
  111.     struct tm t;             /* broken-down time */
  112.  
  113.     t = sftotm(s, fmt);
  114.     if (!errno) time = tmtotime(t);
  115.     return time;
  116. }
  117.  
  118. /****************************************************************************/
  119. struct tm                    /* return tm (if error, errno != 0)            */
  120.     sftotm(                  /* convert formated string to tm               */
  121.         const char *str,     /* source string with time data                */
  122.         const char *fmt)     /* time format                                 */
  123. /****************************************************************************/
  124. {
  125.     struct tm t;        /* tm struct for time */
  126.     char buf[5];        /* string buffer */
  127.     char *s;            /* pointer to string str */
  128.     char *q;            /* temporary pointer to string s */
  129.  
  130.     s = (char *) str;
  131.     errno = 0;
  132.     _rgett_c_warno = 0;
  133.     _tminit(&t);
  134.     for (;;) {
  135.         /* skip white space */
  136.         while (isspace(*s)) s++;
  137.         while (isspace(*fmt)) fmt++;
  138.         if (!*s || !*fmt) break;
  139.         
  140.         if (*fmt == '%') {
  141.             switch (*++fmt) {
  142.             case 'm':  /* month (1 to 12) */
  143.                 q = s;
  144.                 s += istrncpy(buf, s, 2);
  145.                 if (*buf) {
  146.                     fmt++;
  147.                     while (isspace(*s)) s++;
  148.                     while (isspace(*fmt)) fmt++;
  149.                     if (*s=='\0' || isdigit(*s) || *fmt==*s) {
  150.                         t.tm_mon = atoi(buf) - 1;
  151.                         if (t.tm_mon < 0 || t.tm_mon > 11) {
  152.                             /* error - out of domain */
  153.                             errno = EDOM;
  154.                             goto done;
  155.                         }
  156.                         if (*s != '\0' && !isdigit(*s)) s++;
  157.                     } else {
  158.                         _rgett_c_warno = R_WTMFMT;
  159.                         s = q;
  160.                     }
  161.                     if (*fmt != '\0' && *fmt != '%') fmt++;
  162.                 }
  163.                 break;
  164.             case 'd':  /* day of month (1 to 31) */
  165.                 q = s;
  166.                 s += istrncpy(buf, s, 2);
  167.                 if (*buf) {
  168.                     fmt++;
  169.                     while (isspace(*s)) s++;
  170.                     while (isspace(*fmt)) fmt++;
  171.                     if (*s=='\0' || isdigit(*s) || *fmt==*s) {
  172.                         t.tm_mday = atoi(buf);
  173.                         if (t.tm_mday < 1 || t.tm_mday > 31) {
  174.                             /* error - out of domain */
  175.                             errno = EDOM;
  176.                             goto done;
  177.                         }
  178.                         if (*s != '\0' && !isdigit(*s)) s++;
  179.                     } else {
  180.                         _rgett_c_warno = R_WTMFMT;
  181.                         s = q;
  182.                     }
  183.                     if (*fmt != '\0' && *fmt != '%') fmt++;
  184.                 }
  185.                 break;
  186.             case 'y':  /* 2-digit year */
  187.                 q = s;
  188.                 s += istrncpy(buf, s, 2);
  189.                 if (*buf) {
  190.                     fmt++;
  191.                     while (isspace(*s)) s++;
  192.                     while (isspace(*fmt)) fmt++;
  193.                     if (*s=='\0' || isdigit(*s) || *fmt==*s) {
  194.                         t.tm_year = atoi(buf);
  195.                         if (t.tm_year - (_recbegyr % 100) >= 0) {
  196.                             t.tm_year += 100 * (_recbegyr / 100) - 1900;
  197.                         } else {
  198.                             t.tm_year += 100 * (_recbegyr / 100) - 1800;
  199.                         }
  200.                         if (*s != '\0' && !isdigit(*s)) s++;
  201.                     } else {
  202.                         _rgett_c_warno = R_WTMFMT;
  203.                         s = q;
  204.                     }
  205.                     if (*fmt != '\0' && *fmt != '%') fmt++;
  206.                 }
  207.                 break;
  208.             case 'Y':  /* 4-digit year */
  209.                 q = s;
  210.                 s += istrncpy(buf, s, 4);
  211.                 if (*buf) {
  212.                     fmt++;
  213.                     while (isspace(*s)) s++;
  214.                     while (isspace(*fmt)) fmt++;
  215.                     if (*s=='\0' || isdigit(*s) || *fmt==*s) {
  216.                         t.tm_year = atoi(buf) - 1900;
  217.                         if (*s != '\0' && !isdigit(*s)) s++;
  218.                     } else {
  219.                         _rgett_c_warno = R_WTMFMT;
  220.                         s = q;
  221.                     }
  222.                     if (*fmt != '\0' && *fmt != '%') fmt++;
  223.                 }
  224.                 break;
  225.             case 'H':  /* hour (0 to 23) */
  226.                 q = s;
  227.                 s += istrncpy(buf, s, 2);
  228.                 if (*buf) {
  229.                     fmt++;
  230.                     while (isspace(*s)) s++;
  231.                     while (isspace(*fmt)) fmt++;
  232.                     if (*s=='\0' || isdigit(*s) || *fmt==*s) {
  233.                         t.tm_hour = atoi(buf);
  234.                         if (t.tm_hour > 23) {
  235.                             /* error - out of domain */
  236.                             errno = EDOM;
  237.                             goto done;
  238.                         }
  239.                         if (*s != '\0' && !isdigit(*s)) s++;
  240.                     } else {
  241.                         _rgett_c_warno = R_WTMFMT;
  242.                         s = q;
  243.                     }
  244.                     if (*fmt != '\0' && *fmt != '%') fmt++;
  245.                 }
  246.                 break;
  247.             case 'M':  /* minute (0 to 59) */
  248.                 q = s;
  249.                 s += istrncpy(buf, s, 2);
  250.                 if (*buf) {
  251.                     fmt++;
  252.                     while (isspace(*s)) s++;
  253.                     while (isspace(*fmt)) fmt++;
  254.                     if (*s=='\0' || isdigit(*s) || *fmt==*s) {
  255.                         t.tm_min = atoi(buf);
  256.                         if (t.tm_min > 59) {
  257.                             /* error - out of domain */
  258.                             errno = EDOM;
  259.                             goto done;
  260.                         }
  261.                         if (*s != '\0' && !isdigit(*s)) s++;
  262.                     } else {
  263.                         _rgett_c_warno = R_WTMFMT;
  264.                         s = q;
  265.                     }
  266.                     if (*fmt != '\0' && *fmt != '%') fmt++;
  267.                 }
  268.                 break;
  269.             case 'S':  /* second (0 to 61) */
  270.                        /* includes up to two leap seconds */
  271.                 q = s;
  272.                 s += istrncpy(buf, s, 2);
  273.                 if (*buf) {
  274.                     fmt++;
  275.                     while (isspace(*s)) s++;
  276.                     while (isspace(*fmt)) fmt++;
  277.                     if (*s=='\0' || isdigit(*s) || *fmt==*s) {
  278.                         t.tm_sec = atoi(buf);
  279.                         if (t.tm_sec > 61) {
  280.                             /* error - out of domain */
  281.                             errno = EDOM;
  282.                             goto done;
  283.                         }
  284.                         if (*s != '\0' && !isdigit(*s)) s++;
  285.                     } else {
  286.                         _rgett_c_warno = R_WTMFMT;
  287.                         s = q;
  288.                     }
  289.                     if (*fmt != '\0' && *fmt != '%') fmt++;
  290.                 }
  291.                 break;
  292.             case '%':  /* literal % */
  293.                 if (*s=='%') {
  294.                     s++;
  295.                     fmt++;
  296.                 } else {
  297.                     /* error (invalid literal) */
  298.                     errno = EINVAL;
  299.                     goto done;
  300.                 }
  301.                 break;
  302.             default:
  303.                 /* error (invalid format specifier) */
  304.                 errno = EINVAL;
  305.                 goto done;
  306.             }
  307.         } else {
  308.             if (*s==*fmt) {
  309.                 s++;
  310.                 fmt++;
  311.                 continue;
  312.             } else {
  313.                 /* error (mismatch between data and specifier string) */
  314.                 errno = ERANGE;
  315.                 goto done;
  316.             }
  317.         }
  318.     }
  319. done:
  320.     if (!errno) {
  321.         /* warning if any non-whitespace part of format string left */
  322.         while (isspace(*fmt)) fmt++;
  323.         if (*fmt) _rgett_c_warno = R_WTMFMT;
  324.     } else {
  325.         _rgett_c_warno = 0;
  326.     }
  327.     return t;
  328. }
  329.  
  330. /****************************************************************************/
  331. struct tm                    /* return tm                                   */
  332.     rgettm(                  /* get time from record stream                 */
  333.         REC *rp)             /* record pointer                              */
  334. /****************************************************************************/
  335. {
  336.     struct tm t;             /* return tm */
  337.     struct tm val;           /* conversion value         */
  338.     char *fldptr;            /* pointer to field buffer  */
  339.  
  340.     _tminit(&t);
  341.     if (_risready(rp, R_READ)) {
  342.         fldptr = _rfldstr(rp, 0);
  343.         if (fldptr) {
  344.             strims(fldptr);
  345.             for (;;) {
  346.                 if (*fldptr != '\0') {
  347.                     val = sftotm(fldptr, rtmfmt(rp));
  348.                     if (errno) {
  349.                         switch (errno) {
  350.                         case EINVAL:
  351.                             fldptr = _rerrs(rp, R_EINVAL);
  352.                             break;
  353.                         case EDOM:
  354.                             fldptr = _rerrs(rp, R_EDOM);
  355.                             break;
  356.                         case ERANGE:
  357.                             fldptr = _rerrs(rp, R_EINVDAT);
  358.                             break;
  359.                         default:
  360.                             fldptr = _rerrs(rp, R_EFAULT);
  361.                             break;
  362.                         }
  363.                         if (fldptr) { continue; } else { goto done; } 
  364.                     } else {
  365.                         t = val;
  366.                         if (_rgett_c_warno) rsetwarn(rp, _rgett_c_warno);
  367.                         goto done;
  368.                     }
  369.                 } /* missing data */ 
  370.                 fldptr = _rerrs(rp, R_EMISDAT); 
  371.                 if (fldptr) { continue; } else { goto done; }
  372.             }
  373.         } 
  374.     }
  375. done:
  376.     return t;
  377. }
  378.  
  379. /****************************************************************************/
  380. time_t                       /* return time (-1=error)                      */
  381.     rgett(                   /* get time from record stream                 */
  382.         REC *rp)             /* record pointer                              */
  383. /****************************************************************************/
  384. {
  385.     time_t time=(time_t) -1; /* return time (-1 = error) */
  386.     char *fldptr;            /* pointer to field buffer  */
  387.  
  388.     if (_risready(rp, R_READ)) {
  389.         time = tmtotime(rgettm(rp));
  390.         while (time == (time_t) -1) {
  391.             fldptr = _rerrs(rp, R_ERANGE);
  392.             if (fldptr) {
  393.                 time = tmtotime(sftotm(fldptr, rtmfmt(rp)));
  394.             } else {
  395.                 break;
  396.             }
  397.         }
  398.     }
  399.     return time;
  400. }
  401.