Implement OMITFUNC clause in REM command.

This commit is contained in:
David F. Skoll
2008-08-29 20:48:58 -04:00
parent 670369121e
commit 8d8d4b667d
8 changed files with 115 additions and 27 deletions

View File

@@ -145,6 +145,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
trig->priority = DefaultPrio;
trig->sched[0] = 0;
trig->warn[0] = 0;
trig->omitfunc[0] = 0;
trig->tag[0] = 0;
trig->passthru[0] = 0;
tim->ttime = NO_TIME;
@@ -266,6 +267,13 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday;
return OK;
case T_OmitFunc:
r=ParseToken(s, &buf);
if (r) return r;
StrnCpy(trig->omitfunc, DBufValue(&buf), VAR_NAME_LEN);
DBufFree(&buf);
break;
case T_Warn:
r=ParseToken(s, &buf);
if(r) return r;
@@ -551,7 +559,7 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
{
int r, y, m, d;
char PrioExpr[25];
char PrioExpr[VAR_NAME_LEN+25];
char tmpBuf[64];
DynamicBuffer buf, calRow;
DynamicBuffer pre_buf;
@@ -795,9 +803,19 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
jul = jul + t->delta;
else {
r = t->delta;
while(r && jul > JulianToday) {
int iter = 0;
int max = MaxSatIter;
if (max < r*2) max = r*2;
while(iter++ < max) {
if (!r || (jul <= JulianToday)) {
break;
}
jul--;
if (!IsOmitted(jul, t->localomit)) r--;
if (!IsOmitted(jul, t->localomit, t->omitfunc)) r--;
}
if (iter > max) {
/* TODO: Somehow communicate error back to caller!! */
return 0;
}
}
}
@@ -996,10 +1014,17 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul)
if (JulianToday + v.v.val == jul) return 1;
} else {
int j = jul;
while (v.v.val) {
int iter = 0;
int max = MaxSatIter;
if (max < v.v.val * 2) max = v.v.val*2;
while(iter++ <= max) {
j--;
if (!IsOmitted(j, t->localomit)) v.v.val++;
if (!IsOmitted(j, t->localomit, t->omitfunc)) v.v.val++;
if (!v.v.val) {
break;
}
}
if (iter > max) return 0;
if (j == JulianToday) return 1;
}
}

View File

@@ -1302,7 +1302,7 @@ static int FIsomitted(void)
{
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
RetVal.type = INT_TYPE;
RetVal.v.val = IsOmitted(DATEPART(ARG(0)), 0);
RetVal.v.val = IsOmitted(DATEPART(ARG(0)), 0, NULL);
return OK;
}
@@ -2478,7 +2478,7 @@ FNonomitted(void)
ans = 0;
while (d1 < d2) {
if (!IsOmitted(d1++, localomit)) {
if (!IsOmitted(d1++, localomit, NULL)) {
ans++;
}
}

View File

@@ -20,6 +20,7 @@
#include "protos.h"
#include "globals.h"
#include "err.h"
#include "expr.h"
static int BexistsIntArray (int array[], int num, int key);
static void InsertIntoSortedArray (int *array, int num, int key);
@@ -180,7 +181,7 @@ int PopOmitContext(ParsePtr p)
/* Return non-zero if date is OMITted, zero if it is not. */
/* */
/***************************************************************/
int IsOmitted(int jul, int localomit)
int IsOmitted(int jul, int localomit, char const *omitfunc)
{
int y, m, d;
@@ -195,6 +196,23 @@ int IsOmitted(int jul, int localomit)
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d))
return 1;
/* Is it omitted because of omitfunc? */
if (omitfunc && *omitfunc && UserFuncExists(omitfunc)) {
char expr[VAR_NAME_LEN + 32];
char const *s;
int r;
Value v;
sprintf(expr, "%s('%04d-%02d-%02d')",
omitfunc, y, m, d);
s = expr;
r = EvalExpr(&s, &v);
if (!r) {
if (v.type == INT_TYPE && v.v.val != 0) {
return 1;
}
}
}
/* Not omitted */
return 0;
}

View File

@@ -75,7 +75,7 @@ int DoClear (ParsePtr p);
int DestroyOmitContexts (void);
int PushOmitContext (ParsePtr p);
int PopOmitContext (ParsePtr p);
int IsOmitted (int jul, int localomit);
int IsOmitted (int jul, int localomit, char const *omitfunc);
int DoOmit (ParsePtr p);
int QueueReminder (ParsePtr p, Trigger *trig, TimeTrig *tim, char const *sched);
void HandleQueuedReminders (void);

View File

@@ -74,6 +74,7 @@ Token TokArray[] = {
{ "november", 3, T_Month, 10 },
{ "october", 3, T_Month, 9 },
{ "omit", 3, T_Omit, 0 },
{ "omitfunc", 8, T_OmitFunc, 0 },
{ "once", 3, T_Once, 0 },
{ "pop-omit-context", 3, T_Pop, 0 },
{ "preserve", 8, T_Preserve, 0 },

View File

@@ -294,8 +294,19 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
/* Next: If it's an "AFTER"-type skip, back up
until we're at the start of a block of holidays */
if (trig->skip == AFTER_SKIP)
while (IsOmitted(start-1, trig->localomit)) start--;
if (trig->skip == AFTER_SKIP) {
int iter = 0;
while (iter++ <= MaxSatIter) {
if (!IsOmitted(start-1, trig->localomit, trig->omitfunc)) {
break;
}
start--;
}
if (iter > MaxSatIter) {
/* omitfunc must have returned "true" too often */
return -2;
}
}
/* Find the next simple trigger */
simple = NextSimpleTrig(start, trig, err);
@@ -309,12 +320,23 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
/* If there's a BACK, back up... */
if (trig->back != NO_BACK) {
mod = trig->back;
if (mod < 0) simple += mod;
else
while(mod) {
simple--;
if (!IsOmitted(simple, trig->localomit)) mod--;
if (mod < 0) {
simple += mod;
}
else {
int iter = 0;
int max = MaxSatIter;
if (max < mod*2) {
max = mod*2;
}
while(iter++ <= max) {
if (!mod) {
break;
}
simple--;
if (!IsOmitted(simple, trig->localomit, trig->omitfunc)) mod--;
}
}
}
/* If there's a REP, calculate the next occurrence */
@@ -327,12 +349,32 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
}
/* If it's a "BEFORE"-type skip, back up */
if (trig->skip == BEFORE_SKIP)
while(IsOmitted(simple, trig->localomit)) simple--;
if (trig->skip == BEFORE_SKIP) {
int iter = 0;
while(iter++ <= MaxSatIter) {
if (!IsOmitted(simple, trig->localomit, trig->omitfunc)) {
break;
}
simple--;
}
if (iter > MaxSatIter) {
return -2;
}
}
/* If it's an "AFTER"-type skip, jump ahead */
if (trig->skip == AFTER_SKIP)
while (IsOmitted(simple, trig->localomit)) simple++;
if (trig->skip == AFTER_SKIP) {
int iter = 0;
while (iter++ <= MaxSatIter) {
if (!IsOmitted(simple, trig->localomit, trig->omitfunc)) {
break;
}
simple++;
}
if (iter > MaxSatIter) {
return -2;
}
}
/* Return the date */
return simple;
@@ -373,8 +415,8 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
*err = E_REP_FULSPEC;
return -1;
}
while (nattempts++ < TRIG_ATTEMPTS) {
result = GetNextTriggerDate(trig, start, err, &nextstart);
@@ -390,7 +432,7 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
/* If result is >= today, great! */
if (result >= today &&
(trig->skip != SKIP_SKIP || !IsOmitted(result, trig->localomit))) {
(trig->skip != SKIP_SKIP || !IsOmitted(result, trig->localomit, trig->omitfunc))) {
LastTriggerDate = result; /* Save in global var */
LastTrigValid = 1;
if (DebugFlag & DB_PRTTRIG) {
@@ -421,7 +463,7 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
}
if (trig->skip == SKIP_SKIP &&
IsOmitted(result, trig->localomit) &&
IsOmitted(result, trig->localomit, trig->omitfunc) &&
nextstart <= start &&
result >= start) {
nextstart = result + 1;

View File

@@ -56,6 +56,7 @@ typedef struct {
int priority;
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
char warn[VAR_NAME_LEN+1]; /* Warning function */
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
char tag[TAG_LEN+1];
char passthru[PASSTHRU_LEN+1];
} Trigger;
@@ -148,7 +149,8 @@ enum TokTypes
T_Warn,
T_Tag,
T_Duration,
T_LongTime
T_LongTime,
T_OmitFunc
};
/* The structure of a token */

View File

@@ -638,7 +638,7 @@ set a057 value("a05"+"6")
"a05" + "6" => "a056"
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
set a058 version()
version() => "03.01.06"
version() => "03.01.05"
set a059 wkday(today())
today() => 1991-02-16
wkday(1991-02-16) => "Saturday"
@@ -779,7 +779,7 @@ dump
a048 "foo"
a067 "INT"
a039 "February"
a058 "03.01.06"
a058 "03.01.05"
a077 "1992 92
"
a049 21