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

  1. /***************************************************************/
  2. /*                                                             */
  3. /*  DOREM.C                                                    */
  4. /*                                                             */
  5. /*  Contains routines for parsing reminders and evaluating     */
  6. /*  triggers.  Also contains routines for parsing OMIT         */
  7. /*  commands.                                                  */
  8. /*                                                             */
  9. /*  This file is part of REMIND.                               */
  10. /*  Copyright (C) 1992 by David F. Skoll.                      */
  11. /*                                                             */
  12. /***************************************************************/
  13. #include <stdio.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 "globals.h"
  22. #include "err.h"
  23. #include "types.h"
  24. #include "protos.h"
  25. #include "expr.h"
  26.  
  27. PRIVATE int ParseTimeTrig ARGS ((ParsePtr s, TimeTrig *tim));
  28. PRIVATE int ParseLocalOmit ARGS ((ParsePtr s, Trigger *t));
  29. PRIVATE int ParseUntil ARGS ((ParsePtr s, Trigger *t));
  30.  
  31. /***************************************************************/
  32. /*                                                             */
  33. /*  DoRem                                                      */
  34. /*                                                             */
  35. /*  Do the REM command.                                        */
  36. /*                                                             */
  37. /***************************************************************/
  38. #ifdef HAVE_PROTOS
  39. PUBLIC int DoRem(ParsePtr p)
  40. #else
  41. int DoRem(p)
  42. ParsePtr p;
  43. #endif
  44. {
  45.  
  46.    Trigger trig;
  47.    TimeTrig tim;
  48.    int r;
  49.    int jul;
  50.  
  51.    /* Parse the trigger date and time */
  52.    if (r=ParseRem(p, &trig, &tim)) return r;
  53.  
  54.    if (trig.typ == NO_TYPE) return E_EOLN;
  55.    if (trig.typ == SAT_TYPE) return DoSatRemind(&trig, &tim, p);
  56.    /* Calculate the trigger date */
  57.    jul = ComputeTrigger(JulianToday, &trig, &r);
  58.    if (r) return r;
  59.    
  60. /* Queue the reminder, if necessary */
  61. #ifdef HAVE_QUEUED
  62.    if (jul == JulianToday &&
  63.        !(!IgnoreOnce &&
  64.       trig.once != NO_ONCE &&
  65.       FileAccessDate == JulianToday))
  66.       QueueReminder(p, trig.typ, &tim);
  67. /* If we're in daemon mode, do nothing over here */
  68.    if (Daemon) return OK;
  69. #endif
  70.  
  71.  
  72.    if (ShouldTriggerReminder(&trig, &tim, jul)) {
  73.       if (r=TriggerReminder(p, &trig, &tim, jul)) return r;
  74.    }
  75.  
  76.    return OK;
  77. }   
  78.  
  79. /***************************************************************/
  80. /*                                                             */
  81. /*  ParseRem                                                   */
  82. /*                                                             */
  83. /*  Given a parse pointer, parse line and fill in a            */
  84. /*  trigger structure.                                         */
  85. /*                                                             */
  86. /***************************************************************/
  87. #ifdef HAVE_PROTOS
  88. PUBLIC int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
  89. #else
  90. int ParseRem(s, trig, tim)
  91. ParsePtr s;
  92. Trigger *trig;
  93. TimeTrig *tim;
  94. #endif
  95. {
  96.    register int r;
  97.    Token tok;
  98.  
  99.    trig->y = NO_YR;
  100.    trig->m = NO_MON;
  101.    trig->d = NO_DAY;
  102.    trig->wd = NO_WD;
  103.    trig->back = NO_BACK;
  104.    trig->delta = NO_DELTA;
  105.    trig->until = NO_UNTIL;
  106.    trig->rep  = NO_REP;
  107.    trig->localomit = NO_WD;
  108.    trig->skip = NO_SKIP;
  109.    trig->once = NO_ONCE;
  110.    trig->typ = NO_TYPE;
  111.    tim->ttime = NO_TIME;
  112.    tim->delta = NO_DELTA;
  113.    tim->rep   = NO_REP;
  114.  
  115.    while(1) {
  116.       /* Read space-delimited string */
  117.       r = ParseToken(s, TokBuffer);
  118.       if (r) return r;
  119.  
  120.       /* Figure out what we've got */
  121.       FindToken(TokBuffer, &tok);
  122.       switch(tok.type) {
  123.      case T_WkDay:
  124.         if (trig->wd & (1 << tok.val)) {
  125.            Eprint("Weekday specified twice");
  126.            return E_PARSE_ERR;
  127.         }
  128.         trig->wd |= (1 << tok.val);
  129.         break;
  130.  
  131.      case T_Month:
  132.         if (trig->m != NO_MON) {
  133.            Eprint("Month specified twice");
  134.            return E_PARSE_ERR;
  135.         }
  136.         trig->m = tok.val;
  137.         break;
  138.  
  139.      case T_Skip:
  140.         if (trig->skip != NO_SKIP) {
  141.            Eprint("Only use one of BEFORE, AFTER or SKIP");
  142.            return E_PARSE_ERR;
  143.         }
  144.         trig->skip = tok.val;
  145.         break;
  146.  
  147.      case T_At:
  148.         r=ParseTimeTrig(s, tim);
  149.         if (r) return r;
  150.         break;
  151.  
  152.      case T_RemType:
  153.         trig->typ = tok.val;
  154.         if (s->isnested) {
  155.            Eprint("Can't nest '%s' in expression", TokBuffer);
  156.            return E_PARSE_ERR;
  157.             }
  158.         return OK;
  159.  
  160.      case T_Until:
  161.         r=ParseUntil(s, trig);
  162.         if (r) return r;
  163.         break;
  164.  
  165.      case T_Year:
  166.         if (trig->y != NO_YR) {
  167.            Eprint("Year specified twice");
  168.            return E_PARSE_ERR;
  169.         }
  170.         trig->y = tok.val;
  171.         break;
  172.  
  173.      case T_Day:
  174.         if (trig->d != NO_DAY) {
  175.            Eprint("Day of month specified twice");
  176.            return E_PARSE_ERR;
  177.         }
  178.         trig->d = tok.val;
  179.         break;
  180.  
  181.      case T_Rep:
  182.         if (trig->rep != NO_REP) {
  183.            Eprint("Repeat value specified twice");
  184.            return E_PARSE_ERR;
  185.         }
  186.         trig->rep = tok.val;
  187.         break;
  188.  
  189.      case T_Delta:
  190.         if (trig->delta != NO_DELTA) {
  191.            Eprint("Delta value specified twice");
  192.            return E_PARSE_ERR;
  193.         }
  194.         trig->delta = tok.val;
  195.         break;
  196.  
  197.      case T_Back:
  198.         if (trig->back != NO_BACK) {
  199.            Eprint("Back value specified twice");
  200.            return E_PARSE_ERR;
  201.         }
  202.         trig->back = tok.val;
  203.         break;
  204.  
  205.      case T_Once:
  206.         if (trig->once != NO_ONCE) {
  207.            Eprint("ONCE specified twice.  (Hah.)");
  208.            return E_PARSE_ERR;
  209.         }
  210.         trig->once = ONCE_ONCE;
  211.         break;
  212.  
  213.      case T_Omit:
  214.         r = ParseLocalOmit(s, trig);
  215.         if (r) return r;
  216.         break;
  217.  
  218.      case T_Empty:
  219.         return OK;
  220.  
  221.      default:
  222.         Eprint("Unknown token in REM command: %s", TokBuffer);
  223.         return E_PARSE_ERR;
  224.       }
  225.    }
  226. }
  227.  
  228. /***************************************************************/
  229. /*                                                             */
  230. /*  ParseTimeTrig - parse the AT part of a timed reminder      */
  231. /*                                                             */
  232. /***************************************************************/
  233. #ifdef HAVE_PROTOS
  234. PRIVATE int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
  235. #else
  236. static int ParseTimeTrig(s, tim)
  237. ParsePtr s;
  238. TimeTrig *tim;
  239. #endif
  240. {
  241.    Token tok;
  242.    int r;
  243.  
  244.    while(1) {
  245.       r = ParseToken(s, TokBuffer);
  246.       if (r) return r;
  247.       FindToken(TokBuffer, &tok);
  248.       switch(tok.type) {
  249.      case T_Time:
  250.         tim->ttime = tok.val;
  251.             break;
  252.  
  253.      case T_Delta:
  254.         tim->delta = (tok.val > 0) ? tok.val : -tok.val;
  255.         break;
  256.  
  257.      case T_Rep:
  258.         tim->rep = tok.val;
  259.         break;
  260.  
  261.          default:
  262.             if (tim->ttime == NO_TIME) {
  263.                Eprint("Expecting time after AT.");
  264.                return E_PARSE_ERR;
  265.         }
  266. /* Save in global variable */
  267.         LastTriggerTime = tim->ttime;
  268.         PushToken(TokBuffer);
  269.             return OK;
  270.       }
  271.    }
  272. }
  273.  
  274. /***************************************************************/
  275. /*                                                             */
  276. /*  ParseLocalOmit - parse the local OMIT portion of a         */
  277. /*  reminder.                                                  */
  278. /*                                                             */
  279. /***************************************************************/
  280. #ifdef HAVE_PROTOS
  281. PRIVATE int ParseLocalOmit(ParsePtr s, Trigger *t)
  282. #else
  283. static int ParseLocalOmit(s, t)
  284. ParsePtr s;
  285. Trigger *t;
  286. #endif
  287. {
  288.    Token tok;
  289.    int r;
  290.  
  291.    while(1) {
  292.       r = ParseToken(s, TokBuffer);
  293.       if (r) return r;
  294.       FindToken(TokBuffer, &tok);
  295.       switch(tok.type) {
  296.      case T_WkDay:
  297.         t->localomit |= (1 << tok.val);
  298.         break;
  299.  
  300.      default:
  301.         PushToken(TokBuffer);
  302.         return OK;
  303.       }
  304.    }
  305. }
  306.  
  307. /***************************************************************/
  308. /*                                                             */
  309. /*  ParseUntil - parse the UNTIL portion of a reminder         */
  310. /*                                                             */
  311. /***************************************************************/
  312. #ifdef HAVE_PROTOS
  313. PRIVATE int ParseUntil(ParsePtr s, Trigger *t)
  314. #else
  315. static int ParseUntil(s, t)
  316. ParsePtr s;
  317. Trigger *t;
  318. #endif
  319. {
  320.    int y = NO_YR,
  321.        m = NO_MON,
  322.        d = NO_DAY;
  323.  
  324.    Token tok;
  325.    int r;
  326.  
  327.    if (t->until != NO_UNTIL) {
  328.       Eprint("Cannot specify UNTIL twice");
  329.       return E_PARSE_ERR;
  330.    }
  331.  
  332.    while(1) {
  333.       r = ParseToken(s, TokBuffer);
  334.       if (r) return r;
  335.       FindToken(TokBuffer, &tok);
  336.       switch(tok.type) {
  337.      case T_Year:
  338.         if (y != NO_YR) {
  339.            Eprint("Year specified twice in UNTIL");
  340.            return E_PARSE_ERR;
  341.         }
  342.         y = tok.val;
  343.         break;
  344.  
  345.      case T_Month:
  346.         if (m != NO_MON) {
  347.            Eprint("Month specified twice in UNTIL");
  348.            return E_PARSE_ERR;
  349.         }
  350.         m = tok.val;
  351.         break;
  352.  
  353.      case T_Day:
  354.         if (d != NO_DAY) {
  355.            Eprint("Day specified twice in UNTIL");
  356.            return E_PARSE_ERR;
  357.         }
  358.         d = tok.val;
  359.         break;
  360.  
  361.      default:
  362.         if (y == NO_YR || m == NO_MON || d == NO_DAY) {
  363.            Eprint("Incompletely specified UNTIL");
  364.            return E_PARSE_ERR;
  365.         }
  366.         t->until = Julian(y, m, d);
  367.         PushToken(TokBuffer);
  368.         return OK;
  369.       }
  370.    }
  371. }
  372.  
  373. /***************************************************************/
  374. /*                                                             */
  375. /*  TriggerReminder                                            */
  376. /*                                                             */
  377. /*  Trigger the reminder if it's a RUN or MSG type.            */
  378. /*                                                             */
  379. /***************************************************************/
  380. #ifdef HAVE_PROTOS
  381. PUBLIC int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
  382. #else
  383. int TriggerReminder(p, t, tim, jul)
  384. ParsePtr p;
  385. Trigger *t;
  386. TimeTrig *tim;
  387. int jul;
  388. #endif
  389. {
  390.    int r, y, m, d;
  391.    Trigger tempTrig;
  392.    TimeTrig tempTime;
  393.    Parser tempP;
  394.  
  395.    if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED;
  396.    if (t->typ == CAL_TYPE) return OK;
  397.  
  398. /* If we're in Daemon mode, do nothing over here... */
  399.  
  400. /* If it's a MSG-type reminder, issue the banner. */
  401.    if (t->typ == MSG_TYPE && !NumTriggered && !NextMode) {
  402.       CreateParser(Banner, &tempP);
  403.       tempP.allownested = 0;
  404.       tempTrig.typ = MSG_TYPE;
  405.       tempTime.ttime = SystemTime()/60;
  406.       if (!(r=DoSubst(&tempP, SubstBuffer, &tempTrig,
  407.            &tempTime, JulianToday, NORMAL_MODE)))
  408.          if (*SubstBuffer) printf("%s\n", SubstBuffer);
  409.       DestroyParser(&tempP);
  410.    }
  411.  
  412. /* If it's NextMode, process as a CAL-type entry, and issue simple-calendar
  413.    format. */
  414.    if (NextMode) {
  415.       if (r=DoSubst(p, SubstBuffer, t, tim, jul, CAL_MODE)) return r;
  416.       if (!*SubstBuffer) return OK;
  417.       FromJulian(jul, &y, &m, &d);
  418.       printf("%04d/%02d/%02d %s%s\n", y, m+1, d,
  419.                                       SimpleTime(tim->ttime, NULL),
  420.                                       SubstBuffer);
  421.       return OK;
  422.    }
  423.  
  424. /* Put the substituted string into the SubstBuffer */
  425.    if (r=DoSubst(p, SubstBuffer, t, tim, jul, NORMAL_MODE)) return r;
  426.  
  427. /* Go for it... */
  428.    if (t->typ == MSG_TYPE) printf("%s\n", SubstBuffer);
  429.    else system(SubstBuffer);
  430.  
  431.    NumTriggered++;
  432.    return OK;
  433. }
  434.  
  435. /***************************************************************/
  436. /*                                                             */
  437. /*  ShouldTriggerReminder                                      */
  438. /*                                                             */
  439. /*  Return 1 if we should trigger a reminder, based on today's */
  440. /*  date and the trigger.  Return 0 if reminder should not be  */
  441. /*  triggered.                                                 */
  442. /*                                                             */
  443. /***************************************************************/
  444. #ifdef __TURBOC__
  445. #pragma argsused
  446. #endif
  447. #ifdef HAVE_PROTOS
  448. PUBLIC int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
  449. #else
  450. int ShouldTriggerReminder(t, tim, jul)
  451. Trigger *t;
  452. TimeTrig *tim;
  453. int jul;
  454. #endif
  455. {
  456.    int r;
  457.  
  458.    /* Handle the ONCE modifier in the reminder. */
  459.    if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday)
  460.       return 0;
  461.    
  462.    if (jul < JulianToday) return 0;
  463.  
  464.    /* Don't trigger timed reminders if DontIssueAts is true, and if the
  465.       reminder is for today */
  466.  
  467. #ifdef HAVE_QUEUED
  468.    if (jul == JulianToday && DontIssueAts && tim->ttime != NO_TIME) return 0;
  469. #endif
  470.  
  471.    /* Don't trigger "old" timed reminders */
  472. /*** REMOVED...
  473.       if (jul == JulianToday &&
  474.        tim->ttime != NO_TIME &&
  475.        tim->ttime < SystemTime() / 60) return 0;
  476.  *** ...UNTIL HERE */
  477.  
  478.    /* If "infinite delta" option is chosen, always trigger future reminders */
  479.    if (InfiniteDelta || NextMode) return 1;
  480.  
  481.    /* Move back by delta days, if any */
  482.    if (t->delta != NO_DELTA) {
  483.       if (t->delta < 0)
  484.      jul = jul + t->delta;
  485.       else {
  486.      r = t->delta;
  487.      while(r && jul > JulianToday) {
  488.         jul--;
  489.         if (!IsOmitted(jul, t->localomit)) r--;
  490.      }
  491.       }
  492.    }
  493.  
  494.    /* Should we trigger the reminder? */
  495.    return (jul <= JulianToday);
  496. }
  497.  
  498. /***************************************************************/
  499. /*                                                             */
  500. /*  DoSatRemind                                                */
  501. /*                                                             */
  502. /*  Do the "satisfying..." remind calculation.                 */
  503. /*                                                             */
  504. /***************************************************************/
  505. #ifdef __TURBOC__
  506. #pragma argsused
  507. #endif
  508. #ifdef HAVE_PROTOS
  509. PUBLIC int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
  510. #else
  511. int DoSatRemind(trig, tim, p)
  512. Trigger *trig;
  513. TimeTrig *tim;
  514. ParsePtr p;
  515. #endif
  516. {
  517.    int iter, jul, r;
  518.    Value v;
  519.    char *s;
  520.  
  521.    iter = 0;
  522.    jul = JulianToday;
  523.    while (iter++ < MaxSatIter) {
  524.       jul = ComputeTrigger(jul, trig, &r);
  525.       if (r) {
  526.          if (r == E_CANT_TRIG) return OK; else return r;
  527.       }
  528.       s = p->pos;
  529.       r = EvaluateExpr(p, &v);
  530.       p->pos = s;
  531.       if (r) return r;
  532.       if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE;
  533.       if (v.type == INT_TYPE && v.v.val) return OK;
  534.       if (v.type == STR_TYPE && *v.v.str) return OK;
  535.       jul++;
  536.    }
  537.    LastTrigValid = 0;
  538.    return OK;
  539. }
  540.  
  541.