home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / os2 / remind / src / dorem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-31  |  19.2 KB  |  749 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, 1993 by David F. Skoll.                */
  11. /*                                                             */
  12. /***************************************************************/
  13. #include "config.h"
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. #include <string.h>
  17. #ifdef HAVE_STDLIB_H
  18. #include <stdlib.h>
  19. #endif
  20. #ifdef HAVE_MALLOC_H
  21. #include <malloc.h>
  22. #endif
  23. #include "globals.h"
  24. #include "err.h"
  25. #include "types.h"
  26. #include "protos.h"
  27. #include "expr.h"
  28.  
  29. PRIVATE int ParseTimeTrig ARGS ((ParsePtr s, TimeTrig *tim));
  30. PRIVATE int ParseLocalOmit ARGS ((ParsePtr s, Trigger *t));
  31. PRIVATE int ParseScanFrom ARGS ((ParsePtr s, Trigger *t));
  32. PRIVATE int ParsePriority ARGS ((ParsePtr s, Trigger *t));
  33. PRIVATE int ParseUntil ARGS ((ParsePtr s, Trigger *t));
  34.  
  35. /***************************************************************/
  36. /*                                                             */
  37. /*  DoRem                                                      */
  38. /*                                                             */
  39. /*  Do the REM command.                                        */
  40. /*                                                             */
  41. /***************************************************************/
  42. #ifdef HAVE_PROTOS
  43. PUBLIC int DoRem(ParsePtr p)
  44. #else
  45. int DoRem(p)
  46. ParsePtr p;
  47. #endif
  48. {
  49.  
  50.    Trigger trig;
  51.    TimeTrig tim;
  52.    int r;
  53.    int jul;
  54.    char buf[TOKSIZE];
  55.    Token tok;
  56.  
  57.    /* Parse the trigger date and time */
  58.    if ( (r=ParseRem(p, &trig, &tim)) ) return r;
  59.  
  60.    if (trig.typ == NO_TYPE) return E_EOLN;
  61.    if (trig.typ == SAT_TYPE) {
  62.       r=DoSatRemind(&trig, &tim, p);
  63.       if (r) return r;
  64.       r=ParseToken(p, buf);
  65.       if (r) return r;
  66.       FindToken(buf, &tok);
  67.       if (tok.type == T_Empty || tok.type == T_Comment) return OK;
  68.       if (tok.type != T_RemType || tok.val == SAT_TYPE) return E_PARSE_ERR;
  69.       trig.typ = tok.val;
  70.       jul = LastTriggerDate;
  71.       if (!LastTrigValid) return OK;
  72.    } else {
  73.    /* Calculate the trigger date */
  74.       jul = ComputeTrigger(trig.scanfrom, &trig, &r);
  75.       if (r) return r;
  76.    }
  77.    
  78. /* Queue the reminder, if necessary */
  79. #ifdef HAVE_QUEUED
  80.    if (jul == JulianToday &&
  81.        !(!IgnoreOnce &&
  82.       trig.once != NO_ONCE &&
  83.       FileAccessDate == JulianToday))
  84.       QueueReminder(p, trig.typ, &tim, trig.sched);
  85. /* If we're in daemon mode, do nothing over here */
  86.    if (Daemon) return OK;
  87. #endif
  88.  
  89.  
  90.    if (ShouldTriggerReminder(&trig, &tim, jul)) {
  91.       if ( (r=TriggerReminder(p, &trig, &tim, jul, 0)) ) {
  92.      return r;
  93.    }
  94.    }
  95.  
  96.    return OK;
  97. }   
  98.  
  99. /***************************************************************/
  100. /*                                                             */
  101. /*  ParseRem                                                   */
  102. /*                                                             */
  103. /*  Given a parse pointer, parse line and fill in a            */
  104. /*  trigger structure.                                         */
  105. /*                                                             */
  106. /***************************************************************/
  107. #ifdef HAVE_PROTOS
  108. PUBLIC int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
  109. #else
  110. int ParseRem(s, trig, tim)
  111. ParsePtr s;
  112. Trigger *trig;
  113. TimeTrig *tim;
  114. #endif
  115. {
  116.    register int r;
  117.    Token tok;
  118.  
  119.    trig->y = NO_YR;
  120.    trig->m = NO_MON;
  121.    trig->d = NO_DAY;
  122.    trig->wd = NO_WD;
  123.    trig->back = NO_BACK;
  124.    trig->delta = NO_DELTA;
  125.    trig->until = NO_UNTIL;
  126.    trig->rep  = NO_REP;
  127.    trig->localomit = NO_WD;
  128.    trig->skip = NO_SKIP;
  129.    trig->once = NO_ONCE;
  130.    trig->typ = NO_TYPE;
  131.    trig->scanfrom = NO_DATE;
  132.    trig->priority = NO_PRIORITY;
  133.    trig->sched[0] = 0;
  134.    tim->ttime = NO_TIME;
  135.    tim->delta = NO_DELTA;
  136.    tim->rep   = NO_REP;
  137.  
  138.    while(1) {
  139.       /* Read space-delimited string */
  140.       r = ParseToken(s, TokBuffer);
  141.       if (r) return r;
  142.  
  143.       /* Figure out what we've got */
  144.       FindToken(TokBuffer, &tok);
  145.       switch(tok.type) {
  146.      case T_WkDay:
  147.         if (trig->wd & (1 << tok.val)) return E_WD_TWICE;
  148.         trig->wd |= (1 << tok.val);
  149.         break;
  150.  
  151.      case T_Month:
  152.         if (trig->m != NO_MON) return E_MON_TWICE;
  153.         trig->m = tok.val;
  154.         break;
  155.  
  156.      case T_Skip:
  157.         if (trig->skip != NO_SKIP) return E_SKIP_ERR;
  158.         trig->skip = tok.val;
  159.         break;
  160.  
  161.          case T_Priority:
  162.         r=ParsePriority(s, trig);
  163.         if (r) return r;
  164.         break;
  165.  
  166.      case T_At:
  167.         r=ParseTimeTrig(s, tim);
  168.         if (r) return r;
  169.         break;
  170.  
  171.      case T_Scanfrom:
  172.         r=ParseScanFrom(s, trig);
  173.         if (r) return r;
  174.         break;
  175.  
  176.      case T_RemType:
  177.         trig->typ = tok.val;
  178.         if (s->isnested) return E_CANT_NEST_RTYPE;
  179.         if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday;
  180.         return OK;
  181.  
  182.      case T_Until:
  183.         r=ParseUntil(s, trig);
  184.         if (r) return r;
  185.         break;
  186.  
  187.      case T_Year:
  188.         if (trig->y != NO_YR) return E_YR_TWICE;
  189.         trig->y = tok.val;
  190.         break;
  191.  
  192.      case T_Day:
  193.         if (trig->d != NO_DAY) return E_DAY_TWICE;
  194.         trig->d = tok.val;
  195.         break;
  196.  
  197.      case T_Rep:
  198.         if (trig->rep != NO_REP) return E_REP_TWICE;
  199.         trig->rep = tok.val;
  200.         break;
  201.  
  202.      case T_Delta:
  203.         if (trig->delta != NO_DELTA) return E_DELTA_TWICE;
  204.         trig->delta = tok.val;
  205.         break;
  206.  
  207.      case T_Back:
  208.         if (trig->back != NO_BACK) return E_BACK_TWICE;
  209.         trig->back = tok.val;
  210.         break;
  211.  
  212.      case T_Once:
  213.         if (trig->once != NO_ONCE) return E_ONCE_TWICE;
  214.         trig->once = ONCE_ONCE;
  215.         break;
  216.  
  217.      case T_Omit:
  218.         r = ParseLocalOmit(s, trig);
  219.         if (r) return r;
  220.         break;
  221.  
  222.      case T_Empty:
  223.         if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday;
  224.         return OK;
  225.  
  226.      case T_Sched:
  227.         r=ParseToken(s, TokBuffer);
  228.         if(r) return r;
  229.         StrnCpy(trig->sched, TokBuffer, VAR_NAME_LEN);
  230.         break;
  231.  
  232.      default:
  233.         Eprint("%s: %s", ErrMsg[E_UNKNOWN_TOKEN], TokBuffer);
  234.         return E_UNKNOWN_TOKEN;
  235.       }
  236.    }
  237. }
  238.  
  239. /***************************************************************/
  240. /*                                                             */
  241. /*  ParseTimeTrig - parse the AT part of a timed reminder      */
  242. /*                                                             */
  243. /***************************************************************/
  244. #ifdef HAVE_PROTOS
  245. PRIVATE int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
  246. #else
  247. static int ParseTimeTrig(s, tim)
  248. ParsePtr s;
  249. TimeTrig *tim;
  250. #endif
  251. {
  252.    Token tok;
  253.    int r;
  254.  
  255.    while(1) {
  256.       r = ParseToken(s, TokBuffer);
  257.       if (r) return r;
  258.       FindToken(TokBuffer, &tok);
  259.       switch(tok.type) {
  260.      case T_Time:
  261.         tim->ttime = tok.val;
  262.             break;
  263.  
  264.      case T_Delta:
  265.         tim->delta = (tok.val > 0) ? tok.val : -tok.val;
  266.         break;
  267.  
  268.      case T_Rep:
  269.         tim->rep = tok.val;
  270.         break;
  271.  
  272.          default:
  273.             if (tim->ttime == NO_TIME) return E_EXPECT_TIME;
  274. /* Save in global variable */
  275.         LastTriggerTime = tim->ttime;
  276.         PushToken(TokBuffer);
  277.             return OK;
  278.       }
  279.    }
  280. }
  281.  
  282. /***************************************************************/
  283. /*                                                             */
  284. /*  ParseLocalOmit - parse the local OMIT portion of a         */
  285. /*  reminder.                                                  */
  286. /*                                                             */
  287. /***************************************************************/
  288. #ifdef HAVE_PROTOS
  289. PRIVATE int ParseLocalOmit(ParsePtr s, Trigger *t)
  290. #else
  291. static int ParseLocalOmit(s, t)
  292. ParsePtr s;
  293. Trigger *t;
  294. #endif
  295. {
  296.    Token tok;
  297.    int r;
  298.  
  299.    while(1) {
  300.       r = ParseToken(s, TokBuffer);
  301.       if (r) return r;
  302.       FindToken(TokBuffer, &tok);
  303.       switch(tok.type) {
  304.      case T_WkDay:
  305.         t->localomit |= (1 << tok.val);
  306.         break;
  307.  
  308.      default:
  309.         PushToken(TokBuffer);
  310.         return OK;
  311.       }
  312.    }
  313. }
  314.  
  315. /***************************************************************/
  316. /*                                                             */
  317. /*  ParseUntil - parse the UNTIL portion of a reminder         */
  318. /*                                                             */
  319. /***************************************************************/
  320. #ifdef HAVE_PROTOS
  321. PRIVATE int ParseUntil(ParsePtr s, Trigger *t)
  322. #else
  323. static int ParseUntil(s, t)
  324. ParsePtr s;
  325. Trigger *t;
  326. #endif
  327. {
  328.    int y = NO_YR,
  329.        m = NO_MON,
  330.        d = NO_DAY;
  331.  
  332.    Token tok;
  333.    int r;
  334.  
  335.    if (t->until != NO_UNTIL) return E_UNTIL_TWICE;
  336.  
  337.    while(1) {
  338.       r = ParseToken(s, TokBuffer);
  339.       if (r) return r;
  340.       FindToken(TokBuffer, &tok);
  341.       switch(tok.type) {
  342.      case T_Year:
  343.         if (y != NO_YR) {
  344.            Eprint("UNTIL: %s", ErrMsg[E_YR_TWICE]);
  345.            return E_YR_TWICE;
  346.         }
  347.         y = tok.val;
  348.         break;
  349.  
  350.      case T_Month:
  351.         if (m != NO_MON) {
  352.            Eprint("UNTIL: %s", ErrMsg[E_MON_TWICE]);
  353.            return E_MON_TWICE;
  354.         }
  355.         m = tok.val;
  356.         break;
  357.  
  358.      case T_Day:
  359.         if (d != NO_DAY) {
  360.            Eprint("UNTIL: %s", ErrMsg[E_DAY_TWICE]);
  361.            return E_DAY_TWICE;
  362.         }
  363.         d = tok.val;
  364.         break;
  365.  
  366.      default:
  367.         if (y == NO_YR || m == NO_MON || d == NO_DAY) {
  368.            Eprint("UNTIL: %s", ErrMsg[E_INCOMPLETE]);
  369.            return E_INCOMPLETE;
  370.         }
  371.         if (!DateOK(y, m, d)) return E_BAD_DATE;
  372.         t->until = Julian(y, m, d);
  373.         PushToken(TokBuffer);
  374.         return OK;
  375.       }
  376.    }
  377. }
  378.  
  379. /***************************************************************/
  380. /*                                                             */
  381. /*  ParseScanFrom - parse the SCANFROM portion of a reminder   */
  382. /*                                                             */
  383. /***************************************************************/
  384. #ifdef HAVE_PROTOS
  385. PRIVATE int ParseScanFrom(ParsePtr s, Trigger *t)
  386. #else
  387. static int ParseScanFrom(s, t)
  388. ParsePtr s;
  389. Trigger *t;
  390. #endif
  391. {
  392.    int y = NO_YR,
  393.        m = NO_MON,
  394.        d = NO_DAY;
  395.  
  396.    Token tok;
  397.    int r;
  398.  
  399.    if (t->scanfrom != NO_DATE) return E_SCAN_TWICE;
  400.  
  401.    while(1) {
  402.       r = ParseToken(s, TokBuffer);
  403.       if (r) return r;
  404.       FindToken(TokBuffer, &tok);
  405.       switch(tok.type) {
  406.      case T_Year:
  407.         if (y != NO_YR) {
  408.            Eprint("SCANFROM: %s", ErrMsg[E_YR_TWICE]);
  409.            return E_YR_TWICE;
  410.         }
  411.         y = tok.val;
  412.         break;
  413.  
  414.      case T_Month:
  415.         if (m != NO_MON) {
  416.            Eprint("SCANFROM: %s", ErrMsg[E_MON_TWICE]);
  417.            return E_MON_TWICE;
  418.         }
  419.         m = tok.val;
  420.         break;
  421.  
  422.      case T_Day:
  423.         if (d != NO_DAY) {
  424.            Eprint("SCANFROM: %s", ErrMsg[E_DAY_TWICE]);
  425.            return E_DAY_TWICE;
  426.         }
  427.         d = tok.val;
  428.         break;
  429.  
  430.      default:
  431.         if (y == NO_YR || m == NO_MON || d == NO_DAY) {
  432.            Eprint("SCANFROM: %s", ErrMsg[E_INCOMPLETE]);
  433.            return E_INCOMPLETE;
  434.         }
  435.         if (!DateOK(y, m, d)) return E_BAD_DATE;
  436.         t->scanfrom = Julian(y, m, d);
  437.         PushToken(TokBuffer);
  438.         return OK;
  439.       }
  440.    }
  441. }
  442. /***************************************************************/
  443. /*                                                             */
  444. /*  TriggerReminder                                            */
  445. /*                                                             */
  446. /*  Trigger the reminder if it's a RUN or MSG type.            */
  447. /*                                                             */
  448. /***************************************************************/
  449. #ifdef HAVE_PROTOS
  450. PUBLIC int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul,
  451.                int AsPopUp)
  452. #else
  453. int TriggerReminder(p, t, tim, jul, AsPopUp)
  454. ParsePtr p;
  455. Trigger *t;
  456. TimeTrig *tim;
  457. int jul;
  458. int AsPopUp
  459. #endif
  460. {
  461.    int r, y, m, d;
  462.    char PrioExpr[25];
  463.    static char buf[LINELEN+TOKSIZE];
  464.    char *s, *s2;
  465.    Value v;
  466.  
  467.    if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED;
  468.    if (t->typ == CAL_TYPE || t->typ == PS_TYPE || t->typ == PSF_TYPE)
  469.       return OK;
  470.  
  471. /* If it's a MSG-type reminder, and no -k option was used, issue the banner. */
  472.    if ((t->typ == MSG_TYPE || t->typ == MSF_TYPE) 
  473.        && !NumTriggered && !NextMode && !MsgCommand) {
  474.       if (!DoSubstFromString(Banner, SubstBuffer, JulianToday, NO_TIME) && *SubstBuffer)
  475. #ifdef OS2_POPUP
  476.         if (AsPopUp)
  477.             PutlPopUp(SubstBuffer);
  478.         else
  479.            printf("%s\n", SubstBuffer);
  480. #else
  481.         printf("%s\n", SubstBuffer);
  482. #endif
  483.    }
  484.  
  485. /* If it's NextMode, process as a CAL-type entry, and issue simple-calendar
  486.    format. */
  487.    if (NextMode) {
  488.       if ( (r=DoSubst(p, SubstBuffer, t, tim, jul, CAL_MODE)) ) return r;
  489.       if (!*SubstBuffer) return OK;
  490.       FromJulian(jul, &y, &m, &d);
  491. #ifdef OS2_POPUP
  492.       if (AsPopUp) {
  493.       sprintf(buf, "%04d%c%02d%c%02d %s", y, DATESEP, m+1, DATESEP, d,
  494.                     SimpleTime(tim->ttime, NULL));
  495.       StartPopUp();
  496.       PutsPopUp(buf);
  497.       PutlPopUp(SubstBuffer);
  498.       }
  499.       else
  500.       printf("%04d%c%02d%c%02d %s%s\n", y, DATESEP, m+1, DATESEP, d,
  501.                       SimpleTime(tim->ttime, NULL),
  502.                       SubstBuffer);
  503. #else
  504.       printf("%04d%c%02d%c%02d %s%s\n", y, DATESEP, m+1, DATESEP, d,
  505.                                       SimpleTime(tim->ttime, NULL),
  506.                                       SubstBuffer);
  507. #endif
  508.       return OK;
  509.    }
  510.  
  511. /* Put the substituted string into the SubstBuffer */
  512.    s2 = buf;
  513.    *s2 = 0;
  514.    if (UserFuncExists("msgprefix") == 1) {
  515.       sprintf(PrioExpr, "msgprefix(%d)", t->priority);
  516.       s = PrioExpr;
  517.       r = EvalExpr(&s, &v);
  518.       if (!r) {
  519.          if (!DoCoerce(STR_TYPE, &v)) {
  520.         sprintf(s2, "%s", v.v.str);
  521.         s2 += strlen(s2);
  522.          }
  523.      DestroyValue(&v);
  524.       }
  525.    }
  526.    if ( (r=DoSubst(p, s2, t, tim, jul, NORMAL_MODE)) ) return r;
  527.    s2 += strlen(s2);
  528.    if (UserFuncExists("msgsuffix") == 1) {
  529.       sprintf(PrioExpr, "msgsuffix(%d)", t->priority);
  530.       s = PrioExpr;
  531.       r = EvalExpr(&s, &v);
  532.       if (!r) {
  533.          if (!DoCoerce(STR_TYPE, &v)) {
  534.         sprintf(s2, "%s", v.v.str);
  535.         s2 += strlen(s2);
  536.          }
  537.      DestroyValue(&v);
  538.       }
  539.    }
  540. #if 0
  541. #ifdef OS2_POPUP
  542.    if (t->typ == MSF_TYPE) {
  543. #else
  544.    if (t->typ == MSG_TYPE || t->typ == MSF_TYPE) {
  545. #endif
  546. #else
  547.    if (t->typ == MSG_TYPE || t->typ == MSF_TYPE) {
  548. #endif
  549.       *s2++ = '\n';
  550.    }
  551.    *s2 = 0;
  552.  
  553. /* If we are sorting, just queue it up in the sort buffer */
  554.    if (SortByDate) {
  555.       if (InsertIntoSortBuffer(jul, tim->ttime, buf, t->typ, t->priority) == OK) {
  556.          NumTriggered++;
  557.          return OK;
  558.       }
  559.    }
  560.  
  561. /* If we didn't insert the reminder into the sort buffer, issue the
  562.    reminder now. */
  563.    switch(t->typ) {
  564.       case MSG_TYPE:
  565.          if (MsgCommand) {
  566.             sprintf(SubstBuffer, MsgCommand, buf);
  567.         system(SubstBuffer);
  568.          } else {
  569. #ifdef OS2_POPUP
  570.         if (AsPopUp)
  571.             PutlPopUp(buf);
  572.         else
  573.            printf("%s", buf);
  574. #else
  575.             printf("%s", buf);
  576. #endif
  577.          }
  578.      break;
  579.  
  580.       case MSF_TYPE:
  581. #ifdef OS2_POPUP
  582.      if (AsPopUp) {
  583.          StartPopUp();
  584.          FillParagraph(buf, 1);
  585.          EndPopUp();
  586.      }else{
  587.          FillParagraph(buf, 0);
  588.      }
  589. #else
  590.      FillParagraph(buf, 0);
  591. #endif
  592.      break;
  593.  
  594.       case RUN_TYPE:
  595.          system(buf);
  596.      break;
  597.  
  598.       default: /* Unknown/illegal type? */
  599.          return E_SWERR;
  600.    }
  601.  
  602.    NumTriggered++;
  603.    return OK;
  604. }
  605.  
  606. /***************************************************************/
  607. /*                                                             */
  608. /*  ShouldTriggerReminder                                      */
  609. /*                                                             */
  610. /*  Return 1 if we should trigger a reminder, based on today's */
  611. /*  date and the trigger.  Return 0 if reminder should not be  */
  612. /*  triggered.                                                 */
  613. /*                                                             */
  614. /***************************************************************/
  615. #ifdef __TURBOC__
  616. #pragma argsused
  617. #endif
  618. #ifdef HAVE_PROTOS
  619. PUBLIC int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
  620. #else
  621. int ShouldTriggerReminder(t, tim, jul)
  622. Trigger *t;
  623. TimeTrig *tim;
  624. int jul;
  625. #endif
  626. {
  627.    int r;
  628.  
  629.    /* Handle the ONCE modifier in the reminder. */
  630.    if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday)
  631.       return 0;
  632.    
  633.    if (jul < JulianToday) return 0;
  634.  
  635.    /* Don't trigger timed reminders if DontIssueAts is true, and if the
  636.       reminder is for today */
  637.  
  638. #ifdef HAVE_QUEUED
  639.    if (jul == JulianToday && DontIssueAts && tim->ttime != NO_TIME) return 0;
  640. #endif
  641.  
  642.    /* Don't trigger "old" timed reminders */
  643. /*** REMOVED...
  644.       if (jul == JulianToday &&
  645.        tim->ttime != NO_TIME &&
  646.        tim->ttime < SystemTime() / 60) return 0;
  647.  *** ...UNTIL HERE */
  648.  
  649.    /* If "infinite delta" option is chosen, always trigger future reminders */
  650.    if (InfiniteDelta || NextMode) return 1;
  651.  
  652.    /* Move back by delta days, if any */
  653.    if (t->delta != NO_DELTA) {
  654.       if (t->delta < 0)
  655.      jul = jul + t->delta;
  656.       else {
  657.      r = t->delta;
  658.      while(r && jul > JulianToday) {
  659.         jul--;
  660.         if (!IsOmitted(jul, t->localomit)) r--;
  661.      }
  662.       }
  663.    }
  664.  
  665.    /* Should we trigger the reminder? */
  666.    return (jul <= JulianToday);
  667. }
  668.  
  669. /***************************************************************/
  670. /*                                                             */
  671. /*  DoSatRemind                                                */
  672. /*                                                             */
  673. /*  Do the "satisfying..." remind calculation.                 */
  674. /*                                                             */
  675. /***************************************************************/
  676. #ifdef __TURBOC__
  677. #pragma argsused
  678. #endif
  679. #ifdef HAVE_PROTOS
  680. PUBLIC int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
  681. #else
  682. int DoSatRemind(trig, tim, p)
  683. Trigger *trig;
  684. TimeTrig *tim;
  685. ParsePtr p;
  686. #endif
  687. {
  688.    int iter, jul, r;
  689.    Value v;
  690.    char *s, *t;
  691.  
  692.    t = p->pos;
  693.    iter = 0;
  694.    jul = trig->scanfrom;
  695.    while (iter++ < MaxSatIter) {
  696.       jul = ComputeTrigger(jul, trig, &r);
  697.       if (r) {
  698.          if (r == E_CANT_TRIG) return OK; else return r;
  699.       }
  700.       s = p->pos;
  701.       r = EvaluateExpr(p, &v);
  702.       t = p->pos;
  703.       if (r) return r;
  704.       if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE;
  705.       if (v.type == INT_TYPE && v.v.val) return OK;
  706.       if (v.type == STR_TYPE && *v.v.str) return OK;
  707.       p->pos = s;
  708.       jul++;
  709.    }
  710.    p->pos = t;
  711.    LastTrigValid = 0;
  712.    return OK;
  713. }
  714.  
  715. /***************************************************************/
  716. /*                                                             */
  717. /*  ParsePriority - parse the PRIORITY portion of a reminder   */
  718. /*                                                             */
  719. /***************************************************************/
  720. #ifdef HAVE_PROTOS
  721. PRIVATE int ParsePriority(ParsePtr s, Trigger *t)
  722. #else
  723. static int ParsePriority(s, t)
  724. ParsePtr s;
  725. Trigger *t;
  726. #endif
  727. {
  728.    int p, r;
  729.    char *u;
  730.  
  731.    r = ParseToken(s, TokBuffer);
  732.    if(r) return r;
  733.    u = TokBuffer;
  734.  
  735.    if (!isdigit(*u)) return E_EXPECTING_NUMBER;
  736.    p = 0;
  737.    while (isdigit(*u)) {
  738.       p = p*10 + *u - '0';
  739.       u++;
  740.    }
  741.    if (*u) return E_EXPECTING_NUMBER;
  742.  
  743. /* Tricky!  The only way p can be < 0 is if overflow occurred; thus,
  744.    E2HIGH is indeed the appropriate error message. */
  745.    if (p<0 || p>9999) return E_2HIGH;
  746.    t->priority = p;
  747.    return OK;
  748. }
  749.