diff --git a/man/remind.1.in b/man/remind.1.in index b8d7cb0d..b3ce2389 100644 --- a/man/remind.1.in +++ b/man/remind.1.in @@ -300,6 +300,11 @@ Echo lines when displaying error messages .TP .B f Trace the reading of reminder files +.TP +.B s +Upon exit, print the high-water mark of the operator and value stacks +used for expression-parsing. This is unlikely to be useful unless +you're intimately familiar with Remind's source code. .RE .TP \fB\-g\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR]]]] diff --git a/src/custom.h b/src/custom.h index 09808a6e..51429336 100644 --- a/src/custom.h +++ b/src/custom.h @@ -117,7 +117,7 @@ /*---------------------------------------------------------------------*/ /* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */ /*---------------------------------------------------------------------*/ -#define VAL_STACK_SIZE 1000 +#define VAL_STACK_SIZE 100 /*---------------------------------------------------------------------*/ /* INCLUDE_NEST: How many nested INCLUDES do we handle? */ diff --git a/src/custom.h.in b/src/custom.h.in index 09808a6e..51429336 100644 --- a/src/custom.h.in +++ b/src/custom.h.in @@ -117,7 +117,7 @@ /*---------------------------------------------------------------------*/ /* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */ /*---------------------------------------------------------------------*/ -#define VAL_STACK_SIZE 1000 +#define VAL_STACK_SIZE 100 /*---------------------------------------------------------------------*/ /* INCLUDE_NEST: How many nested INCLUDES do we handle? */ diff --git a/src/expr.c b/src/expr.c index a4f8381d..e812dfd0 100644 --- a/src/expr.c +++ b/src/expr.c @@ -87,10 +87,11 @@ extern BuiltinFunc Func[]; static Operator OpStack[OP_STACK_SIZE]; static int OpStackPtr = 0; - +static int OpStackHiWater = 0; /* ValStack can't be static - needed by funcs.c */ - Value ValStack[VAL_STACK_SIZE]; - int ValStackPtr = 0; +Value ValStack[VAL_STACK_SIZE]; +int ValStackPtr = 0; +int ValStackHiWater = 0; /***************************************************************/ /* */ @@ -1485,3 +1486,11 @@ int FnPopValStack(Value *val) return OK; } } + +void DebugExitFunc(void) +{ + if (DebugFlag & DB_EXPR_STACKS) { + fprintf(stderr, "Operator stack high water: %d\n", OpStackHiWater); + fprintf(stderr, " Value stack high water: %d\n", ValStackHiWater); + } +} diff --git a/src/expr.h b/src/expr.h index 2c75dc4e..4999511f 100644 --- a/src/expr.h +++ b/src/expr.h @@ -33,10 +33,8 @@ for speed. BEWARE: These macros invoke return if an error happens ! */ #define PushOpStack(op) \ -if (OpStackPtr >= OP_STACK_SIZE) \ -return E_OP_STK_OVER; \ -else \ -OpStack[OpStackPtr++] = (op) + do { if (OpStackPtr >= OP_STACK_SIZE) return E_OP_STK_OVER; \ + else { OpStack[OpStackPtr++] = (op); if (OpStackPtr > OpStackHiWater) OpStackHiWater = OpStackPtr; } } while(0) #define PopOpStack(op) \ if (OpStackPtr <= 0) \ @@ -45,12 +43,13 @@ else \ (op) = OpStack[--OpStackPtr] #define PushValStack(val) \ -if (ValStackPtr >= VAL_STACK_SIZE) { \ +do { if (ValStackPtr >= VAL_STACK_SIZE) { \ DestroyValue(val); \ return E_VA_STK_OVER; \ -} \ -else \ -ValStack[ValStackPtr++] = (val) +} else { \ + ValStack[ValStackPtr++] = (val); \ + if (ValStackPtr > ValStackHiWater) ValStackHiWater = ValStackPtr; \ +} } while (0); #define PopValStack(val) \ if (ValStackPtr <= 0) \ diff --git a/src/funcs.c b/src/funcs.c index 175fa4ec..e36f7a60 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -195,6 +195,7 @@ static int CacheHebYear, CacheHebMon, CacheHebDay; /* We need access to the value stack */ extern Value ValStack[]; extern int ValStackPtr; +extern int ValStackHiWater; /* Macro for accessing arguments from the value stack - args are numbered from 0 to (Nargs - 1) */ diff --git a/src/init.c b/src/init.c index b88d843e..8b73bde1 100644 --- a/src/init.c +++ b/src/init.c @@ -78,6 +78,7 @@ static void ProcessLongOption(char const *arg); * t = Display trigger dates * v = Dump variables at end * l = Display entire line in error messages + * s = Display expression-parsing stack usage before exit * -e = Send messages normally sent to stderr to stdout instead * -z[n] = Daemon mode waking up every n (def 1) minutes. * -bn = Time format for cal (0, 1, or 2) @@ -604,6 +605,7 @@ void InitRemind(int argc, char const *argv[]) case 'D': while (*arg) { switch(*arg++) { + case 's': case 'S': DebugFlag |= DB_EXPR_STACKS; break; case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break; case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break; case 't': case 'T': DebugFlag |= DB_PRTTRIG; break; diff --git a/src/main.c b/src/main.c index 88895f11..8b449d19 100644 --- a/src/main.c +++ b/src/main.c @@ -76,6 +76,8 @@ int main(int argc, char *argv[]) DBufInit(&(LastTrigger.tags)); ClearLastTriggers(); + atexit(DebugExitFunc); + if (DoCalendar || (DoSimpleCalendar && (!NextMode || PsCal))) { ProduceCalendar(); return 0; @@ -1016,6 +1018,12 @@ int DoDebug(ParsePtr p) else DebugFlag &= ~DB_ECHO_LINE; break; + case 's': + case 'S': + if (val) DebugFlag |= DB_EXPR_STACKS; + else DebugFlag &= ~DB_EXPR_STACKS; + break; + case 'x': case 'X': if (val) DebugFlag |= DB_PRTEXPR; diff --git a/src/protos.h b/src/protos.h index e47cdc47..632aec7a 100644 --- a/src/protos.h +++ b/src/protos.h @@ -174,6 +174,8 @@ int AddGlobalOmit(int dse); void set_lat_and_long_from_components(void); void set_components_from_lat_and_long(void); +void DebugExitFunc(void); + int GetTerminalBackground(void); char const *get_day_name(int wkday); diff --git a/src/types.h b/src/types.h index 280037cf..c44c9747 100644 --- a/src/types.h +++ b/src/types.h @@ -150,6 +150,7 @@ typedef Parser *ParsePtr; /* Pointer to parser structure */ #define DB_DUMP_VARS 8 #define DB_ECHO_LINE 16 #define DB_TRACE_FILES 32 +#define DB_EXPR_STACKS 64 /* Enumeration of the tokens */ enum TokTypes