ftp.nice.ch/pub/next/unix/calendars/remind.3.0.13.N.bs.tar.gz#/remind-3.0.13/omit.c

This is omit.c in view mode; [Download] [Up]

/***************************************************************/
/*                                                             */
/*  OMIT.C                                                     */
/*                                                             */
/*  This file handles all global OMIT commands, and maintains  */
/*  the data structures for OMITted dates.                     */
/*                                                             */
/*  This file is part of REMIND.                               */
/*  Copyright (C) 1992, 1993, 1994 by David F. Skoll           */
/*                                                             */
/***************************************************************/
#include "config.h"
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include "types.h"
#include "protos.h"
#include "globals.h"
#include "err.h"

PRIVATE int BexistsIntArray ARGS ((int array[], int num, int key));
PRIVATE void InsertIntoSortedArray ARGS ((int *array, int num, int key));

/* Arrays for the global omits */
static int FullOmitArray[MAX_FULL_OMITS];
static int PartialOmitArray[MAX_PARTIAL_OMITS];

/* How many of each omit types do we have? */
static int NumFullOmits, NumPartialOmits;

/* The structure for saving and restoring OMIT contexts */
typedef struct omitcontext {
   struct omitcontext *next;
   int numfull, numpart;
   int *fullsave;
   int *partsave;
} OmitContext;

/* The stack of saved omit contexts */
static OmitContext *SavedOmitContexts = NULL;

/***************************************************************/
/*                                                             */
/*  ClearGlobalOmits                                           */
/*                                                             */
/*  Clear all the global OMIT context.                         */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int ClearGlobalOmits(void)
#else
int ClearGlobalOmits()
#endif
{
   NumFullOmits = NumPartialOmits = 0;
   return OK;
}

/***************************************************************/
/*                                                             */
/*  DoClear                                                    */
/*                                                             */
/*  The command-line function CLEAR-OMIT-CONTEXT               */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoClear(ParsePtr p)
#else
int DoClear(p)
ParsePtr p;
#endif
{
   ClearGlobalOmits();
   return VerifyEoln(p);
}

/***************************************************************/
/*                                                             */
/*  DestroyOmitContexts                                        */
/*                                                             */
/*  Free all the memory used by saved OMIT contexts.           */
/*  As a side effect, return the number of OMIT contexts       */
/*  destroyed.                                                 */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DestroyOmitContexts(void)
#else
int DestroyOmitContexts()
#endif
{
   OmitContext *c = SavedOmitContexts;
   OmitContext *d;
   int num = 0;

   while (c) {
      num++;
      if (c->fullsave) free(c->fullsave);
      if (c->partsave) free(c->partsave);
      d = c->next;
      free(c);
      c = d;
   }
   SavedOmitContexts = NULL;
   return num;
}

/***************************************************************/
/*                                                             */
/*  PushOmitContext                                            */
/*                                                             */
/*  Push the OMIT context on to the stack.                     */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int PushOmitContext(ParsePtr p)
#else
int PushOmitContext(p)
ParsePtr p;
#endif
{
   register int i;
   OmitContext *context;

/* Create the saved context */
   context = NEW(OmitContext);
   if (!context) return E_NO_MEM;

   context->numfull = NumFullOmits;
   context->numpart = NumPartialOmits;
   context->fullsave = (int *) malloc(NumFullOmits * sizeof(int));
   if (NumFullOmits && !context->fullsave) {
      free(context);
      return E_NO_MEM;
   }
   context->partsave = (int *) malloc(NumPartialOmits * sizeof(int));
   if (NumPartialOmits && !context->partsave) {
      free(context->fullsave);
      free(context);
      return E_NO_MEM;
   }
      
/* Copy the context over */
   for (i=0; i<NumFullOmits; i++)
      *(context->fullsave + i) = FullOmitArray[i];

   for (i=0; i<NumPartialOmits; i++)
      *(context->partsave + i) = PartialOmitArray[i];

/* Add the context to the stack */
   context->next = SavedOmitContexts;
   SavedOmitContexts = context;
   return VerifyEoln(p);
}

/***************************************************************/
/*                                                             */
/*  PopOmitContext                                             */
/*                                                             */
/*  Pop the OMIT context off of the stack.                     */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int PopOmitContext(ParsePtr p)
#else
int PopOmitContext(p)
ParsePtr p;
#endif
{

   register int i;
   OmitContext *c = SavedOmitContexts;

   if (!c) return E_POP_NO_PUSH;
   NumFullOmits = c->numfull;
   NumPartialOmits = c->numpart;

/* Copy the context over */
   for (i=0; i<NumFullOmits; i++)
      FullOmitArray[i] = *(c->fullsave + i);

   for (i=0; i<NumPartialOmits; i++)
      PartialOmitArray[i] = *(c->partsave + i);

/* Remove the context from the stack */
   SavedOmitContexts = c->next;

/* Free memory used by the saved context */
   if (c->partsave) free(c->partsave);
   if (c->fullsave) free(c->fullsave);
   free(c);

   return VerifyEoln(p);
}

/***************************************************************/
/*                                                             */
/*  IsOmitted                                                  */
/*                                                             */
/*  Return non-zero if date is OMITted, zero if it is not.     */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int IsOmitted(int jul, int localomit)
#else
int IsOmitted(jul, localomit)
int jul, localomit;
#endif
{
   int y, m, d;

   /* Is it omitted because of local omits? */
   if (localomit & (1 << (jul % 7))) return 1;

   /* Is it omitted because of fully-specified omits? */
   if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) return 1;

   /* Get the syndrome */
   FromJulian(jul, &y, &m, &d);
   if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d))
      return 1;

   /* Not omitted */
   return 0;
}

/***************************************************************/
/*                                                             */
/*  BexistsIntArray                                            */
/*                                                             */
/*  Perform a binary search on an integer array.  Return 1 if  */
/*  element is found, 0 otherwise.                             */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int BexistsIntArray(int array[], int num, int key)
#else
static int BexistsIntArray(array, num, key)
int array[], num, key;
#endif
{
   int top=num-1, bot=0, mid;

   while (top >= bot) {
      mid = (top+bot)/2;
      if (array[mid] == key) return 1;
      else if (array[mid] > key) top = mid-1;
      else bot=mid+1;
   }
   return 0;
}

/***************************************************************/
/*                                                             */
/*  InsertIntoSortedArray                                      */
/*                                                             */
/*  Insert a key into a sorted array.  We assume that there is */
/*  room in the array for it.                                  */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void InsertIntoSortedArray(int *array, int num, int key)
#else
static void InsertIntoSortedArray(array, num, key)
int *array, num, key;
#endif
{
   /* num is number of elements CURRENTLY in the array. */
   int *cur = array+num;

   while (cur > array && *(cur-1) > key) {
      *cur = *(cur-1);
      cur--;
   }
   *cur = key;
}

/***************************************************************/
/*                                                             */
/*  DoOmit                                                     */
/*                                                             */
/*  Do a global OMIT command.                                  */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoOmit(ParsePtr p)
#else
int DoOmit(p)
ParsePtr p;
#endif
{
   int y = NO_YR, m = NO_MON, d = NO_DAY, r;
   Token tok;
   int parsing=1;
   int syndrome;
   
/* Parse the OMIT.  We need a month and day; year is optional. */
   while(parsing) {
      if ( (r=ParseToken(p, TokBuffer)) ) return r;
      FindToken(TokBuffer, &tok);
      switch (tok.type) {
         case T_Year:
	    if (y != NO_YR) return E_YR_TWICE;
	    y = tok.val;
	    break;

         case T_Month:
	    if (m != NO_MON) return E_MON_TWICE;
	    m = tok.val;
	    break;

         case T_Day:
	    if (d != NO_DAY) return E_DAY_TWICE;
	    d = tok.val;
	    break;
	 
	 case T_Delta:
	    break;

	 case T_Empty:
	 case T_Comment:
	 case T_RemType:
	 case T_Priority:
	    parsing = 0;
	    break;

	 default:
	    Eprint("%s: '%s' (OMIT)", ErrMsg[E_UNKNOWN_TOKEN], TokBuffer);
	    return E_UNKNOWN_TOKEN;
      }
   }
   if (m == NO_MON || d == NO_DAY) return E_SPEC_MON_DAY;

   if (y == NO_YR) {
      if (NumPartialOmits == MAX_PARTIAL_OMITS) return E_2MANY_PART;

      if (d > MonthDays[m]) return E_BAD_DATE;
      syndrome = (m<<5) + d;
      if (!BexistsIntArray(PartialOmitArray, NumPartialOmits, syndrome)) {
         InsertIntoSortedArray(PartialOmitArray, NumPartialOmits, syndrome);
         NumPartialOmits++;
      }
   } else {
      if (NumFullOmits == MAX_FULL_OMITS) return E_2MANY_FULL;

      if (d > DaysInMonth(m, y)) return E_BAD_DATE;
      syndrome = Julian(y, m, d);
      if (!BexistsIntArray(FullOmitArray, NumFullOmits, syndrome)) {
         InsertIntoSortedArray(FullOmitArray, NumFullOmits, syndrome);
         NumFullOmits++;
      }
   }
   if (tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
   return OK;

}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.