home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR24 / REMIN301.ZIP / REMIN300.ZIP / TOKEN.C < prev    next >
C/C++ Source or Header  |  1992-11-10  |  9KB  |  288 lines

  1. /***************************************************************/
  2. /*                                                             */
  3. /*  TOKEN.C                                                    */
  4. /*                                                             */
  5. /*  Contains routines for parsing the reminder file and        */
  6. /*  classifying the tokens parsed.                             */
  7. /*                                                             */
  8. /*  This file is part of REMIND.                               */
  9. /*  Copyright (C) 1991 by David F. Skoll.                      */
  10. /*                                                             */
  11. /***************************************************************/
  12. #include <stdio.h>
  13. #include <ctype.h>
  14. #include "config.h"
  15. #ifdef HAVE_STDLIB_H
  16. #include <stdlib.h>
  17. #endif
  18. #ifdef HAVE_MALLOC_H
  19. #include <malloc.h>
  20. #endif
  21. #include "types.h"
  22. #include "globals.h"
  23. #include "protos.h"
  24. #include "err.h"
  25.  
  26. /* The macro PARSENUM parses a char pointer as an integer.  It simply
  27.    executes 'return' if an initial non-numeric char is found. */
  28. #define PARSENUM(var, string) \
  29.    if (!isdigit(*(string))) return; \
  30.    var = 0; \
  31.    while (isdigit(*(string))) { \
  32.       var *= 10; \
  33.       var += *(string) - '0'; \
  34.       string++; \
  35.    }
  36.  
  37. #define UPPER(c) ( ((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 'A' : (c) )
  38.  
  39. /* The big array holding all recognized (literal) tokens in reminder file.
  40.    Keep this array sorted, or software will not work. */
  41. Token TokArray[] = {
  42.    /* NAME          MINLEN      TYPE           VALUE */
  43.  
  44.    { "after",         3,     T_Skip,     AFTER_SKIP },
  45.    { "april",        3,    T_Month,    3 },
  46.    { "at",        2,    T_At,        0 },
  47.    { "august",        3,    T_Month,    7 },
  48.    { "banner",        3,    T_Banner,    0 },
  49.    { "before",         3,     T_Skip,     BEFORE_SKIP },
  50.    { "cal",         3,     T_RemType,     CAL_TYPE },
  51.    { "clear-omit-context", 5,   T_Clr,          0 },
  52.    { "debug",           5,      T_Debug,        0 },
  53.    { "december",     3,    T_Month,    11 },
  54.    { "dumpvars",        4,      T_Dumpvars,     0 },
  55.    { "else",         4,     T_Else,     0 },
  56.    { "endif",         5,     T_EndIf,     0 },
  57.    { "errmsg",          6,      T_ErrMsg,       0 },
  58.    { "exit",        4,    T_Exit,        0 },
  59.    { "february",     3,     T_Month,    1 },
  60.    { "friday",         3,    T_WkDay,    4 },
  61.    { "fset",        4,    T_Fset,        0 },
  62.    { "if",        2,    T_If,        0 },
  63.    { "iftrig",        6,    T_IfTrig,    0 },
  64.    { "include",     3,     T_Include,     0 },
  65.    { "january",     3,     T_Month,    0 },
  66.    { "july",        3,    T_Month,    6 },
  67.    { "june",        3,    T_Month,    5 },
  68.    { "march",        3,    T_Month,    2 },
  69.    { "may",        3,     T_Month,     4 },
  70.    { "monday",         3,    T_WkDay,    0 },
  71.    { "msg",         3,     T_RemType,     MSG_TYPE },
  72.    { "november",     3,     T_Month,    10 },
  73.    { "october",        3,     T_Month,    9 },
  74.    { "omit",        3,    T_Omit,        0 },
  75.    { "once",         3,     T_Once,        0 },
  76.    { "pop-omit-context", 3,    T_Pop,        0 },
  77.    { "preserve",        8,      T_Preserve,     0 },
  78.    { "Push-omit-context", 4,     T_Push,        0 },
  79.    { "rem",        3,    T_Rem,        0 },
  80.    { "run",         3,     T_RemType,     RUN_TYPE },
  81.    { "satisfy",        7,    T_RemType,      SAT_TYPE },
  82.    { "saturday",    3,    T_WkDay,    5 },
  83.    { "september",     3,     T_Month,     8 },
  84.    { "set",        3,    T_Set,        0 },
  85.    { "skip",         3,     T_Skip,     SKIP_SKIP },
  86.    { "sunday",         3,    T_WkDay,    6 },
  87.    { "thursday",    3,    T_WkDay,    3 },
  88.    { "tuesday",        3,    T_WkDay,    1 },
  89.    { "unset",         5,     T_UnSet,     0 },
  90.    { "until",         3,     T_Until,    0 },
  91.    { "wednesday",    3,    T_WkDay,    2 }
  92. };
  93.  
  94. PRIVATE int TokStrCmp ARGS((const Token *t, const char *s));
  95.  
  96. /***************************************************************/
  97. /*                                                             */
  98. /*  FindInitialToken                                           */
  99. /*                                                             */
  100. /*  Find the initial token on the command line.  If it's a     */
  101. /*  left square bracket, return a T_Illegal type.              */
  102. /*                                                             */
  103. /***************************************************************/
  104. #ifdef HAVE_PROTOS
  105. PUBLIC char *FindInitialToken(Token *tok, char *s)
  106. #else
  107. char *FindInitialToken(tok, s)
  108. Token *tok;
  109. char *s;
  110. #endif
  111. {
  112.    char *t;
  113.    int len=0;
  114.    
  115.    while (isspace(*s)) s++;
  116.  
  117.    t = TokBuffer;
  118.  
  119.    while (*s && !isspace(*s)) {
  120.       if (len < TOKSIZE) {
  121.          *t++ = *s++;
  122.      len++;
  123.       }else s++;
  124.    }
  125.  
  126.    *t = 0;
  127.  
  128.    FindToken(TokBuffer, tok);
  129.    return s;
  130. }
  131.      
  132.  
  133. /***************************************************************/
  134. /*                                                             */
  135. /*  FindToken                                                  */
  136. /*                                                             */
  137. /*  Given a string, which token is it?                         */
  138. /*                                                             */
  139. /***************************************************************/
  140. #ifdef HAVE_PROTOS
  141. PUBLIC void FindToken(const char *s, Token *tok)
  142. #else
  143. void FindToken(s, tok)
  144. char *s;
  145. Token *tok;
  146. #endif
  147. {
  148.    register int top, bot, mid, r;
  149.  
  150.    tok->type = T_Illegal;
  151.    if (! *s) {
  152.       tok->type = T_Empty;
  153.       return;
  154.    }
  155.        
  156.    if (*s == '#' || *s == ';') {
  157.       tok->type = T_Comment;
  158.       return;
  159.    }
  160.  
  161.    /* Quickly give up the search if first char not a letter */
  162.    if ( ! ((*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z')) ) {
  163.       FindNumericToken(s, tok);
  164.       return;
  165.    }
  166.  
  167.    bot = 0;
  168.    top = sizeof(TokArray) / sizeof(TokArray[0]) - 1;
  169.  
  170.    while(top >= bot) {
  171.       mid = (top + bot) / 2;
  172.       r = TokStrCmp(&TokArray[mid], s);
  173.       if (!r) {
  174.      tok->type = TokArray[mid].type;
  175.      tok->val  = TokArray[mid].val;
  176.      return;
  177.       }
  178.       if (r > 0) top = mid-1; else bot=mid+1;
  179.    }
  180.    return;
  181. }
  182.  
  183. /***************************************************************/
  184. /*                                                             */
  185. /*  FindNumericToken                                           */
  186. /*                                                             */
  187. /*  Parse a numeric token:                                     */
  188. /*  Year - number between 1990 and 2085, or 90-99.             */
  189. /*  Day - number between 1 and 31                              */
  190. /*  Delta - +[+]n                                              */
  191. /*  Back - -[-]n                                               */
  192. /*  Rep - *n                                                   */
  193. /*                                                             */
  194. /***************************************************************/
  195. #ifdef HAVE_PROTOS
  196. PUBLIC void FindNumericToken(const char *s, Token *t)
  197. #else
  198. void FindNumericToken(s, t)
  199. char *s;
  200. Token *t;
  201. #endif
  202. {
  203.    int mult = 1, hour, min;
  204.  
  205.    t->type = T_Illegal;
  206.    t->val = 0;
  207.    if (isdigit(*s)) {
  208.       PARSENUM(t->val, s);
  209.  
  210.       /* If we hit a colon, we've probably got a time hr:min */
  211.       if (*s == ':') {
  212.      s++;
  213.      hour = t->val;
  214.      PARSENUM(min, s);
  215.      if (*s || hour > 23 || min > 59) return;  /* Illegal time */
  216.      t->val = hour*60 + min;  /* Convert to minutes past midnight */
  217.      t->type = T_Time;
  218.      return;
  219.       }
  220.  
  221.       /* If we hit a non-digit, error! */
  222.       if (*s) return;
  223.  
  224.       /* Special hack - convert years between 90 and 99 to 1990 and 1999 */
  225.       if (t->val >= 90 && t->val <= 99) t->val += 1900;
  226.  
  227.       /* Classify the number we've got */
  228.       if (t->val >= BASE && t->val <= BASE+YR_RANGE) t->type = T_Year;
  229.       else if (t->val >= 1 && t->val <= 31) t->type = T_Day;
  230.       else t->type = T_Number;
  231.       return;
  232.    } else if (*s == '*') {
  233.       s++;
  234.       PARSENUM(t->val, s);
  235.       if (*s) return;  /* Illegal token if followed by non-numeric char */
  236.       t->type = T_Rep;
  237.       return;
  238.    } else if (*s == '+') {
  239.       s++;
  240.       if (*s == '+') { mult = -1; s++; }
  241.       PARSENUM(t->val, s);
  242.       if (*s) return;  /* Illegal token if followed by non-numeric char */
  243.       t->type = T_Delta;
  244.       t->val *= mult;
  245.       return;
  246.    } else if (*s == '-') {
  247.       s++;
  248.       if (*s == '-') { mult = -1; s++; }
  249.       PARSENUM(t->val, s);
  250.       if (*s) return;  /* Illegal token if followed by non-numeric char */
  251.       t->type = T_Back;
  252.       t->val *= mult;
  253.       return;
  254.    }
  255.    return;  /* Unknown token type */
  256. }
  257.  
  258.  
  259. /***************************************************************/
  260. /*                                                             */
  261. /*  TokStrCmp                                                  */
  262. /*                                                             */
  263. /*  Compare a token to a string.                               */
  264. /*                                                             */
  265. /***************************************************************/
  266. #ifdef HAVE_PROTOS
  267. PRIVATE int TokStrCmp(const Token *t, const char *s)
  268. #else
  269. static int TokStrCmp(t, s)
  270. Token *t;
  271. char *s;
  272. #endif
  273. {
  274.    register int r;
  275.    register int l=0;
  276.    char *tk = t->name;
  277.    while(*tk && *s) {
  278.       r = UPPER(*tk) - UPPER(*s);
  279.       tk++;
  280.       s++;
  281.       l++;
  282.       if (r) return r;
  283.    }
  284.    if (l < t->MinLen) return 1;
  285.    if (!*s) return 0;
  286.    return (*tk - *s);
  287. }
  288.