1
/***************************************************************/
5
/* This file handles all global OMIT commands, and maintains */
6
/* the data structures for OMITted dates. */
8
/* This file is part of REMIND. */
9
/* Copyright (C) 1992-1998 by David F. Skoll */
10
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
12
/***************************************************************/
15
static char const RCSID[] = "$Id: omit.c,v 1.6 2000/02/18 03:46:03 dfs Exp $";
32
PRIVATE int BexistsIntArray ARGS ((int array[], int num, int key));
33
PRIVATE void InsertIntoSortedArray ARGS ((int *array, int num, int key));
35
/* Arrays for the global omits */
36
static int FullOmitArray[MAX_FULL_OMITS];
37
static int PartialOmitArray[MAX_PARTIAL_OMITS];
39
/* How many of each omit types do we have? */
40
static int NumFullOmits, NumPartialOmits;
42
/* The structure for saving and restoring OMIT contexts */
43
typedef struct omitcontext {
44
struct omitcontext *next;
50
/* The stack of saved omit contexts */
51
static OmitContext *SavedOmitContexts = NULL;
53
/***************************************************************/
55
/* ClearGlobalOmits */
57
/* Clear all the global OMIT context. */
59
/***************************************************************/
61
PUBLIC int ClearGlobalOmits(void)
63
int ClearGlobalOmits()
66
NumFullOmits = NumPartialOmits = 0;
70
/***************************************************************/
74
/* The command-line function CLEAR-OMIT-CONTEXT */
76
/***************************************************************/
78
PUBLIC int DoClear(ParsePtr p)
88
/***************************************************************/
90
/* DestroyOmitContexts */
92
/* Free all the memory used by saved OMIT contexts. */
93
/* As a side effect, return the number of OMIT contexts */
96
/***************************************************************/
98
PUBLIC int DestroyOmitContexts(void)
100
int DestroyOmitContexts()
103
OmitContext *c = SavedOmitContexts;
109
if (c->fullsave) free(c->fullsave);
110
if (c->partsave) free(c->partsave);
115
SavedOmitContexts = NULL;
119
/***************************************************************/
121
/* PushOmitContext */
123
/* Push the OMIT context on to the stack. */
125
/***************************************************************/
127
PUBLIC int PushOmitContext(ParsePtr p)
129
int PushOmitContext(p)
134
OmitContext *context;
136
/* Create the saved context */
137
context = NEW(OmitContext);
138
if (!context) return E_NO_MEM;
140
context->numfull = NumFullOmits;
141
context->numpart = NumPartialOmits;
142
context->fullsave = (int *) malloc(NumFullOmits * sizeof(int));
143
if (NumFullOmits && !context->fullsave) {
147
context->partsave = (int *) malloc(NumPartialOmits * sizeof(int));
148
if (NumPartialOmits && !context->partsave) {
149
free(context->fullsave);
154
/* Copy the context over */
155
for (i=0; i<NumFullOmits; i++)
156
*(context->fullsave + i) = FullOmitArray[i];
158
for (i=0; i<NumPartialOmits; i++)
159
*(context->partsave + i) = PartialOmitArray[i];
161
/* Add the context to the stack */
162
context->next = SavedOmitContexts;
163
SavedOmitContexts = context;
164
return VerifyEoln(p);
167
/***************************************************************/
171
/* Pop the OMIT context off of the stack. */
173
/***************************************************************/
175
PUBLIC int PopOmitContext(ParsePtr p)
177
int PopOmitContext(p)
183
OmitContext *c = SavedOmitContexts;
185
if (!c) return E_POP_NO_PUSH;
186
NumFullOmits = c->numfull;
187
NumPartialOmits = c->numpart;
189
/* Copy the context over */
190
for (i=0; i<NumFullOmits; i++)
191
FullOmitArray[i] = *(c->fullsave + i);
193
for (i=0; i<NumPartialOmits; i++)
194
PartialOmitArray[i] = *(c->partsave + i);
196
/* Remove the context from the stack */
197
SavedOmitContexts = c->next;
199
/* Free memory used by the saved context */
200
if (c->partsave) free(c->partsave);
201
if (c->fullsave) free(c->fullsave);
204
return VerifyEoln(p);
207
/***************************************************************/
211
/* Return non-zero if date is OMITted, zero if it is not. */
213
/***************************************************************/
215
PUBLIC int IsOmitted(int jul, int localomit)
217
int IsOmitted(jul, localomit)
223
/* Is it omitted because of local omits? */
224
if (localomit & (1 << (jul % 7))) return 1;
226
/* Is it omitted because of fully-specified omits? */
227
if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) return 1;
229
/* Get the syndrome */
230
FromJulian(jul, &y, &m, &d);
231
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d))
238
/***************************************************************/
240
/* BexistsIntArray */
242
/* Perform a binary search on an integer array. Return 1 if */
243
/* element is found, 0 otherwise. */
245
/***************************************************************/
247
PRIVATE int BexistsIntArray(int array[], int num, int key)
249
static int BexistsIntArray(array, num, key)
250
int array[], num, key;
253
int top=num-1, bot=0, mid;
257
if (array[mid] == key) return 1;
258
else if (array[mid] > key) top = mid-1;
264
/***************************************************************/
266
/* InsertIntoSortedArray */
268
/* Insert a key into a sorted array. We assume that there is */
269
/* room in the array for it. */
271
/***************************************************************/
273
PRIVATE void InsertIntoSortedArray(int *array, int num, int key)
275
static void InsertIntoSortedArray(array, num, key)
276
int *array, num, key;
279
/* num is number of elements CURRENTLY in the array. */
280
int *cur = array+num;
282
while (cur > array && *(cur-1) > key) {
289
/***************************************************************/
293
/* Do a global OMIT command. */
295
/***************************************************************/
297
PUBLIC int DoOmit(ParsePtr p)
303
int y = NO_YR, m = NO_MON, d = NO_DAY, r;
311
/* Parse the OMIT. We need a month and day; year is optional. */
313
if ( (r=ParseToken(p, &buf)) ) return r;
314
FindToken(DBufValue(&buf), &tok);
318
if (y != NO_YR) return E_YR_TWICE;
324
if (m != NO_MON) return E_MON_TWICE;
330
if (d != NO_DAY) return E_DAY_TWICE;
349
Eprint("%s: `%s' (OMIT)", ErrMsg[E_UNKNOWN_TOKEN],
352
return E_UNKNOWN_TOKEN;
355
if (m == NO_MON || d == NO_DAY) return E_SPEC_MON_DAY;
358
if (NumPartialOmits == MAX_PARTIAL_OMITS) return E_2MANY_PART;
360
if (d > MonthDays[m]) return E_BAD_DATE;
361
syndrome = (m<<5) + d;
362
if (!BexistsIntArray(PartialOmitArray, NumPartialOmits, syndrome)) {
363
InsertIntoSortedArray(PartialOmitArray, NumPartialOmits, syndrome);
367
if (NumFullOmits == MAX_FULL_OMITS) return E_2MANY_FULL;
369
if (d > DaysInMonth(m, y)) return E_BAD_DATE;
370
syndrome = Julian(y, m, d);
371
if (!BexistsIntArray(FullOmitArray, NumFullOmits, syndrome)) {
372
InsertIntoSortedArray(FullOmitArray, NumFullOmits, syndrome);
376
if (tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;