Add PUSH-SYSVARS and POP-SYSVARS commands.

This commit is contained in:
Dianne Skoll
2025-07-22 17:20:58 -04:00
parent 4b898b2ba1
commit 7325375ccd
12 changed files with 1089 additions and 805 deletions

View File

@@ -110,15 +110,17 @@
(defconst remind-keywords
(sort
(list "ADDOMIT" "AFTER" "AT" "BAN" "BANNER" "BEFORE" "CAL" "CLEAR"
"CLEAR-OMIT-CONTEXT" "DEBUG" "DO" "DUMP" "DUMPVARS" "DURATION" "ELSE"
"ENDIF" "ERRMSG" "EXIT" "EXPR" "FIRST" "FLUSH" "FOURTH" "FRENAME" "FROM" "FSET"
"FUNSET" "IF" "IFTRIG" "IN" "INC" "INCLUDE" "INCLUDECMD" "INFO" "LAST"
"LASTDAY" "LASTWORKDAY" "MAYBE" "MAYBE-UNCOMPUTABLE" "MSF" "MSG"
"NOQUEUE" "OMIT" "OMITFUNC" "ONCE" "POP" "POP-OMIT-CONTEXT" "PRESERVE"
"PRIORITY" "PS" "PSFILE" "PUSH" "PUSH-OMIT-CONTEXT" "REM" "RUN"
"SATISFY" "SCAN" "SCANFROM" "SCHED" "SECOND" "SET" "SKIP" "SPECIAL"
"SYSINCLUDE" "TAG" "THIRD" "THROUGH" "TRANSLATE" "TRANS" "UNSET"
"UNTIL" "WARN")
"CLEAR-OMIT-CONTEXT" "DEBUG" "DO" "DUMP" "DUMPVARS"
"DURATION" "ELSE" "ENDIF" "ERRMSG" "EXIT" "EXPR" "FIRST"
"FLUSH" "FOURTH" "FRENAME" "FROM" "FSET" "FUNSET" "IF"
"IFTRIG" "IN" "INC" "INCLUDE" "INCLUDECMD" "INFO" "LAST"
"LASTDAY" "LASTWORKDAY" "MAYBE" "MAYBE-UNCOMPUTABLE" "MSF"
"MSG" "NOQUEUE" "OMIT" "OMITFUNC" "ONCE" "POP"
"POP-OMIT-CONTEXT" "POP-SYSVARS" "PRESERVE" "PRIORITY" "PS"
"PSFILE" "PUSH" "PUSH-SYSVARS" "PUSH-OMIT-CONTEXT" "REM"
"RUN" "SATISFY" "SCAN" "SCANFROM" "SCHED" "SECOND" "SET"
"SKIP" "SPECIAL" "SYSINCLUDE" "TAG" "THIRD" "THROUGH"
"TRANSLATE" "TRANS" "UNSET" "UNTIL" "WARN")
#'(lambda (a b) (> (length a) (length b)))))

View File

@@ -2579,7 +2579,7 @@ For example, to delete all the variables declared above, use:
UNSET a b mydir time date
.fi
.PP
.B SYSTEM VARIABLES
.SH SYSTEM VARIABLES
.PP
In addition to the regular user variables, \fBRemind\fR has several
"system variables" that are used to query or control the operating
@@ -3125,7 +3125,31 @@ Note: If any of the calendar modes are in effect, then the
values of $Daemon, $DontFork, $DontTrigAts, $DontQueue, $HushMode,
$IgnoreOnce, $InfDelta, and $NextMode are not meaningful.
.PP
.B BUILT-IN FUNCTIONS
.SH SAVING AND RESTORING SYSTEM VARIABLES
.PP
Just as with the OMIT context, you can save and restore the values of
all (modifiable) system variables. For example:
.PP
.nf
# Save all system variables
PUSH-SYSVARS
SET $DefaultColor "255 0 0"
SET $AddBlankLines 0
REM MSG Hello
# Restore all system variables
POP-SYSVARS
# Now the changes to $DefaultColor and $AddBlankLines
# have been undone
.fi
.PP
As you see from the example, PUSH-SYSVARS saves the values of all system
variables, and POP-SYSVARS restores them to the values they had at the
time of the matching PUSH-SYSVARS call.
.PP
.SH BUILT-IN FUNCTIONS
.PP
\fBRemind\fR has a plethora of built-in functions. The syntax for a function
call is the same as in C - the function name, followed a comma-separated list

View File

@@ -1806,6 +1806,18 @@ static void GenerateCalEntries(int col)
break;
case T_Pop: r=PopOmitContext(&p); break;
case T_Push: r=PushOmitContext(&p); break;
case T_PushSysvars:
r=PushSysvars();
if (r == OK) {
r = VerifyEoln(&p);
}
break;
case T_PopSysvars:
r=PopSysvars();
if (r == OK) {
r = VerifyEoln(&p);
}
break;
case T_Preserve: r=DoPreserve(&p); break;
case T_Expr: r = DoExpr(&p); break;
case T_Translate: r = DoTranslate(&p); break;

View File

@@ -30,8 +30,8 @@
#define E_CANT_PARSE_WKDAY 8
#define E_NO_MEM 9
#define E_BAD_NUMBER 10
/* #define E_OP_STK_UNDER 11 */
/* #define E_VA_STK_UNDER 12 */
#define E_PUSHSV_NO_POP 11
#define E_POPSV_NO_PUSH 12
#define E_CANT_COERCE 13
#define E_BAD_TYPE 14
#define E_DATE_OVER 15
@@ -158,8 +158,8 @@ EXTERN char *ErrMsg[]
/* E_CANT_PARSE_WKDAY*/ "Invalid weekday name",
/* E_NO_MEM */ "Out of memory",
/* E_BAD_NUMBER */ "Ill-formed number",
/* E_OP_STK_UNDER */ "",
/* E_VA_STK_UNDER */ "",
/* E_PUSHSV_NO_POP */ "Warning: PUSH-SYSVARS without matching POP-SYSVARS",
/* E_POPSV_NO_PUSH */ "POP-SYSVARS without matching PUSH-SYSVARS",
/* E_CANT_COERCE */ "Can't coerce",
/* E_BAD_TYPE */ "Type mismatch",
/* E_DATE_OVER */ "Date overflow",

View File

@@ -181,8 +181,14 @@ int main(int argc, char *argv[])
}
if (!Hush) {
if (DestroyOmitContexts(1))
if (DestroyOmitContexts(1)) {
FreshLine = 1;
Eprint("%s", GetErr(E_PUSH_NOPOP));
}
if (EmptySysvarStack()) {
FreshLine = 1;
Eprint("%s", GetErr(E_PUSHSV_NO_POP));
}
if (!Daemon && !NextMode && !NumTriggered && !NumQueued) {
printf("%s\n", GetErr(E_NOREMINDERS));
} else if (!Daemon && !NextMode && !NumTriggered) {
@@ -235,6 +241,7 @@ PerIterationInit(void)
{
ClearGlobalOmits();
DestroyOmitContexts(1);
EmptySysvarStack();
DestroyVars(0);
DefaultColorR = -1;
DefaultColorG = -1;
@@ -366,6 +373,18 @@ static void DoReminders(void)
case T_Pop: r=PopOmitContext(&p); break;
case T_Preserve: r=DoPreserve(&p); break;
case T_Push: r=PushOmitContext(&p); break;
case T_PushSysvars:
r=PushSysvars();
if (r == OK) {
r = VerifyEoln(&p);
}
break;
case T_PopSysvars:
r=PopSysvars();
if (r == OK) {
r = VerifyEoln(&p);
}
break;
case T_Expr: r = DoExpr(&p); break;
case T_Translate: r = DoTranslate(&p); break;
case T_RemType: if (tok.val == RUN_TYPE) {

View File

@@ -121,12 +121,9 @@ int PushOmitContext(ParsePtr p)
context = NEW(OmitContext);
if (!context) return E_NO_MEM;
if (GetCurrentFilename()) {
context->filename = GetCurrentFilename();
} else {
context->filename = "";
}
context->filename = GetCurrentFilename();
context->lineno = LineNo;
context->numfull = NumFullOmits;
context->numpart = NumPartialOmits;
context->weekdaysave = WeekdayOmits;

View File

@@ -147,6 +147,9 @@ int SetVar (char const *str, Value const *val, int nonconst_expr);
int DoSet (Parser *p);
int DoUnset (Parser *p);
int DoDump (ParsePtr p);
int PushSysvars(void);
int EmptySysvarStack(void);
int PopSysvars(void);
void DumpVarTable (int dump_constness);
void DumpUnusedVars(void);
void DestroyVars (int all);

View File

@@ -91,11 +91,13 @@ Token TokArray[] = {
{ "omitfunc", 8, T_OmitFunc, 0 },
{ "once", 4, T_Once, 0 },
{ "pop-omit-context", 3, T_Pop, 0 },
{ "pop-sysvars", 11, T_PopSysvars, 0 },
{ "preserve", 8, T_Preserve, 0 },
{ "priority", 8, T_Priority, 0 },
{ "ps", 2, T_RemType, PS_TYPE },
{ "psfile", 6, T_RemType, PSF_TYPE },
{ "push-omit-context", 4, T_Push, 0 },
{ "push-sysvars", 12, T_PushSysvars, 0 },
{ "rem", 3, T_Rem, 0 },
{ "run", 3, T_RemType, RUN_TYPE },
{ "satisfy", 7, T_RemType, SAT_TYPE },

View File

@@ -228,13 +228,14 @@ enum TokTypes
{ T_Illegal,
T_AddOmit, T_At, T_Back, T_BackAdj, T_Banner, T_Clr, T_Comment,
T_Date, T_DateTime, T_Day, T_Debug, T_Delta, T_Dumpvars, T_Duration,
T_Else, T_Empty, T_EndIf, T_ErrMsg, T_Exit, T_Expr,
T_Flush, T_Frename, T_Fset, T_Funset, T_If, T_IfTrig, T_In,
T_Include, T_IncludeCmd, T_IncludeR, T_IncludeSys, T_Info, T_LastBack,
T_LongTime, T_MaybeUncomputable, T_Month, T_NoQueue, T_Number, T_Omit,
T_OmitFunc, T_Once, T_Ordinal, T_Pop, T_Preserve, T_Priority, T_Push,T_Rem,
T_RemType, T_Rep, 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
T_Else, T_Empty, T_EndIf, T_ErrMsg, T_Exit, T_Expr, T_Flush,
T_Frename, T_Fset, T_Funset, T_If, T_IfTrig, T_In, T_Include,
T_IncludeCmd, T_IncludeR, T_IncludeSys, T_Info, T_LastBack,
T_LongTime, T_MaybeUncomputable, T_Month, T_NoQueue, T_Number,
T_Omit, T_OmitFunc, T_Once, T_Ordinal, T_Pop, T_PopSysvars,
T_Preserve, T_Priority, T_Push, T_PushSysvars, T_Rem, T_RemType,
T_Rep, 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
};
/* The structure of a token */
@@ -311,3 +312,9 @@ typedef struct udf_struct {
int lineno_start;
int recurse_flag;
} UserFunc;
/* A pushed systtem variable */
typedef struct {
char const *name;
Value v;
} PushedSysvar;

View File

@@ -1079,6 +1079,91 @@ static SysVar SysVarArr[] = {
};
#define NUMSYSVARS ( sizeof(SysVarArr) / sizeof(SysVar) )
static size_t NumPushableSysvars = 0;
struct pushed_sysvars {
struct pushed_sysvars *next;
char const *filename;
int lineno;
PushedSysvar *vars;
};
static struct pushed_sysvars *SysvarStack = NULL;
static size_t CountPushableSysvars(void)
{
if (NumPushableSysvars != 0) return NumPushableSysvars;
size_t i;
for (i=0; i<NUMSYSVARS; i++) {
if (SysVarArr[i].modifiable) {
NumPushableSysvars++;
}
}
return NumPushableSysvars;
}
int PushSysvars(void)
{
size_t i, j;
struct pushed_sysvars *ps = NEW(struct pushed_sysvars);
if (!ps) return E_NO_MEM;
ps->filename = GetCurrentFilename();
ps->lineno = LineNo;
ps->next = SysvarStack;
ps->vars = calloc(CountPushableSysvars(), sizeof(PushedSysvar));
if (!ps->vars) {
free(ps);
return E_NO_MEM;
}
j = 0;
for (i=0; i<NUMSYSVARS; i++) {
if (SysVarArr[i].modifiable) {
ps->vars[j].name = SysVarArr[i].name;
(void) GetSysVar(ps->vars[j].name, &(ps->vars[j].v));
/* fprintf(ErrFp, "push($%s) => %s\n", ps->vars[j].name, PrintValue(&(ps->vars[j].v), NULL)); */
j++;
}
}
SysvarStack = ps;
return OK;
}
int PopSysvars(void)
{
if (!SysvarStack) {
return E_POPSV_NO_PUSH;
}
size_t n = CountPushableSysvars();
size_t i;
struct pushed_sysvars *ps = SysvarStack;
if (strcmp(ps->filename, GetCurrentFilename())) {
Wprint(tr("POP-SYSVARS at %s:%d matches PUSH-SYSVARS in different file: %s:%d"), GetCurrentFilename(), LineNo, ps->filename, ps->lineno);
}
SysvarStack = ps->next;
for (i=0; i<n; i++) {
/* fprintf(ErrFp, "pop($%s) => %s\n", ps->vars[i].name, PrintValue(&(ps->vars[i].v), NULL)); */
(void) SetSysVar(ps->vars[i].name, &(ps->vars[i].v));
DestroyValue(ps->vars[i].v);
}
free(ps->vars);
free(ps);
return OK;
}
int EmptySysvarStack(void)
{
int j=0;
while(SysvarStack) {
j++;
PopSysvars();
}
return j;
}
static void DumpSysVar (char const *name, const SysVar *v);
static int SetTranslatableVariable(SysVar const *v, Value const *value)

File diff suppressed because one or more lines are too long

View File

@@ -272,7 +272,7 @@ set $LatDeg 30
set $LatMin 30
set $LatSec 0
set $LongDeg -25
set $LongMin 15
set $LongMin -15
set $LongSec 0
set a000 abs(1)
@@ -478,6 +478,12 @@ REM MAYBE-UNCOMPUTABLE Mon OMIT Mon SKIP MSG Never ever ever...
REM MAYBE-UNCOMPUTABLE Mon SATISFY [wkdaynum($T) == 3] MSG Nope nope...
dump
PUSH-SYSVARS
set $Tomorrow "HAHA, tomorrow"
set $Latitude "0"
set $DefaultColor "42 42 42"
dump $
POP-SYSVARS
dump $
msg [$April]%
msg [$August]%