Add RETURN command

Suggestion from Hymie! on Remind mailing list.
This commit is contained in:
Dianne Skoll
2025-08-06 10:41:29 -04:00
parent 86dcd9ce89
commit 24ed30fee0
13 changed files with 178 additions and 27 deletions

View File

@@ -117,7 +117,7 @@
"LASTDAY" "LASTWORKDAY" "MAYBE" "MAYBE-UNCOMPUTABLE" "MSF"
"MSG" "NOQUEUE" "OMIT" "OMITFUNC" "ONCE" "POP"
"POP-OMIT-CONTEXT" "POP-FUNCS" "POP-VARS" "PRESERVE" "PRIORITY" "PS"
"PSFILE" "PUSH" "PUSH-FUNCS" "PUSH-VARS" "PUSH-OMIT-CONTEXT" "REM"
"PSFILE" "PUSH" "PUSH-FUNCS" "PUSH-VARS" "PUSH-OMIT-CONTEXT" "REM" "RETURN"
"RUN" "SATISFY" "SCAN" "SCANFROM" "SCHED" "SECOND" "SET"
"SKIP" "SPECIAL" "SYSINCLUDE" "TAG" "THIRD" "THROUGH"
"TRANSLATE" "TRANS" "UNSET" "UNTIL" "WARN")

View File

@@ -1,29 +1,32 @@
# SPDX-License-Identifier: GPL-2.0-only
if !defined("__autolang__")
SET __autolang__ 1
PRESERVE __autolang__
PUSH-VARS autolang
SET autolang getenv("REMIND_LANG")
if defined("__autolang__")
RETURN
endif
IF autolang == ""
SET autolang getenv("LC_ALL")
ENDIF
IF autolang == ""
SET autolang getenv("LANGUAGE")
ENDIF
IF autolang == ""
SET autolang getenv("LANG")
ENDIF
SET __autolang__ 1
PRESERVE __autolang__
IF autolang != ""
IF access($SysInclude + "/lang/" + lower(substr(autolang, 1, 5)) + ".rem", "r") == 0
SYSINCLUDE lang/[lower(substr(autolang, 1, 5))].rem
ELSE
IF access($SysInclude + "/lang/" + lower(substr(autolang, 1, 2)) + ".rem", "r") == 0
SYSINCLUDE lang/[lower(substr(autolang, 1, 2))].rem
ENDIF
ENDIF
ENDIF
POP-VARS
PUSH-VARS autolang
SET autolang getenv("REMIND_LANG")
IF autolang == ""
SET autolang getenv("LC_ALL")
ENDIF
IF autolang == ""
SET autolang getenv("LANGUAGE")
ENDIF
IF autolang == ""
SET autolang getenv("LANG")
ENDIF
IF autolang != ""
IF access($SysInclude + "/lang/" + lower(substr(autolang, 1, 5)) + ".rem", "r") == 0
SYSINCLUDE lang/[lower(substr(autolang, 1, 5))].rem
ELSE
IF access($SysInclude + "/lang/" + lower(substr(autolang, 1, 2)) + ".rem", "r") == 0
SYSINCLUDE lang/[lower(substr(autolang, 1, 2))].rem
ENDIF
ENDIF
ENDIF
POP-VARS

View File

@@ -2068,6 +2068,24 @@ relative pathnames under the system directory containing standard reminder
scripts. For this version of \fBRemind\fR, the system directory is
"@prefix@/share/remind".
.PP
.SH THE RETURN COMMAND
.PP
The \fBRETURN\fR command causes \fBRemind\fR to ignore the remaining
contents of the file currently being processed. It can be used as a
quick way to "exit" from an included file (though it also works at
the top-level.)
.PP
Here is an example of how \fBRETURN\fR might be used:
.PP
.nf
IF already_done
RETURN
ENDIF
set already_done 1
preserve already_done
# Do expensive processing here
.fi
.PP
.SH THE RUN COMMAND
.PP
If you include other files in your reminder script, you may not always

View File

@@ -1777,6 +1777,7 @@ static void GenerateCalEntries(int col)
case T_ErrMsg: r=DoErrMsg(&p); break;
case T_Rem: r=DoCalRem(&p, col); break;
case T_If: r=DoIf(&p); break;
case T_Return: r=DoReturn(&p); break;
case T_IfTrig: r=DoIfTrig(&p); break;
case T_Else: r=DoElse(&p); break;
case T_EndIf: r=DoEndif(&p); break;

View File

@@ -24,6 +24,9 @@ static int if_pointer = 0;
/* The base pointer for the current file */
static int base_pointer = 0;
/* True if a "RETURN" statement was encountered in current file */
static int return_encountered = 0;
/*
* The current state of the IF...ELSE...ENDIF context is stored in
* an array of "ifentry" objects, from the outermost to the
@@ -103,6 +106,19 @@ encounter_else(void)
return OK;
}
/***************************************************************/
/* */
/* DoReturn - handle the RETURN command */
/* */
/***************************************************************/
int
DoReturn(ParsePtr p)
{
int r = VerifyEoln(p);
return_encountered = 1;
return r;
}
/***************************************************************/
/* */
/* encounter_endif - note that the most-recently-pushed IF */
@@ -162,6 +178,10 @@ int
should_ignore_line(void)
{
int i;
if (return_encountered) {
return 1;
}
for (i=base_pointer; i<if_pointer; i++) {
if (( IfArray[i].if_true && !IfArray[i].before_else) ||
(!IfArray[i].if_true && IfArray[i].before_else)) {
@@ -193,11 +213,13 @@ in_constant_context(void)
/* */
/* pop_excess_ifs - pop excess IFs from the stack, printing */
/* error messages as needed. */
/* Also resets return_encountered */
/* */
/***************************************************************/
void
pop_excess_ifs(char const *fname)
{
return_encountered = 0;
if (if_pointer <= base_pointer) {
return;
}

View File

@@ -333,6 +333,7 @@ static void DoReminders(void)
case T_Rem: r=DoRem(&p); purge_handled = 1; break;
case T_ErrMsg: r=DoErrMsg(&p); break;
case T_If: r=DoIf(&p); break;
case T_Return: r=DoReturn(&p); break;
case T_IfTrig: r=DoIfTrig(&p); break;
case T_Else: r=DoElse(&p); break;
case T_EndIf: r=DoEndif(&p); break;

View File

@@ -103,8 +103,8 @@ int SystemDate (int *y, int *m, int *d);
int DoIf (ParsePtr p);
int DoElse (ParsePtr p);
int DoEndif (ParsePtr p);
int DoReturn (ParsePtr p);
int DoIfTrig (ParsePtr p);
int ShouldIgnoreLine (void);
int VerifyEoln (ParsePtr p);
int DoRun (ParsePtr p);
int DoExpr (ParsePtr p);

View File

@@ -101,6 +101,7 @@ Token TokArray[] = {
{ "push-omit-context", 4, T_Push, 0 },
{ "push-vars", 9, T_PushVars, 0 },
{ "rem", 3, T_Rem, 0 },
{ "return", 6, T_Return, 0 },
{ "run", 3, T_RemType, RUN_TYPE },
{ "satisfy", 7, T_RemType, SAT_TYPE },
{ "saturday", 3, T_WkDay, 5 },

View File

@@ -234,7 +234,7 @@ enum TokTypes
T_LongTime, T_MaybeUncomputable, T_Month, T_NoQueue, T_Number,
T_Omit, T_OmitFunc, T_Once, T_Ordinal, T_Pop, T_PopFuncs, T_PopVars,
T_Preserve, T_Priority, T_Push, T_PushFuncs, T_PushVars, T_Rem,
T_RemType, T_Rep, T_Scanfrom, T_Sched, T_Set, T_Skip, T_Tag,
T_RemType, T_Rep, T_Return, T_Scanfrom, T_Sched, T_Set, T_Skip, T_Tag,
T_Through, T_Time, T_Translate, T_UnSet, T_Until, T_Warn, T_WkDay,
T_Year
};

5
tests/ret1.rem Normal file
View File

@@ -0,0 +1,5 @@
DO ret2.rem
IF ($Ud % 5) != 0
RETURN
ENDIF
REM MSG On days divisible by 5

7
tests/ret2.rem Normal file
View File

@@ -0,0 +1,7 @@
REM MSG Always
IF $Ud % 2
REM MSG On odd days
RETURN
REM MSG Won't appear
ENDIF
REM MSG On even days

View File

@@ -745,6 +745,12 @@ set y 1000
unset y
EOF
# Test RETURN statement
../src/remind ../tests/ret1.rem 4 June 2000 >> ../tests/test.out 2>&1
../src/remind ../tests/ret1.rem 5 June 2000 >> ../tests/test.out 2>&1
../src/remind ../tests/ret1.rem 7 June 2000 >> ../tests/test.out 2>&1
../src/remind -s ../tests/ret1.rem 1 June 2000 >> ../tests/test.out 2>&1
# Make sure all the include files are ok
find ../include -type f -name '*.rem' | while read x; do ../src/remind -du -n $x 1 Jan 2024 2>>../tests/test.out 1>/dev/null; done

View File

@@ -24450,6 +24450,7 @@ push
push-omit-context
push-vars
rem
return
run
satisfy
scan
@@ -38764,3 +38765,89 @@ The following variables were set, but not subsequently used:
x - defined at -stdin-:9
d - defined at -stdin-:5
No reminders.
Reminders for Sunday, 4th June, 2000:
Always
On even days
Reminders for Monday, 5th June, 2000:
Always
On odd days
On days divisible by 5
Reminders for Wednesday, 7th June, 2000:
Always
On odd days
2000/06/01 * * * * Always
2000/06/01 * * * * On odd days
2000/06/02 * * * * Always
2000/06/02 * * * * On even days
2000/06/03 * * * * Always
2000/06/03 * * * * On odd days
2000/06/04 * * * * Always
2000/06/04 * * * * On even days
2000/06/05 * * * * Always
2000/06/05 * * * * On odd days
2000/06/05 * * * * On days divisible by 5
2000/06/06 * * * * Always
2000/06/06 * * * * On even days
2000/06/07 * * * * Always
2000/06/07 * * * * On odd days
2000/06/08 * * * * Always
2000/06/08 * * * * On even days
2000/06/09 * * * * Always
2000/06/09 * * * * On odd days
2000/06/10 * * * * Always
2000/06/10 * * * * On even days
2000/06/10 * * * * On days divisible by 5
2000/06/11 * * * * Always
2000/06/11 * * * * On odd days
2000/06/12 * * * * Always
2000/06/12 * * * * On even days
2000/06/13 * * * * Always
2000/06/13 * * * * On odd days
2000/06/14 * * * * Always
2000/06/14 * * * * On even days
2000/06/15 * * * * Always
2000/06/15 * * * * On odd days
2000/06/15 * * * * On days divisible by 5
2000/06/16 * * * * Always
2000/06/16 * * * * On even days
2000/06/17 * * * * Always
2000/06/17 * * * * On odd days
2000/06/18 * * * * Always
2000/06/18 * * * * On even days
2000/06/19 * * * * Always
2000/06/19 * * * * On odd days
2000/06/20 * * * * Always
2000/06/20 * * * * On even days
2000/06/20 * * * * On days divisible by 5
2000/06/21 * * * * Always
2000/06/21 * * * * On odd days
2000/06/22 * * * * Always
2000/06/22 * * * * On even days
2000/06/23 * * * * Always
2000/06/23 * * * * On odd days
2000/06/24 * * * * Always
2000/06/24 * * * * On even days
2000/06/25 * * * * Always
2000/06/25 * * * * On odd days
2000/06/25 * * * * On days divisible by 5
2000/06/26 * * * * Always
2000/06/26 * * * * On even days
2000/06/27 * * * * Always
2000/06/27 * * * * On odd days
2000/06/28 * * * * Always
2000/06/28 * * * * On even days
2000/06/29 * * * * Always
2000/06/29 * * * * On odd days
2000/06/30 * * * * Always
2000/06/30 * * * * On even days
2000/06/30 * * * * On days divisible by 5