diff --git a/src/calendar.c b/src/calendar.c index 313e5a2c..c4d94165 100644 --- a/src/calendar.c +++ b/src/calendar.c @@ -871,7 +871,7 @@ static int DoCalRem(ParsePtr p, int col) char evalBuf[64]; sprintf(evalBuf, "calprefix(%d)", trig.priority); s2 = evalBuf; - r = EvalExpr(&s2, &v); + r = EvalExpr(&s2, &v, NULL); if (!r) { if (!DoCoerce(STR_TYPE, &v)) { if (DBufPuts(&obuf, v.v.str) != OK) { @@ -908,7 +908,7 @@ static int DoCalRem(ParsePtr p, int col) char evalBuf[64]; sprintf(evalBuf, "calsuffix(%d)", trig.priority); s2 = evalBuf; - r = EvalExpr(&s2, &v); + r = EvalExpr(&s2, &v, NULL); if (!r) { if (!DoCoerce(STR_TYPE, &v)) { if (DBufPuts(&obuf, v.v.str) != OK) { diff --git a/src/dorem.c b/src/dorem.c index 32208fa4..fc30a842 100644 --- a/src/dorem.c +++ b/src/dorem.c @@ -109,8 +109,13 @@ int DoRem(ParsePtr p) if (PurgeMode) { if (trig.expired || jul < JulianToday) { if (p->expr_happened) { - PurgeEchoLine("%s\n", "#!P: Next line may have expired, but contains expression"); - PurgeEchoLine("%s\n", CurLine); + if (p->nonconst_expr) { + PurgeEchoLine("%s\n", "#!P: Next line may have expired, but contains non-constant expression"); + PurgeEchoLine("%s\n", CurLine); + } else { + PurgeEchoLine("%s\n", "#!P: Next line has expired, but contains expression... please verify"); + PurgeEchoLine("#!P: Expired: %s\n", CurLine); + } } else { PurgeEchoLine("#!P: Expired: %s\n", CurLine); } @@ -780,7 +785,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul) if (UserFuncExists("msgprefix") == 1) { sprintf(PrioExpr, "msgprefix(%d)", t->priority); s = PrioExpr; - r = EvalExpr(&s, &v); + r = EvalExpr(&s, &v, NULL); if (!r) { if (!DoCoerce(STR_TYPE, &v)) { if (DBufPuts(&buf, v.v.str) != OK) { @@ -799,7 +804,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul) if (UserFuncExists("msgsuffix") == 1) { sprintf(PrioExpr, "msgsuffix(%d)", t->priority); s = PrioExpr; - r = EvalExpr(&s, &v); + r = EvalExpr(&s, &v, NULL); if (!r) { if (!DoCoerce(STR_TYPE, &v)) { if (DBufPuts(&buf, v.v.str) != OK) { @@ -1098,7 +1103,7 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err) for (i=1; ; i++) { sprintf(buffer, "%s(%d)", t->warn, i); s = buffer; - r = EvalExpr(&s, &v); + r = EvalExpr(&s, &v, NULL); if (r) { Eprint("%s: `%s': %s", ErrMsg[M_BAD_WARN_FUNC], t->warn, ErrMsg[r]); diff --git a/src/expr.c b/src/expr.c index bdb3b3cc..31f832d8 100644 --- a/src/expr.c +++ b/src/expr.c @@ -41,7 +41,7 @@ static int Multiply(void), Divide(void), Mod(void), Add(void), UnMinus(void), LogNot(void), Compare(int); -static int MakeValue (char const *s, Value *v, Var *locals); +static int MakeValue (char const *s, Value *v, Var *locals, ParsePtr p); /* Binary operators - all left-associative */ @@ -303,14 +303,14 @@ static int ParseExprToken(DynamicBuffer *buf, char const **in) /* Put the result into value pointed to by v. */ /* */ /***************************************************************/ -int EvalExpr(char const **e, Value *v) +int EvalExpr(char const **e, Value *v, ParsePtr p) { int r; OpStackPtr = 0; ValStackPtr = 0; - r = Evaluate(e, NULL); + r = Evaluate(e, NULL, p); /* Put last character parsed back onto input stream */ if (DBufLen(&ExprBuf)) (*e)--; @@ -326,7 +326,7 @@ int EvalExpr(char const **e, Value *v) } /* Evaluate - do the actual work of evaluation. */ -int Evaluate(char const **s, Var *locals) +int Evaluate(char const **s, Var *locals, ParsePtr p) { int OpBase, ValBase; int r; @@ -351,7 +351,7 @@ int Evaluate(char const **s, Var *locals) if (*DBufValue(&ExprBuf) == '(') { /* Parenthesized expression */ DBufFree(&ExprBuf); - r = Evaluate(s, locals); /* Leaves the last parsed token in ExprBuf */ + r = Evaluate(s, locals, p); /* Leaves the last parsed token in ExprBuf */ if (r) return r; r = OK; if (*DBufValue(&ExprBuf) != ')') { @@ -376,7 +376,7 @@ int Evaluate(char const **s, Var *locals) if (PeekChar(s) == ')') { /* Function has no arguments */ if (f) r = CallFunc(f, 0); else { - r = CallUserFunc(ufname, 0); + r = CallUserFunc(ufname, 0, p); free((char *) ufname); } if (r) return r; @@ -385,7 +385,7 @@ int Evaluate(char const **s, Var *locals) } else { /* Function has some arguments */ while(1) { args++; - r = Evaluate(s, locals); + r = Evaluate(s, locals, p); if (r) { if (!f) free((char *) ufname); return r; @@ -401,7 +401,7 @@ int Evaluate(char const **s, Var *locals) } if (f) r = CallFunc(f, args); else { - r = CallUserFunc(ufname, args); + r = CallUserFunc(ufname, args, p); free((char *) ufname); } DBufFree(&ExprBuf); @@ -422,7 +422,7 @@ int Evaluate(char const **s, Var *locals) DBufFree(&ExprBuf); return E_ILLEGAL_CHAR; } else { /* Must be a literal value */ - r = MakeValue(DBufValue(&ExprBuf), &va, locals); + r = MakeValue(DBufValue(&ExprBuf), &va, locals, p); DBufFree(&ExprBuf); if (r) return r; PushValStack(va); @@ -486,7 +486,7 @@ int Evaluate(char const **s, Var *locals) /* a date or the value of a symbol. */ /* */ /***************************************************************/ -static int MakeValue(char const *s, Value *v, Var *locals) +static int MakeValue(char const *s, Value *v, Var *locals, ParsePtr p) { int len; int h, m, r; @@ -541,6 +541,7 @@ static int MakeValue(char const *s, Value *v, Var *locals) v->v.val = len; return OK; } else if (*s == '$') { /* A system variable */ + if (p) p->nonconst_expr = 1; if (DebugFlag & DB_PRTEXPR) fprintf(ErrFp, "%s => ", s); r = GetSysVar(s+1, v); @@ -551,9 +552,11 @@ static int MakeValue(char const *s, Value *v, Var *locals) Putc('\n', ErrFp); } return r; - } else /* Must be a symbol */ + } else { /* Must be a symbol */ + if (p) p->nonconst_expr = 1; if (DebugFlag & DB_PRTEXPR) fprintf(ErrFp, "%s => ", s); + } r = GetVarValue(s, v, locals); if (! (DebugFlag & DB_PRTEXPR)) return r; if (r == OK) { diff --git a/src/files.c b/src/files.c index bce25686..89aa376c 100644 --- a/src/files.c +++ b/src/files.c @@ -200,6 +200,11 @@ static int ReadLineFromFile(void) } if (feof(fp)) { FCLOSE(fp); + if ((DBufLen(&buf) == 0) && + (DBufLen(&LineBuffer) == 0) && PurgeMode) { + if (PurgeFP != NULL && PurgeFP != stdout) fclose(PurgeFP); + PurgeFP = NULL; + } } l = DBufLen(&buf); if (l && (DBufValue(&buf)[l-1] == '\\')) { diff --git a/src/globals.h b/src/globals.h index df0a64c7..b97f0377 100644 --- a/src/globals.h +++ b/src/globals.h @@ -80,7 +80,7 @@ EXTERN INIT( int MaxStringLen, MAX_STR_LEN); EXTERN INIT( char *FileName, NULL); EXTERN INIT( int UseStdin, 0); EXTERN INIT( int PurgeMode, 0); -EXTERN INIT( int PurgeIncludeDepth, 99999); +EXTERN INIT( int PurgeIncludeDepth, 0); EXTERN FILE *ErrFp; EXTERN INIT( FILE *PurgeFP, NULL); EXTERN INIT( int NumIfs, 0); diff --git a/src/init.c b/src/init.c index d10d7ed8..abeee905 100644 --- a/src/init.c +++ b/src/init.c @@ -754,7 +754,7 @@ static void InitializeVar(char const *str) return; } - r=EvalExpr(&expr, &val); + r=EvalExpr(&expr, &val, NULL); if (r) { fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]); return; diff --git a/src/main.c b/src/main.c index 6b1f7063..832dc0c4 100644 --- a/src/main.c +++ b/src/main.c @@ -192,7 +192,9 @@ static void DoReminders(void) { /*** IGNORE THE LINE ***/ if (PurgeMode) { - PurgeEchoLine("%s\n", CurLine); + if (strncmp(CurLine, "#!P", 3)) { + PurgeEchoLine("%s\n", CurLine); + } } } else { @@ -203,6 +205,9 @@ static void DoReminders(void) case T_Empty: case T_Comment: + if (!strncmp(CurLine, "#!P", 3)) { + purge_handled = 1; + } break; case T_Rem: r=DoRem(&p); purge_handled = 1; break; @@ -387,7 +392,7 @@ int ParseChar(ParsePtr p, int *err, int peek) } p->expr_happened = 1; p->pos++; - r = EvalExpr(&(p->pos), &val); + r = EvalExpr(&(p->pos), &val, p); if (r) { *err = r; DestroyParser(p); @@ -530,7 +535,7 @@ int EvaluateExpr(ParsePtr p, Value *v) (p->pos)++; bracketed = 1; } - r = EvalExpr(&(p->pos), v); + r = EvalExpr(&(p->pos), v, p); if (r) return r; if (bracketed) { if (*p->pos != END_OF_EXPR) return E_MISS_END; @@ -607,6 +612,7 @@ void CreateParser(char const *s, ParsePtr p) p->allownested = 1; p->tokenPushed = NULL; p->expr_happened = 0; + p->nonconst_expr = 0; DBufInit(&p->pushedToken); } diff --git a/src/omit.c b/src/omit.c index 57e4a065..f564325d 100644 --- a/src/omit.c +++ b/src/omit.c @@ -198,7 +198,7 @@ int IsOmitted(int jul, int localomit, char const *omitfunc, int *omit) sprintf(expr, "%s('%04d-%02d-%02d')", omitfunc, y, m+1, d); s = expr; - r = EvalExpr(&s, &v); + r = EvalExpr(&s, &v, NULL); if (r) return r; if (v.type == INT_TYPE && v.v.val != 0) { *omit = 1; diff --git a/src/protos.h b/src/protos.h index 9c2c1db4..6c665351 100644 --- a/src/protos.h +++ b/src/protos.h @@ -21,7 +21,7 @@ #include "dynbuf.h" -int CallUserFunc (char const *name, int nargs); +int CallUserFunc (char const *name, int nargs, ParsePtr p); int DoFset (ParsePtr p); void ProduceCalendar (void); char const *SimpleTime (int tim); @@ -35,7 +35,7 @@ int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int jul, int *err); int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul, int mode); int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int jul, int tim); int ParseLiteralDate (char const **s, int *jul, int *tim); -int EvalExpr (char const **e, Value *v); +int EvalExpr (char const **e, Value *v, ParsePtr p); int DoCoerce (char type, Value *v); void PrintValue (Value *v, FILE *fp); int CopyValue (Value *dest, const Value *src); @@ -55,7 +55,7 @@ int ParseChar (ParsePtr p, int *err, int peek); int ParseToken (ParsePtr p, DynamicBuffer *dbuf); int ParseIdentifier (ParsePtr p, DynamicBuffer *dbuf); int EvaluateExpr (ParsePtr p, Value *v); -int Evaluate (char const **s, Var *locals); +int Evaluate (char const **s, Var *locals, ParsePtr p); int FnPopValStack (Value *val); void Eprint (char const *fmt, ...); void OutputLine (FILE *fp); diff --git a/src/queue.c b/src/queue.c index 4d023593..e442e1e9 100644 --- a/src/queue.c +++ b/src/queue.c @@ -411,7 +411,7 @@ static int CalculateNextTimeUsingSched(QueuedRem *q) char exprBuf[VAR_NAME_LEN+32]; sprintf(exprBuf, "%s(%d)", q->sched, q->ntrig); s = exprBuf; - r = EvalExpr(&s, &v); + r = EvalExpr(&s, &v, NULL); if (r) { q->sched[0] = 0; return NO_TIME; diff --git a/src/sort.c b/src/sort.c index d6e3b716..1531d126 100644 --- a/src/sort.c +++ b/src/sort.c @@ -181,7 +181,7 @@ static void IssueSortBanner(int jul) FromJulian(jul, &y, &m, &d); sprintf(BanExpr, "sortbanner('%04d/%02d/%02d')", y, m+1, d); - y = EvalExpr(&s, &v); + y = EvalExpr(&s, &v, NULL); if (y) return; if (DoCoerce(STR_TYPE, &v)) return; DBufInit(&buf); diff --git a/src/types.h b/src/types.h index ecfd6d9b..feb499e7 100644 --- a/src/types.h +++ b/src/types.h @@ -96,6 +96,7 @@ typedef struct { DynamicBuffer pushedToken; /* Pushed-back token */ char const *tokenPushed; /* NULL if no pushed-back token */ char expr_happened; /* Did we encounter an [expression] ? */ + char nonconst_expr; /* Did we encounter a non-constant [expression] ? */ } Parser; typedef Parser *ParsePtr; /* Pointer to parser structure */ diff --git a/src/userfns.c b/src/userfns.c index 115c6fb7..67ab3e85 100644 --- a/src/userfns.c +++ b/src/userfns.c @@ -243,7 +243,7 @@ static void FSet(UserFunc *f) /* Call a user-defined function. */ /* */ /***************************************************************/ -int CallUserFunc(char const *name, int nargs) +int CallUserFunc(char const *name, int nargs, ParsePtr p) { UserFunc *f; int h = HashVal(name) % FUNC_HASH_SIZE; @@ -301,7 +301,7 @@ int CallUserFunc(char const *name, int nargs) /* Skip the opening bracket, if there's one */ while (isempty(*s)) s++; if (*s == BEG_OF_EXPR) s++; - h = Evaluate(&s, f->locals); + h = Evaluate(&s, f->locals, p); f->IsActive = 0; DestroyLocalVals(f); if (DebugFlag &DB_PRTEXPR) { diff --git a/tests/purge_dir/f3.rem b/tests/purge_dir/f3.rem index b73d3844..35025012 100644 --- a/tests/purge_dir/f3.rem +++ b/tests/purge_dir/f3.rem @@ -16,14 +16,26 @@ IFTRIG 1991 REM MSG wookie ENDIF -REM [1990+1] MSG old-with-expression +REM [1990+1] MSG old-with-constant-expression REM [1990+1] \ - MSG Continued line + MSG Continued line-old-with-constant-expression REM 1990 \ MSG expired-continued-line +set y 1990 + +REM [y+1] MSG old-with-nonconstant-expression + +# A comment that should be preserved + +#!P A comment that should be nuked because it \ +starts with #!P + +REM [y+1] \ + MSG Continued-line-old-with-nonconstant-expression + OMIT 25 Dec MSG woaaahh! OMIT 24 Dec diff --git a/tests/test-rem b/tests/test-rem index ba808afd..77174f4a 100644 --- a/tests/test-rem +++ b/tests/test-rem @@ -68,7 +68,7 @@ echo "Sort Test" >> ../tests/test.out (echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -gaaad - 1 Jan 2000 >> ../tests/test.out 2>&1 echo "Purge Test" >> ../tests/test.out -../src/remind -j ../tests/purge_dir/f1.rem >> ../tests/test.out 2>&1 +../src/remind -j999 ../tests/purge_dir/f1.rem >> ../tests/test.out 2>&1 echo "F1" >> ../tests/test.out cat ../tests/purge_dir/f1.rem.purged >> ../tests/test.out echo "F2" >> ../tests/test.out diff --git a/tests/test.cmp b/tests/test.cmp index 57c30ec2..0d0430cd 100644 --- a/tests/test.cmp +++ b/tests/test.cmp @@ -2166,7 +2166,6 @@ REM 3 feb 2012 MSG new #!P: Expired: REM 3 1998 MSG old INCLUDE [filedir()]/f3.rem - F3 # This is f3.rem @@ -2191,16 +2190,28 @@ IFTRIG 1991 REM MSG wookie ENDIF -#!P: Next line may have expired, but contains expression -REM [1990+1] MSG old-with-expression +#!P: Next line has expired, but contains expression... please verify +#!P: Expired: REM [1990+1] MSG old-with-constant-expression -#!P: Next line may have expired, but contains expression -REM [1990+1] \ - MSG Continued line +#!P: Next line has expired, but contains expression... please verify +#!P: Expired: REM [1990+1] \ + MSG Continued line-old-with-constant-expression #!P: Expired: REM 1990 \ MSG expired-continued-line +set y 1990 + +#!P: Next line may have expired, but contains non-constant expression +REM [y+1] MSG old-with-nonconstant-expression + +# A comment that should be preserved + + +#!P: Next line may have expired, but contains non-constant expression +REM [y+1] \ + MSG Continued-line-old-with-nonconstant-expression + OMIT 25 Dec MSG woaaahh! OMIT 24 Dec @@ -2222,7 +2233,6 @@ DUMP $ EXIT 0 PRESERVE i - ../tests/runtest.rem(2): shell(): RUN disabled ../tests/runinc.rem(1): shell(): RUN disabled ../tests/runinc.rem(3): shell(): RUN disabled