Compare commits

...

8 Commits

Author SHA1 Message Date
Dianne Skoll
e33bf4e80a Explicitly set sa_flags in sigaction. 2024-06-06 10:42:04 -04:00
Dianne Skoll
b3af44d212 Update docs/WHATSNEW for 05.00.00 release. 2024-06-06 10:28:38 -04:00
Dianne Skoll
1e753d5209 Preserve variables needed across iterations. 2024-06-05 15:08:12 -04:00
Dianne Skoll
4bf31005ea Better error location in a couple more cases. 2024-06-05 09:15:10 -04:00
Dianne Skoll
7c86bc910a Better diagnostics of unmatched IFs 2024-06-05 09:08:04 -04:00
Dianne Skoll
4f146a99a9 Simplify Eprint logic. 2024-06-04 21:10:17 -04:00
Dianne Skoll
a6a638e0e6 Add test for UNMATCHED PUSH 2024-06-04 16:27:23 -04:00
Dianne Skoll
325814f5e1 Print the location of unmatched PUSH 2024-06-04 16:25:14 -04:00
14 changed files with 119 additions and 42 deletions

View File

@@ -1,6 +1,6 @@
CHANGES TO REMIND
* VERSION 5.0 Patch 0 - 2024-??-??
* VERSION 5.0 Patch 0 - 2024-06-06
* MAJOR CHANGE: The expression evaluation engine has been completely replaced
with a new one that splits parsing and evaluating into two separate steps.
@@ -33,6 +33,12 @@ CHANGES TO REMIND
and it will work for values of n that don't cause integer overflow.
* IMPROVEMENT: If there's an unmatched PUSH-OMIT-CONTEXT, print the
filename and line number containing it.
* IMPROVEMENT: If there's an IF with a missing ENDIF, print the filename
and line number of the IF statement.
* NEW FEATURE: Add EXPR OFF command to completely disable expression
evaluation. Useful if you INCLUDE files that you don't expect to
contain expressions and may come from slightly untrustworthy sources.

View File

@@ -87,3 +87,5 @@ SET daylightST_starts_str "Beginn Sommerzeit"
# Daylight saving time ends
SET daylightST_ends_str "Ende Sommerzeit"
PRESERVE earthseasons_Perihelion_str earthseasons_EquinoxMar_str earthseasons_SolsticeJun_str earthseasons_Aphelion_str earthseasons_EquinoxSep_str earthseasons_SolsticeDec_str daylightST_starts_str daylightST_ends_str

View File

@@ -81,3 +81,5 @@ SET daylightST_starts_str "Έναρξη θέρους"
# Daylight saving time ends
SET daylightST_ends_str "Τέλος θέρους"
PRESERVE earthseasons_Perihelion_str earthseasons_EquinoxMar_str earthseasons_SolsticeJun_str earthseasons_Aphelion_str earthseasons_EquinoxSep_str earthseasons_SolsticeDec_str daylightST_starts_str daylightST_ends_str

View File

@@ -2503,6 +2503,8 @@ expr_node *parse_expression(char const **e, int *r, Var *locals)
*r == E_PARSE_ERR ||
*r == E_MISS_RIGHT_PAREN ||
*r == E_EXPECTING_EOL ||
*r == E_PARSE_ERR ||
*r == E_EOLN ||
*r == E_ILLEGAL_CHAR) {
orig = o2;
while (*orig) {

View File

@@ -79,6 +79,7 @@ typedef struct {
int LineNo;
unsigned int IfFlags;
int NumIfs;
int IfLinenos[IF_NEST];
long offset;
CachedLine *CLine;
int ownedByMe;
@@ -526,8 +527,14 @@ static int NextChainedFile(IncludeStruct *i)
static int PopFile(void)
{
IncludeStruct *i;
int j;
if (!Hush && NumIfs) Eprint("%s", ErrMsg[E_MISS_ENDIF]);
if (!Hush && NumIfs) {
Eprint("%s", ErrMsg[E_MISS_ENDIF]);
for (j=NumIfs-1; j >=0; j--) {
fprintf(ErrFp, "%s(%d): IF without ENDIF\n", FileName, IfLinenos[j]);
}
}
if (!IStackPtr) return E_EOF;
i = &IStack[IStackPtr-1];
@@ -547,6 +554,7 @@ static int PopFile(void)
LineNo = i->LineNo;
IfFlags = i->IfFlags;
memcpy(IfLinenos, i->IfLinenos, IF_NEST);
NumIfs = i->NumIfs;
CLine = i->CLine;
fp = NULL;
@@ -871,6 +879,7 @@ static int IncludeCmd(char const *cmd)
i->LineNo = LineNo;
i->NumIfs = NumIfs;
i->IfFlags = IfFlags;
memcpy(i->IfLinenos, IfLinenos, IF_NEST);
i->CLine = CLine;
i->offset = -1L;
i->chain = NULL;
@@ -973,6 +982,7 @@ int IncludeFile(char const *fname)
i->LineNo = LineNo;
i->NumIfs = NumIfs;
i->IfFlags = IfFlags;
memcpy(i->IfLinenos, IfLinenos, IF_NEST);
i->CLine = CLine;
i->offset = -1L;
i->chain = NULL;

View File

@@ -114,6 +114,7 @@ EXTERN INIT( int PurgeIncludeDepth, 0);
EXTERN INIT( FILE *PurgeFP, NULL);
EXTERN INIT( int NumIfs, 0);
EXTERN INIT( unsigned int IfFlags, 0);
EXTERN INIT( int IfLinenos[IF_NEST], {0});
EXTERN INIT( int LastTrigValid, 0);
EXTERN Trigger LastTrigger;
EXTERN TimeTrig LastTimeTrig;

View File

@@ -109,6 +109,7 @@ int main(int argc, char *argv[])
act.sa_handler = sigalrm;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
if (sigaction(SIGALRM, &act, NULL) < 0) {
fprintf(stderr, "%s: sigaction() failed: %s\n",
argv[0], strerror(errno));
@@ -116,6 +117,7 @@ int main(int argc, char *argv[])
}
act.sa_handler = sigxcpu;
act.sa_flags = SA_RESTART;
sigemptyset(&act.sa_mask);
if (sigaction(SIGXCPU, &act, NULL) < 0) {
fprintf(stderr, "%s: sigaction() failed: %s\n",
@@ -151,7 +153,7 @@ int main(int argc, char *argv[])
}
if (!Hush) {
if (DestroyOmitContexts())
if (DestroyOmitContexts(1))
Eprint("%s", ErrMsg[E_PUSH_NOPOP]);
if (!Daemon && !NextMode && !NumTriggered && !NumQueued) {
printf("%s\n", ErrMsg[E_NOREMINDERS]);
@@ -204,7 +206,7 @@ void
PerIterationInit(void)
{
ClearGlobalOmits();
DestroyOmitContexts();
DestroyOmitContexts(1);
DestroyVars(0);
DefaultColorR = -1;
DefaultColorG = -1;
@@ -757,43 +759,36 @@ void Wprint(char const *fmt, ...)
void Eprint(char const *fmt, ...)
{
va_list argptr;
char const *fname;
/* Check if more than one error msg. from this line */
if (!FreshLine && !ShowAllErrors) return;
if (FreshLine && FileName) {
FreshLine = 0;
if (strcmp(FileName, "-")) {
(void) fprintf(ErrFp, "%s(%d): ", FileName, LineNo);
va_start(argptr, fmt);
(void) vfprintf(ErrFp, fmt, argptr);
(void) fputc('\n', ErrFp);
va_end(argptr);
if (print_callstack(ErrFp)) {
(void) fprintf(ErrFp, "\n");
}
} else {
(void) fprintf(ErrFp, "-stdin-(%d): ", LineNo);
va_start(argptr, fmt);
(void) vfprintf(ErrFp, fmt, argptr);
(void) fputc('\n', ErrFp);
va_end(argptr);
if (print_callstack(ErrFp)) {
(void) fprintf(ErrFp, "\n");
}
}
if (DebugFlag & DB_PRTLINE) OutputLine(ErrFp);
} else if (FileName) {
fprintf(ErrFp, " ");
va_start(argptr, fmt);
(void) vfprintf(ErrFp, fmt, argptr);
(void) fputc('\n', ErrFp);
va_end(argptr);
if (print_callstack(ErrFp)) {
(void) fprintf(ErrFp, "\n");
}
if (!FileName) {
return;
}
return;
if (strcmp(FileName, "-")) {
fname = FileName;
} else {
fname = "-stdin-";
}
if (FreshLine) {
(void) fprintf(ErrFp, "%s(%d): ", fname, LineNo);
} else {
fprintf(ErrFp, " ");
}
va_start(argptr, fmt);
(void) vfprintf(ErrFp, fmt, argptr);
(void) fputc('\n', ErrFp);
va_end(argptr);
if (print_callstack(ErrFp)) {
(void) fprintf(ErrFp, "\n");
}
if (FreshLine) {
if (DebugFlag & DB_PRTLINE) OutputLine(ErrFp);
}
FreshLine = 0;
}
/***************************************************************/
@@ -962,6 +957,7 @@ int DoIf(ParsePtr p)
}
}
IfLinenos[NumIfs] = LineNo;
NumIfs++;
IfFlags &= ~(IF_MASK << (2*NumIfs - 2));
IfFlags |= syndrome << (2 * NumIfs - 2);
@@ -1215,7 +1211,7 @@ int DoBanner(ParsePtr p)
}
}
DBufFree(&Banner);
err = DBufPuts(&Banner, DBufValue(&buf));
DBufFree(&buf);
return err;

View File

@@ -14,7 +14,7 @@
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "types.h"
#include "protos.h"
@@ -36,6 +36,8 @@ int NumFullOmits, NumPartialOmits;
/* The structure for saving and restoring OMIT contexts */
typedef struct omitcontext {
struct omitcontext *next;
char *filename;
int lineno;
int numfull, numpart;
int *fullsave;
int *partsave;
@@ -78,19 +80,25 @@ int DoClear(ParsePtr p)
/* */
/* Free all the memory used by saved OMIT contexts. */
/* As a side effect, return the number of OMIT contexts */
/* destroyed. */
/* destroyed. If print_unmatched is true, print an error for */
/* each undestroyed OMIT contect */
/* */
/***************************************************************/
int DestroyOmitContexts(void)
int DestroyOmitContexts(int print_unmatched)
{
OmitContext *c = SavedOmitContexts;
OmitContext *d;
int num = 0;
while (c) {
if (print_unmatched) {
Wprint("Unmatched PUSH-OMIT-CONTEXT at %s(%d)",
c->filename, c->lineno);
}
num++;
if (c->fullsave) free(c->fullsave);
if (c->partsave) free(c->partsave);
if (c->filename) free(c->filename);
d = c->next;
free(c);
c = d;
@@ -115,16 +123,28 @@ int PushOmitContext(ParsePtr p)
context = NEW(OmitContext);
if (!context) return E_NO_MEM;
if (FileName) {
context->filename = StrDup(FileName);
} else {
context->filename = StrDup("");
}
if (!context->filename) {
free(context);
return E_NO_MEM;
}
context->lineno = LineNo;
context->numfull = NumFullOmits;
context->numpart = NumPartialOmits;
context->weekdaysave = WeekdayOmits;
context->fullsave = malloc(NumFullOmits * sizeof(int));
if (NumFullOmits && !context->fullsave) {
free(context->filename);
free(context);
return E_NO_MEM;
}
context->partsave = malloc(NumPartialOmits * sizeof(int));
if (NumPartialOmits && !context->partsave) {
free(context->filename);
free(context->fullsave);
free(context);
return E_NO_MEM;
@@ -174,6 +194,7 @@ int PopOmitContext(ParsePtr p)
/* Free memory used by the saved context */
if (c->partsave) free(c->partsave);
if (c->fullsave) free(c->fullsave);
if (c->filename) free(c->filename);
free(c);
return VerifyEoln(p);

View File

@@ -111,7 +111,7 @@ int DoExpr (ParsePtr p);
int DoErrMsg (ParsePtr p);
int ClearGlobalOmits (void);
int DoClear (ParsePtr p);
int DestroyOmitContexts (void);
int DestroyOmitContexts (int print_unmatched);
int PushOmitContext (ParsePtr p);
int PopOmitContext (ParsePtr p);
int IsOmitted (int dse, int localomit, char const *omitfunc, int *omit);

View File

@@ -359,7 +359,8 @@ void HandleQueuedReminders(void)
if (ShouldFork || Daemon) {
sa.sa_handler = SigIntHandler;
sa.sa_flags = 0;
sa.sa_flags = SA_RESTART;
sigemptyset(&sa.sa_mask);
(void) sigaction(SIGINT, &sa, NULL);
sa.sa_handler = SigContHandler;
(void) sigaction(SIGCONT, &sa, NULL);

4
tests/if1.rem Normal file
View File

@@ -0,0 +1,4 @@
BANNER %
set $AddBlankLines 0
IF 1
INCLUDE [filedir()]/if2.rem

5
tests/if2.rem Normal file
View File

@@ -0,0 +1,5 @@
# Another unmatched IF
IF 0
ELSE
IF 1

View File

@@ -551,6 +551,24 @@ EOF
../src/remind ../tests/expr.rem >> ../tests/test.out 2>&1
../src/remind - <<'EOF' >> ../tests/test.out 2>&1
PUSH
POP
PUSH
PUSH
POP
POP
PUSH
PUSH
POP
PUSH
POP
PUSH
POP
EOF
../src/remind ../tests/if1.rem 2020-03-03 >> ../tests/test.out 2>&1
# Remove references to SysInclude, which is build-specific
grep -F -v '$SysInclude' < ../tests/test.out > ../tests/test.out.1 && mv -f ../tests/test.out.1 ../tests/test.out
cmp -s ../tests/test.out ../tests/test.cmp

View File

@@ -12346,3 +12346,12 @@ No reminders.
Expression nodes high-water: 499
Expression nodes leaked: 0
Parse level high-water: 2001
-stdin-(14): Unmatched PUSH-OMIT-CONTEXT at -(7)
-stdin-(14): Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT
No reminders.
../tests/if2.rem(6): Warning: Missing ENDIF
../tests/if2.rem(4): IF without ENDIF
../tests/if2.rem(2): IF without ENDIF
../tests/if1.rem(5): Warning: Missing ENDIF
../tests/if1.rem(3): IF without ENDIF
No reminders.