home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2302 / Date.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  8.7 KB  |  359 lines

  1. /*
  2.  * Author: Jason Baietto, jason@ssd.csd.harris.com
  3.  * xdiary Copyright 1990 Harris Corporation
  4.  *
  5.  * Permission to use, copy, modify, and distribute, this software and its
  6.  * documentation for any purpose is hereby granted without fee, provided that
  7.  * the above copyright notice appear in all copies and that both that
  8.  * copyright notice and this permission notice appear in supporting
  9.  * documentation, and that the name of the copyright holder be used in
  10.  * advertising or publicity pertaining to distribution of the software with
  11.  * specific, written prior permission, and that no fee is charged for further
  12.  * distribution of this software, or any modifications thereof.  The copyright
  13.  * holder makes no representations about the suitability of this software for
  14.  * any purpose.  It is provided "as is" without express or implied warranty.
  15.  *
  16.  * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  17.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND IN NO
  18.  * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  19.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ITS USE,
  20.  * LOSS OF DATA, PROFITS, QPA OR GPA, WHETHER IN AN ACTION OF CONTRACT,
  21.  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
  22.  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include <values.h>
  28. #include <X11/StringDefs.h>
  29. #include <X11/IntrinsicP.h>
  30. #include "DateP.h"
  31. #include "StrTable.h"
  32. #include "common.h"
  33.  
  34. static void process_digit_token();
  35. static void process_alpha_token();
  36. static int convert_month_string_to_number();
  37. static int compare_string();
  38. static void construct_date();
  39.  
  40. char * default_month_names[] = {
  41.    "january", "february", "march", "april", "may", "june", "july",
  42.    "august", "september", "october", "november", "december" };
  43.  
  44. static int days_in_month[] = 
  45.    /* jan feb mar apr may jun jul aug sep oct nov dec */
  46.    {  0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31  };
  47.  
  48.  
  49. static StringTable month_names = default_month_names;
  50.  
  51. static int token[3];
  52. static int state[3];
  53. static int count;
  54.  
  55. #define STRING (0)
  56. #define NUMBER (1)
  57.  
  58. static char * beg_ptr;
  59. static char * cur_ptr;
  60. static Date date;
  61.  
  62. static int european;
  63.  
  64. Date convert_string_to_date(table, string)
  65. StringTable table;
  66. char * string;
  67. {
  68.    int in_alpha_token = FALSE;
  69.    int in_digit_token = FALSE;
  70.    date.month = date.day = date.year = 0;
  71.    beg_ptr = cur_ptr = string;
  72.    count = 0;
  73.    european = FALSE;
  74.  
  75.    /* Was a string table specified? */
  76.    if (table) {
  77.       month_names = table;
  78.    }
  79.  
  80.    while (*cur_ptr) {
  81.       if (isalpha(*cur_ptr)) {
  82.          if (in_digit_token) {
  83.             /* Finished processing a digit token. */
  84.             process_digit_token();
  85.             in_digit_token = FALSE;
  86.          } else if (in_alpha_token) {
  87.             /* Still scanning an alpha token. */
  88.          } else {
  89.             /* Start processing an alpha token. */
  90.             in_alpha_token = TRUE;
  91.             beg_ptr = cur_ptr;
  92.          }
  93.       } else if (isdigit(*cur_ptr)) {
  94.          if (in_alpha_token) {
  95.             /* Finished processing a digit token. */
  96.             process_digit_token();
  97.             in_digit_token = FALSE;
  98.          } else if (in_digit_token) {
  99.             /* Still scannin a digit token. */
  100.          } else {
  101.             /* Start processing a digit token. */
  102.             in_digit_token = TRUE;
  103.             beg_ptr = cur_ptr;
  104.          }
  105.       } else {
  106.          if (in_alpha_token) {
  107.             /* Finished processing an alpha token. */
  108.             process_alpha_token();
  109.             in_alpha_token = FALSE;
  110.          } else if (in_digit_token) {
  111.             /* Finished processing a digit token. */
  112.             process_digit_token();
  113.             in_digit_token = FALSE;
  114.          }
  115.  
  116.          /* Ignore garbage between tokens, but look for periods. */
  117.          if (*cur_ptr == '.') {
  118.             european = TRUE;
  119.          }
  120.       }
  121.       cur_ptr++;
  122.    }/*while*/
  123.  
  124.    if (in_alpha_token) {
  125.       process_alpha_token();
  126.    } else if (in_digit_token) {
  127.       process_digit_token();
  128.    }
  129.  
  130.    construct_date();
  131.  
  132.    if (!is_valid_date(&date)) {
  133.       date.month = 0;
  134.       date.day   = 0;
  135.       date.year  = 0;
  136.    }
  137.  
  138.    return date;
  139. }
  140.  
  141.  
  142.  
  143. static void process_alpha_token()
  144. {
  145.    if (count < 3) {
  146.       token[count] = convert_month_string_to_number();
  147.       state[count] = STRING;
  148.    }
  149.    count++;
  150. }
  151.  
  152.  
  153.  
  154. static void process_digit_token()
  155. {
  156.    if (count < 3) {
  157.       token[count] = atoi(beg_ptr);
  158.       if (token[count] > MAXSHORT) {
  159.          token[count] = 0;
  160.       }
  161.       state[count] = NUMBER;
  162.    }
  163.    count++;
  164. }
  165.  
  166.  
  167.  
  168. static int convert_month_string_to_number()
  169. {
  170.    int month;
  171.    for (month = 0; month < 12; month ++) {
  172.       if (compare_string(month_names[month])) {
  173.          return month+1;
  174.       }
  175.    }
  176.  
  177.    /* Nothing matched. */
  178.    return 0;
  179. }
  180.  
  181.  
  182.  
  183. static int compare_string(string)
  184. char * string;
  185. {
  186.    char * token_ptr = beg_ptr;
  187.    char * string_ptr = string;
  188.  
  189.    while (token_ptr < cur_ptr) {
  190.       if (DOWNCASE(*string_ptr) == DOWNCASE(*token_ptr)) {
  191.          /* Letters match (case ignored) */
  192.          token_ptr++;
  193.          string_ptr++;
  194.       } else {
  195.          /* Doesn't match. */
  196.          break;
  197.       }
  198.    }
  199.  
  200.    if (token_ptr == cur_ptr) {
  201.       /* We got to the end without a mismatch. */
  202.       return TRUE;
  203.    } else {
  204.       /* String and token didn't match. */
  205.       return FALSE;
  206.    }
  207.    
  208. }
  209.  
  210.  
  211.  
  212.  
  213. static void construct_date()
  214. {
  215.    date.day   = 0;
  216.    date.month = 0;
  217.    date.year  = 0;
  218.  
  219.  
  220.    if (count == 1) {
  221.  
  222.       if (state[0] == NUMBER) {
  223.          /* number, done */
  224.       } else {
  225.          /* string, error */
  226.          return;
  227.       }
  228.  
  229.       date.day   = 0;
  230.       date.month = 1;
  231.       date.year  = token[0];
  232.  
  233.    } else if (count == 2) {
  234.  
  235.       if (state[0] == STRING) {
  236.          /* string */
  237.          if (state[1] == NUMBER) {
  238.             /* string number, done */
  239.          } else {
  240.             /* string string, error */
  241.             return;
  242.          }
  243.       } else {
  244.          /* number */
  245.          if (state[1] == NUMBER) {
  246.             /* number number, done */
  247.          } else {
  248.             /* number string, error */
  249.             return;
  250.          }
  251.       }
  252.  
  253.       /* Month Year */
  254.       date.day   = 0;
  255.       date.month = token[0];
  256.       date.year  = token[1];
  257.  
  258.    } else if (count == 3) {
  259.  
  260.       if (state[0] == STRING) {
  261.          /* string */
  262.          if (state[1] == NUMBER) {
  263.             /* string number */
  264.             if (state[2] == NUMBER) {
  265.                /* string number number, done */
  266.             } else {
  267.                /* string number string, error */
  268.                return;
  269.             }
  270.          } else {
  271.             /* string string, error */
  272.             return;
  273.          }
  274.  
  275.          /* Month Day Year */
  276.          date.month = token[0];
  277.          date.day   = token[1];
  278.          date.year  = token[2];
  279.  
  280.       } else {
  281.  
  282.          /* number */
  283.          if (state[1] == STRING) {
  284.             /* number string */
  285.             if (state[2] == NUMBER) {
  286.                /* number string number, done */
  287.                /* Day Month Year */
  288.                date.day   = token[0];
  289.                date.month = token[1];
  290.                date.year  = token[2];
  291.             } else {
  292.                /* number string string, error */
  293.                return;
  294.             }
  295.          } else {
  296.             /* number number */
  297.             if (state[2] == NUMBER) {
  298.                /* number number number, done */
  299.                if (european) {
  300.                   /* Day Month Year */
  301.                   date.day   = token[0];
  302.                   date.month = token[1];
  303.                   date.year  = token[2];
  304.                } else {
  305.                   /* Month Day Year */
  306.                   date.month = token[0];
  307.                   date.day   = token[1];
  308.                   date.year  = token[2];
  309.                }
  310.             } else {
  311.                /* number number string, error */
  312.                return;
  313.             }
  314.          }
  315.       }
  316.    }
  317. }
  318.  
  319.  
  320.  
  321. int is_valid_date(date_ptr)
  322. Date * date_ptr;
  323. {
  324.    if (date_ptr->month < 1 || date_ptr->month > 12) {
  325.       /* None or an invalid month was specified. */
  326.       return FALSE;
  327.    }
  328.  
  329.    if (date_ptr->year <= 0) {
  330.       /* No year was specified. */
  331.       return FALSE;
  332.    }
  333.  
  334.    if (date_ptr->year < 100) {
  335.       /* Bump a two digit year into the 20th century. */
  336.       date_ptr->year += 1900;
  337.    }
  338.  
  339.    if (!date_ptr->day) {
  340.       /* It's okay if no day is specified. */
  341.       return TRUE;
  342.    } else {
  343.       if (date_ptr->day < 0 || date_ptr->day > days_in_month[date_ptr->month]) {
  344.          /* An invalid day was specified. */
  345.          return FALSE;
  346.       } else {
  347.          /* One last error check. */
  348.          if (date_ptr->month == FEBRUARY 
  349.              && date_ptr->day == 29 
  350.              && !A_LEAP_YEAR(date_ptr->year)) {
  351.             return FALSE;
  352.          } else {
  353.             /* A valid day was specified. */
  354.             return TRUE;
  355.          }
  356.       }
  357.    }
  358. }
  359.