home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / remind23.lzh / remind.2 / dorem.c < prev    next >
C/C++ Source or Header  |  1991-02-24  |  12KB  |  427 lines

  1. #include <stdio.h>
  2. #ifndef UNIX
  3. #include <stdlib.h>
  4. #endif
  5. #include <string.h>
  6. #include <ctype.h>
  7. #include "defines.h"
  8. #include "globals.h"
  9. #include "protos.h"
  10.  
  11. /***************************************************************/
  12. /*                                                             */
  13. /*  int DoRem(char **s)                                        */
  14. /*                                                             */
  15. /*  Process a reminder.  Return 0 if reminder not emitted,     */
  16. /*  positive if emitted, or negative if in the past and        */
  17. /*  will never be emitted.                                     */
  18. /*                                                             */
  19. /***************************************************************/
  20. #ifdef __STDC__
  21. int DoRem(char **s)
  22. #else
  23. int DoRem(s)
  24. char **s;
  25.  
  26. #endif
  27. {
  28.    int d, m, y, wd, cons, delta, back, omit, done, jul, once, repeat, skip;
  29.    int ud, um, uy; /* Date of UNTIL */
  30.    int uj;
  31.    int tim, tdelta, trep;
  32.    int d2, m2, y2;
  33.    Token tok;
  34.    int trigger;
  35.    char NeedNewToken;
  36.  
  37.    uj = ud = um = uy = d = m = y = tim = tdelta = trep = -1;
  38.    back = delta = repeat = cons = wd = omit = once = skip = 0;
  39.  
  40.  
  41.    done = 0;
  42.    NeedNewToken = 1;
  43.    while (!done) {
  44.       if (NeedNewToken) tok = ParseToken(s);
  45.       NeedNewToken = 1;
  46.       switch (tok.type) {
  47.  
  48.          case Until_t:
  49.         NeedNewToken = 0;
  50.         while (!done) {
  51.            tok = ParseToken(s);
  52.            switch (tok.type) {
  53.               case Year_t:
  54.              if (uy != -1) {
  55.                 Eprint("Year duplicated in UNTIL.\n");
  56.             return 0;
  57.              }
  58.              uy = tok.val;
  59.              break;
  60.  
  61.               case Month_t:
  62.              if (um != -1) {
  63.                 Eprint("Month duplicated in UNTIL.\n");
  64.             return 0;
  65.              }
  66.              um = tok.val;
  67.              break;
  68.  
  69.               case Day_t:
  70.              if (ud != -1) {
  71.                 Eprint("Day duplicated in UNTIL.\n");
  72.             return 0;
  73.              }
  74.              ud = tok.val;
  75.              break;
  76.  
  77.                   default:
  78.              done = 1; break;
  79.            }
  80.         }
  81.         if (uy == -1 || um == -1 || ud == -1) {
  82.            Eprint("Year, month and day must all be specified after UNTIL\n");
  83.            return 0;
  84.             }
  85.             if (CheckDate(ud, um, uy)) {
  86.                Eprint("Invalid date for UNTIL.\n");
  87.                return 0;
  88.             }
  89.         uj = Julian(ud, um, uy);
  90.         done = 0; break;
  91.  
  92.          case Omit_t:
  93.         NeedNewToken = 0;
  94.               while (!done) {
  95.            tok = ParseToken(s);
  96.            switch(tok.type) {
  97.               case WkDay_t:
  98.                  if (omit & (1 << tok.val)) {
  99.                 Eprint("%s duplicated.\n", tok.str);
  100.                 return 0;
  101.                     }
  102.                     omit |= 1 << tok.val;
  103.                     break;
  104.  
  105.               default: done = 1; break;
  106.                }
  107.               }
  108.         done = 0;
  109.         break;
  110.  
  111.      case At_t:
  112.         NeedNewToken = 0;
  113.               while (!done) {
  114.                tok = ParseToken(s);
  115.                switch(tok.type) {
  116.  
  117.                   case Time_t:
  118.                         if (tim != -1) {
  119.                     Eprint("Time specified twice.\n");
  120.                        return 0;
  121.                     }
  122.                     else tim = tok.val;
  123.                         break;
  124.  
  125.                   case Repeat_t:
  126.                         if (trep != -1) {
  127.                         Eprint("Time repeat factor specified twice.\n");
  128.                         return 0;
  129.                        }
  130.                        trep = tok.val;
  131.                        if (trep <= 0) {
  132.                        Eprint("Invalid value for timerepeat factor: %d\n", repeat);
  133.                        return 0;
  134.                        }
  135.                        break;
  136.  
  137.                   case Delta_t:
  138.                  if (tdelta != -1) {
  139.                     Eprint("Time delta specified twice.\n");
  140.                         return 0;
  141.                      }
  142.                   tdelta = ABS(tok.val);
  143.                      break;
  144.  
  145.               default: done = 1; break;
  146.                }
  147.               }
  148.         done = 0; break;
  149.  
  150.      case Eol_t:
  151.         Eprint("Missing MSG or RUN in reminder.\n");
  152.         return 0;
  153.  
  154.      case Run_t:
  155.      case Msg_t: done = 1; break;
  156.  
  157.      case Skip_t:
  158.         if (skip) {
  159.            Eprint("Can only have one of BEFORE, AFTER or SKIP.\n");
  160.            return 0;
  161.             }
  162.         skip = tok.val;
  163.         break;
  164.  
  165.      case Unknown_t:
  166.         Eprint("Unknown token %s in reminder.\n", tok.str);
  167.         return 0;
  168.  
  169.          case Repeat_t:
  170.             if (repeat) {
  171.                Eprint("Repeat factor specified twice.\n");
  172.                return 0;
  173.             }
  174.             repeat = tok.val;
  175.             if (repeat <= 0) {
  176.                Eprint("Invalid value for repeat factor: %d\n", repeat);
  177.                return 0;
  178.             }
  179.             break;
  180.  
  181.      case WkDay_t:
  182.         if (wd & (1 << tok.val)) {
  183.            Eprint("%s duplicated.\n", tok.str);
  184.            return 0;
  185.         }
  186.         wd |= 1 << tok.val;
  187.         cons |= WKDAY_M;
  188.         break;
  189.  
  190.      case Year_t:
  191.         if (y != -1) {
  192.            Eprint("Year specified twice.\n");
  193.            return 0;
  194.         }
  195.         y = tok.val;
  196.         cons |= YEAR_M;
  197.         break;
  198.  
  199.      case Month_t:
  200.         if (m != -1) {
  201.            Eprint("Month specified twice.\n");
  202.            return 0;
  203.         }
  204.         m = tok.val;
  205.         cons |= MONTH_M;
  206.         break;
  207.  
  208.      case Day_t:
  209.         if (d != -1) {
  210.            Eprint("Day specified twice.\n");
  211.            return 0;
  212.         }
  213.         d = tok.val;
  214.         cons |= DAY_M;
  215.         break;
  216.  
  217.      case Delta_t:
  218.         if (delta) {
  219.            Eprint("Delta specified twice.\n");
  220.            return 0;
  221.         }
  222.         delta = tok.val;
  223.         break;
  224.  
  225.      case Back_t:
  226.         if (back) {
  227.            Eprint("Back specified twice.\n");
  228.            return 0;
  229.         }
  230.         back = tok.val;
  231.         break;
  232.  
  233.      case Once_t:
  234.         if (once) {
  235.            Eprint("ONCE specified twice.  (How's that for an error message??)\n");
  236.            return 0;
  237.         }
  238.         once = 1;
  239.         break;
  240.  
  241.      default:
  242.         Eprint("Can't use token %s here.\n", tok.str);
  243.         return 0;
  244.       }
  245.    }
  246.  
  247.    /* Do some sanity checking on the reminder */
  248.    if (repeat && (d == -1 || m == -1 || y == -1)) {
  249.       Eprint("Can't use repeat counter unless you fully specify the date.\n");
  250.       return 0;
  251.    }
  252.  
  253.    if (skip && (wd & omit)) {
  254.       Eprint("Conflict between weekday list and local OMIT\n");
  255.       return 0;
  256.    }
  257.  
  258.    if (d != -1 && m != -1 && CheckDate(d, m, y)) {
  259.       Eprint("Illegal date specification.\n");
  260.       return 0;
  261.    }
  262.    if (y != -1 && (y < BASE || y > BASE + 85)) {
  263.       Eprint("Illegal date specification.\n");
  264.       return 0;
  265.    }
  266.  
  267.    /* Print some helpful stuff if debugging */
  268.    if (Debug) {
  269.       if (back > 7) Eprint("Warning: 'back' > 7 could slow execution severely.\n");
  270.       if (delta > 30 && (omit || NumFullOmit || NumPartOmit))
  271.      Eprint("Warning: 'delta' > 30 with OMITs could slow execution severely.\n");
  272.    }
  273.  
  274.    if (omit == 127) {
  275.       Eprint("Can't omit every day!\n");
  276.       return 0;
  277.    }
  278.  
  279.    if (IgOnce) once = 0; 
  280.  
  281.    /* Check if we can quickly determine reminder is not to be emitted */
  282.    if (once && !Debug && !Purge && (LastRun == JulianToday)) return 0;
  283.  
  284.    /* Have we passed the UNTIL date ? */
  285.    if (uj != -1 && uj < JulianToday) {
  286.       if (Debug) Eprint("Reminder has expired.\n");
  287.       return -1;
  288.    }
  289.  
  290.    jul = GetTriggerDate(d, m, y, wd, cons, back, repeat, omit, skip);
  291.    if (uj != -1 && uj < jul) {
  292.       if (Debug) Eprint("Reminder has expired.\n");
  293.       return -1;
  294.    }
  295.  
  296.    if (Calendar) {
  297.       if (jul == JulianToday) {
  298.          while (isspace(**s)) (*s)++;
  299.          strcpy(WorkBuf, *s);
  300.          CalTime = tim;
  301.          if (tok.type == Run_t) return 2; else return 1;
  302.       } else return 0;
  303.    }
  304.  
  305.    if (jul == -1) {
  306.       if (Debug) Eprint("Reminder has expired.\n");
  307.       return -1;
  308.    } else if (jul == -2) return 0;
  309.  
  310.    FromJulian(jul, &d2, &m2, &y2);
  311.  
  312.    /* If we're in "Next" mode, output this one in simple-calendar format */
  313.    if (Next) {
  314.       DoSubst(*s, WorkBuf, d2, m2, y2, jul, tok.type, tim, 1);
  315.       if (!*WorkBuf) return 0;
  316.       printf("%04d/%02d/%02d: ", y2, m2+1, d2);
  317.       printf("%s\n", WorkBuf);
  318.       return 0;
  319.    }
  320.        
  321.    /* Figure out if the reminder should be triggered */
  322.  
  323.    trigger = MoveBack(jul, delta, omit);
  324.  
  325.    if(Debug) {
  326.       Eprint("%sTrigger date: %s, %d %s, %d.\n", 
  327.               (trigger <= JulianToday ? "*" : ""), DayName[jul % 7], 
  328.           d2, MonthName[m2], y2);
  329.       return 0;
  330.    }
  331.    if (Purge || (once && (LastRun == JulianToday))) return 0;
  332.  
  333.    while (isspace(**s)) (*s)++;
  334.  
  335.    if (trigger <= JulianToday && !(tok.type == Run_t && IgRun)) { 
  336.       /* Trigger a reminder */
  337. #ifdef UNIX
  338.       if (QueueAts && (jul == JulianToday) && (tim != -1)) {
  339.          DoAt(tim, tdelta, trep, *s, tok.type);
  340.       }
  341.       if (!PrintAts && (jul == JulianToday) && tim != -1) return 0;
  342. #endif
  343.       if (tok.type == Msg_t) {
  344.          if (NumEmitted == 0) {
  345.             NumEmitted++;
  346.             DoSubst(Banner, WorkBuf, CurDay, CurMon, CurYear, 
  347.                     JulianToday, Msg_t, (int) (SystemTime()/ 60), 0);
  348.             printf("%s\n", WorkBuf);
  349.          }
  350.          DoSubst(*s, WorkBuf, d2, m2, y2, jul, tok.type, tim, 0);
  351.          printf("%s\n", WorkBuf);
  352.       }
  353.       else if (tok.type == Run_t) {
  354.          DoSubst(*s, WorkBuf, d2, m2, y2, jul, tok.type, tim, 0);
  355.          system(WorkBuf);
  356.       }
  357.       else Eprint("Error: Invalid token type %d\n", tok.type);
  358.       return 1;
  359.    } else return 0;
  360.  
  361. }
  362.  
  363. /***************************************************************/
  364. /*                                                             */
  365. /* GetTriggerDate                                              */
  366. /*                                                             */
  367. /* Gets the trigger date for a reminder, returns the julian    */
  368. /* date, or -1 if the reminder has expired.                    */
  369. /* Returns -2 if an error occurs.                              */
  370. /*                                                             */
  371. /***************************************************************/
  372. #ifdef __STDC__
  373. int GetTriggerDate(int d, int m, int y, int wd, int cons, int back, int repeat, int omit, int skip)
  374. #else
  375. int GetTriggerDate(d, m, y, wd, cons, back, repeat, omit, skip)
  376. int d, m, y, wd, cons, back, repeat, omit, skip;
  377. #endif
  378. #define MAXATTEMPTS 25  /* Maximum number of attempts before giving up */
  379.  
  380. {
  381.    int i, d2, m2, y2, jul;
  382.    int d1, m1, y1, julstart;
  383.    int nattempts = 0;
  384.  
  385.    julstart = JulianToday;
  386.  
  387.    /* If we have a skip factor of 3 (AFTER), then we must back up to
  388.       the beginning of the block of omitted days. */
  389.    if (skip == 3) while(julstart>=1 && IsOmitted(julstart-1, omit)) julstart--;
  390.  
  391.    FromJulian(julstart, &d1, &m1, &y1);
  392.  
  393.    /* Make a first stab at the date */
  394.    i = TryNextDate(&d2, &m2, &y2, d1, m1, y1, d, m, y, wd, cons, 0);
  395.    if (!i || repeat) jul = Julian(d2, m2, y2);
  396.  
  397.    if (!repeat && !back && !skip) {
  398.       if (i) return -1; else return jul;
  399.    }
  400.  
  401.    if (i && !repeat) return -1;
  402.  
  403.    while (nattempts++ < MAXATTEMPTS) {
  404.       if (back) jul = MoveBack(jul, back, omit);
  405.       if (repeat) {
  406.          if (jul < julstart) {
  407.         jul += ((julstart - jul) / repeat) * repeat;
  408.         if (jul < julstart) jul += repeat;
  409.          }
  410.       }
  411.       if (skip == 2)      while (IsOmitted(jul, omit)) jul--;
  412.       else if (skip == 3) while (IsOmitted(jul, omit)) jul++;
  413.       if ((skip == 1 && IsOmitted(jul, omit)) || jul < JulianToday) {
  414.          if (!repeat) {
  415.             i = TryNextDate(&d2, &m2, &y2, d2, m2, y2, d, m, y, wd, cons, 1);
  416.             if (i) return -1;
  417.             jul = Julian(d2, m2, y2);
  418.          } else {
  419.             jul += repeat;
  420.         back = 0;  /* We've already handled the back! */
  421.          }
  422.       } else return jul;
  423.    }
  424.    Eprint("Couldn't compute a trigger date - check that date is sensible.\n");
  425.    return -2;
  426. }
  427.