home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume17 / remind / part03 / omits.c < prev    next >
C/C++ Source or Header  |  1991-02-19  |  11KB  |  331 lines

  1. /***************************************************************/
  2. /*                                                             */
  3. /*  OMITS.C                                                    */
  4. /*                                                             */
  5. /*  By David Skoll - 12 February 1991                          */
  6. /*                                                             */
  7. /*  Handle all code related to global OMITs                    */
  8. /*                                                             */
  9. /***************************************************************/
  10. #include <stdio.h>
  11. #ifndef UNIX
  12. #include <stdlib.h>
  13. #endif
  14.  
  15. #ifndef NO_MALLOC_H
  16. #include <malloc.h>
  17. #endif
  18.  
  19. #include "defines.h"
  20. #include "protos.h"
  21. #include "globals.h"
  22.  
  23. /* Define an OMIT stack buffer */
  24. typedef struct omit_stack {
  25.    struct omit_stack *next;
  26.    int NumFullOmit;
  27.    int NumPartOmit;
  28.    int Omits[1];
  29. } OmitBuffer;
  30.  
  31. /* Variables that we only want visible here */
  32. static OmitBuffer *OmitStack = (OmitBuffer *) NULL;
  33.  
  34. /***************************************************************/
  35. /*                                                             */
  36. /*  int DoGlobalOmit(char **s)                                 */
  37. /*                                                             */
  38. /*  Add an entry to the global ommissions array.  Either       */
  39. /*  a fully-specified date, or a mm-yy type date.              */
  40. /*  Return 0 if OK, -1 if date is in past, -2 if problem.      */
  41. /*                                                             */
  42. /***************************************************************/
  43. #ifdef __STDC__
  44. int DoGlobalOmit(char **s)
  45. #else
  46. int DoGlobalOmit(s)
  47.      char **s;
  48. #endif
  49. {
  50.    int d = -1, m = -1, y = -1;
  51.    int omit;
  52.    int *ptr;
  53.    Token tok;
  54.    char *olds = *s;
  55.  
  56.    tok.type = Unknown_t;
  57.    while(tok.type != Eol_t && tok.type != Run_t && tok.type != Msg_t) {
  58.       tok = ParseToken(s);
  59.       switch (tok.type) {
  60.      case Year_t:  y = tok.val; break;
  61.      case Month_t: m = tok.val; break;
  62.      case Day_t:   d = tok.val; break;
  63.  
  64.      case Delta_t:
  65.      case Eol_t:
  66.      case Msg_t:
  67.      case Run_t: break;
  68.      default:      Eprint("Invalid token '%s' for OMIT command.\n", tok.str);
  69.                return -2;
  70.       }
  71.    }
  72.  
  73.    if (d == -1 || m == -1 || CheckDate(d, m, y)) {
  74.       Eprint("Invalid date specification.\n");
  75.       return -2;
  76.    }
  77.  
  78.    if (y == -1) { /* Only mm-dd specified */
  79.       if (NumPartOmit == POMITSIZE) {
  80.      Eprint("Too many partially-specified OMITs.\n");
  81.      return -2;
  82.       }
  83.       omit = (m << 5) + d;
  84.       ptr = PartOmitArray + NumPartOmit;
  85.       NumPartOmit++;
  86.       while (ptr > PartOmitArray && *(ptr-1) > omit) {
  87.      *ptr = *(ptr-1);
  88.      ptr--;
  89.       }
  90.       *ptr = omit;
  91.  
  92.       /* Check if the bonehead already has it - if so, delete it */
  93.       if (ptr > PartOmitArray && *(ptr-1) == *ptr) {
  94.      if (Debug) Eprint("Duplicated partially-specified OMIT.\n");
  95.      NumPartOmit--;
  96.      while (ptr < NumPartOmit+PartOmitArray) {
  97.         *ptr = *(ptr + 1);
  98.         ptr++;
  99.      }
  100.       }
  101.       /* If we got a DELTA, a MSG or a RUN, then execute DoRem */
  102.       if (tok.type == Delta_t || tok.type == Run_t || tok.type == Msg_t)
  103.           return DoRem(&olds);
  104.    } else { /* All three specified */
  105.       if (NumFullOmit == FOMITSIZE) {
  106.      Eprint("Too many fully-specified OMITs.\n");
  107.      return -2;
  108.       }
  109.       omit = Julian(d, m, y);
  110.  
  111.       ptr = FullOmitArray + NumFullOmit;
  112.       NumFullOmit++;
  113.       while (ptr > FullOmitArray && *(ptr-1) > omit) {
  114.      *ptr = *(ptr-1);
  115.      ptr--;
  116.       }
  117.       *ptr = omit;
  118.  
  119.       /* Check if the bonehead already has it - if so, delete it */
  120.       if (ptr > FullOmitArray && *(ptr-1) == *ptr) {
  121.      if (Debug) Eprint("Duplicated fully-specified OMIT.\n");
  122.      NumFullOmit--;
  123.      while (ptr < NumFullOmit+FullOmitArray) {
  124.         *ptr = *(ptr + 1);
  125.         ptr++;
  126.      }
  127.       }
  128.       if (omit < JulianToday) {
  129.      if (Debug) Eprint("Omit has expired.\n");
  130.      return -1;
  131.       }
  132.       /* If we got a DELTA, a MSG or a RUN, then execute DoRem */
  133.       if (tok.type == Delta_t || tok.type == Run_t || tok.type == Msg_t)
  134.          return DoRem(&olds);
  135.    }
  136.    return 0;
  137. }
  138.  
  139. /***************************************************************/
  140. /*                                                             */
  141. /* PushOmitContext                                             */
  142. /*                                                             */
  143. /* Push the Global OMIT context onto a stack.                  */
  144. /*                                                             */
  145. /* Returns 0 for success, 1 for failure.                       */
  146. /*                                                             */
  147. /***************************************************************/
  148. #ifdef __STDC__
  149. int PushOmitContext(void)
  150. #else
  151. int PushOmitContext()
  152. #endif
  153. {
  154.    OmitBuffer *new = (OmitBuffer *) malloc( sizeof(OmitBuffer) +
  155.                      (NumFullOmit + NumPartOmit - 1) * sizeof(int));
  156.  
  157.    if (!new) {
  158.       Eprint("Unable to allocate memory for PUSH-OMIT-CONTEXT.\n");
  159.       return 1;
  160.    }
  161.  
  162.    new->NumFullOmit = NumFullOmit;
  163.    new->NumPartOmit = NumPartOmit;
  164.  
  165.    CopyInts(FullOmitArray, &(new->Omits[0]), NumFullOmit);
  166.    CopyInts(PartOmitArray, &(new->Omits[NumFullOmit]), NumPartOmit);
  167.  
  168.    new->next = OmitStack;
  169.    OmitStack = new;
  170.  
  171.    return 0;
  172. }
  173.  
  174. /***************************************************************/
  175. /*                                                             */
  176. /* PopOmitContext                                              */
  177. /*                                                             */
  178. /* Restore the OMIT context from the stack.                    */
  179. /*                                                             */
  180. /* Returns 0 for success, 1 for failure.                       */
  181. /*                                                             */
  182. /***************************************************************/
  183. #ifdef __STDC__
  184. int PopOmitContext(void)
  185. #else
  186. int PopOmitContext()
  187. #endif
  188. {
  189.  
  190.    OmitBuffer *temp;
  191.  
  192.    if (!OmitStack) {
  193.       Eprint("No saved contexts for POP-OMIT-CONTEXT.\n");
  194.       return 1;
  195.    }
  196.  
  197.    NumFullOmit = OmitStack->NumFullOmit;
  198.    NumPartOmit = OmitStack->NumPartOmit;
  199.  
  200.    CopyInts(&(OmitStack->Omits[0]), FullOmitArray, NumFullOmit);
  201.    CopyInts(&(OmitStack->Omits[NumFullOmit]), PartOmitArray, NumPartOmit);
  202.  
  203.    temp = OmitStack->next;
  204.    free(OmitStack);
  205.    OmitStack = temp;
  206.    return 0;
  207. }
  208.  
  209. /***************************************************************/
  210. /*                                                             */
  211. /*  ClearOmitContext                                           */
  212. /*                                                             */
  213. /*  Get rid of all global OMITS.                               */
  214. /*                                                             */
  215. /***************************************************************/
  216. #ifdef __STDC__
  217. void ClearOmitContext(void)
  218. #else
  219. void ClearOmitContext()
  220. #endif
  221. {
  222.    NumFullOmit = NumPartOmit = 0;
  223. }
  224.  
  225. /***************************************************************/
  226. /*                                                             */
  227. /*  CopyInts                                                   */
  228. /*                                                             */
  229. /*  Copy integer values from one array to another.             */
  230. /*                                                             */
  231. /***************************************************************/
  232. #ifdef __STDC__
  233. void CopyInts(int *from, int *to, int count)
  234. #else
  235. void CopyInts(from, to, count)
  236. int *from, *to, count;
  237. #endif
  238. {
  239.    while (count--) *to++ = *from++;
  240. }
  241.  
  242. /***************************************************************/
  243. /*                                                             */
  244. /*  FreeStackedOmits                                           */
  245. /*                                                             */
  246. /*  Get rid of all the stacked OMIT contexts                   */
  247. /*                                                             */
  248. /***************************************************************/
  249. #ifdef __STDC__
  250. void FreeStackedOmits(void)
  251. #else
  252. void FreeStackedOmits()
  253. #endif
  254. {
  255.    OmitBuffer *current = OmitStack, *next;
  256.  
  257.    if (current && Debug) Eprint("Warning - more PUSH-OMIT-CONTEXTs than POP-OMIT-CONTEXTs\n");
  258.  
  259.    while (current) {
  260.       next = current->next;
  261.       free(current);
  262.       current = next;
  263.    }
  264.  
  265.    OmitStack = (OmitBuffer *) NULL;
  266. }
  267.  
  268. /***************************************************************/
  269. /*                                                             */
  270. /* IsOmitted                                                   */
  271. /*                                                             */
  272. /* Returns non-zero if the julian date should be omitted, 0    */
  273. /* otherwise.                                                  */
  274. /*                                                             */
  275. /***************************************************************/
  276. #ifdef __STDC__
  277. int IsOmitted(int jul, int localomit)
  278. #else
  279. int IsOmitted(jul, localomit)
  280. int jul, localomit;
  281. #endif
  282. {
  283.    int d, m, y;
  284.  
  285.    /* Check if we should omit because of local omit */
  286.    if (localomit & 1 << (jul % 7)) return 1;
  287.  
  288.    /* Check if we should omit because of fully-specified global omit */
  289.    if (NumFullOmit && my_bsearch(jul, FullOmitArray, NumFullOmit)) return 1;
  290.  
  291.    /* Check if we should omit because of partially-specified global omits */
  292.    if (NumPartOmit) {
  293.       FromJulian(jul, &d, &m, &y);
  294.       if (my_bsearch((m << 5)+d, PartOmitArray, NumPartOmit)) return 1;
  295.    }
  296.  
  297.    /* Looks cool - don't omit */
  298.    return 0;
  299. }
  300.  
  301. /***************************************************************/
  302. /*                                                             */
  303. /*  my_bsearch                                                 */
  304. /*                                                             */
  305. /*  A simplified version of bsearch() for people whose library */
  306. /*  does not have the full version.  This only works when      */
  307. /*  searching a sorted array of integers.                      */
  308. /*                                                             */
  309. /***************************************************************/
  310. #ifdef __STDC__
  311. int *my_bsearch(int key, int *array, int number)
  312. #else
  313. int *my_bsearch(key, array, number)
  314. int key, *array, number;
  315. #endif
  316. {
  317.    int top = number - 1;
  318.    int bot = 0;
  319.    int mid;
  320.  
  321.    while (top >= bot) {
  322.       mid = (top+bot)/2;
  323.       if (*(array+mid) == key) return array+mid;
  324.       else if (*(array+mid) > key) top = mid-1;
  325.       else bot = mid+1;
  326.    }
  327.  
  328.    /* Oh, well - unsuccessful search.  Return NULL */
  329.    return NULL;
  330. }
  331.