home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / os2 / remind / src / token.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-20  |  10.9 KB  |  348 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) 1992, 1993 by David F. Skoll.                */
  10. /*                                                             */
  11. /***************************************************************/
  12. #include "config.h"
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <ctype.h>
  16. #ifdef HAVE_STDLIB_H
  17. #include <stdlib.h>
  18. #endif
  19. #ifdef HAVE_MALLOC_H
  20. #include <malloc.h>
  21. #endif
  22. #include "types.h"
  23. #include "globals.h"
  24. #include "protos.h"
  25. #include "err.h"
  26.  
  27. /* The macro PARSENUM parses a char pointer as an integer.  It simply
  28.    executes 'return' if an initial non-numeric char is found. */
  29. #define PARSENUM(var, string) \
  30.    if (!isdigit(*(string))) return; \
  31.    var = 0; \
  32.    while (isdigit(*(string))) { \
  33.       var *= 10; \
  34.       var += *(string) - '0'; \
  35.       string++; \
  36.    }
  37.  
  38. #define UPPER(c) ( ((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 'A' : (c) )
  39.  
  40. /* The big array holding all recognized (literal) tokens in reminder file.
  41.    Keep this array sorted, or software will not work. */
  42. Token TokArray[] = {
  43.    /* NAME          MINLEN      TYPE           VALUE */
  44.  
  45.    { "after",         3,     T_Skip,     AFTER_SKIP },
  46.    { "april",        3,    T_Month,    3 },
  47.    { "at",        2,    T_At,        0 },
  48.    { "august",        3,    T_Month,    7 },
  49.    { "banner",        3,    T_Banner,    0 },
  50.    { "before",         3,     T_Skip,     BEFORE_SKIP },
  51.    { "cal",         3,     T_RemType,     CAL_TYPE },
  52.    { "clear-omit-context", 5,   T_Clr,          0 },
  53.    { "debug",           5,      T_Debug,        0 },
  54.    { "december",     3,    T_Month,    11 },
  55.    { "dumpvars",        4,      T_Dumpvars,     0 },
  56.    { "else",         4,     T_Else,     0 },
  57.    { "endif",         5,     T_EndIf,     0 },
  58.    { "errmsg",          6,      T_ErrMsg,       0 },
  59.    { "exit",        4,    T_Exit,        0 },
  60.    { "february",     3,     T_Month,    1 },
  61.    { "flush",        5,    T_Flush,    0 },
  62.    { "friday",         3,    T_WkDay,    4 },
  63.    { "fset",        4,    T_Fset,        0 },
  64.    { "if",        2,    T_If,        0 },
  65.    { "iftrig",        6,    T_IfTrig,    0 },
  66.    { "include",     3,     T_Include,     0 },
  67.    { "january",     3,     T_Month,    0 },
  68.    { "july",        3,    T_Month,    6 },
  69.    { "june",        3,    T_Month,    5 },
  70.    { "march",        3,    T_Month,    2 },
  71.    { "may",        3,     T_Month,     4 },
  72.    { "monday",         3,    T_WkDay,    0 },
  73.    { "msf",        3,    T_RemType,    MSF_TYPE },
  74.    { "msg",         3,     T_RemType,     MSG_TYPE },
  75.    { "november",     3,     T_Month,    10 },
  76.    { "october",        3,     T_Month,    9 },
  77.    { "omit",        3,    T_Omit,        0 },
  78.    { "once",         3,     T_Once,        0 },
  79.    { "pop-omit-context", 3,    T_Pop,        0 },
  80.    { "preserve",        8,      T_Preserve,     0 },
  81.    { "priority",    8,    T_Priority,    0 },
  82.    { "ps",         2,     T_RemType,     PS_TYPE },
  83.    { "psfile",         6,     T_RemType,     PSF_TYPE },
  84.    { "push-omit-context", 4,     T_Push,        0 },
  85.    { "rem",        3,    T_Rem,        0 },
  86.    { "run",         3,     T_RemType,     RUN_TYPE },
  87.    { "satisfy",        7,    T_RemType,      SAT_TYPE },
  88.    { "saturday",    3,    T_WkDay,    5 },
  89.    { "scanfrom",    4,    T_Scanfrom,    0 },
  90.    { "sched",        5,    T_Sched,    0 },
  91.    { "september",     3,     T_Month,     8 },
  92.    { "set",        3,    T_Set,        0 },
  93.    { "skip",         3,     T_Skip,     SKIP_SKIP },
  94.    { "sunday",         3,    T_WkDay,    6 },
  95.    { "thursday",    3,    T_WkDay,    3 },
  96.    { "tuesday",        3,    T_WkDay,    1 },
  97.    { "unset",         5,     T_UnSet,     0 },
  98.    { "until",         3,     T_Until,    0 },
  99.    { "wednesday",    3,    T_WkDay,    2 }
  100. };
  101.  
  102. /* If language != English, we must also search the following... */
  103. #if LANG != ENGLISH
  104. Token NonEnglishToks[] = {
  105.    /* NAME          MINLEN      TYPE           VALUE */
  106.  
  107.    { L_MONDAY,           3,       T_WkDay,        0 },
  108.    { L_TUESDAY,           3,       T_WkDay,        1 },
  109.    { L_WEDNESDAY,      3,       T_WkDay,        2 },
  110.    { L_THURSDAY,       3,       T_WkDay,        3 },
  111.    { L_FRIDAY,           3,       T_WkDay,        4 },
  112.    { L_SATURDAY,       3,       T_WkDay,        5 },
  113.    { L_SUNDAY,           3,       T_WkDay,        6 },
  114.    { L_JAN,            3,       T_Month,        0 },
  115.    { L_FEB,            3,       T_Month,        1 },
  116.    { L_MAR,            3,       T_Month,        2 },
  117.    { L_APR,            3,       T_Month,        3 },
  118.    { L_MAY,            3,       T_Month,        4 },
  119.    { L_JUN,            3,       T_Month,        5 },
  120.    { L_JUL,            3,       T_Month,        6 },
  121.    { L_AUG,            3,       T_Month,        7 },
  122.    { L_SEP,            3,       T_Month,        8 },
  123.    { L_OCT,            3,       T_Month,        9 },
  124.    { L_NOV,            3,       T_Month,        10 },
  125.    { L_DEC,            3,       T_Month,        11 }
  126. };
  127. #endif
  128.  
  129. PRIVATE int TokStrCmp ARGS((const Token *t, const char *s));
  130.  
  131. /***************************************************************/
  132. /*                                                             */
  133. /*  FindInitialToken                                           */
  134. /*                                                             */
  135. /*  Find the initial token on the command line.  If it's a     */
  136. /*  left square bracket, return a T_Illegal type.              */
  137. /*                                                             */
  138. /***************************************************************/
  139. #ifdef HAVE_PROTOS
  140. PUBLIC char *FindInitialToken(Token *tok, char *s)
  141. #else
  142. char *FindInitialToken(tok, s)
  143. Token *tok;
  144. char *s;
  145. #endif
  146. {
  147.    char *t;
  148.    int len=0;
  149.    
  150.    while (isspace(*s)) s++;
  151.  
  152.    t = TokBuffer;
  153.  
  154.    while (*s && !isspace(*s)) {
  155.       if (len < TOKSIZE) {
  156.          *t++ = *s++;
  157.      len++;
  158.       }else s++;
  159.    }
  160.  
  161.    *t = 0;
  162.  
  163.    FindToken(TokBuffer, tok);
  164.    return s;
  165. }
  166.      
  167.  
  168. /***************************************************************/
  169. /*                                                             */
  170. /*  FindToken                                                  */
  171. /*                                                             */
  172. /*  Given a string, which token is it?                         */
  173. /*                                                             */
  174. /***************************************************************/
  175. #ifdef HAVE_PROTOS
  176. PUBLIC void FindToken(const char *s, Token *tok)
  177. #else
  178. void FindToken(s, tok)
  179. char *s;
  180. Token *tok;
  181. #endif
  182. {
  183.    register int top, bot, mid, r;
  184.    int l;
  185.  
  186.    tok->type = T_Illegal;
  187.    if (! *s) {
  188.       tok->type = T_Empty;
  189.       return;
  190.    }
  191.        
  192.    if (*s == '#' || *s == ';') {
  193.       tok->type = T_Comment;
  194.       return;
  195.    }
  196.  
  197.    /* Quickly give up the search if first char not a letter */
  198.    if ( ! isalpha(*s)) {
  199.       FindNumericToken(s, tok);
  200.       return;
  201.    }
  202.  
  203.    l = strlen(s);
  204.    bot = 0;
  205.    top = sizeof(TokArray) / sizeof(TokArray[0]) - 1;
  206.  
  207.    while(top >= bot) {
  208.       mid = (top + bot) / 2;
  209.       r = TokStrCmp(&TokArray[mid], s);
  210.       if (!r) {
  211.          if (l >= TokArray[mid].MinLen) {
  212.            tok->type = TokArray[mid].type;
  213.         tok->val  = TokArray[mid].val;
  214.         return;
  215.          } else {
  216.         while (mid && !TokStrCmp(&TokArray[mid-1],s)) mid--;
  217.         while (!TokStrCmp(&TokArray[mid], s) && l < TokArray[mid].MinLen)
  218.            mid++;
  219.         if (!TokStrCmp(&TokArray[mid], s)) {
  220.            tok->type = TokArray[mid].type;
  221.            tok->val = TokArray[mid].val;
  222.            return;
  223.         }
  224.          }
  225.      break;
  226.        }
  227.       if (r > 0) top = mid-1; else bot=mid+1;
  228.    }
  229.  
  230. /* If language is other than English, search the DayNames[] and MonthNames[]
  231.    array. */
  232. #if LANG != ENGLISH
  233.     for (r=0; r<(sizeof(NonEnglishToks) / sizeof(Token)); r++) {
  234.        if (l >= NonEnglishToks[r].MinLen && 
  235.                 !TokStrCmp(&NonEnglishToks[r], s)) {
  236.           tok->type = NonEnglishToks[r].type;
  237.           tok->val = NonEnglishToks[r].val;
  238.       return;
  239.        }
  240.     }
  241. #endif
  242.  
  243.    return;
  244. }
  245.  
  246. /***************************************************************/
  247. /*                                                             */
  248. /*  FindNumericToken                                           */
  249. /*                                                             */
  250. /*  Parse a numeric token:                                     */
  251. /*  Year - number between 1990 and 2085, or 90-99.             */
  252. /*  Day - number between 1 and 31                              */
  253. /*  Delta - +[+]n                                              */
  254. /*  Back - -[-]n                                               */
  255. /*  Rep - *n                                                   */
  256. /*                                                             */
  257. /***************************************************************/
  258. #ifdef HAVE_PROTOS
  259. PUBLIC void FindNumericToken(const char *s, Token *t)
  260. #else
  261. void FindNumericToken(s, t)
  262. char *s;
  263. Token *t;
  264. #endif
  265. {
  266.    int mult = 1, hour, min;
  267.  
  268.    t->type = T_Illegal;
  269.    t->val = 0;
  270.    if (isdigit(*s)) {
  271.       PARSENUM(t->val, s);
  272.  
  273.       /* If we hit a colon or a period, we've probably got a time hr:min */
  274.       if (*s == ':' || *s == '.' || *s == TIMESEP) {
  275.      s++;
  276.      hour = t->val;
  277.      PARSENUM(min, s);
  278.      if (*s || hour > 23 || min > 59) return;  /* Illegal time */
  279.      t->val = hour*60 + min;  /* Convert to minutes past midnight */
  280.      t->type = T_Time;
  281.      return;
  282.       }
  283.  
  284.       /* If we hit a non-digit, error! */
  285.       if (*s) return;
  286.  
  287.       /* Special hack - convert years between 90 and 99 to 1990 and 1999 */
  288.       if (t->val >= 90 && t->val <= 99) t->val += 1900;
  289.  
  290.       /* Classify the number we've got */
  291.       if (t->val >= BASE && t->val <= BASE+YR_RANGE) t->type = T_Year;
  292.       else if (t->val >= 1 && t->val <= 31) t->type = T_Day;
  293.       else t->type = T_Number;
  294.       return;
  295.    } else if (*s == '*') {
  296.       s++;
  297.       PARSENUM(t->val, s);
  298.       if (*s) return;  /* Illegal token if followed by non-numeric char */
  299.       t->type = T_Rep;
  300.       return;
  301.    } else if (*s == '+') {
  302.       s++;
  303.       if (*s == '+') { mult = -1; s++; }
  304.       PARSENUM(t->val, s);
  305.       if (*s) return;  /* Illegal token if followed by non-numeric char */
  306.       t->type = T_Delta;
  307.       t->val *= mult;
  308.       return;
  309.    } else if (*s == '-') {
  310.       s++;
  311.       if (*s == '-') { mult = -1; s++; }
  312.       PARSENUM(t->val, s);
  313.       if (*s) return;  /* Illegal token if followed by non-numeric char */
  314.       t->type = T_Back;
  315.       t->val *= mult;
  316.       return;
  317.    }
  318.    return;  /* Unknown token type */
  319. }
  320.  
  321.  
  322. /***************************************************************/
  323. /*                                                             */
  324. /*  TokStrCmp                                                  */
  325. /*                                                             */
  326. /*  Compare a token to a string.                               */
  327. /*                                                             */
  328. /***************************************************************/
  329. #ifdef HAVE_PROTOS
  330. PRIVATE int TokStrCmp(const Token *t, const char *s)
  331. #else
  332. static int TokStrCmp(t, s)
  333. Token *t;
  334. char *s;
  335. #endif
  336. {
  337.    register int r;
  338.    char *tk = t->name;
  339.    while(*tk && *s) {
  340.       r = UPPER(*tk) - UPPER(*s);
  341.       tk++;
  342.       s++;
  343.       if (r) return r;
  344.    }
  345.    if (!*s) return 0;
  346.    return (*tk - *s);
  347. }
  348.