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

  1. /***************************************************************/
  2. /*                                                             */
  3. /*  OMIT.C                                                     */
  4. /*                                                             */
  5. /*  This file handles all global OMIT commands, and maintains  */
  6. /*  the data structures for OMITted dates.                     */
  7. /*                                                             */
  8. /*  This file is part of REMIND.                               */
  9. /*  Copyright (C) 1992 by David F. Skoll.                      */
  10. /*                                                             */
  11. /***************************************************************/
  12. #include "config.h"
  13. #include <stdio.h>
  14. #ifdef HAVE_STDLIB_H
  15. #include <stdlib.h>
  16. #endif
  17. #ifdef HAVE_MALLOC_H
  18. #include <malloc.h>
  19. #endif
  20. #include "types.h"
  21. #include "protos.h"
  22. #include "globals.h"
  23. #include "err.h"
  24.  
  25. PRIVATE int BexistsIntArray ARGS ((int array[], int num, int key));
  26. PRIVATE void InsertIntoSortedArray ARGS ((int *array, int num, int key));
  27.  
  28. /* Arrays for the global omits */
  29. static int FullOmitArray[MAX_FULL_OMITS];
  30. static int PartialOmitArray[MAX_PARTIAL_OMITS];
  31.  
  32. /* How many of each omit types do we have? */
  33. static int NumFullOmits, NumPartialOmits;
  34.  
  35. /* The structure for saving and restoring OMIT contexts */
  36. typedef struct _omitcontext {
  37.    struct _omitcontext *next;
  38.    int numfull, numpart;
  39.    int *fullsave;
  40.    int *partsave;
  41. } OmitContext;
  42.  
  43. /* The stack of saved omit contexts */
  44. static OmitContext *SavedOmitContexts = NULL;
  45.  
  46. /***************************************************************/
  47. /*                                                             */
  48. /*  ClearGlobalOmits                                           */
  49. /*                                                             */
  50. /*  Clear all the global OMIT context.                         */
  51. /*                                                             */
  52. /***************************************************************/
  53. #ifdef HAVE_PROTOS
  54. PUBLIC int ClearGlobalOmits(void)
  55. #else
  56. int ClearGlobalOmits()
  57. #endif
  58. {
  59.    NumFullOmits = NumPartialOmits = 0;
  60.    return OK;
  61. }
  62.  
  63. /***************************************************************/
  64. /*                                                             */
  65. /*  DoClear                                                    */
  66. /*                                                             */
  67. /*  The command-line function CLEAR-OMIT-CONTEXT               */
  68. /*                                                             */
  69. /***************************************************************/
  70. #ifdef HAVE_PROTOS
  71. PUBLIC int DoClear(ParsePtr p)
  72. #else
  73. int DoClear(p)
  74. ParsePtr p;
  75. #endif
  76. {
  77.    ClearGlobalOmits();
  78.    return VerifyEoln(p);
  79. }
  80.  
  81. /***************************************************************/
  82. /*                                                             */
  83. /*  DestroyOmitContexts                                        */
  84. /*                                                             */
  85. /*  Free all the memory used by saved OMIT contexts.           */
  86. /*  As a side effect, return the number of OMIT contexts       */
  87. /*  destroyed.                                                 */
  88. /*                                                             */
  89. /***************************************************************/
  90. #ifdef HAVE_PROTOS
  91. PUBLIC int DestroyOmitContexts(void)
  92. #else
  93. int DestroyOmitContexts()
  94. #endif
  95. {
  96.    OmitContext *c = SavedOmitContexts;
  97.    OmitContext *d;
  98.    int num = 0;
  99.  
  100.    while (c) {
  101.       num++;
  102.       if (c->fullsave) free(c->fullsave);
  103.       if (c->partsave) free(c->partsave);
  104.       d = c->next;
  105.       free(c);
  106.       c = d;
  107.    }
  108.    SavedOmitContexts = NULL;
  109.    return num;
  110. }
  111.  
  112. /***************************************************************/
  113. /*                                                             */
  114. /*  PushOmitContext                                            */
  115. /*                                                             */
  116. /*  Push the OMIT context on to the stack.                     */
  117. /*                                                             */
  118. /***************************************************************/
  119. #ifdef HAVE_PROTOS
  120. PUBLIC int PushOmitContext(ParsePtr p)
  121. #else
  122. int PushOmitContext(p)
  123. ParsePtr p;
  124. #endif
  125. {
  126.    register int i;
  127.    OmitContext *context;
  128.  
  129. /* Create the saved context */
  130.    context = NEW(OmitContext);
  131.    if (!context) return E_NO_MEM;
  132.  
  133.    context->numfull = NumFullOmits;
  134.    context->numpart = NumPartialOmits;
  135.    context->fullsave = (int *) malloc(NumFullOmits * sizeof(int));
  136.    if (NumFullOmits && !context->fullsave) {
  137.       free(context);
  138.       return E_NO_MEM;
  139.    }
  140.    context->partsave = (int *) malloc(NumPartialOmits * sizeof(int));
  141.    if (NumPartialOmits && !context->partsave) {
  142.       free(context->fullsave);
  143.       free(context);
  144.       return E_NO_MEM;
  145.    }
  146.       
  147. /* Copy the context over */
  148.    for (i=0; i<NumFullOmits; i++)
  149.       *(context->fullsave + i) = FullOmitArray[i];
  150.  
  151.    for (i=0; i<NumPartialOmits; i++)
  152.       *(context->partsave + i) = PartialOmitArray[i];
  153.  
  154. /* Add the context to the stack */
  155.    context->next = SavedOmitContexts;
  156.    SavedOmitContexts = context;
  157.    return VerifyEoln(p);
  158. }
  159.  
  160. /***************************************************************/
  161. /*                                                             */
  162. /*  PopOmitContext                                             */
  163. /*                                                             */
  164. /*  Pop the OMIT context off of the stack.                     */
  165. /*                                                             */
  166. /***************************************************************/
  167. #ifdef HAVE_PROTOS
  168. PUBLIC int PopOmitContext(ParsePtr p)
  169. #else
  170. int PopOmitContext(p)
  171. ParsePtr p;
  172. #endif
  173. {
  174.  
  175.    register int i;
  176.    OmitContext *c = SavedOmitContexts;
  177.  
  178.    if (!c) return E_POP_NO_PUSH;
  179.    NumFullOmits = c->numfull;
  180.    NumPartialOmits = c->numpart;
  181.  
  182. /* Copy the context over */
  183.    for (i=0; i<NumFullOmits; i++)
  184.       FullOmitArray[i] = *(c->fullsave + i);
  185.  
  186.    for (i=0; i<NumPartialOmits; i++)
  187.       PartialOmitArray[i] = *(c->partsave + i);
  188.  
  189. /* Remove the context from the stack */
  190.    SavedOmitContexts = c->next;
  191.  
  192. /* Free memory used by the saved context */
  193.    if (c->partsave) free(c->partsave);
  194.    if (c->fullsave) free(c->fullsave);
  195.    free(c);
  196.  
  197.    return VerifyEoln(p);
  198. }
  199.  
  200. /***************************************************************/
  201. /*                                                             */
  202. /*  IsOmitted                                                  */
  203. /*                                                             */
  204. /*  Return non-zero if date is OMITted, zero if it is not.     */
  205. /*                                                             */
  206. /***************************************************************/
  207. #ifdef HAVE_PROTOS
  208. PUBLIC int IsOmitted(int jul, int localomit)
  209. #else
  210. int IsOmitted(jul, localomit)
  211. int jul, localomit;
  212. #endif
  213. {
  214.    int y, m, d;
  215.  
  216.    /* Is it omitted because of local omits? */
  217.    if (localomit & (1 << (jul % 7))) return 1;
  218.  
  219.    /* Is it omitted because of fully-specified omits? */
  220.    if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) return 1;
  221.  
  222.    /* Get the syndrome */
  223.    FromJulian(jul, &y, &m, &d);
  224.    if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d))
  225.       return 1;
  226.  
  227.    /* Not omitted */
  228.    return 0;
  229. }
  230.  
  231. /***************************************************************/
  232. /*                                                             */
  233. /*  BexistsIntArray                                            */
  234. /*                                                             */
  235. /*  Perform a binary search on an integer array.  Return 1 if  */
  236. /*  element is found, 0 otherwise.                             */
  237. /*                                                             */
  238. /***************************************************************/
  239. #ifdef HAVE_PROTOS
  240. PRIVATE int BexistsIntArray(int array[], int num, int key)
  241. #else
  242. static int BexistsIntArray(array, num, key)
  243. int array[], num, key;
  244. #endif
  245. {
  246.    int top=num-1, bot=0, mid;
  247.  
  248.    while (top >= bot) {
  249.       mid = (top+bot)/2;
  250.       if (array[mid] == key) return 1;
  251.       else if (array[mid] > key) top = mid-1;
  252.       else bot=mid+1;
  253.    }
  254.    return 0;
  255. }
  256.  
  257. /***************************************************************/
  258. /*                                                             */
  259. /*  InsertIntoSortedArray                                      */
  260. /*                                                             */
  261. /*  Insert a key into a sorted array.  We assume that there is */
  262. /*  room in the array for it.                                  */
  263. /*                                                             */
  264. /***************************************************************/
  265. #ifdef HAVE_PROTOS
  266. PRIVATE void InsertIntoSortedArray(int *array, int num, int key)
  267. #else
  268. static void InsertIntoSortedArray(array, num, key)
  269. int *array, num, key;
  270. #endif
  271. {
  272.    /* num is number of elements CURRENTLY in the array. */
  273.    int *cur = array+num;
  274.  
  275.    while (cur > array && *(cur-1) > key) {
  276.       *cur = *(cur-1);
  277.       cur--;
  278.    }
  279.    *cur = key;
  280. }
  281.  
  282. /***************************************************************/
  283. /*                                                             */
  284. /*  DoOmit                                                     */
  285. /*                                                             */
  286. /*  Do a global OMIT command.                                  */
  287. /*                                                             */
  288. /***************************************************************/
  289. #ifdef HAVE_PROTOS
  290. PUBLIC int DoOmit(ParsePtr p)
  291. #else
  292. int DoOmit(p)
  293. ParsePtr p;
  294. #endif
  295. {
  296.    int y = NO_YR, m = NO_MON, d = NO_DAY, r;
  297.    Token tok;
  298.    int parsing=1;
  299.    int syndrome;
  300.    
  301. /* Parse the OMIT.  We need a month and day; year is optional. */
  302.    while(parsing) {
  303.       if (r=ParseToken(p, TokBuffer)) return r;
  304.       FindToken(TokBuffer, &tok);
  305.       switch (tok.type) {
  306.          case T_Year:
  307.         if (y != NO_YR) {
  308.            Eprint("Year specified twice");
  309.            return E_PARSE_ERR;
  310.         }
  311.         y = tok.val;
  312.         break;
  313.  
  314.          case T_Month:
  315.         if (m != NO_MON) {
  316.            Eprint("Month specified twice");
  317.            return E_PARSE_ERR;
  318.         }
  319.         m = tok.val;
  320.         break;
  321.  
  322.          case T_Day:
  323.         if (d != NO_DAY) {
  324.            Eprint("Day specified twice");
  325.            return E_PARSE_ERR;
  326.         }
  327.         d = tok.val;
  328.         break;
  329.      
  330.      case T_Delta:
  331.         break;
  332.  
  333.      case T_Empty:
  334.      case T_Comment:
  335.      case T_RemType:
  336.         parsing = 0;
  337.         break;
  338.  
  339.      default:
  340.         Eprint("Unknown token '%s' in OMIT command", TokBuffer);
  341.         return E_PARSE_ERR;
  342.       }
  343.    }
  344.    if (m == NO_MON || d == NO_DAY) {
  345.       Eprint("Must specify month and day in OMIT command");
  346.       return E_PARSE_ERR;
  347.    }
  348.    if (y == NO_YR) {
  349.       if (NumPartialOmits == MAX_PARTIAL_OMITS) {
  350.          Eprint("Too many partial OMITs");
  351.      return E_NO_MEM;
  352.       }
  353.       if (d > MonthDays[m]) return E_BAD_DATE;
  354.       syndrome = (m<<5) + d;
  355.       if (!BexistsIntArray(PartialOmitArray, NumPartialOmits, syndrome)) {
  356.          InsertIntoSortedArray(PartialOmitArray, NumPartialOmits, syndrome);
  357.          NumPartialOmits++;
  358.       }
  359.    } else {
  360.       if (NumFullOmits == MAX_FULL_OMITS) {
  361.          Eprint("Too many full OMITs");
  362.      return E_NO_MEM;
  363.       }
  364.       if (d > DaysInMonth(m, y)) return E_BAD_DATE;
  365.       syndrome = Julian(y, m, d);
  366.       if (!BexistsIntArray(FullOmitArray, NumFullOmits, syndrome)) {
  367.          InsertIntoSortedArray(FullOmitArray, NumFullOmits, syndrome);
  368.          NumFullOmits++;
  369.       }
  370.    }
  371.    if (tok.type == T_RemType) return E_PARSE_AS_REM;
  372.    return OK;
  373.  
  374. }
  375.