diff --git a/man/remind.1 b/man/remind.1 index 67ecad84..915464f2 100644 --- a/man/remind.1 +++ b/man/remind.1 @@ -1,4 +1,4 @@ -.\" $Id: remind.1,v 1.2 1998-02-02 02:57:47 dfs Exp $ +.\" $Id: remind.1,v 1.3 1998-02-07 05:35:50 dfs Exp $ .TH REMIND 1 "1 February 1998" .UC 4 .SH NAME @@ -807,6 +807,25 @@ However, discussion must be deferred until after expressions and user-defined functions are explained. See the subsection "Precise Scheduling" further on. .PP +.B TAG AND DURATION +.PP +The \fBTAG\fR keyword lets you "tag" certain reminders. Currently, +this facility is not used, but it may be used by certain back-ends +or systems built around \fBRemind\fR. The \fBTAG\fR keyword should +be followed by a tag consisting of up to 32 characters. +.PP +The \fBDURATION\fR keyword makes sense only for timed reminders; +it specifies the duration of an event. Currently, this is not +used, but it may be used in future by back-ends or scheduling +systems built around \fBRemind\fR. For example, if you have +a 90-minute meeting starting at 1:00pm, you could use: +.PP +.nf + REM 5 March 1999 AT 13:00 DURATION 1:30 MSG Meeting +.fi +.PP +Note that \fIduration\fR is specified in hours and minutes. +.PP .SH THE SUBSTITUTION FILTER .PP Before being processed, the body of a @@ -3662,8 +3681,8 @@ The UTC functions may not be reliable under MS-DOS. The MS-DOS version of \fBRemind\fR does not support queuing or timed activation of reminders. .PP -\fBRemind\fR has some built-in limits on total line length, -substitution buffer length, number of global \fBOMIT\fRs, etc. +\fBRemind\fR has some built-in limits (for example, +number of global \fBOMIT\fRs.) .PP .SH BIBLIOGRAPHY .PP diff --git a/src/Makefile.in b/src/Makefile.in index 2bfae8a8..f2f5c6df 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,6 +1,6 @@ # Makefile.in for REMIND # -# $Id: Makefile.in,v 1.6 1998-01-20 03:14:20 dfs Exp $ +# $Id: Makefile.in,v 1.7 1998-02-07 05:35:55 dfs Exp $ VERSION= 03.00.18 SHELL= /bin/sh @@ -23,8 +23,8 @@ MANS= ../man/kall.1 ../man/rem.1 ../man/rem2ps.1 ../man/remind.1 \ .SUFFIXES: .SUFFIXES: .c .o -REMINDSRCS= calendar.c dorem.c dosubst.c expr.c files.c funcs.c globals.c \ - hbcal.c init.c main.c moon.c omit.c queue.c sort.c \ +REMINDSRCS= calendar.c dynbuf.c dorem.c dosubst.c expr.c files.c funcs.c \ + globals.c hbcal.c init.c main.c moon.c omit.c queue.c sort.c \ token.c trigger.c userfns.c utils.c var.c REMINDOBJS= $(REMINDSRCS:.c=.o) @@ -37,8 +37,8 @@ test: remind .c.o: @CC@ -c @CFLAGS@ @DEFS@ $(LANGDEF) -DUNIX $*.c -rem2ps: rem2ps.o - @CC@ @LDFLAGS@ -o rem2ps rem2ps.o +rem2ps: rem2ps.o dynbuf.o + @CC@ @LDFLAGS@ -o rem2ps rem2ps.o dynbuf.o remind: $(REMINDOBJS) @CC@ @LDFLAGS@ -o remind $(REMINDOBJS) @LIBS@ diff --git a/src/calendar.c b/src/calendar.c index 20d3858f..8ea5bb28 100644 --- a/src/calendar.c +++ b/src/calendar.c @@ -10,7 +10,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: calendar.c,v 1.4 1998-02-02 02:58:08 dfs Exp $"; +static char const RCSID[] = "$Id: calendar.c,v 1.5 1998-02-07 05:35:55 dfs Exp $"; #include #include @@ -650,10 +650,11 @@ int col; CalEntry *CurPs = CalPs[col]; CalEntry *e; char *s, *s2; - static char buf[TOKSIZE]; - static char obuf[LINELEN]; + DynamicBuffer buf, obuf; Token tok; + DBufInit(&buf); + /* Parse the trigger date and time */ if ( (r=ParseRem(p, &trig, &tim)) ) return r; @@ -665,16 +666,21 @@ int col; if (trig.typ == SAT_TYPE) { r=DoSatRemind(&trig, &tim, p); if (r) return r; - r=ParseToken(p, buf); + r=ParseToken(p, &buf); if (r) return r; - FindToken(buf, &tok); + FindToken(DBufValue(&buf), &tok); + DBufFree(&buf); if (tok.type == T_Empty || tok.type == T_Comment) return OK; if (tok.type != T_RemType || tok.val == SAT_TYPE) return E_PARSE_ERR; if (tok.val == PASSTHRU_TYPE) { - r=ParseToken(p, buf); + r=ParseToken(p, &buf); if (r) return r; - if (!*buf) return E_EOLN; - StrnCpy(trig.passthru, buf, PASSTHRU_LEN); + if (!DBufLen(&buf)) { + DBufFree(&buf); + return E_EOLN; + } + StrnCpy(trig.passthru, DBufValue(&buf), PASSTHRU_LEN); + DBufFree(&buf); } trig.typ = tok.val; jul = LastTriggerDate; @@ -702,45 +708,66 @@ int col; } /* If trigger date == today, add it to the current entry */ + DBufInit(&obuf); if (jul == JulianToday) { NumTriggered++; - s = obuf; - *s = 0; - if (DoSimpleCalendar || tim.ttime != NO_TIME) - s += strlen(SimpleTime(tim.ttime, s)); + if (DoSimpleCalendar || tim.ttime != NO_TIME) { + if (DBufPuts(&obuf, SimpleTime(tim.ttime)) != OK) { + DBufFree(&obuf); + return E_NO_MEM; + } + } if (trig.typ != PASSTHRU_TYPE && UserFuncExists("calprefix")==1) { - sprintf(buf, "calprefix(%d)", trig.priority); - s2 = buf; + char evalBuf[64]; + sprintf(evalBuf, "calprefix(%d)", trig.priority); + s2 = evalBuf; r = EvalExpr(&s2, &v); if (!r) { if (!DoCoerce(STR_TYPE, &v)) { - strcat(s, v.v.str); - s += strlen(s); + if (DBufPuts(&obuf, v.v.str) != OK) { + DestroyValue(v); + DBufFree(&obuf); + return E_NO_MEM; + } } DestroyValue(v); } } - if ( (r=DoSubst(p, s, &trig, &tim, jul, CAL_MODE)) ) return r; - if (!*s) return OK; + if ( (r=DoSubst(p, &obuf, &trig, &tim, jul, CAL_MODE)) ) { + DBufFree(&obuf); + return r; + } + if (!DBufLen(&obuf)) { + DBufFree(&obuf); + return OK; + } if (trig.typ != PASSTHRU_TYPE && UserFuncExists("calsuffix")==1) { - sprintf(buf, "calsuffix(%d)", trig.priority); - s2 = buf; + char evalBuf[64]; + sprintf(evalBuf, "calsuffix(%d)", trig.priority); + s2 = evalBuf; r = EvalExpr(&s2, &v); if (!r) { if (!DoCoerce(STR_TYPE, &v)) { - strcat(s, v.v.str); - s += strlen(s); + if (DBufPuts(&obuf, v.v.str) != OK) { + DestroyValue(v); + DBufFree(&obuf); + return E_NO_MEM; + } } DestroyValue(v); } } - s = obuf; + s = DBufValue(&obuf); if (!DoSimpleCalendar) while (isspace(*s)) s++; e = NEW(CalEntry); - if (!e) return E_NO_MEM; + if (!e) { + DBufFree(&obuf); + return E_NO_MEM; + } e->text = StrDup(s); + DBufFree(&obuf); if (!e->text) { free(e); return E_NO_MEM; @@ -890,24 +917,21 @@ static void WriteCalDays() /* SimpleTime */ /* */ /* Format the time according to simple time format. */ -/* If out is NULL, result placed in internal static buffer. */ +/* Answer is returned in a static buffer. */ /* A trailing space is always added. */ /* */ /***************************************************************/ #ifdef HAVE_PROTOS -PUBLIC char *SimpleTime(int tim, char *out) +PUBLIC char *SimpleTime(int tim) #else -char *SimpleTime(tim, out) +char *SimpleTime(tim) int tim; -char *out; #endif { - static buf[9]; + static char buf[32]; int h, min, hh; - - if (!out) out = (char *) buf; - *out = 0; + buf[0] = 0; switch(ScFormat) { @@ -918,7 +942,7 @@ char *out; if (h == 0) hh=12; else if (h > 12) hh=h-12; else hh=h; - sprintf(out, "%2d%c%02d%s ", hh, TIMESEP, min, (h>=12) ? L_PM : L_AM); + sprintf(buf, "%2d%c%02d%s ", hh, TIMESEP, min, (h>=12) ? L_PM : L_AM); } break; @@ -926,11 +950,11 @@ char *out; if (tim != NO_TIME) { h = tim / 60; min = tim % 60; - sprintf(out, "%02d%c%02d ", h, TIMESEP, min); + sprintf(buf, "%02d%c%02d ", h, TIMESEP, min); } break; } - return out; + return buf; } /***************************************************************/ diff --git a/src/custom.h b/src/custom.h index a33537fa..43ca0932 100644 --- a/src/custom.h +++ b/src/custom.h @@ -10,7 +10,7 @@ /* */ /***************************************************************/ -/* $Id: custom.h,v 1.7 1998-01-20 03:14:20 dfs Exp $ */ +/* $Id: custom.h,v 1.8 1998-02-07 05:35:56 dfs Exp $ */ /*---------------------------------------------------------------------*/ /* LAT_DEG, LAT_MIN and LAT_SEC: Latitude of your location */ @@ -134,11 +134,6 @@ /*---------------------------------------------------------------------*/ #define MAX_PRT_LEN 40 -/*---------------------------------------------------------------------*/ -/* LINELEN: The maximum length of an input line */ -/*---------------------------------------------------------------------*/ -#define LINELEN 4096 - /*---------------------------------------------------------------------*/ /* OP_STACK_SIZE: The size of the operator stack for expr. parsing */ /*---------------------------------------------------------------------*/ @@ -190,16 +185,6 @@ /*---------------------------------------------------------------------*/ #define MAX_PARTIAL_OMITS 75 -/*---------------------------------------------------------------------*/ -/* The size of statically-allocated buffers for tokens. */ -/*---------------------------------------------------------------------*/ -#define TOKSIZE 1024 - -/*---------------------------------------------------------------------*/ -/* The size of the buffer for the shell() function. */ -/*---------------------------------------------------------------------*/ -#define SHELLSIZE 512 - /*---------------------------------------------------------------------*/ /* A newline - some systems need "\n\r" */ /*---------------------------------------------------------------------*/ diff --git a/src/dorem.c b/src/dorem.c index 0dd3ec60..f174a736 100644 --- a/src/dorem.c +++ b/src/dorem.c @@ -12,7 +12,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: dorem.c,v 1.2 1998-01-17 03:58:27 dfs Exp $"; +static char const RCSID[] = "$Id: dorem.c,v 1.3 1998-02-07 05:35:56 dfs Exp $"; #include #include @@ -66,9 +66,11 @@ ParsePtr p; TimeTrig tim; int r; int jul; - char buf[TOKSIZE]; + DynamicBuffer buf; Token tok; + DBufInit(&buf); + /* Parse the trigger date and time */ if ( (r=ParseRem(p, &trig, &tim)) ) return r; @@ -76,18 +78,27 @@ ParsePtr p; if (trig.typ == SAT_TYPE) { r=DoSatRemind(&trig, &tim, p); if (r) return r; - r=ParseToken(p, buf); + r=ParseToken(p, &buf); if (r) return r; - FindToken(buf, &tok); - if (tok.type == T_Empty || tok.type == T_Comment) return OK; + FindToken(DBufValue(&buf), &tok); + DBufFree(&buf); + if (tok.type == T_Empty || tok.type == T_Comment) { + DBufFree(&buf); + return OK; + } if (tok.type != T_RemType || tok.val == SAT_TYPE) { + DBufFree(&buf); return E_PARSE_ERR; } if (tok.val == PASSTHRU_TYPE) { - r=ParseToken(p, buf); + r=ParseToken(p, &buf); if (r) return r; - if (!*buf) return E_EOLN; - StrnCpy(trig.passthru, buf, PASSTHRU_LEN); + if (!DBufLen(&buf)) { + DBufFree(&buf); + return E_EOLN; + } + StrnCpy(trig.passthru, DBufValue(&buf), PASSTHRU_LEN); + DBufFree(&buf); } trig.typ = tok.val; jul = LastTriggerDate; @@ -112,16 +123,17 @@ ParsePtr p; if (ShouldTriggerReminder(&trig, &tim, jul)) { #ifdef OS2_POPUP - if ( (r=TriggerReminder(p, &trig, &tim, jul, 0)) ) { + if ( (r=TriggerReminder(p, &trig, &tim, jul, 0)) ) #else - if ( (r=TriggerReminder(p, &trig, &tim, jul)) ) { + if ( (r=TriggerReminder(p, &trig, &tim, jul)) ) #endif + { return r; } - } + } - return OK; - } + return OK; +} /***************************************************************/ /* */ @@ -132,170 +144,196 @@ ParsePtr p; /* */ /***************************************************************/ #ifdef HAVE_PROTOS - PUBLIC int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim) +PUBLIC int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim) #else - int ParseRem(s, trig, tim) - ParsePtr s; + int ParseRem(s, trig, tim) + ParsePtr s; Trigger *trig; TimeTrig *tim; #endif - { - register int r; - Token tok; +{ + register int r; + DynamicBuffer buf; + Token tok; - trig->y = NO_YR; - trig->m = NO_MON; - trig->d = NO_DAY; - trig->wd = NO_WD; - trig->back = NO_BACK; - trig->delta = NO_DELTA; - trig->until = NO_UNTIL; - trig->rep = NO_REP; - trig->localomit = NO_WD; - trig->skip = NO_SKIP; - trig->once = NO_ONCE; - trig->typ = NO_TYPE; - trig->scanfrom = NO_DATE; - trig->priority = DefaultPrio; - trig->sched[0] = 0; - trig->warn[0] = 0; - trig->tag[0] = 0; - tim->ttime = NO_TIME; - tim->delta = NO_DELTA; - tim->rep = NO_REP; - tim->duration = NO_TIME; + DBufInit(&buf); - while(1) { - /* Read space-delimited string */ - r = ParseToken(s, TokBuffer); + trig->y = NO_YR; + trig->m = NO_MON; + trig->d = NO_DAY; + trig->wd = NO_WD; + trig->back = NO_BACK; + trig->delta = NO_DELTA; + trig->until = NO_UNTIL; + trig->rep = NO_REP; + trig->localomit = NO_WD; + trig->skip = NO_SKIP; + trig->once = NO_ONCE; + trig->typ = NO_TYPE; + trig->scanfrom = NO_DATE; + trig->priority = DefaultPrio; + trig->sched[0] = 0; + trig->warn[0] = 0; + trig->tag[0] = 0; + tim->ttime = NO_TIME; + tim->delta = NO_DELTA; + tim->rep = NO_REP; + tim->duration = NO_TIME; + + while(1) { + /* Read space-delimited string */ + r = ParseToken(s, &buf); + if (r) return r; + + /* Figure out what we've got */ + FindToken(DBufValue(&buf), &tok); + switch(tok.type) { + case T_WkDay: + DBufFree(&buf); + if (trig->wd & (1 << tok.val)) return E_WD_TWICE; + trig->wd |= (1 << tok.val); + break; + + case T_Month: + DBufFree(&buf); + if (trig->m != NO_MON) return E_MON_TWICE; + trig->m = tok.val; + break; + + case T_Skip: + DBufFree(&buf); + if (trig->skip != NO_SKIP) return E_SKIP_ERR; + trig->skip = tok.val; + break; + + case T_Priority: + DBufFree(&buf); + r=ParsePriority(s, trig); if (r) return r; + break; - /* Figure out what we've got */ - FindToken(TokBuffer, &tok); - switch(tok.type) { - case T_WkDay: - if (trig->wd & (1 << tok.val)) return E_WD_TWICE; - trig->wd |= (1 << tok.val); - break; + case T_At: + DBufFree(&buf); + r=ParseTimeTrig(s, tim); + if (r) return r; + break; - case T_Month: - if (trig->m != NO_MON) return E_MON_TWICE; - trig->m = tok.val; - break; + case T_Scanfrom: + DBufFree(&buf); + r=ParseScanFrom(s, trig); + if (r) return r; + break; - case T_Skip: - if (trig->skip != NO_SKIP) return E_SKIP_ERR; - trig->skip = tok.val; - break; - - case T_Priority: - r=ParsePriority(s, trig); + case T_RemType: + DBufFree(&buf); + trig->typ = tok.val; + if (s->isnested) return E_CANT_NEST_RTYPE; + if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday; + if (trig->typ == PASSTHRU_TYPE) { + r = ParseToken(s, &buf); if (r) return r; - break; - - case T_At: - r=ParseTimeTrig(s, tim); - if (r) return r; - break; - - case T_Scanfrom: - r=ParseScanFrom(s, trig); - if (r) return r; - break; - - case T_RemType: - trig->typ = tok.val; - if (s->isnested) return E_CANT_NEST_RTYPE; - if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday; - if (trig->typ == PASSTHRU_TYPE) { - r = ParseToken(s, TokBuffer); - if (r) return r; - if (!*TokBuffer) return E_EOLN; - StrnCpy(trig->passthru, TokBuffer, PASSTHRU_LEN); + if (!DBufLen(&buf)) { + DBufFree(&buf); + return E_EOLN; } - return OK; - - case T_Until: - r=ParseUntil(s, trig); - if (r) return r; - break; - - case T_Year: - if (trig->y != NO_YR) return E_YR_TWICE; - trig->y = tok.val; - break; - - case T_Day: - if (trig->d != NO_DAY) return E_DAY_TWICE; - trig->d = tok.val; - break; - - case T_Rep: - if (trig->rep != NO_REP) return E_REP_TWICE; - trig->rep = tok.val; - break; - - case T_Delta: - if (trig->delta != NO_DELTA) return E_DELTA_TWICE; - trig->delta = tok.val; - break; - - case T_Back: - if (trig->back != NO_BACK) return E_BACK_TWICE; - trig->back = tok.val; - break; - - case T_Once: - if (trig->once != NO_ONCE) return E_ONCE_TWICE; - trig->once = ONCE_ONCE; - break; - - case T_Omit: - r = ParseLocalOmit(s, trig); - if (r) return r; - break; - - case T_Empty: - if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday; - return OK; - - case T_Warn: - r=ParseToken(s, TokBuffer); - if(r) return r; - StrnCpy(trig->warn, TokBuffer, VAR_NAME_LEN); - break; - - case T_Tag: - r = ParseToken(s, TokBuffer); - if (r) return r; - StrnCpy(trig->tag, TokBuffer, TAG_LEN); - break; - - case T_Duration: - r = ParseToken(s, TokBuffer); - if (r) return r; - FindToken(TokBuffer, &tok); - switch(tok.type) { - case T_Time: - tim->duration = tok.val; - break; - default: - return E_BAD_TIME; - } - break; - - case T_Sched: - r=ParseToken(s, TokBuffer); - if(r) return r; - StrnCpy(trig->sched, TokBuffer, VAR_NAME_LEN); - break; - - default: - Eprint("%s: %s", ErrMsg[E_UNKNOWN_TOKEN], TokBuffer); - return E_UNKNOWN_TOKEN; + StrnCpy(trig->passthru, DBufValue(&buf), PASSTHRU_LEN); } + return OK; + + case T_Until: + DBufFree(&buf); + r=ParseUntil(s, trig); + if (r) return r; + break; + + case T_Year: + DBufFree(&buf); + if (trig->y != NO_YR) return E_YR_TWICE; + trig->y = tok.val; + break; + + case T_Day: + DBufFree(&buf); + if (trig->d != NO_DAY) return E_DAY_TWICE; + trig->d = tok.val; + break; + + case T_Rep: + DBufFree(&buf); + if (trig->rep != NO_REP) return E_REP_TWICE; + trig->rep = tok.val; + break; + + case T_Delta: + DBufFree(&buf); + if (trig->delta != NO_DELTA) return E_DELTA_TWICE; + trig->delta = tok.val; + break; + + case T_Back: + DBufFree(&buf); + if (trig->back != NO_BACK) return E_BACK_TWICE; + trig->back = tok.val; + break; + + case T_Once: + DBufFree(&buf); + if (trig->once != NO_ONCE) return E_ONCE_TWICE; + trig->once = ONCE_ONCE; + break; + + case T_Omit: + DBufFree(&buf); + r = ParseLocalOmit(s, trig); + if (r) return r; + break; + + case T_Empty: + DBufFree(&buf); + if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday; + return OK; + + case T_Warn: + r=ParseToken(s, &buf); + if(r) return r; + StrnCpy(trig->warn, DBufValue(&buf), VAR_NAME_LEN); + DBufFree(&buf); + break; + + case T_Tag: + r = ParseToken(s, &buf); + if (r) return r; + StrnCpy(trig->tag, DBufValue(&buf), TAG_LEN); + break; + + case T_Duration: + r = ParseToken(s, &buf); + if (r) return r; + FindToken(DBufValue(&buf), &tok); + DBufFree(&buf); + switch(tok.type) { + case T_Time: + tim->duration = tok.val; + break; + default: + return E_BAD_TIME; + } + break; + + case T_Sched: + r=ParseToken(s, &buf); + if(r) return r; + StrnCpy(trig->sched, DBufValue(&buf), VAR_NAME_LEN); + DBufFree(&buf); + break; + + default: + Eprint("%s: %s", ErrMsg[E_UNKNOWN_TOKEN], DBufValue(&buf)); + DBufFree(&buf); + return E_UNKNOWN_TOKEN; } } +} /***************************************************************/ /* */ @@ -303,42 +341,50 @@ ParsePtr p; /* */ /***************************************************************/ #ifdef HAVE_PROTOS - PRIVATE int ParseTimeTrig(ParsePtr s, TimeTrig *tim) +PRIVATE int ParseTimeTrig(ParsePtr s, TimeTrig *tim) #else - static int ParseTimeTrig(s, tim) - ParsePtr s; + static int ParseTimeTrig(s, tim) + ParsePtr s; TimeTrig *tim; #endif - { - Token tok; - int r; +{ + Token tok; + int r; - while(1) { - r = ParseToken(s, TokBuffer); - if (r) return r; - FindToken(TokBuffer, &tok); - switch(tok.type) { - case T_Time: - tim->ttime = tok.val; - break; + DynamicBuffer buf; + DBufInit(&buf); - case T_Delta: - tim->delta = (tok.val > 0) ? tok.val : -tok.val; - break; + while(1) { + r = ParseToken(s, &buf); + if (r) return r; + FindToken(DBufValue(&buf), &tok); + switch(tok.type) { + case T_Time: + DBufFree(&buf); + tim->ttime = tok.val; + break; - case T_Rep: - tim->rep = tok.val; - break; + case T_Delta: + DBufFree(&buf); + tim->delta = (tok.val > 0) ? tok.val : -tok.val; + break; - default: - if (tim->ttime == NO_TIME) return E_EXPECT_TIME; -/* Save in global variable */ - LastTriggerTime = tim->ttime; - PushToken(TokBuffer); - return OK; - } + case T_Rep: + DBufFree(&buf); + tim->rep = tok.val; + break; + + default: + if (tim->ttime == NO_TIME) return E_EXPECT_TIME; + + /* Save trigger time in global variable */ + LastTriggerTime = tim->ttime; + PushToken(DBufValue(&buf)); + DBufFree(&buf); + return OK; } } +} /***************************************************************/ /* */ @@ -347,31 +393,35 @@ ParsePtr p; /* */ /***************************************************************/ #ifdef HAVE_PROTOS - PRIVATE int ParseLocalOmit(ParsePtr s, Trigger *t) +PRIVATE int ParseLocalOmit(ParsePtr s, Trigger *t) #else - static int ParseLocalOmit(s, t) - ParsePtr s; + static int ParseLocalOmit(s, t) + ParsePtr s; Trigger *t; #endif - { - Token tok; - int r; +{ + Token tok; + int r; + DynamicBuffer buf; + DBufInit(&buf); - while(1) { - r = ParseToken(s, TokBuffer); - if (r) return r; - FindToken(TokBuffer, &tok); - switch(tok.type) { - case T_WkDay: - t->localomit |= (1 << tok.val); - break; + while(1) { + r = ParseToken(s, &buf); + if (r) return r; + FindToken(DBufValue(&buf), &tok); + switch(tok.type) { + case T_WkDay: + DBufFree(&buf); + t->localomit |= (1 << tok.val); + break; - default: - PushToken(TokBuffer); - return OK; - } + default: + PushToken(DBufValue(&buf)); + DBufFree(&buf); + return OK; } } +} /***************************************************************/ /* */ @@ -379,63 +429,73 @@ ParsePtr p; /* */ /***************************************************************/ #ifdef HAVE_PROTOS - PRIVATE int ParseUntil(ParsePtr s, Trigger *t) +PRIVATE int ParseUntil(ParsePtr s, Trigger *t) #else - static int ParseUntil(s, t) - ParsePtr s; + static int ParseUntil(s, t) + ParsePtr s; Trigger *t; #endif - { - int y = NO_YR, - m = NO_MON, - d = NO_DAY; +{ + int y = NO_YR, + m = NO_MON, + d = NO_DAY; - Token tok; - int r; + Token tok; + int r; + DynamicBuffer buf; + DBufInit(&buf); - if (t->until != NO_UNTIL) return E_UNTIL_TWICE; + if (t->until != NO_UNTIL) return E_UNTIL_TWICE; - while(1) { - r = ParseToken(s, TokBuffer); - if (r) return r; - FindToken(TokBuffer, &tok); - switch(tok.type) { - case T_Year: - if (y != NO_YR) { - Eprint("UNTIL: %s", ErrMsg[E_YR_TWICE]); - return E_YR_TWICE; - } - y = tok.val; - break; - - case T_Month: - if (m != NO_MON) { - Eprint("UNTIL: %s", ErrMsg[E_MON_TWICE]); - return E_MON_TWICE; - } - m = tok.val; - break; - - case T_Day: - if (d != NO_DAY) { - Eprint("UNTIL: %s", ErrMsg[E_DAY_TWICE]); - return E_DAY_TWICE; - } - d = tok.val; - break; - - default: - if (y == NO_YR || m == NO_MON || d == NO_DAY) { - Eprint("UNTIL: %s", ErrMsg[E_INCOMPLETE]); - return E_INCOMPLETE; - } - if (!DateOK(y, m, d)) return E_BAD_DATE; - t->until = Julian(y, m, d); - PushToken(TokBuffer); - return OK; + while(1) { + r = ParseToken(s, &buf); + if (r) return r; + FindToken(DBufValue(&buf), &tok); + switch(tok.type) { + case T_Year: + DBufFree(&buf); + if (y != NO_YR) { + Eprint("UNTIL: %s", ErrMsg[E_YR_TWICE]); + return E_YR_TWICE; } + y = tok.val; + break; + + case T_Month: + DBufFree(&buf); + if (m != NO_MON) { + Eprint("UNTIL: %s", ErrMsg[E_MON_TWICE]); + return E_MON_TWICE; + } + m = tok.val; + break; + + case T_Day: + DBufFree(&buf); + if (d != NO_DAY) { + Eprint("UNTIL: %s", ErrMsg[E_DAY_TWICE]); + return E_DAY_TWICE; + } + d = tok.val; + break; + + default: + if (y == NO_YR || m == NO_MON || d == NO_DAY) { + Eprint("UNTIL: %s", ErrMsg[E_INCOMPLETE]); + DBufFree(&buf); + return E_INCOMPLETE; + } + if (!DateOK(y, m, d)) { + DBufFree(&buf); + return E_BAD_DATE; + } + t->until = Julian(y, m, d); + PushToken(DBufValue(&buf)); + DBufFree(&buf); + return OK; } } +} /***************************************************************/ /* */ @@ -443,63 +503,73 @@ ParsePtr p; /* */ /***************************************************************/ #ifdef HAVE_PROTOS - PRIVATE int ParseScanFrom(ParsePtr s, Trigger *t) +PRIVATE int ParseScanFrom(ParsePtr s, Trigger *t) #else - static int ParseScanFrom(s, t) - ParsePtr s; + static int ParseScanFrom(s, t) + ParsePtr s; Trigger *t; #endif - { - int y = NO_YR, - m = NO_MON, - d = NO_DAY; +{ + int y = NO_YR, + m = NO_MON, + d = NO_DAY; - Token tok; - int r; + Token tok; + int r; + DynamicBuffer buf; + DBufInit(&buf); - if (t->scanfrom != NO_DATE) return E_SCAN_TWICE; + if (t->scanfrom != NO_DATE) return E_SCAN_TWICE; - while(1) { - r = ParseToken(s, TokBuffer); - if (r) return r; - FindToken(TokBuffer, &tok); - switch(tok.type) { - case T_Year: - if (y != NO_YR) { - Eprint("SCANFROM: %s", ErrMsg[E_YR_TWICE]); - return E_YR_TWICE; - } - y = tok.val; - break; - - case T_Month: - if (m != NO_MON) { - Eprint("SCANFROM: %s", ErrMsg[E_MON_TWICE]); - return E_MON_TWICE; - } - m = tok.val; - break; - - case T_Day: - if (d != NO_DAY) { - Eprint("SCANFROM: %s", ErrMsg[E_DAY_TWICE]); - return E_DAY_TWICE; - } - d = tok.val; - break; - - default: - if (y == NO_YR || m == NO_MON || d == NO_DAY) { - Eprint("SCANFROM: %s", ErrMsg[E_INCOMPLETE]); - return E_INCOMPLETE; - } - if (!DateOK(y, m, d)) return E_BAD_DATE; - t->scanfrom = Julian(y, m, d); - PushToken(TokBuffer); - return OK; + while(1) { + r = ParseToken(s, &buf); + if (r) return r; + FindToken(DBufValue(&buf), &tok); + switch(tok.type) { + case T_Year: + DBufFree(&buf); + if (y != NO_YR) { + Eprint("SCANFROM: %s", ErrMsg[E_YR_TWICE]); + return E_YR_TWICE; } + y = tok.val; + break; + + case T_Month: + DBufFree(&buf); + if (m != NO_MON) { + Eprint("SCANFROM: %s", ErrMsg[E_MON_TWICE]); + return E_MON_TWICE; + } + m = tok.val; + break; + + case T_Day: + DBufFree(&buf); + if (d != NO_DAY) { + Eprint("SCANFROM: %s", ErrMsg[E_DAY_TWICE]); + return E_DAY_TWICE; + } + d = tok.val; + break; + + default: + if (y == NO_YR || m == NO_MON || d == NO_DAY) { + Eprint("SCANFROM: %s", ErrMsg[E_INCOMPLETE]); + DBufFree(&buf); + return E_INCOMPLETE; + } + if (!DateOK(y, m, d)) { + DBufFree(&buf); + return E_BAD_DATE; + } + t->scanfrom = Julian(y, m, d); + PushToken(DBufValue(&buf)); + DBufFree(&buf); + return OK; } } +} /***************************************************************/ /* */ /* TriggerReminder */ @@ -509,167 +579,184 @@ ParsePtr p; /***************************************************************/ #ifdef HAVE_PROTOS #ifdef OS2_POPUP - PUBLIC int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul, - int AsPopUp) +PUBLIC int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul, + int AsPopUp) #else /* ! OS2_POPUP */ - PUBLIC int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul) + PUBLIC int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul) #endif /* OS2_POPUP */ #else /* ! HAVE_PROTOS */ #ifdef OS2_POPUP - int TriggerReminder(p, t, tim, jul, AsPopUp) - ParsePtr p; + int TriggerReminder(p, t, tim, jul, AsPopUp) + ParsePtr p; Trigger *t; TimeTrig *tim; int jul; int AsPopUp; #else /* ! OS2_POPUP */ int TriggerReminder(p, t, tim, jul) - ParsePtr p; + ParsePtr p; Trigger *t; TimeTrig *tim; int jul; #endif /* OS2_POPUP */ #endif /* HAVE_PROTOS */ - { - int r, y, m, d; - char PrioExpr[25]; - static char buf[LINELEN+TOKSIZE]; - char *s, *s2; - Value v; - - if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED; - if (t->typ == PASSTHRU_TYPE || - t->typ == CAL_TYPE || - t->typ == PS_TYPE || - t->typ == PSF_TYPE) - return OK; +{ + int r, y, m, d; + char PrioExpr[25]; + DynamicBuffer buf; + char *s, *s2; + Value v; + DBufInit(&buf); + if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED; + if (t->typ == PASSTHRU_TYPE || + t->typ == CAL_TYPE || + t->typ == PS_TYPE || + t->typ == PSF_TYPE) + return OK; /* If it's a MSG-type reminder, and no -k option was used, issue the banner. */ - if ((t->typ == MSG_TYPE || t->typ == MSF_TYPE) - && !NumTriggered && !NextMode && !MsgCommand) { - if (!DoSubstFromString(Banner, SubstBuffer, JulianToday, NO_TIME) && *SubstBuffer) + if ((t->typ == MSG_TYPE || t->typ == MSF_TYPE) + && !NumTriggered && !NextMode && !MsgCommand) { + if (!DoSubstFromString(DBufValue(&Banner), &buf, + JulianToday, NO_TIME) && + DBufLen(&buf)) { #ifdef OS2_POPUP - if (AsPopUp) - PutlPopUp(SubstBuffer); - else - printf("%s\n", SubstBuffer); + if (AsPopUp) + PutlPopUp(DBufValue(&buf)); + else + printf("%s\n", DBufValue(&buf)); #else - printf("%s\n", SubstBuffer); + printf("%s\n", DBufValue(&buf)); #endif } + } /* If it's NextMode, process as a CAL-type entry, and issue simple-calendar format. */ - if (NextMode) { - if ( (r=DoSubst(p, SubstBuffer, t, tim, jul, CAL_MODE)) ) return r; - if (!*SubstBuffer) return OK; - FromJulian(jul, &y, &m, &d); -#ifdef OS2_POPUP - if (AsPopUp) { - sprintf(buf, "%04d%c%02d%c%02d %s", y, DATESEP, m+1, DATESEP, d, - SimpleTime(tim->ttime, NULL)); - StartPopUp(); - PutsPopUp(buf); - PutlPopUp(SubstBuffer); - } - else - printf("%04d%c%02d%c%02d %s%s\n", y, DATESEP, m+1, DATESEP, d, - SimpleTime(tim->ttime, NULL), - SubstBuffer); -#else - printf("%04d%c%02d%c%02d %s%s\n", y, DATESEP, m+1, DATESEP, d, - SimpleTime(tim->ttime, NULL), - SubstBuffer); -#endif + if (NextMode) { + if ( (r=DoSubst(p, &buf, t, tim, jul, CAL_MODE)) ) return r; + if (!DBufLen(&buf)) { + DBufFree(&buf); return OK; } + FromJulian(jul, &y, &m, &d); +#ifdef OS2_POPUP + if (AsPopUp) { + char tmpBuf[64]; + sprintf(tmpBuf, "%04d%c%02d%c%02d %s", y, DATESEP, m+1, DATESEP, d, + SimpleTime(tim->ttime)); + StartPopUp(); + PutsPopUp(tmpBuf); + PutlPopUp(DBufValue(&buf)); + } + else + printf("%04d%c%02d%c%02d %s%s\n", y, DATESEP, m+1, DATESEP, d, + SimpleTime(tim->ttime), + DBufValue(&buf)); +#else + printf("%04d%c%02d%c%02d %s%s\n", y, DATESEP, m+1, DATESEP, d, + SimpleTime(tim->ttime), + DBufValue(&buf)); +#endif + DBufFree(&buf); + return OK; + } -/* Put the substituted string into the SubstBuffer */ - s2 = buf; - *s2 = 0; - if (UserFuncExists("msgprefix") == 1) { - sprintf(PrioExpr, "msgprefix(%d)", t->priority); - s = PrioExpr; - r = EvalExpr(&s, &v); - if (!r) { - if (!DoCoerce(STR_TYPE, &v)) { - sprintf(s2, "%s", v.v.str); - s2 += strlen(s2); +/* Put the substituted string into the substitution buffer */ + if (UserFuncExists("msgprefix") == 1) { + sprintf(PrioExpr, "msgprefix(%d)", t->priority); + s = PrioExpr; + r = EvalExpr(&s, &v); + if (!r) { + if (!DoCoerce(STR_TYPE, &v)) { + if (DBufPuts(&buf, v.v.str) != OK) { + DBufFree(&buf); + DestroyValue(v); + return E_NO_MEM; } - DestroyValue(v); } + DestroyValue(v); } - if ( (r=DoSubst(p, s2, t, tim, jul, NORMAL_MODE)) ) return r; - s2 += strlen(s2); - if (UserFuncExists("msgsuffix") == 1) { - sprintf(PrioExpr, "msgsuffix(%d)", t->priority); - s = PrioExpr; - r = EvalExpr(&s, &v); - if (!r) { - if (!DoCoerce(STR_TYPE, &v)) { - sprintf(s2, "%s", v.v.str); - s2 += strlen(s2); + } + if ( (r=DoSubst(p, &buf, t, tim, jul, NORMAL_MODE)) ) return r; + if (UserFuncExists("msgsuffix") == 1) { + sprintf(PrioExpr, "msgsuffix(%d)", t->priority); + s = PrioExpr; + r = EvalExpr(&s, &v); + if (!r) { + if (!DoCoerce(STR_TYPE, &v)) { + if (DBufPuts(&buf, v.v.str) != OK) { + DBufFree(&buf); + DestroyValue(v); + return E_NO_MEM; } - DestroyValue(v); } + DestroyValue(v); } - if ((!MsgCommand && t->typ == MSG_TYPE) || t->typ == MSF_TYPE) { - *s2++ = '\n'; + } + if ((!MsgCommand && t->typ == MSG_TYPE) || t->typ == MSF_TYPE) { + if (DBufPutc(&buf, '\n') != OK) { + DBufFree(&buf); + return E_NO_MEM; } - *s2 = 0; + } /* If we are sorting, just queue it up in the sort buffer */ - if (SortByDate) { - if (InsertIntoSortBuffer(jul, tim->ttime, buf, t->typ, t->priority) == OK) { - NumTriggered++; - return OK; - } + if (SortByDate) { + if (InsertIntoSortBuffer(jul, tim->ttime, DBufValue(&buf), + t->typ, t->priority) == OK) { + DBufFree(&buf); + NumTriggered++; + return OK; } + } /* If we didn't insert the reminder into the sort buffer, issue the reminder now. */ - switch(t->typ) { - case MSG_TYPE: - if (MsgCommand) { - DoMsgCommand(MsgCommand, buf); - } else { + switch(t->typ) { + case MSG_TYPE: + if (MsgCommand) { + DoMsgCommand(MsgCommand, DBufValue(&buf)); + } else { #ifdef OS2_POPUP - if (AsPopUp) - PutlPopUp(buf); - else - printf("%s", buf); + if (AsPopUp) + PutlPopUp(DBufValue(&buf)); + else + printf("%s", DBufValue(&buf)); #else - printf("%s", buf); + printf("%s", DBufValue(&buf)); #endif - } - break; - - case MSF_TYPE: -#ifdef OS2_POPUP - if (AsPopUp) { - StartPopUp(); - FillParagraph(buf, 1); - EndPopUp(); - } else { - FillParagraph(buf, 0); - } -#else - FillParagraph(buf); -#endif - break; - - case RUN_TYPE: - system(buf); - break; - - default: /* Unknown/illegal type? */ - return E_SWERR; } + break; - NumTriggered++; - return OK; + case MSF_TYPE: +#ifdef OS2_POPUP + if (AsPopUp) { + StartPopUp(); + FillParagraph(DBufValue(&buf), 1); + EndPopUp(); + } else { + FillParagraph(DBufValue(&buf), 0); + } +#else + FillParagraph(DBufValue(&buf)); +#endif + break; + + case RUN_TYPE: + system(DBufValue(&buf)); + break; + + default: /* Unknown/illegal type? */ + DBufFree(&buf); + return E_SWERR; } + DBufFree(&buf); + NumTriggered++; + return OK; +} + /***************************************************************/ /* */ /* ShouldTriggerReminder */ @@ -685,59 +772,59 @@ ParsePtr p; #ifdef HAVE_PROTOS PUBLIC int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul) #else -int ShouldTriggerReminder(t, tim, jul) -Trigger *t; -TimeTrig *tim; -int jul; + int ShouldTriggerReminder(t, tim, jul) + Trigger *t; + TimeTrig *tim; + int jul; #endif - { - int r; +{ + int r; - /* Handle the ONCE modifier in the reminder. */ - if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday) - return 0; + /* Handle the ONCE modifier in the reminder. */ + if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday) + return 0; - if (jul < JulianToday) return 0; + if (jul < JulianToday) return 0; - /* Don't trigger timed reminders if DontIssueAts is true, and if the - reminder is for today */ + /* Don't trigger timed reminders if DontIssueAts is true, and if the + reminder is for today */ #ifdef HAVE_QUEUED - if (jul == JulianToday && DontIssueAts && tim->ttime != NO_TIME) return 0; + if (jul == JulianToday && DontIssueAts && tim->ttime != NO_TIME) return 0; #endif - /* Don't trigger "old" timed reminders */ + /* Don't trigger "old" timed reminders */ /*** REMOVED... if (jul == JulianToday && tim->ttime != NO_TIME && tim->ttime < SystemTime(0) / 60) return 0; *** ...UNTIL HERE */ - /* If "infinite delta" option is chosen, always trigger future reminders */ - if (InfiniteDelta || NextMode) return 1; + /* If "infinite delta" option is chosen, always trigger future reminders */ + if (InfiniteDelta || NextMode) return 1; - /* If there's a "warn" function, it overrides any deltas */ - if (t->warn[0] != 0) { - return ShouldTriggerBasedOnWarn(t, jul); - } + /* If there's a "warn" function, it overrides any deltas */ + if (t->warn[0] != 0) { + return ShouldTriggerBasedOnWarn(t, jul); + } - /* Move back by delta days, if any */ - if (t->delta != NO_DELTA) { - if (t->delta < 0) - jul = jul + t->delta; - else { - r = t->delta; - while(r && jul > JulianToday) { - jul--; - if (!IsOmitted(jul, t->localomit)) r--; - } + /* Move back by delta days, if any */ + if (t->delta != NO_DELTA) { + if (t->delta < 0) + jul = jul + t->delta; + else { + r = t->delta; + while(r && jul > JulianToday) { + jul--; + if (!IsOmitted(jul, t->localomit)) r--; } } - - /* Should we trigger the reminder? */ - return (jul <= JulianToday); } + /* Should we trigger the reminder? */ + return (jul <= JulianToday); +} + /***************************************************************/ /* */ /* DoSatRemind */ @@ -749,40 +836,40 @@ int jul; #pragma argsused #endif #ifdef HAVE_PROTOS - PUBLIC int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p) +PUBLIC int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p) #else - int DoSatRemind(trig, tim, p) - Trigger *trig; + int DoSatRemind(trig, tim, p) + Trigger *trig; TimeTrig *tim; ParsePtr p; #endif - { - int iter, jul, r; - Value v; - char *s, *t; +{ + int iter, jul, r; + Value v; + char *s, *t; - t = p->pos; - iter = 0; - jul = trig->scanfrom; - while (iter++ < MaxSatIter) { - jul = ComputeTrigger(jul, trig, &r); - if (r) { - if (r == E_CANT_TRIG) return OK; else return r; - } - s = p->pos; - r = EvaluateExpr(p, &v); - t = p->pos; - if (r) return r; - if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE; - if (v.type == INT_TYPE && v.v.val) return OK; - if (v.type == STR_TYPE && *v.v.str) return OK; - p->pos = s; - jul++; + t = p->pos; + iter = 0; + jul = trig->scanfrom; + while (iter++ < MaxSatIter) { + jul = ComputeTrigger(jul, trig, &r); + if (r) { + if (r == E_CANT_TRIG) return OK; else return r; } - p->pos = t; - LastTrigValid = 0; - return OK; + s = p->pos; + r = EvaluateExpr(p, &v); + t = p->pos; + if (r) return r; + if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE; + if (v.type == INT_TYPE && v.v.val) return OK; + if (v.type == STR_TYPE && *v.v.str) return OK; + p->pos = s; + jul++; } + p->pos = t; + LastTrigValid = 0; + return OK; +} /***************************************************************/ /* */ @@ -790,34 +877,44 @@ int jul; /* */ /***************************************************************/ #ifdef HAVE_PROTOS - PRIVATE int ParsePriority(ParsePtr s, Trigger *t) +PRIVATE int ParsePriority(ParsePtr s, Trigger *t) #else - static int ParsePriority(s, t) - ParsePtr s; + static int ParsePriority(s, t) + ParsePtr s; Trigger *t; #endif - { - int p, r; - char *u; +{ + int p, r; + char *u; + DynamicBuffer buf; + DBufInit(&buf); - r = ParseToken(s, TokBuffer); - if(r) return r; - u = TokBuffer; + r = ParseToken(s, &buf); + if(r) return r; + u = DBufValue(&buf); - if (!isdigit(*u)) return E_EXPECTING_NUMBER; - p = 0; - while (isdigit(*u)) { - p = p*10 + *u - '0'; - u++; - } - if (*u) return E_EXPECTING_NUMBER; + if (!isdigit(*u)) { + DBufFree(&buf); + return E_EXPECTING_NUMBER; + } + p = 0; + while (isdigit(*u)) { + p = p*10 + *u - '0'; + u++; + } + if (*u) { + DBufFree(&buf); + return E_EXPECTING_NUMBER; + } + + DBufFree(&buf); /* Tricky! The only way p can be < 0 is if overflow occurred; thus, E2HIGH is indeed the appropriate error message. */ - if (p<0 || p>9999) return E_2HIGH; - t->priority = p; - return OK; - } + if (p<0 || p>9999) return E_2HIGH; + t->priority = p; + return OK; +} /***************************************************************/ /* */ @@ -827,32 +924,40 @@ int jul; /* */ /***************************************************************/ #ifdef HAVE_PROTOS - PUBLIC void DoMsgCommand(char *cmd, char *msg) +PUBLIC int DoMsgCommand(char *cmd, char *msg) #else - void DoMsgCommand(cmd, msg) - char *cmd; + int DoMsgCommand(cmd, msg) + char *cmd; char *msg; #endif - { +{ #ifdef WANT_SHELL_ESCAPING - char buf[2*LINELEN+TOKSIZE]; - char *s, *t; - - /* Escape shell characters in msg INCLUDING WHITESPACE! */ - for (t=buf, s=msg; *s; s++) { - if (isspace(*s) || strchr(EscapeMe, *s)) *t++ = '\\'; - *t++ = *s; + DynamicBuffer buf; + char *s, *t; + char execBuffer[512]; + + /* Escape shell characters in msg INCLUDING WHITESPACE! */ + for (s=msg; *s; s++) { + if (isspace(*s) || strchr(EscapeMe, *s)) { + if (DBufPutc(&buf, '\\') != OK) { + DBufFree(&buf); + return E_NO_MEM; + } + } + if (DBufPutc(&buf, *s) != OK) { + DBufFree(&buf); + return E_NO_MEM; } - *t = 0; - - /* Use SubstBuffer -- not too safe, since no check for overflow... */ - sprintf(SubstBuffer, cmd, buf); -#else - sprintf(SubstBuffer, cmd, msg); -#endif /* WANT_SHELL_ESCAPING */ - system(SubstBuffer); } + /* Use a static buffer */ + snprintf(execBuffer, 512, cmd, DBufValue(&buf)); + DBufFree(&buf); +#else + snprintf(execBuffer, 512, cmd, msg); +#endif /* WANT_SHELL_ESCAPING */ + system(execBuffer); +} /***************************************************************/ /* */ @@ -865,12 +970,12 @@ int jul; #ifdef HAVE_PROTOS PRIVATE int ShouldTriggerBasedOnWarn(Trigger *t, int jul) #else -static int ShouldTriggerBasedOnWarn(t, jul) -Trigger *t; -int jul; + static int ShouldTriggerBasedOnWarn(t, jul) + Trigger *t; + int jul; #endif { - char buffer[VAR_NAME_LEN+15]; + char buffer[VAR_NAME_LEN+32]; int i; char *s; int r; diff --git a/src/dosubst.c b/src/dosubst.c index eb956f1d..8af90531 100644 --- a/src/dosubst.c +++ b/src/dosubst.c @@ -11,7 +11,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: dosubst.c,v 1.2 1998-01-17 03:58:28 dfs Exp $"; +static char const RCSID[] = "$Id: dosubst.c,v 1.3 1998-02-07 05:35:57 dfs Exp $"; #define L_IN_DOSUBST #include @@ -40,6 +40,8 @@ static char const RCSID[] = "$Id: dosubst.c,v 1.2 1998-01-17 03:58:28 dfs Exp $" static char TODAY[] = L_TODAY; static char TOMORROW[] = L_TOMORROW; +#define SHIP_OUT(s) if(DBufPuts(dbuf, s) != OK) return E_NO_MEM + /***************************************************************/ /* */ /* DoSubst */ @@ -50,11 +52,11 @@ static char TOMORROW[] = L_TOMORROW; /* */ /***************************************************************/ #ifdef HAVE_PROTOS -PUBLIC int DoSubst(ParsePtr p, char *out, Trigger *t, TimeTrig *tt, int jul, int mode) +PUBLIC int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul, int mode) #else -int DoSubst(p, out, t, tt, jul, mode) +int DoSubst(p, dbuf, t, tt, jul, mode) ParsePtr p; -char *out; +DynamicBuffer *dbuf; Trigger *t; TimeTrig *tt; int jul, mode; @@ -71,11 +73,13 @@ int jul, mode; int tdiff, adiff, mdiff, hdiff; char *mplu, *hplu, *when, *plu; int has_quote = 0; - char *s = out; - char *os; + char *ss, *os; + char s[256]; FromJulian(jul, &y, &m, &d); + DBufInit(dbuf); + if (tim == NO_TIME) tim = curtime; tdiff = tim - curtime; adiff = ABS(tdiff); @@ -136,25 +140,29 @@ int jul, mode; while(1) { c = ParseChar(p, &err, 0); - if (err) return err; + if (err) { + DBufFree(dbuf); + return err; + } if (c == '\n') continue; if (!c) { - if (mode != CAL_MODE && t->typ != RUN_TYPE && !MsgCommand) - *s++ = '\n'; - *s++ = 0; + if (mode != CAL_MODE && t->typ != RUN_TYPE && !MsgCommand) { + if (DBufPutc(dbuf, '\n') != OK) return E_NO_MEM; + } break; } if (c != '%') { - *s++ = c; + if (DBufPutc(dbuf, c) != OK) return E_NO_MEM; continue; } c = ParseChar(p, &err, 0); - if (err) return err; + if (err) { + DBufFree(dbuf); + return err; + } if (!c) { - *s++ = 0; break; } - os = s; done = 0; if (diff <= 1) { switch(UPPER(c)) { @@ -198,7 +206,7 @@ int jul, mode; case 'V': #endif sprintf(s, "%s", (diff ? TOMORROW : TODAY)); - s += strlen(s); + SHIP_OUT(s); done = 1; break; @@ -214,7 +222,7 @@ int jul, mode; sprintf(s, "%s %s, %d %s, %d", L_ON, DayName[jul%7], d, MonthName[m], y); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'B': @@ -223,7 +231,7 @@ int jul, mode; #else sprintf(s, L_INXDAYS, diff); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'C': @@ -232,7 +240,7 @@ int jul, mode; #else sprintf(s, "%s %s", L_ON, DayName[jul%7]); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'D': @@ -241,7 +249,7 @@ int jul, mode; #else sprintf(s, "%d", d); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'E': @@ -251,7 +259,7 @@ int jul, mode; sprintf(s, "%s %02d%c%02d%c%04d", L_ON, d, DATESEP, m+1, DATESEP, y); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'F': @@ -260,7 +268,7 @@ int jul, mode; #else sprintf(s, "%s %02d%c%02d%c%04d", L_ON, m+1, DATESEP, d, DATESEP, y); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'G': @@ -269,7 +277,7 @@ int jul, mode; #else sprintf(s, "%s %s, %d %s", L_ON, DayName[jul%7], d, MonthName[m]); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'H': @@ -278,7 +286,7 @@ int jul, mode; #else sprintf(s, "%s %02d%c%02d", L_ON, d, DATESEP, m+1); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'I': @@ -287,7 +295,7 @@ int jul, mode; #else sprintf(s, "%s %02d%c%02d", L_ON, m+1, DATESEP, d); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'J': @@ -297,7 +305,7 @@ int jul, mode; sprintf(s, "%s %s, %s %d%s, %d", L_ON, DayName[jul%7], MonthName[m], d, plu, y); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'K': @@ -307,7 +315,7 @@ int jul, mode; sprintf(s, "%s %s, %s %d%s", L_ON, DayName[jul%7], MonthName[m], d, plu); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'L': @@ -316,7 +324,7 @@ int jul, mode; #else sprintf(s, "%s %04d%c%02d%c%02d", L_ON, y, DATESEP, m+1, DATESEP, d); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'M': @@ -325,7 +333,7 @@ int jul, mode; #else sprintf(s, "%s", MonthName[m]); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'N': @@ -334,7 +342,7 @@ int jul, mode; #else sprintf(s, "%d", m+1); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'O': @@ -344,7 +352,7 @@ int jul, mode; if (RealToday == JulianToday) sprintf(s, " (%s)", L_TODAY); else *s = 0; #endif - s += strlen(s); + SHIP_OUT(s); break; case 'P': @@ -353,7 +361,7 @@ int jul, mode; #else sprintf(s, (diff == 1 ? "" : L_PLURAL)); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'Q': @@ -362,7 +370,7 @@ int jul, mode; #else sprintf(s, (diff == 1 ? "'s" : "s'")); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'R': @@ -371,7 +379,7 @@ int jul, mode; #else sprintf(s, "%02d", d); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'S': @@ -380,7 +388,7 @@ int jul, mode; #else sprintf(s, plu); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'T': @@ -389,7 +397,7 @@ int jul, mode; #else sprintf(s, "%02d", m+1); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'U': @@ -399,7 +407,7 @@ int jul, mode; sprintf(s, "%s %s, %d%s %s, %d", L_ON, DayName[jul%7], d, plu, MonthName[m], y); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'V': @@ -409,7 +417,7 @@ int jul, mode; sprintf(s, "%s %s, %d%s %s", L_ON, DayName[jul%7], d, plu, MonthName[m]); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'W': @@ -418,7 +426,7 @@ int jul, mode; #else sprintf(s, DayName[jul%7]); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'X': @@ -427,7 +435,7 @@ int jul, mode; #else sprintf(s, "%d", diff); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'Y': @@ -436,7 +444,7 @@ int jul, mode; #else sprintf(s, "%d", y); #endif - s += strlen(s); + SHIP_OUT(s); break; case 'Z': @@ -445,7 +453,7 @@ int jul, mode; #else sprintf(s, "%d", y % 100); #endif - s += strlen(s); + SHIP_OUT(s); break; case '1': @@ -462,7 +470,7 @@ int jul, mode; sprintf(s, "%d %s%s %s %d %s%s %s", hdiff, L_HOUR, hplu, L_AND, mdiff, L_MINUTE, mplu, when); #endif - s += strlen(s); + SHIP_OUT(s); break; case '2': @@ -471,7 +479,7 @@ int jul, mode; #else sprintf(s, "%s %d%c%02d%s", L_AT, hh, TIMESEP, min, pm); #endif - s += strlen(s); + SHIP_OUT(s); break; case '3': @@ -481,7 +489,7 @@ int jul, mode; sprintf(s, "%s %02d%c%02d", L_AT, h, TIMESEP, min); #endif - s += strlen(s); + SHIP_OUT(s); break; case '4': @@ -490,7 +498,7 @@ int jul, mode; #else sprintf(s, "%d", tdiff); #endif - s += strlen(s); + SHIP_OUT(s); break; case '5': @@ -499,7 +507,7 @@ int jul, mode; #else sprintf(s, "%d", adiff); #endif - s += strlen(s); + SHIP_OUT(s); break; case '6': @@ -508,7 +516,7 @@ int jul, mode; #else sprintf(s, when); #endif - s += strlen(s); + SHIP_OUT(s); break; case '7': @@ -517,7 +525,7 @@ int jul, mode; #else sprintf(s, "%d", hdiff); #endif - s += strlen(s); + SHIP_OUT(s); break; case '8': @@ -526,7 +534,7 @@ int jul, mode; #else sprintf(s, "%d", mdiff); #endif - s += strlen(s); + SHIP_OUT(s); break; case '9': @@ -535,7 +543,7 @@ int jul, mode; #else sprintf(s, mplu); #endif - s += strlen(s); + SHIP_OUT(s); break; case '0': @@ -544,7 +552,7 @@ int jul, mode; #else sprintf(s, hplu); #endif - s += strlen(s); + SHIP_OUT(s); break; case '!': @@ -553,7 +561,7 @@ int jul, mode; #else sprintf(s, (tdiff >= 0 ? L_IS : L_WAS)); #endif - s += strlen(s); + SHIP_OUT(s); break; case '@': @@ -562,7 +570,7 @@ int jul, mode; #else sprintf(s, "%d%c%02d%s", chh, TIMESEP, cmin, cpm); #endif - s += strlen(s); + SHIP_OUT(s); break; case '#': @@ -571,7 +579,7 @@ int jul, mode; #else sprintf(s, "%02d%c%02d", ch, TIMESEP, cmin); #endif - s += strlen(s); + SHIP_OUT(s); break; case '_': @@ -579,7 +587,7 @@ int jul, mode; sprintf(s, "%s", NL); else sprintf(s, " "); - s += strlen(s); + SHIP_OUT(s); break; case QUOTE_MARKER: @@ -587,14 +595,17 @@ int jul, mode; break; case '"': - *s++ = QUOTE_MARKER; + if (DBufPutc(dbuf, QUOTE_MARKER) != OK) return E_NO_MEM; has_quote = 1; break; default: - *s++ = c; + if (DBufPutc(dbuf, c) != OK) return E_NO_MEM; + } + if (isupper(c)) { + os = DBufValue(dbuf) - strlen(s); + *os = UPPER(*os); } - if (isupper(c)) *os = UPPER(*os); } /* We're outside the big while loop. The only way to get here is for c to @@ -605,32 +616,32 @@ int jul, mode; /* If there are NO quotes, then: If CAL_MODE && RUN_TYPE, we don't want the reminder in the calendar. Zero the output buffer and quit. */ if (!has_quote) { - if (mode == CAL_MODE && t->typ == RUN_TYPE) *out = 0; + if (mode == CAL_MODE && t->typ == RUN_TYPE) DBufValue(dbuf) = 0; return OK; } /* There ARE quotes. If in CAL_MODE, delete everything before first quote and after second quote. If in NORMAL_MODE, delete the %" sequences. */ - s = out; - os = out; + ss = DBufValue(dbuf); + os = ss; if (mode == NORMAL_MODE) { - while (*s) { - if (*s != QUOTE_MARKER) *os++ = *s; - s++; + while (*ss) { + if (*ss != QUOTE_MARKER) *os++ = *ss; + ss++; } *os = 0; } else { /* Skip past the quote marker */ - while (*s && (*s != QUOTE_MARKER)) s++; + while (*ss && (*ss != QUOTE_MARKER)) ss++; /* Security check... actually, *s must == QUOTE_MARKER at this point, but it doesn't hurt to make it a bit robust. */ - if (*s) s++; + if (*ss) ss++; /* Copy the output until the next QUOTE_MARKER */ - while (*s && (*s != QUOTE_MARKER)) *os++ = *s++; + while (*ss && (*ss != QUOTE_MARKER)) *os++ = *ss++; *os = 0; } @@ -648,11 +659,12 @@ int jul, mode; /* */ /***************************************************************/ #ifdef HAVE_PROTOS -PUBLIC int DoSubstFromString(char *source, char *dest, int jul, int tim) +PUBLIC int DoSubstFromString(char *source, DynamicBuffer *dbuf, + int jul, int tim) #else -int DoSubstFromString(source, dest, jul, tim) +int DoSubstFromString(source, dbuf, jul, tim) char *source; -char *dest; +DynamicBuffer *dbuf; int jul; int tim; #endif @@ -669,7 +681,7 @@ int tim; tempTrig.typ = MSG_TYPE; tempTime.ttime = tim; - r = DoSubst(&tempP, dest, &tempTrig, &tempTime, jul, NORMAL_MODE); + r = DoSubst(&tempP, dbuf, &tempTrig, &tempTime, jul, NORMAL_MODE); DestroyParser(&tempP); return r; } diff --git a/src/dynbuf.c b/src/dynbuf.c new file mode 100644 index 00000000..6df5c3b6 --- /dev/null +++ b/src/dynbuf.c @@ -0,0 +1,206 @@ +/***************************************************************/ +/* */ +/* DYNBUF.C */ +/* */ +/* Implementation of functions for manipulating dynamic */ +/* buffers. */ +/* */ +/* This file is part of REMIND. */ +/* Copyright (C) 1992-1998 by David F. Skoll */ +/* */ +/***************************************************************/ + +static char const RCSID[] = +"$Id: dynbuf.c,v 1.1 1998-02-07 05:35:57 dfs Exp $"; + +#include "config.h" +#include "dynbuf.h" +#include "err.h" +#include + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_MALLOC_H +#include +#endif + +/********************************************************************** +%FUNCTION: DBufMakeRoom +%ARGUMENTS: + dbuf -- pointer to a dynamic buffer + n -- size to expand to +%RETURNS: + OK if all went well; E_NO_MEM if out of memory +%DESCRIPTION: + Doubles the size of dynamic buffer until it has room for at least + 'n' characters, not including trailing '\0' +**********************************************************************/ +#ifdef HAVE_PROTOS +PRIVATE int DBufMakeRoom(DynamicBuffer *dbuf, int n) +#else +static int DBufMakeRoom(dbuf, n) +DynamicBuffer *dbuf; +int n; +#endif +{ + /* Double size until it's greater than n (strictly > to leave room + for trailing '\0' */ + int size = dbuf->allocatedLen; + char *buf; + + if (size > n) return OK; + + while (size <= n) { + size *= 2; + } + + /* Allocate memory */ + buf = (char *) malloc(size); + if (!buf) return E_NO_MEM; + + /* Copy contents */ + strcpy(buf, dbuf->buffer); + + /* Free contents if necessary */ + if (dbuf->buffer != dbuf->staticBuf) free(dbuf->buffer); + dbuf->buffer = buf; + dbuf->allocatedLen = size; + return OK; +} + +/********************************************************************** +%FUNCTION: DBufInit +%ARGUMENTS: + dbuf -- pointer to a dynamic buffer +%RETURNS: + Nothing +%DESCRIPTION: + Initializes a dynamic buffer +**********************************************************************/ +#ifdef HAVE_PROTOS +PUBLIC void DBufInit(DynamicBuffer *dbuf) +#else +void DBufInit(dbuf) +DynamicBuffer *dbuf; +#endif +{ + dbuf->buffer = dbuf->staticBuf; + dbuf->len = 0; + dbuf->allocatedLen = DBUF_STATIC_SIZE; + dbuf->buffer[0] = 0; +} + +/********************************************************************** +%FUNCTION: DBufPutc +%ARGUMENTS: + dbuf -- pointer to a dynamic buffer + c -- character to append to buffer +%RETURNS: + OK if all went well; E_NO_MEM if out of memory +%DESCRIPTION: + Appends a character to the buffer. +**********************************************************************/ +#ifdef HAVE_PROTOS +PUBLIC int DBufPutc(DynamicBuffer *dbuf, char c) +#else +int DBufPutc(dbuf, c) +DynamicBuffer *dbuf; +char c; +#endif +{ + if (dbuf->allocatedLen == dbuf->len+1) { + if (DBufMakeRoom(dbuf, dbuf->len+1) != OK) return E_NO_MEM; + } + dbuf->buffer[dbuf->len++] = c; + dbuf->buffer[dbuf->len] = 0; + return OK; +} + +/********************************************************************** +%FUNCTION: DBufPuts +%ARGUMENTS: + dbuf -- pointer to a dynamic buffer + str -- string to append to buffer +%RETURNS: + OK if all went well; E_NO_MEM if out of memory +%DESCRIPTION: + Appends a string to the buffer. +**********************************************************************/ +#ifdef HAVE_PROTOS +PUBLIC int DBufPuts(DynamicBuffer *dbuf, char *str) +#else +int DBufPuts(dbuf, str) +DynamicBuffer *dbuf; +char *str; +#endif +{ + int l = strlen(str); + if (!l) return OK; + + if (DBufMakeRoom(dbuf, dbuf->len+l) != OK) return E_NO_MEM; + strcpy((dbuf->buffer+dbuf->len), str); + dbuf->len += l; + return OK; +} + +/********************************************************************** +%FUNCTION: DBufFree +%ARGUMENTS: + dbuf -- pointer to a dynamic buffer +%RETURNS: + Nothing +%DESCRIPTION: + Frees and reinitializes a dynamic buffer +**********************************************************************/ +#ifdef HAVE_PROTOS +PUBLIC void DBufFree(DynamicBuffer *dbuf) +#else +void DBufFree(dbuf) +DynamicBuffer *dbuf; +#endif +{ + if (dbuf->buffer != dbuf->staticBuf) free(dbuf->buffer); + DBufInit(dbuf); +} + +/********************************************************************** +%FUNCTION: DBufGets +%ARGUMENTS: + dbuf -- pointer to a dynamic buffer + fp -- file to read from +%RETURNS: + OK or E_NO_MEM +%DESCRIPTION: + Reads an entire line from a file and appends to dbuf. Does not include + trailing newline. +**********************************************************************/ +#ifdef HAVE_PROTOS +PUBLIC int DBufGets(DynamicBuffer *dbuf, FILE *fp) +#else +int DBufGets(dbuf, fp) +DynamicBuffer *dbuf; +FILE *fp +#endif +{ + char tmp[256]; /* Safe to hard-code */ + int busy = 1; + int l; + + DBufFree(dbuf); + + while(busy) { + *tmp = 0; + fgets(tmp, 256, fp); + if (!*tmp) return OK; + l = strlen(tmp) - 1; + if (tmp[l] == '\n') { + tmp[l] = 0; + busy = 0; + } + if (DBufPuts(dbuf, tmp) != OK) return E_NO_MEM; + } + return OK; +} + diff --git a/src/dynbuf.h b/src/dynbuf.h new file mode 100644 index 00000000..114bb87b --- /dev/null +++ b/src/dynbuf.h @@ -0,0 +1,44 @@ +/***************************************************************/ +/* */ +/* DYNBUF.H */ +/* */ +/* Declaration of functions for manipulating dynamic buffers */ +/* */ +/* This file is part of REMIND. */ +/* Copyright (C) 1992-1998 by David F. Skoll */ +/* */ +/***************************************************************/ + +/* $Id: dynbuf.h,v 1.1 1998-02-07 05:35:57 dfs Exp $ */ + +#ifndef DYNBUF_H +#define DYNBUF_H + +#include /* For FILE */ + +#define DBUF_STATIC_SIZE 128 +typedef struct { + char *buffer; + int len; + int allocatedLen; + char staticBuf[DBUF_STATIC_SIZE]; +} DynamicBuffer; + +#ifndef ARGS +#ifdef HAVE_PROTOS +#define ARGS(x) x +#else +#define ARGS(x) () +#endif +#endif + +void DBufInit(DynamicBuffer *dbuf); +int DBufPutc(DynamicBuffer *dbuf, char c); +int DBufPuts(DynamicBuffer *dbuf, char *str); +void DBufFree(DynamicBuffer *dbuf); +int DBufGets(DynamicBuffer *dbuf, FILE *fp); + +#define DBufValue(bufPtr) ((bufPtr)->buffer) +#define DBufLen(bufPtr) ((bufPtr)->len) + +#endif /* DYNBUF_H */ diff --git a/src/expr.c b/src/expr.c index 295f97dd..894c60b4 100644 --- a/src/expr.c +++ b/src/expr.c @@ -10,7 +10,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: expr.c,v 1.2 1998-01-17 03:58:28 dfs Exp $"; +static char const RCSID[] = "$Id: expr.c,v 1.3 1998-02-07 05:35:58 dfs Exp $"; #include #include @@ -38,8 +38,9 @@ static char const RCSID[] = "$Id: expr.c,v 1.2 1998-01-17 03:58:28 dfs Exp $"; #define LE 4 #define NE 5 -static char ExprBuf[TOKSIZE+1]; -static char CoerceBuf[TOKSIZE+1]; +DynamicBuffer ExprBuf; + +static char CoerceBuf[512]; extern int NumFuncs; #ifdef HAVE_PROTOS @@ -177,24 +178,27 @@ char **s; /* */ /***************************************************************/ #ifdef HAVE_PROTOS -PRIVATE int ParseExprToken(char *out, char **in) +PRIVATE int ParseExprToken(DynamicBuffer *buf, char **in) #else -static int ParseExprToken(out, in) -char *out; +static int ParseExprToken(buf, in) +DynamicBuffer *buf; char **in; #endif { char c; - *out = 0; + DBufFree(buf); /* Skip white space */ while (**in && isspace(**in)) (*in)++; if (!**in) return OK; - *out++ = c = *(*in)++; - *out = 0; + c = *(*in)++; + if (DBufPutc(buf, c) != OK) { + DBufFree(buf); + return E_NO_MEM; + } switch(c) { case COMMA: @@ -210,8 +214,10 @@ char **in; case '&': case '|': case '=': if (**in == c) { - *out++ = c; - *out = 0; + if (DBufPutc(buf, c) != OK) { + DBufFree(buf); + return E_NO_MEM; + } (*in)++; } return OK; @@ -219,8 +225,10 @@ char **in; case '!': case '>': case '<': if (**in == '=') { - *out++ = '='; - *out = 0; + if (DBufPutc(buf, c) != OK) { + DBufFree(buf); + return E_NO_MEM; + } (*in)++; } return OK; @@ -229,17 +237,32 @@ char **in; /* Handle the parsing of quoted strings */ if (c == '\"') { if (!**in) return E_MISS_QUOTE; - while (**in) if ((c = *out++ = *(*in)++) == '\"') break; - *out = 0; - if (c == '\"') return OK ; else return E_MISS_QUOTE; + while (**in) { + c = *(*in)++; + if (DBufPutc(buf, c) != OK) { + DBufFree(buf); + return E_NO_MEM; + } + if (c == '\"') break; + } + if (c == '\"') return OK; + DBufFree(buf); + return E_MISS_QUOTE; } /* Dates can be specified with single-quotes */ if (c == '\'') { if (!**in) return E_MISS_QUOTE; - while (**in) if ((c = *out++ = *(*in)++) == '\'') break; - *out = 0; - if (c == '\'') return OK ; else return E_MISS_QUOTE; + while (**in) { + c = *(*in)++; + if (DBufPutc(buf, c) != OK) { + DBufFree(buf); + return E_NO_MEM; + } + if (c == '\'') break; + } + if (c == '\'') return OK; + DBufFree(buf); } if (!ISID(c) && c != '$') { @@ -248,16 +271,24 @@ char **in; } /* Parse a constant, variable name or function */ - while (ISID(**in) || **in == ':' || **in == '.' || **in == TIMESEP) - *out++ = *(*in)++; - + while (ISID(**in) || **in == ':' || **in == '.' || **in == TIMESEP) { + if (DBufPutc(buf, **in) != OK) { + DBufFree(buf); + return E_NO_MEM; + } + (*in)++; + } /* Chew up any remaining white space */ while (**in && isspace(**in)) (*in)++; /* Peek ahead - is it '('? Then we have a function call */ - if (**in == '(') *out++ = *(*in)++; - - *out = 0; + if (**in == '(') { + if (DBufPutc(buf, **in++) != OK) { + DBufFree(buf); + return E_NO_MEM; + } + (*in)++; + } return OK; } @@ -280,10 +311,12 @@ Value *v; OpStackPtr = 0; ValStackPtr = 0; + r = Evaluate(e, NULL); /* Put last character parsed back onto input stream */ - if (*ExprBuf) (*e)--; + if (DBufLen(&ExprBuf)) (*e)--; + DBufFree(&ExprBuf); if (r) { CleanStack(); @@ -316,21 +349,35 @@ Var *locals; while(1) { /* Looking for a value. Accept: value, unary op, func. call or left paren */ - r = ParseExprToken(ExprBuf, s); + r = ParseExprToken(&ExprBuf, s); if (r) return r; - if (!*ExprBuf) return E_EOLN; + if (!DBufLen(&ExprBuf)) { + DBufFree(&ExprBuf); + return E_EOLN; + } - if (*ExprBuf == '(') { /* Parenthesized expression */ + if (*DBufValue(&ExprBuf) == '(') { /* Parenthesized expression */ + DBufFree(&ExprBuf); r = Evaluate(s, locals); /* Leaves the last parsed token in ExprBuf */ if (r) return r; - if (*ExprBuf != ')') return E_MISS_RIGHT_PAREN; - } else if (*ExprBuf == '+') continue; /* Ignore unary + */ - else if (*(ExprBuf + strlen(ExprBuf) -1) == '(') { /* Function Call */ - *(ExprBuf + strlen(ExprBuf) - 1) = 0; - f = FindFunc(ExprBuf, Func, NumFuncs); + r = OK; + if (*DBufValue(&ExprBuf) != ')') { + DBufFree(&ExprBuf); + return E_MISS_RIGHT_PAREN; + } + return OK; + } else if (*DBufValue(&ExprBuf) == '+') { + continue; /* Ignore unary + */ + } + else if (*(DBufValue(&ExprBuf) + DBufLen(&ExprBuf) -1) == '(') { /* Function Call */ + *(DBufValue(&ExprBuf) + DBufLen(&ExprBuf) - 1) = 0; + f = FindFunc(DBufValue(&ExprBuf), Func, NumFuncs); if (!f) { - ufname = StrDup(ExprBuf); + ufname = StrDup(DBufValue(&ExprBuf)); + DBufFree(&ExprBuf); if (!ufname) return E_NO_MEM; + } else { + DBufFree(&ExprBuf); } args = 0; if (PeekChar(s) == ')') { /* Function has no arguments */ @@ -340,7 +387,8 @@ Var *locals; free(ufname); } if (r) return r; - (void) ParseExprToken(ExprBuf, s); /* Guaranteed to be right paren. */ + (void) ParseExprToken(&ExprBuf, s); /* Guaranteed to be right paren. */ + DBufFree(&ExprBuf); } else { /* Function has some arguments */ while(1) { args++; @@ -349,10 +397,12 @@ Var *locals; if (!f) free(ufname); return r; } - if (*ExprBuf == ')') break; - else if (*ExprBuf != ',') { + if (*DBufValue(&ExprBuf) == ')') break; + else if (*DBufValue(&ExprBuf) != ',') { if (!f) free(ufname); - Eprint("%s: `%c'", ErrMsg[E_EXPECT_COMMA], *ExprBuf); + Eprint("%s: `%c'", ErrMsg[E_EXPECT_COMMA], + *DBufValue(&ExprBuf)); + DBufFree(&ExprBuf); return E_EXPECT_COMMA; } } @@ -362,27 +412,37 @@ Var *locals; free(ufname); } if (r) return r; + DBufFree(&ExprBuf); } } else { /* Unary operator */ - f = FindFunc(ExprBuf, UnOp, NUM_UN_OPS); + f = FindFunc(DBufValue(&ExprBuf), UnOp, NUM_UN_OPS); if (f) { + DBufFree(&ExprBuf); PushOpStack(*f); continue; /* Still looking for an atomic vlue */ - } else if (!ISID(*ExprBuf) && *ExprBuf != '$' - && *ExprBuf != '"' && *ExprBuf != '\'') { - Eprint("%s `%c'", ErrMsg[E_ILLEGAL_CHAR], *ExprBuf); + } else if (!ISID(*DBufValue(&ExprBuf)) && + *DBufValue(&ExprBuf) != '$' && + *DBufValue(&ExprBuf) != '"' && + *DBufValue(&ExprBuf) != '\'') { + Eprint("%s `%c'", ErrMsg[E_ILLEGAL_CHAR], + *DBufValue(&ExprBuf)); + DBufFree(&ExprBuf); return E_ILLEGAL_CHAR; } else { /* Must be a literal value */ - r = MakeValue(ExprBuf, &va, locals); + r = MakeValue(DBufValue(&ExprBuf), &va, locals); + DBufFree(&ExprBuf); if (r) return r; PushValStack(va); } } /* OK, we've got a literal value; now, we're looking for the end of the expression, or a binary operator. */ - r = ParseExprToken(ExprBuf, s); + r = ParseExprToken(&ExprBuf, s); if (r) return r; - if (*ExprBuf == 0 || *ExprBuf == ',' || *ExprBuf == ']' || *ExprBuf == ')') { + if (*DBufValue(&ExprBuf) == 0 || + *DBufValue(&ExprBuf) == ',' || + *DBufValue(&ExprBuf) == ']' || + *DBufValue(&ExprBuf) == ')') { /* We've hit the end of the expression. Pop off and evaluate until OpStackPtr = OpBase and ValStackPtr = ValBase+1 */ while (OpStackPtr > OpBase) { @@ -392,14 +452,20 @@ Var *locals; else r=(op.func)(); if (r) { + DBufFree(&ExprBuf); Eprint("`%s': %s", op.name, ErrMsg[r]); return r; } } - if (ValStackPtr != ValBase+1) return E_STACK_ERR; else return OK; + if (ValStackPtr != ValBase+1) { + DBufFree(&ExprBuf); + return E_STACK_ERR; + } + return OK; } /* Must be a binary operator */ - f = FindFunc(ExprBuf, BinOp, NUM_BIN_OPS); + f = FindFunc(DBufValue(&ExprBuf), BinOp, NUM_BIN_OPS); + DBufFree(&ExprBuf); if (!f) return E_EXPECTING_BINOP; /* While operators of higher or equal precedence are on the stack, diff --git a/src/files.c b/src/files.c index 9231767d..f6132aab 100644 --- a/src/files.c +++ b/src/files.c @@ -12,7 +12,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: files.c,v 1.3 1998-01-17 04:50:51 dfs Exp $"; +static char const RCSID[] = "$Id: files.c,v 1.4 1998-02-07 05:35:58 dfs Exp $"; #include @@ -146,36 +146,54 @@ int ReadLine() #ifdef HAVE_PROTOS PRIVATE int ReadLineFromFile(void) #else -static ReadLineFromFile() +static int ReadLineFromFile() #endif { int l; char *ptr; char *tmp; - CurLine = LineBuffer; - *LineBuffer = (char) 0; - l = 0; - ptr = LineBuffer; + DynamicBuffer buf; + + DBufInit(&buf); + DBufFree(&LineBuffer); + while(fp) { - tmp=fgets(ptr, LINELEN-l, fp); + if (DBufGets(&buf, fp) != OK) { + DBufFree(&LineBuffer); + return E_NO_MEM; + } LineNo++; - if (ferror(fp)) return E_IO_ERR; - if (feof(fp) || !tmp) { + if (ferror(fp)) { + DBufFree(&buf); + DBufFree(&LineBuffer); + return E_IO_ERR; + } + if (feof(fp) || !DBufLen(&buf)) { + DBufFree(&buf); FCLOSE(fp); } - l = strlen(LineBuffer); - if (l && (LineBuffer[l-1] == '\n')) LineBuffer[--l] = '\0'; - if (l && (LineBuffer[l-1] == '\\')) { - l--; - ptr = LineBuffer+l; - if (l >= LINELEN-1) return E_LINE_2_LONG; + l = DBufLen(&buf); + if (l && (DBufValue(&buf)[l-1] == '\\')) { + DBufValue(&buf)[l-1] = 0; + if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) { + DBufFree(&buf); + DBufFree(&LineBuffer); + return E_NO_MEM; + } continue; } + if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) { + DBufFree(&buf); + DBufFree(&LineBuffer); + return E_NO_MEM; + } FreshLine = 1; + CurLine = DBufValue(&LineBuffer); if (DebugFlag & DB_ECHO_LINE) OutputLine(ErrFp); return OK; } + CurLine = DBufValue(&LineBuffer); return OK; } @@ -296,13 +314,14 @@ char *fname; return r; } /* Skip blank chars */ - s = LineBuffer; + s = DBufValue(&LineBuffer); while (isspace(*s)) s++; if (*s && *s!=';' && *s!='#') { /* Add the line to the cache */ if (!cl) { cf->cache = NEW(CachedLine); if (!cf->cache) { + DBufFree(&LineBuffer); DestroyCache(cf); ShouldCache = 0; FCLOSE(fp); @@ -312,6 +331,7 @@ char *fname; } else { cl->next = NEW(CachedLine); if (!cl->next) { + DBufFree(&LineBuffer); DestroyCache(cf); ShouldCache = 0; FCLOSE(fp); @@ -322,6 +342,7 @@ char *fname; cl->next = NULL; cl->LineNo = LineNo; cl->text = StrDup(s); + DBufFree(&LineBuffer); if (!cl->text) { DestroyCache(cf); ShouldCache = 0; @@ -400,13 +421,18 @@ int DoInclude(p) ParsePtr p; #endif { - char tok[TOKSIZE]; + DynamicBuffer buf; int r, e; - if ( (r=ParseToken(p, tok)) ) return r; + DBufInit(&buf); + if ( (r=ParseToken(p, &buf)) ) return r; e = VerifyEoln(p); if (e) Eprint("%s", ErrMsg[e]); - if ( (r=IncludeFile(tok)) ) return r; + if ( (r=IncludeFile(DBufValue(&buf))) ) { + DBufFree(&buf); + return r; + } + DBufFree(&buf); NumIfs = 0; IfFlags = 0; return OK; diff --git a/src/funcs.c b/src/funcs.c index 01a1ba1c..7f0c0e08 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -11,7 +11,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: funcs.c,v 1.3 1998-01-17 04:50:51 dfs Exp $"; +static char const RCSID[] = "$Id: funcs.c,v 1.4 1998-02-07 05:35:59 dfs Exp $"; #include @@ -248,7 +248,7 @@ Operator Func[] = { { "realnow", 0, 0, FRealnow}, { "realtoday", 0, 0, FRealtoday }, { "sgn", 1, 1, FSgn }, - { "shell", 1, 1, FShell }, + { "shell", 1, 2, FShell }, { "strlen", 1, 1, FStrlen }, { "substr", 2, 3, FSubstr }, { "sunrise", 0, 1, FSunrise}, @@ -1301,35 +1301,50 @@ PRIVATE int FShell(void) static int FShell() #endif { - char buf[SHELLSIZE+1]; - int ch, len; + DynamicBuffer buf; + int ch, r; FILE *fp; - char *s; + int maxlen = -1; + + DBufInit(&buf); if (RunDisabled) return E_RUN_DISABLED; if (ARG(0).type != STR_TYPE) return E_BAD_TYPE; - s = buf; - len = 0; + if (Nargs >= 2) { + if (ARG(1).type != INT_TYPE) return E_BAD_TYPE; + maxlen = ARG(1).v.val; + } fp = POPEN(ARG(0).v.str, "r"); if (!fp) return E_IO_ERR; - while (len < SHELLSIZE) { + while (1) { ch = getc(fp); if (ch == EOF) { break; } - if (isspace(ch)) *s++ = ' '; - else *s++ = ch; - len++; + if (isspace(ch)) ch = ' '; + if (DBufPutc(&buf, (char) ch) != OK) { + PCLOSE(fp); + DBufFree(&buf); + return E_NO_MEM; + } + if (maxlen > 0 && DBufLen(&buf) >= maxlen) { + break; + } } - *s = 0; /* Delete trailing newline (converted to space) */ - if (s > buf && *(s-1) == ' ') *(s-1) = 0; + if (DBufLen(&buf) && DBufValue(&buf)[DBufLen(&buf)-1] == ' ') { + DBufValue(&buf)[DBufLen(&buf)-1] = 0; + } #if defined(__MSDOS__) || defined(__OS2__) - if (s-1 > buf && *(s-2) == ' ') *(s-2) = 0; + if (DBufLen(&buf) > 1 && DBufValue(&buf)[DBufLen(&buf)-2] == ' ') { + DBufValue(&buf)[DBufLen(&buf)-2] = 0; + } #endif PCLOSE(fp); - return RetStrVal(buf); + r = RetStrVal(DBufValue(&buf)); + DBufFree(&buf); + return r; } /***************************************************************/ @@ -1497,24 +1512,33 @@ PRIVATE int FFiledir(void) static int FFiledir() #endif { - char TmpBuf[LINELEN]; /* Should be _POSIX_PATH_MAX ? */ char *s; + DynamicBuffer buf; + int r; - strcpy(TmpBuf, FileName); - s = TmpBuf + strlen(TmpBuf) - 1; - if (s < TmpBuf) return RetStrVal("."); + DBufInit(&buf); + + if (DBufPuts(&buf, FileName) != OK) return E_NO_MEM; + if (DBufLen(&buf) == 0) { + DBufFree(&buf); + return RetStrVal("."); + } + + s = DBufValue(&buf) + DBufLen(&buf) - 1; #if defined(__OS2__) || defined(__MSDOS__) /* Both '\\' and '/' can be part of path; handle drive letters. */ - while (s > TmpBuf && !strchr("\\/:", *s)) s--; + while (s > DBufValue(&buf) && !strchr("\\/:", *s)) s--; if (*s == ':') { s[1] = '.'; s += 2; } - if (s > TmpBuf) *s = '/'; + if (s > DBufValue(&buf)) *s = '/'; #else - while (s > TmpBuf && *s != '/') s--; + while (s > DBufValue(&buf) && *s != '/') s--; #endif if (*s == '/') { *s = 0; - return RetStrVal(TmpBuf); - } else return RetStrVal("."); + r = RetStrVal(DBufValue(&buf)); + } else r = RetStrVal("."); + DBufFree(&buf); + return r; } /***************************************************************/ /* */ @@ -1689,7 +1713,9 @@ static int FDosubst() #endif { int jul, tim, r; - char TmpBuf[LINELEN]; + DynamicBuffer buf; + + DBufInit(&buf); jul = NO_DATE; tim = NO_TIME; @@ -1703,8 +1729,10 @@ static int FDosubst() } } - if ((r=DoSubstFromString(ARG(0).v.str, TmpBuf, jul, tim))) return r; - return RetStrVal(TmpBuf); + if ((r=DoSubstFromString(ARG(0).v.str, &buf, jul, tim))) return r; + r = RetStrVal(DBufValue(&buf)); + DBufFree(&buf); + return r; } /***************************************************************/ diff --git a/src/globals.h b/src/globals.h index 865dc0aa..ff5e8086 100644 --- a/src/globals.h +++ b/src/globals.h @@ -11,7 +11,7 @@ /* */ /***************************************************************/ -/* $Id: globals.h,v 1.1 1998-01-15 02:50:29 dfs Exp $ */ +/* $Id: globals.h,v 1.2 1998-02-07 05:35:59 dfs Exp $ */ #ifdef MK_GLOBALS #undef EXTERN @@ -36,9 +36,6 @@ EXTERN int CurMon; EXTERN int CurYear; EXTERN int LineNo; EXTERN int FreshLine; -EXTERN char LineBuffer[LINELEN]; -EXTERN char SubstBuffer[LINELEN]; -EXTERN char TokBuffer[TOKSIZE+1]; EXTERN INIT( char *MsgCommand, NULL); EXTERN INIT( int ShowAllErrors, 0); EXTERN INIT( int DebugFlag, 0); @@ -113,9 +110,11 @@ EXTERN INIT( char *EndSentIg, "\"')]}>"); /* We need the language stuff here... */ #include "lang.h" +#include "dynbuf.h" -EXTERN INIT( char Banner[LINELEN], L_BANNER); - +EXTERN DynamicBuffer Banner; +EXTERN DynamicBuffer LineBuffer; +EXTERN DynamicBuffer TPushBuffer; /* List of months */ EXTERN char *EnglishMonthName[] #ifdef MK_GLOBALS diff --git a/src/init.c b/src/init.c index 38a11fdd..400236dd 100644 --- a/src/init.c +++ b/src/init.c @@ -12,7 +12,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: init.c,v 1.2 1998-01-17 03:58:29 dfs Exp $"; +static char const RCSID[] = "$Id: init.c,v 1.3 1998-02-07 05:36:00 dfs Exp $"; #define L_IN_INIT 1 #include @@ -120,6 +120,13 @@ char *argv[]; int y, m, d, rep; Token tok; + /* Initialize global dynamic buffers */ + DBufInit(&Banner); + DBufInit(&LineBuffer); + DBufInit(&TPushBuffer); + + DBufPuts(&Banner, L_BANNER); + /* Make sure remind is not installed set-uid or set-gid */ #ifdef UNIX if (getgid() != getegid() || diff --git a/src/main.c b/src/main.c index aa663043..2bd12236 100644 --- a/src/main.c +++ b/src/main.c @@ -11,7 +11,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: main.c,v 1.3 1998-01-17 04:50:52 dfs Exp $"; +static char const RCSID[] = "$Id: main.c,v 1.4 1998-02-07 05:36:01 dfs Exp $"; #ifdef HAVE_STDLIB_H #include @@ -73,7 +73,6 @@ long timegm ARGS((struct tm *tm)); long timelocal ARGS((struct tm *tm)); #endif -static char TPushBuffer[TOKSIZE+1]; /* Buffer for pushing back a token. */ static char *TokenPushed = NULL; /* Whooo... the putchar/Putchar/PutChar macros are a mess... @@ -393,9 +392,17 @@ int peek; int r; *err = 0; - if (TokenPushed && *TokenPushed) + if (TokenPushed && *TokenPushed) { if (peek) return *TokenPushed; - else return *TokenPushed++; + else { + r = *TokenPushed++; + if (!r) { + DBufFree(&TPushBuffer); + TokenPushed = NULL; + } + return r; + } + } while(1) { if (p->isnested) { @@ -482,17 +489,16 @@ int peek; /* */ /***************************************************************/ #ifdef HAVE_PROTOS -PUBLIC int ParseToken(ParsePtr p, char *out) +PUBLIC int ParseToken(ParsePtr p, DynamicBuffer *dbuf) #else -int ParseToken(p, out) +int ParseToken(p, dbuf) ParsePtr p; -char *out; +DynamicBuffer *dbuf; #endif { int c, err; - int len = 0; - *out = 0; + DBufFree(dbuf); c = ParseChar(p, &err, 0); if (err) return err; @@ -501,22 +507,17 @@ char *out; if (err) return err; } if (!c) return OK; - *out++ = c; - len++; - while (c && !isspace(c)) { + if (DBufPutc(dbuf, c) != OK) { + DBufFree(dbuf); + return E_NO_MEM; + } c = ParseChar(p, &err, 0); - if (err) return err; - if (len < TOKSIZE && c && !isspace(c)) { - *out++ = c; - len++; + if (err) { + DBufFree(dbuf); + return err; } } - /* Ignore trailing commas */ - if (len > 0 && *(out-1) == ',') { - out--; - } - *out = 0; return OK; } @@ -530,17 +531,16 @@ char *out; /* */ /***************************************************************/ #ifdef HAVE_PROTOS -PUBLIC int ParseIdentifier(ParsePtr p, char *out) +PUBLIC int ParseIdentifier(ParsePtr p, DynamicBuffer *dbuf) #else -int ParseIdentifier(p, out) +int ParseIdentifier(p, dbuf) ParsePtr p; -char *out; +DynamicBuffer *dbuf; #endif { int c, err; - int len = 0; - *out = 0; + DBufFree(dbuf); c = ParseChar(p, &err, 0); if (err) return err; @@ -550,23 +550,26 @@ char *out; } if (!c) return E_EOLN; if (c != '$' && c != '_' && !isalpha(c)) return E_BAD_ID; - *out++ = c; - *out = 0; - len++; + if (DBufPutc(dbuf, c) != OK) { + DBufFree(dbuf); + return E_NO_MEM; + } while (1) { c = ParseChar(p, &err, 1); - if (err) return err; + if (err) { + DBufFree(dbuf); + return err; + } if (c != '_' && !isalnum(c)) return OK; - - if (len < TOKSIZE) { - c = ParseChar(p, &err, 0); /* Guaranteed to work */ - *out++ = c; - *out = 0; - len++; + c = ParseChar(p, &err, 0); /* Guaranteed to work */ + if (DBufPutc(dbuf, c) != OK) { + DBufFree(dbuf); + return E_NO_MEM; } } } + /***************************************************************/ /* */ /* EvaluateExpr */ @@ -730,17 +733,20 @@ ParsePtr p; /* */ /***************************************************************/ #ifdef HAVE_PROTOS -PUBLIC void PushToken(const char *tok) +PUBLIC int PushToken(const char *tok) #else -void PushToken(tok) +int PushToken(tok) char *tok; #endif { - TokenPushed = TPushBuffer; - strcpy(TPushBuffer, tok); - strcat(TPushBuffer, " "); /* Separate the pushed token from the next - token */ - + DBufFree(&TPushBuffer); + if (DBufPuts(&TPushBuffer, (char *) tok) != OK || + DBufPutc(&TPushBuffer, ' ') != OK) { + DBufFree(&TPushBuffer); + return E_NO_MEM; + } + TokenPushed = DBufValue(&TPushBuffer); + return OK; } /***************************************************************/ @@ -986,11 +992,18 @@ ParsePtr p; { int r; - if ( (r = ParseToken(p, TokBuffer)) ) return r; - if (*TokBuffer && (*TokBuffer != '#') && (*TokBuffer != ';')) { - Eprint("%s: `%s'", ErrMsg[E_EXPECTING_EOL], TokBuffer); + DynamicBuffer buf; + DBufInit(&buf); + + if ( (r = ParseToken(p, &buf)) ) return r; + if (*DBufValue(&buf) && + (*DBufValue(&buf) != '#') && + (*DBufValue(&buf) != ';')) { + Eprint("%s: `%s'", ErrMsg[E_EXPECTING_EOL], DBufValue(&buf)); + DBufFree(&buf); return E_EXTRANEOUS_TOKEN; } + DBufFree(&buf); return OK; } @@ -1084,9 +1097,9 @@ ParsePtr p; { int err; int c; - char buf[LINELEN]; /* So we don't mess up the banner if an error occurs */ - char *s; + DynamicBuffer buf; + DBufInit(&buf); c = ParseChar(p, &err, 0); if (err) return err; while (isspace(c)) { @@ -1094,16 +1107,20 @@ ParsePtr p; if (err) return err; } if (!c) return E_EOLN; - s = buf; while(c) { - *s++ = c; + if (DBufPutc(&buf, c) != OK) return E_NO_MEM; c = ParseChar(p, &err, 0); - if (err) return err; + if (err) { + DBufFree(&buf); + return err; + } } - *s++ = 0; - strcpy(Banner, buf); - return OK; + DBufFree(&Banner); + + err = DBufPuts(&Banner, DBufValue(&buf)); + DBufFree(&buf); + return err; } /***************************************************************/ @@ -1123,16 +1140,23 @@ ParsePtr p; { int r; - if ( (r=ParseToken(p, TokBuffer)) ) return r; + DynamicBuffer buf; + DBufInit(&buf); + + if ( (r=ParseToken(p, &buf)) ) return r; /* Only allow RUN ON in top-level script */ - if (! StrCmpi(TokBuffer, "ON")) { + if (! StrCmpi(DBufValue(&buf), "ON")) { if (TopLevel()) RunDisabled &= ~RUN_SCRIPT; } /* But allow RUN OFF anywhere */ - else if (! StrCmpi(TokBuffer, "OFF")) + else if (! StrCmpi(DBufValue(&buf), "OFF")) RunDisabled |= RUN_SCRIPT; - else return E_PARSE_ERR; + else { + DBufFree(&buf); + return E_PARSE_ERR; + } + DBufFree(&buf); return VerifyEoln(p); } @@ -1197,13 +1221,18 @@ ParsePtr p; int r; char *s; + DynamicBuffer buf; + + DBufInit(&buf); t.typ = MSG_TYPE; tt.ttime = SystemTime(0) / 60; - if ( (r=DoSubst(p, SubstBuffer, &t, &tt, JulianToday, NORMAL_MODE)) ) + if ( (r=DoSubst(p, &buf, &t, &tt, JulianToday, NORMAL_MODE)) ) { return r; - s = SubstBuffer; + } + s = DBufValue(&buf); while (isspace(*s)) s++; fprintf(ErrFp, "%s\n", s); + DBufFree(&buf); return OK; } diff --git a/src/omit.c b/src/omit.c index 92da0199..37b43a68 100644 --- a/src/omit.c +++ b/src/omit.c @@ -11,7 +11,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: omit.c,v 1.2 1998-01-17 03:58:31 dfs Exp $"; +static char const RCSID[] = "$Id: omit.c,v 1.3 1998-02-07 05:36:02 dfs Exp $"; #include @@ -303,28 +303,35 @@ ParsePtr p; Token tok; int parsing=1; int syndrome; - + + DynamicBuffer buf; + DBufInit(&buf); + /* Parse the OMIT. We need a month and day; year is optional. */ while(parsing) { - if ( (r=ParseToken(p, TokBuffer)) ) return r; - FindToken(TokBuffer, &tok); + if ( (r=ParseToken(p, &buf)) ) return r; + FindToken(DBufValue(&buf), &tok); switch (tok.type) { case T_Year: + DBufFree(&buf); if (y != NO_YR) return E_YR_TWICE; y = tok.val; break; case T_Month: + DBufFree(&buf); if (m != NO_MON) return E_MON_TWICE; m = tok.val; break; case T_Day: + DBufFree(&buf); if (d != NO_DAY) return E_DAY_TWICE; d = tok.val; break; case T_Delta: + DBufFree(&buf); break; case T_Empty: @@ -333,11 +340,14 @@ ParsePtr p; case T_Priority: case T_Tag: case T_Duration: + DBufFree(&buf); parsing = 0; break; default: - Eprint("%s: `%s' (OMIT)", ErrMsg[E_UNKNOWN_TOKEN], TokBuffer); + Eprint("%s: `%s' (OMIT)", ErrMsg[E_UNKNOWN_TOKEN], + DBufValue(&buf)); + DBufFree(&buf); return E_UNKNOWN_TOKEN; } } diff --git a/src/protos.h b/src/protos.h index cf496a31..f4e6ddf8 100644 --- a/src/protos.h +++ b/src/protos.h @@ -9,7 +9,7 @@ /* */ /***************************************************************/ -/* $Id: protos.h,v 1.2 1998-01-17 03:58:31 dfs Exp $ */ +/* $Id: protos.h,v 1.3 1998-02-07 05:36:02 dfs Exp $ */ #ifdef HAVE_PROTOS #define ARGS(x) x @@ -23,6 +23,8 @@ /* Define a general malloc routine for creating pointers to objects */ #define NEW(type) ((type *) malloc(sizeof(type))) +#include "dynbuf.h" + #ifndef HAVE_STRSTR char *strstr ARGS ((char *s1, char *s2)); #endif @@ -30,7 +32,7 @@ char *strstr ARGS ((char *s1, char *s2)); int CallUserFunc ARGS ((char *name, int nargs)); int DoFset ARGS ((ParsePtr p)); void ProduceCalendar ARGS ((void)); -char *SimpleTime ARGS ((int tim, char *out)); +char *SimpleTime ARGS ((int tim)); int DoRem ARGS ((ParsePtr p)); int DoFlush ARGS ((ParsePtr p)); void DoExit ARGS ((ParsePtr p)); @@ -42,8 +44,8 @@ int TriggerReminder ARGS ((ParsePtr p, Trigger *t, TimeTrig *tim, int jul, int TriggerReminder ARGS ((ParsePtr p, Trigger *t, TimeTrig *tim, int jul)); #endif int ShouldTriggerReminder ARGS ((Trigger *t, TimeTrig *tim, int jul)); -int DoSubst ARGS ((ParsePtr p, char *out, Trigger *t, TimeTrig *tt, int jul, int mode)); -int DoSubstFromString ARGS ((char *source, char *dest, int jul, int tim)); +int DoSubst ARGS ((ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul, int mode)); +int DoSubstFromString ARGS ((char *source, DynamicBuffer *dbuf, int jul, int tim)); int EvalExpr ARGS ((char **e, Value *v)); int DoCoerce ARGS ((char type, Value *v)); void PrintValue ARGS ((Value *v, FILE *fp)); @@ -63,8 +65,8 @@ int main ARGS ((int argc, char *argv[])); int Julian ARGS ((int year, int month, int day)); void FromJulian ARGS ((int jul, int *y, int *m, int *d)); int ParseChar ARGS ((ParsePtr p, int *err, int peek)); -int ParseToken ARGS ((ParsePtr p, char *out)); -int ParseIdentifier ARGS ((ParsePtr p, char *out)); +int ParseToken ARGS ((ParsePtr p, DynamicBuffer *dbuf)); +int ParseIdentifier ARGS ((ParsePtr p, DynamicBuffer *dbuf)); int EvaluateExpr ARGS ((ParsePtr p, Value *v)); int Evaluate ARGS ((char **s, Var *locals)); int FnPopValStack ARGS ((Value *val)); @@ -72,7 +74,7 @@ void Eprint ARGS ((const char *fmt, ...)); void OutputLine ARGS ((FILE *fp)); void CreateParser ARGS ((char *s, ParsePtr p)); void DestroyParser ARGS ((ParsePtr p)); -void PushToken ARGS ((const char *tok)); +int PushToken ARGS ((const char *tok)); long SystemTime ARGS ((int realtime)); int SystemDate ARGS ((int *y, int *m, int *d)); int DoIf ARGS ((ParsePtr p)); @@ -115,7 +117,7 @@ void DestroyVars ARGS ((int all)); int PreserveVar ARGS ((char *name)); int DoPreserve ARGS ((Parser *p)); int DoSatRemind ARGS ((Trigger *trig, TimeTrig *tim, ParsePtr p)); -void DoMsgCommand ARGS ((char *cmd, char *msg)); +int DoMsgCommand ARGS ((char *cmd, char *msg)); int ParseNonSpaceChar ARGS ((ParsePtr p, int *err, int peek)); unsigned int HashVal ARGS ((const char *str)); int DateOK ARGS ((int y, int m, int d)); diff --git a/src/queue.c b/src/queue.c index b12918fd..1f115ca1 100644 --- a/src/queue.c +++ b/src/queue.c @@ -10,7 +10,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: queue.c,v 1.2 1998-01-17 03:58:31 dfs Exp $"; +static char const RCSID[] = "$Id: queue.c,v 1.3 1998-02-07 05:36:02 dfs Exp $"; /* We only want object code generated if we have queued reminders */ #ifdef HAVE_QUEUED @@ -382,8 +382,9 @@ QueuedRem *q; RunDisabled = q->RunDisabled; /* Don't want weird scheduling functions to be a security hole! */ while(1) { - sprintf(LineBuffer, "%s(%d)", q->sched, q->ntrig); - s = LineBuffer; + char exprBuf[VAR_NAME_LEN+32]; + sprintf(exprBuf, "%s(%d)", q->sched, q->ntrig); + s = exprBuf; r = EvalExpr(&s, &v); if (r) { q->sched[0] = 0; diff --git a/src/rem2ps.c b/src/rem2ps.c index 4163753d..79d507e4 100644 --- a/src/rem2ps.c +++ b/src/rem2ps.c @@ -10,7 +10,8 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: rem2ps.c,v 1.3 1998-01-24 03:20:07 dfs Exp $"; +#include "dynbuf.h" +static char const RCSID[] = "$Id: rem2ps.c,v 1.4 1998-02-07 05:36:03 dfs Exp $"; #include #include @@ -97,8 +98,6 @@ char PortraitMode; char NoSmallCal; char UseISO; -char LineBuffer[LINELEN]; - char *HeadFont="Helvetica"; char *TitleFont="Helvetica"; char *DayFont="Helvetica-BoldOblique"; @@ -152,6 +151,8 @@ char argv[]; { /* If stdin is a tty - probably wrong. */ + DynamicBuffer buf; + DBufInit(&buf); Init(argc, argv); if (isatty(0)) { @@ -160,8 +161,8 @@ char argv[]; /* Search for a valid input file */ while (!feof(stdin)) { - gets(LineBuffer); - if (!strcmp(LineBuffer, PSBEGIN)) { + DBufGets(&buf, stdin); + if (!strcmp(DBufValue(&buf), PSBEGIN)) { if (!validfile) { if (Verbose) { fprintf(stderr, "Rem2PS: Version %s Copyright 1992-1997 by David F. Skoll\n\n", VERSION); @@ -203,18 +204,19 @@ void DoPsCal() int firstcol; char *startOfBody; char passthru[PASSTHRU_LEN+1]; - + DynamicBuffer buf; CalEntry *c, *d; /* Read the month and year name, followed by # days in month and 1st day of month */ - gets(LineBuffer); - sscanf(LineBuffer, "%s %s %d %d %d", month, year, &days, &wkday, + DBufInit(&buf); + DBufGets(&buf, stdin); + sscanf(DBufValue(&buf), "%s %s %d %d %d", month, year, &days, &wkday, &MondayFirst); /* Get day names */ - gets(LineBuffer); - sscanf(LineBuffer, "%32s %32s %32s %32s %32s %32s %32s", + DBufGets(&buf, stdin); + sscanf(DBufValue(&buf), "%32s %32s %32s %32s %32s %32s %32s", DayName[0], DayName[1], DayName[2], DayName[3], DayName[4], DayName[5], DayName[6]); @@ -224,10 +226,11 @@ void DoPsCal() WriteProlog(); } - gets(LineBuffer); - sscanf(LineBuffer, "%s %d", prevm, &prevdays); - gets(LineBuffer); - sscanf(LineBuffer, "%s %d", nextm, &nextdays); + DBufGets(&buf, stdin); + sscanf(DBufValue(&buf), "%s %d", prevm, &prevdays); + DBufGets(&buf, stdin); + sscanf(DBufValue(&buf), "%s %d", nextm, &nextdays); + DBufFree(&buf); MaxDay = days; FirstWkDay = wkday; @@ -277,11 +280,14 @@ void DoPsCal() exit(1); } - gets(LineBuffer); - if (!strcmp(LineBuffer, PSEND)) break; + DBufGets(&buf, stdin); + if (!strcmp(DBufValue(&buf), PSEND)) { + DBufFree(&buf); + break; + } /* Read the day number - a bit of a hack! */ - DayNum = (LineBuffer[8] - '0') * 10 + LineBuffer[9] - '0'; + DayNum = (DBufValue(&buf)[8] - '0') * 10 + DBufValue(&buf)[9] - '0'; if (DayNum != CurDay) { for(; CurDaynext = NULL; /* Skip the tag, duration and time */ - startOfBody = LineBuffer+10; + startOfBody = DBufValue(&buf)+10; /* Eat the passthru */ startOfBody = EatToken(startOfBody, passthru, PASSTHRU_LEN); @@ -391,7 +397,7 @@ void WriteProlog() char *isostuff; FILE *fp; int nread; - char buffer[LINELEN]; + char buffer[512]; if (!PortraitMode) { i = x; x = y; y = i; @@ -466,7 +472,7 @@ void WriteProlog() fprintf(stderr, "Could not open prologue file `%s'\n", UserProlog); } else { while(1) { - nread = fread(buffer, sizeof(char), LINELEN, fp); + nread = fread(buffer, sizeof(char), 512, fp); if (!nread) break; fwrite(buffer, sizeof(char), nread, stdout); } @@ -870,7 +876,7 @@ int DoQueuedPs() CalEntry *e, *n; FILE *fp; int fnoff; - char buffer[LINELEN]; + char buffer[512]; if (!MondayFirst) begin = CurDay - WkDayNum; else begin = CurDay - (WkDayNum ? WkDayNum-1 : 6); @@ -905,7 +911,7 @@ int DoQueuedPs() fprintf(stderr, "Could not open PostScript file `%s'\n", e->entry+1); } else { while(1) { - nread = fread(buffer, sizeof(char), LINELEN, fp); + nread = fread(buffer, sizeof(char), 512, fp); if (!nread) break; fwrite(buffer, sizeof(char), nread, stdout); } diff --git a/src/sort.c b/src/sort.c index 84684022..0f571bd0 100644 --- a/src/sort.c +++ b/src/sort.c @@ -10,7 +10,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: sort.c,v 1.2 1998-01-17 03:58:33 dfs Exp $"; +static char const RCSID[] = "$Id: sort.c,v 1.3 1998-02-07 05:36:03 dfs Exp $"; #include #include @@ -205,10 +205,11 @@ static void IssueSortBanner(jul) int jul; #endif { - char BanExpr[25]; + char BanExpr[64]; int y, m, d; Value v; char *s = BanExpr; + DynamicBuffer buf; if (UserFuncExists("sortbanner") != 1) return; @@ -217,8 +218,11 @@ int jul; y = EvalExpr(&s, &v); if (y) return; if (DoCoerce(STR_TYPE, &v)) return; - if (!DoSubstFromString(v.v.str, SubstBuffer, jul, NO_TIME)) - if (*SubstBuffer) printf("%s\n", SubstBuffer); + DBufInit(&buf); + if (!DoSubstFromString(v.v.str, &buf, jul, NO_TIME)) { + if (*DBufValue(&buf)) printf("%s\n", DBufValue(&buf)); + DBufFree(&buf); + } DestroyValue(v); } diff --git a/src/token.c b/src/token.c index 3dc6e866..afbc9132 100644 --- a/src/token.c +++ b/src/token.c @@ -11,7 +11,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: token.c,v 1.2 1998-01-17 03:58:33 dfs Exp $"; +static char const RCSID[] = "$Id: token.c,v 1.3 1998-02-07 05:36:03 dfs Exp $"; #include #include @@ -156,26 +156,20 @@ char *s; { char *t; int len=0; - + DynamicBuffer buf; + DBufInit(&buf); + + tok->type = T_Illegal; + while (isspace(*s)) s++; - t = TokBuffer; - while (*s && !isspace(*s)) { - if (len < TOKSIZE) { - *t++ = *s++; - len++; - } else s++; + if (DBufPutc(&buf, *s++) != OK) return s; } - /* Ignore trailing commas */ - if (t > TokBuffer && *(t-1) == ',') { - *(t-1) = 0; - } else { - *t = 0; - } + FindToken(DBufValue(&buf), tok); + DBufFree(&buf); - FindToken(TokBuffer, tok); return s; } diff --git a/src/userfns.c b/src/userfns.c index b24b8064..d728fcae 100644 --- a/src/userfns.c +++ b/src/userfns.c @@ -11,7 +11,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: userfns.c,v 1.2 1998-01-17 03:58:34 dfs Exp $"; +static char const RCSID[] = "$Id: userfns.c,v 1.3 1998-02-07 05:36:04 dfs Exp $"; #include #include @@ -38,7 +38,6 @@ typedef struct udf_struct { char name[VAR_NAME_LEN+1]; char *text; Var *locals; - char IsCached; char IsActive; int nargs; } UserFunc; @@ -79,27 +78,42 @@ ParsePtr p; UserFunc *func; Var *v; + DynamicBuffer buf; + DBufInit(&buf); + /* Get the function name */ - if ( (r=ParseIdentifier(p, TokBuffer)) ) return r; - if (*TokBuffer == '$') return E_BAD_ID; + if ( (r=ParseIdentifier(p, &buf)) ) return r; + if (*DBufValue(&buf) == '$') { + DBufFree(&buf); + return E_BAD_ID; + } /* Should be followed by '(' */ c = ParseNonSpaceChar(p, &r, 0); - if (r) return r; - if (c != '(') return E_PARSE_ERR; + if (r) { + DBufFree(&buf); + return r; + } + if (c != '(') { + DBufFree(&buf); + return E_PARSE_ERR; + } func = NEW(UserFunc); - if (!func) return E_NO_MEM; - StrnCpy(func->name, TokBuffer, VAR_NAME_LEN); + if (!func) { + DBufFree(&buf); + return E_NO_MEM; + } + StrnCpy(func->name, DBufValue(&buf), VAR_NAME_LEN); + DBufFree(&buf); if (!Hush) { - if (FindFunc(TokBuffer, Func, NumFuncs)) { + if (FindFunc(DBufValue(&buf), Func, NumFuncs)) { Eprint("%s: `%s'", ErrMsg[E_REDEF_FUNC], - TokBuffer); + DBufValue(&buf)); } } func->locals = NULL; func->text = NULL; - func->IsCached = 1; func->IsActive = 0; func->nargs = 0; @@ -114,16 +128,21 @@ ParsePtr p; } else { while(1) { - if ( (r=ParseIdentifier(p, TokBuffer)) ) return r; - if (*TokBuffer == '$') return E_BAD_ID; + if ( (r=ParseIdentifier(p, &buf)) ) return r; + if (*DBufValue(&buf) == '$') { + DBufFree(&buf); + return E_BAD_ID; + } v = NEW(Var); - func->nargs++; - v->v.type = ERR_TYPE; if (!v) { + DBufFree(&buf); DestroyUserFunc(func); return E_NO_MEM; } - StrnCpy(v->name, TokBuffer, VAR_NAME_LEN); + func->nargs++; + v->v.type = ERR_TYPE; + StrnCpy(v->name, DBufValue(&buf), VAR_NAME_LEN); + DBufFree(&buf); v->next = func->locals; func->locals = v; c = ParseNonSpaceChar(p, &r, 0); @@ -142,18 +161,10 @@ ParsePtr p; return E_PARSE_ERR; } - /* A bit of trickery here - if the definition is already cached, - no point in copying it. */ - if (CurLine != LineBuffer) { - func->IsCached = 1; - func->text = p->pos; - } else { - func->IsCached = 0; - func->text = StrDup(p->pos); - if (!func->text) { - DestroyUserFunc(func); - return E_NO_MEM; - } + func->text = StrDup(p->pos); + if (!func->text) { + DestroyUserFunc(func); + return E_NO_MEM; } /* If an old definition of this function exists, destroy it */ @@ -190,7 +201,7 @@ UserFunc *f; } /* Free the function definition */ - if (f->text && !f->IsCached) free(f->text); + if (f->text) free(f->text); /* Free the data structure itself */ free(f); diff --git a/src/var.c b/src/var.c index 1aaa276c..9b02aa00 100644 --- a/src/var.c +++ b/src/var.c @@ -11,7 +11,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: var.c,v 1.2 1998-01-17 03:58:34 dfs Exp $"; +static char const RCSID[] = "$Id: var.c,v 1.3 1998-02-07 05:36:04 dfs Exp $"; #include #include @@ -218,14 +218,22 @@ Parser *p; Value v; int r; - r = ParseIdentifier(p, TokBuffer); + DynamicBuffer buf; + DBufInit(&buf); + + r = ParseIdentifier(p, &buf); if (r) return r; r = EvaluateExpr(p, &v); - if (r) return r; + if (r) { + DBufFree(&buf); + return r; + } - if (*TokBuffer == '$') return SetSysVar(TokBuffer+1, &v); - else return SetVar(TokBuffer, &v); + if (*DBufValue(&buf) == '$') r = SetSysVar(DBufValue(&buf)+1, &v); + else r = SetVar(DBufValue(&buf), &v); + DBufFree(&buf); + return r; } /***************************************************************/ @@ -242,18 +250,27 @@ Parser *p; { int r; - r = ParseToken(p, TokBuffer); - if (r) return r; - if (!*TokBuffer) return E_EOLN; + DynamicBuffer buf; + DBufInit(&buf); - (void) DeleteVar(TokBuffer); /* Ignore error - nosuchvar */ + r = ParseToken(p, &buf); + if (r) return r; + if (!DBufLen(&buf)) { + DBufFree(&buf); + return E_EOLN; + } + + (void) DeleteVar(DBufValue(&buf)); /* Ignore error - nosuchvar */ /* Keep going... */ while(1) { - r = ParseToken(p, TokBuffer); + r = ParseToken(p, &buf); if (r) return r; - if (!*TokBuffer) return OK; - (void) DeleteVar(TokBuffer); + if (!DBufLen(&buf)) { + DBufFree(&buf); + return OK; + } + (void) DeleteVar(DBufValue(&buf)); } } @@ -273,30 +290,41 @@ ParsePtr p; { int r; Var *v; + DynamicBuffer buf; - r = ParseToken(p, TokBuffer); + DBufInit(&buf); + r = ParseToken(p, &buf); if (r) return r; - if (!*TokBuffer || *TokBuffer == '#' || *TokBuffer == ';') { + if (!*DBufValue(&buf) || + *DBufValue(&buf) == '#' || + *DBufValue(&buf) == ';') { + DBufFree(&buf); DumpVarTable(); return OK; } fprintf(ErrFp, "%*s %s\n\n", VAR_NAME_LEN, VARIABLE, VALUE); while(1) { - if (*TokBuffer == '$') { - DumpSysVarByName(TokBuffer+1); + if (*DBufValue(&buf) == '$') { + DumpSysVarByName(DBufValue(&buf)+1); } else { - v = FindVar(TokBuffer, 0); - TokBuffer[VAR_NAME_LEN] = 0; - if (!v) fprintf(ErrFp, "%*s %s\n", VAR_NAME_LEN, TokBuffer, UNDEF); + v = FindVar(DBufValue(&buf), 0); + DBufValue(&buf)[VAR_NAME_LEN] = 0; + if (!v) fprintf(ErrFp, "%*s %s\n", VAR_NAME_LEN, + DBufValue(&buf), UNDEF); else { fprintf(ErrFp, "%*s ", VAR_NAME_LEN, v->name); PrintValue(&(v->v), ErrFp); fprintf(ErrFp, "\n"); } } - r = ParseToken(p, TokBuffer); + r = ParseToken(p, &buf); if (r) return r; - if (!*TokBuffer || *TokBuffer == '#' || *TokBuffer == ';') return OK; + if (!*DBufValue(&buf) || + *DBufValue(&buf) == '#' || + *DBufValue(&buf) == ';') { + DBufFree(&buf); + return OK; + } } } @@ -404,19 +432,30 @@ Parser *p; { int r; - r = ParseToken(p, TokBuffer); - if (r) return r; - if (!*TokBuffer) return E_EOLN; + DynamicBuffer buf; + DBufInit(&buf); - r = PreserveVar(TokBuffer); + r = ParseToken(p, &buf); + if (r) return r; + if (DBufLen(&buf)) { + DBufFree(&buf); + return E_EOLN; + } + + r = PreserveVar(DBufValue(&buf)); + DBufFree(&buf); if (r) return r; /* Keep going... */ while(1) { - r = ParseToken(p, TokBuffer); + r = ParseToken(p, &buf); if (r) return r; - if (!*TokBuffer) return OK; - r = PreserveVar(TokBuffer); + if (!DBufLen(&buf)) { + DBufFree(&buf); + return OK; + } + r = PreserveVar(DBufValue(&buf)); + DBufFree(&buf); if (r) return r; } }