mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 06:18:47 +02:00
Add catcherr() built-in function.
This commit is contained in:
@@ -164,7 +164,7 @@
|
||||
(defconst remind-builtin-functions
|
||||
(sort
|
||||
(list "_" "abs" "access" "adawn" "adusk" "ampm" "ansicolor" "args" "asc"
|
||||
"baseyr" "catch" "char" "choose" "coerce" "columns" "current" "date"
|
||||
"baseyr" "catch" "catcherr" "char" "choose" "coerce" "columns" "current" "date"
|
||||
"datepart" "datetime" "dawn" "day" "daysinmon" "defined" "dosubst"
|
||||
"dusk" "easterdate" "escape" "evaltrig" "filedate" "filedatetime"
|
||||
"filedir" "filename" "getenv" "hebdate" "hebday" "hebmon" "hebyear"
|
||||
|
||||
@@ -3288,6 +3288,29 @@ Note in the last example that catch does \fInot\fR protect you from errors
|
||||
in the evaluation of \fBarg2\fR.
|
||||
.RE
|
||||
.TP
|
||||
.B catcherr()
|
||||
Returns a string representing the error message from the most
|
||||
recently-evaluated \fBcatch()\fR function whose first argument yielded
|
||||
an error. Note that the error message is always in English even if
|
||||
\fBRemind\fR has been localized; this lets you reliably test the return
|
||||
value. Here are some examples:
|
||||
.RS
|
||||
.PP
|
||||
.nf
|
||||
# No "catch" invocations yet: sets a to "Ok"
|
||||
set a catcherr()
|
||||
|
||||
# Sets b to "oops" and a to "Division by zero"
|
||||
set b catch(1/0, "oops")
|
||||
set a catcherr()
|
||||
|
||||
# Sets b to 1 and a to "Division by zero". The catch error
|
||||
# is never cleared by a non-error catch()
|
||||
set b catch(4-3, "not-evaluated")
|
||||
set a catcherr()
|
||||
.fi
|
||||
.RE
|
||||
.TP
|
||||
.B char(i_i1 [,i_i2...])
|
||||
This function can take any number of \fBINT\fR arguments. It returns
|
||||
a \fBSTRING\fR consisting of the bytes specified by the arguments.
|
||||
|
||||
21
src/funcs.c
21
src/funcs.c
@@ -64,6 +64,9 @@
|
||||
#define PUT(x) DBufPuts(&DebugBuf, x)
|
||||
#define OUT() do { fprintf(ErrFp, "%s\n", DBufValue(&DebugBuf)); DBufFree(&DebugBuf); } while(0)
|
||||
|
||||
/* Last error from catch() */
|
||||
static int LastCatchError = OK;
|
||||
|
||||
static int
|
||||
solstice_equinox_for_year(int y, int which);
|
||||
|
||||
@@ -79,6 +82,7 @@ static int FArgs (func_info *);
|
||||
static int FAsc (func_info *);
|
||||
static int FBaseyr (func_info *);
|
||||
static int FCatch (expr_node *, Value *, Value *, int *);
|
||||
static int FCatchErr (func_info *);
|
||||
static int FChar (func_info *);
|
||||
static int FChoose (expr_node *, Value *, Value *, int *);
|
||||
static int FCoerce (func_info *);
|
||||
@@ -245,6 +249,7 @@ BuiltinFunc Func[] = {
|
||||
{ "asc", 1, 1, 1, FAsc, NULL },
|
||||
{ "baseyr", 0, 0, 1, FBaseyr, NULL },
|
||||
{ "catch", 2, 2, 1, NULL, FCatch }, /* NEW-STYLE */
|
||||
{ "catcherr", 0, 0, 0, FCatchErr, NULL },
|
||||
{ "char", 1, NO_MAX, 1, FChar, NULL },
|
||||
{ "choose", 2, NO_MAX, 1, NULL, FChoose }, /*NEW-STYLE*/
|
||||
{ "coerce", 2, 2, 1, FCoerce, NULL },
|
||||
@@ -1320,6 +1325,9 @@ static int FCatch(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Save the catch error */
|
||||
LastCatchError = r;
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
PUT("*");
|
||||
PUT(GetErr(r));
|
||||
@@ -1344,6 +1352,19 @@ static int FCatch(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* FCatchErr */
|
||||
/* Return (as a string) the English error thrown by the last */
|
||||
/* catch() expression that errored out. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int FCatchErr(func_info *info)
|
||||
{
|
||||
return RetStrVal(GetEnglishErr(LastCatchError), info);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* FChoose */
|
||||
|
||||
@@ -2138,6 +2138,14 @@ int GetOnceDate(void)
|
||||
return OnceDate;
|
||||
}
|
||||
|
||||
char const *GetEnglishErr(int r)
|
||||
{
|
||||
if (r < 0 || r >= NumErrs) {
|
||||
r = E_SWERR;
|
||||
}
|
||||
return ErrMsg[r];
|
||||
}
|
||||
|
||||
char const *GetErr(int r)
|
||||
{
|
||||
char const *msg;
|
||||
|
||||
@@ -271,6 +271,7 @@ void InitTranslationTable(void);
|
||||
char const *GetTranslatedString(char const *orig);
|
||||
int GetTranslatedStringTryingVariants(char const *orig, DynamicBuffer *out);
|
||||
char const *GetErr(int r);
|
||||
char const *GetEnglishErr(int r);
|
||||
char const *tr(char const *s);
|
||||
void print_escaped_string(FILE *fp, char const *s);
|
||||
void print_escaped_string_helper(FILE *fp, char const *s, int esc_for_remind, int json);
|
||||
|
||||
@@ -16256,27 +16256,39 @@ D'oh, a file whose name has spaces! ../tests/with space.rem
|
||||
|
||||
DEBUG +x
|
||||
# Test catch() built-in function
|
||||
set m catcherr()
|
||||
catcherr() => "Ok"
|
||||
set a catch(4/2, 33)
|
||||
4 / 2 => 2
|
||||
catch(2, ?) => 2
|
||||
set m catcherr()
|
||||
catcherr() => "Ok"
|
||||
set a catch(4/0, 33)
|
||||
4 / 0 => Division by zero
|
||||
catch(*Division by zero*, 33) => 33
|
||||
set m catcherr()
|
||||
catcherr() => "Division by zero"
|
||||
set a catch(4/0, 1/0)
|
||||
4 / 0 => Division by zero
|
||||
1 / 0 => Division by zero
|
||||
../tests/test.rem(1444): `/': Division by zero
|
||||
../tests/test.rem(1447): `/': Division by zero
|
||||
catch(*Division by zero*, *Division by zero*) => Division by zero
|
||||
set m catcherr()
|
||||
catcherr() => "Division by zero"
|
||||
set a catch(catch(4/0, 1/0), 39)
|
||||
4 / 0 => Division by zero
|
||||
1 / 0 => Division by zero
|
||||
catch(*Division by zero*, *Division by zero*) => Division by zero
|
||||
catch(*Division by zero*, 39) => 39
|
||||
set m catcherr()
|
||||
catcherr() => "Division by zero"
|
||||
set a catch(4/0, catch(4/0, 39))
|
||||
4 / 0 => Division by zero
|
||||
4 / 0 => Division by zero
|
||||
catch(*Division by zero*, 39) => 39
|
||||
catch(*Division by zero*, 39) => 39
|
||||
set m catcherr()
|
||||
catcherr() => "Division by zero"
|
||||
set a catch(1/0, catch("f" * "g", catch($IntMin*88, 42)))
|
||||
1 / 0 => Division by zero
|
||||
"f" * "g" => Type mismatch
|
||||
@@ -16285,10 +16297,12 @@ $IntMin => -2147483648
|
||||
catch(*Number too high*, 42) => 42
|
||||
catch(*Type mismatch*, 42) => 42
|
||||
catch(*Division by zero*, 42) => 42
|
||||
set m catcherr()
|
||||
catcherr() => "Number too high"
|
||||
DEBUG -x
|
||||
DEBUG -e
|
||||
Variable hash table statistics:
|
||||
Entries: 100141; Buckets: 87719; Non-empty Buckets: 66299
|
||||
Entries: 100142; Buckets: 87719; Non-empty Buckets: 66300
|
||||
Maxlen: 5; Minlen: 0; Avglen: 1.142; Stddev: 0.878; Avg nonempty len: 1.510
|
||||
Growths: 13; Shrinks: 0
|
||||
Function hash table statistics:
|
||||
@@ -24110,6 +24124,7 @@ args
|
||||
asc
|
||||
baseyr
|
||||
catch
|
||||
catcherr
|
||||
char
|
||||
choose
|
||||
coerce
|
||||
|
||||
@@ -1439,12 +1439,19 @@ do "with space.rem"
|
||||
|
||||
DEBUG +x
|
||||
# Test catch() built-in function
|
||||
set m catcherr()
|
||||
set a catch(4/2, 33)
|
||||
set m catcherr()
|
||||
set a catch(4/0, 33)
|
||||
set m catcherr()
|
||||
set a catch(4/0, 1/0)
|
||||
set m catcherr()
|
||||
set a catch(catch(4/0, 1/0), 39)
|
||||
set m catcherr()
|
||||
set a catch(4/0, catch(4/0, 39))
|
||||
set m catcherr()
|
||||
set a catch(1/0, catch("f" * "g", catch($IntMin*88, 42)))
|
||||
set m catcherr()
|
||||
DEBUG -x
|
||||
DEBUG -e
|
||||
|
||||
|
||||
Reference in New Issue
Block a user