Compare commits

..

19 Commits

Author SHA1 Message Date
Dianne Skoll
4ab8897577 Update WHATSNEW. 2025-07-16 11:07:43 -04:00
Dianne Skoll
9613417a2e Bump version to 05.04.02 2025-07-16 11:03:25 -04:00
Dianne Skoll
f808a2963d When using -dt, print the trigger date for a fully-specified but expired trigger. 2025-07-09 12:11:38 -04:00
Dianne Skoll
96a4dc3189 Make macro safer. 2025-07-07 22:21:53 -04:00
Dianne Skoll
3c60285466 Add Chinese new year dates 2051 through 2100. 2025-07-05 17:50:53 -04:00
Dianne Skoll
6fed350e1f Give better error messages thant "Type mismatch" for bad month or weekday names. 2025-07-05 09:52:30 -04:00
Dianne Skoll
9f220555af Exit early from FromDSE if all we need is the year. 2025-07-02 14:39:15 -04:00
Dianne Skoll
005ccef953 Pass NULLs in a bunch of places where FromDSE result is not needed. 2025-07-02 14:21:32 -04:00
Dianne Skoll
578c98c865 Pass NULLs to FromDSE for info we don't need. 2025-07-02 14:10:42 -04:00
Dianne Skoll
64bf3381c6 Document mon(STRING) 2025-07-02 14:02:42 -04:00
Dianne Skoll
02ade6fc58 Add tests. 2025-07-02 11:42:03 -04:00
Dianne Skoll
2954fca8d8 Allow month to be specified by name in all places where it can be specified by number. 2025-07-02 11:40:02 -04:00
Dianne Skoll
8356dacf2a Allow first argument of daysinmon to be a string. 2025-07-02 11:20:15 -04:00
Dianne Skoll
4fd145cf4e Allow daysinmon() to take a single DATE or DATETIME argument. 2025-07-02 10:14:48 -04:00
Dianne Skoll
1af2bdf8f1 Add test to ensure "unsatisfied" SATISFY clears trigvalid() 2025-07-01 16:51:16 -04:00
Dianne Skoll
9b98e65e01 Don't set trigvalid() for a reminder whose SATISFY clause is never satisfied. 2025-07-01 16:49:06 -04:00
Dianne Skoll
0f83b98698 Fix bug that didn't save trigger date for a fully-specified REM in the past. 2025-06-30 19:23:45 -04:00
Dianne Skoll
4fd62f9894 Move contents of NOTE-ABOUT-AI.txt into README.md 2025-06-26 10:51:34 -04:00
Dianne Skoll
cc06592fe0 Update documentation to reflect reality. 2025-06-18 11:02:37 -04:00
19 changed files with 339 additions and 144 deletions

View File

@@ -1,28 +0,0 @@
Some Notes about AI/LLMs/GPTs/etc.
==================================
1) No part of Remind was written using AI of any type.
I certify that all of the C, Perl and Tcl code in Remind was written
by a human being. I certify that all code in .rem files other than
ones under include/holidays was written by a human being. The code
under include/holidays was derived from the Python "holidays" library
and I have no direct knowledge of the provenance of that library,
though I suspect it's entirely or almost entirely human-written.
I certify that all of the man pages and other documentation that
ship with Remind were human-written and not generated with any sort
of AI.
2) No AI-generated patches or other sorts of contributions to Remind
will be accepted.
3) Remind's source code may not be used to train an AI model,
including an LLM model, unless all of the output of said model is
released under the GNU General Public License, version 2. If you use
any of Remind's source code to train your model, then anything that
the model produces is a derived product of Remind and must be licensed
under the same terms as Remind.
--
Dianne Skoll

View File

@@ -68,6 +68,26 @@ with a [slide deck](https://dianne.skoll.ca/projects/remind/download/remind-oclu
I made a while back. There's also a (long) [YouTube video](https://www.youtube.com/watch?v=0SNgvsDvx7M) that serves as an
introduction to Remind.
## A Note about AI
1. No part of Remind was written using AI of any type.<br><br>
I certify that all of the C, Perl and Tcl code in Remind was written
by a human being. I certify that all code in `.rem` files other than
ones under `include/holidays` was written by a human being. The code
under `include/holidays` was derived from the Python "holidays" library
and I have no direct knowledge of the provenance of that library,
though I suspect it's entirely or almost entirely human-written.
2. No AI-generated patches or other sorts of contributions to Remind
will be accepted.
3. Remind's source code may not be used to train an AI model,
including an LLM model, unless all of the output of said model is
released under the GNU General Public License, version 2. If you use
any of Remind's source code to train your model, then anything that
the model produces is a derived product of Remind and must be licensed
under the same terms as Remind.
---
Contact info: dianne@skoll.ca

18
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.71 for remind 05.04.01.
# Generated by GNU Autoconf 2.71 for remind 05.04.02.
#
#
# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
@@ -608,8 +608,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='remind'
PACKAGE_TARNAME='remind'
PACKAGE_VERSION='05.04.01'
PACKAGE_STRING='remind 05.04.01'
PACKAGE_VERSION='05.04.02'
PACKAGE_STRING='remind 05.04.02'
PACKAGE_BUGREPORT=''
PACKAGE_URL='https://dianne.skoll.ca/projects/remind/'
@@ -1265,7 +1265,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures remind 05.04.01 to adapt to many kinds of systems.
\`configure' configures remind 05.04.02 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1327,7 +1327,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of remind 05.04.01:";;
short | recursive ) echo "Configuration of remind 05.04.02:";;
esac
cat <<\_ACEOF
@@ -1415,7 +1415,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
remind configure 05.04.01
remind configure 05.04.02
generated by GNU Autoconf 2.71
Copyright (C) 2021 Free Software Foundation, Inc.
@@ -1865,7 +1865,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by remind $as_me 05.04.01, which was
It was created by remind $as_me 05.04.02, which was
generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw
@@ -4710,7 +4710,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by remind $as_me 05.04.01, which was
This file was extended by remind $as_me 05.04.02, which was
generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -4775,7 +4775,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
remind config.status 05.04.01
remind config.status 05.04.02
configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"

View File

@@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(remind, 05.04.01, , , https://dianne.skoll.ca/projects/remind/)
AC_INIT(remind, 05.04.02, , , https://dianne.skoll.ca/projects/remind/)
AC_CONFIG_SRCDIR([src/queue.c])
cat <<'EOF'

View File

@@ -1,5 +1,26 @@
CHANGES TO REMIND
* VERSION 5,4 Patch 2 - 2025-07-16
- MINOR CHANGE: remind: Allow daysinmon() to take a DATE or DATETIME
argument.
- MINOR CHANGE: remind: All functions that want an integer month number
will now also accept a string naming the month.
= UPDATE: include/holidays/chinese-new-year.rem: Add dates for Chinese
New Year for 2051 through 2100.
- BUG FIX: remind: Set trigdate() correctly for a fully-specified
date, even if it's in the past, as the manual documnented. Bug
found by Tim Chase.
- DOCUMENTATION FIX: rem2html: Document the correct Perl module
prerequisites.
- CODE FIXES: remind: Various minor improvements to the code with
no user-visible changes.
* VERSION 5.4 Patch 1 - 2025-06-15
- MAJOR BUG FIX: remind: In some circumstances, a REM command could
@@ -1528,10 +1549,10 @@ CHANGES TO REMIND
- NEW FEATURE: Add "-u+username" variant to tell Remind to switch users to
"username" without disabling RUN directives. Idea courtesy of Ian! D. Allen
- CHANGE: rem2html: rem2html has been moved out of the www/ directory into
its own rem2html/ directory. If your system has the prerequisites
(namely Perl, Getopt::Long and JSON::Any) then rem2html will be installed
by "make install".
- CHANGE: rem2html: rem2html has been moved out of the www/ directory
into its own rem2html/ directory. If your system has the
prerequisites (namely Perl, Getopt::Long and JSON::MaybeXS) then
rem2html will be installed by "make install".
- CHANGE: Remove "cm2rem". It was about 20 years obsolete.

View File

@@ -28,3 +28,53 @@ REM 26 Jan 2047 INFO "Url: https://en.wikipedia.org/wiki/Rabbit_(zodiac)" MSG %
REM 14 Feb 2048 INFO "Url: https://en.wikipedia.org/wiki/Dragon_(zodiac)" MSG %(Chinese New Year) (%(Dragon))
REM 2 Feb 2049 INFO "Url: https://en.wikipedia.org/wiki/Snake_(zodiac)" MSG %(Chinese New Year) (%(Snake))
REM 23 Jan 2050 INFO "Url: https://en.wikipedia.org/wiki/Horse_(zodiac)" MSG %(Chinese New Year) (%(Horse))
REM 11 Feb 2051 INFO "Url: https://en.wikipedia.org/wiki/Goat_(zodiac)" MSG %(Chinese New Year) (%(Goat))
REM 1 Feb 2052 INFO "Url: https://en.wikipedia.org/wiki/Monkey_(zodiac)" MSG %(Chinese New Year) (%(Monkey))
REM 19 Feb 2053 INFO "Url: https://en.wikipedia.org/wiki/Rooster_(zodiac)" MSG %(Chinese New Year) (%(Rooster))
REM 8 Feb 2054 INFO "Url: https://en.wikipedia.org/wiki/Dog_(zodiac)" MSG %(Chinese New Year) (%(Dog))
REM 28 Jan 2055 INFO "Url: https://en.wikipedia.org/wiki/Pig_(zodiac)" MSG %(Chinese New Year) (%(Pig))
REM 15 Feb 2056 INFO "Url: https://en.wikipedia.org/wiki/Rat_(zodiac)" MSG %(Chinese New Year) (%(Rat))
REM 4 Feb 2057 INFO "Url: https://en.wikipedia.org/wiki/Ox_(zodiac)" MSG %(Chinese New Year) (%(Ox))
REM 24 Jan 2058 INFO "Url: https://en.wikipedia.org/wiki/Tiger_(zodiac)" MSG %(Chinese New Year) (%(Tiger))
REM 12 Feb 2059 INFO "Url: https://en.wikipedia.org/wiki/Rabbit_(zodiac)" MSG %(Chinese New Year) (%(Rabbit))
REM 2 Feb 2060 INFO "Url: https://en.wikipedia.org/wiki/Dragon_(zodiac)" MSG %(Chinese New Year) (%(Dragon))
REM 21 Jan 2061 INFO "Url: https://en.wikipedia.org/wiki/Snake_(zodiac)" MSG %(Chinese New Year) (%(Snake))
REM 9 Feb 2062 INFO "Url: https://en.wikipedia.org/wiki/Horse_(zodiac)" MSG %(Chinese New Year) (%(Horse))
REM 29 Jan 2063 INFO "Url: https://en.wikipedia.org/wiki/Goat_(zodiac)" MSG %(Chinese New Year) (%(Goat))
REM 17 Feb 2064 INFO "Url: https://en.wikipedia.org/wiki/Monkey_(zodiac)" MSG %(Chinese New Year) (%(Monkey))
REM 5 Feb 2065 INFO "Url: https://en.wikipedia.org/wiki/Rooster_(zodiac)" MSG %(Chinese New Year) (%(Rooster))
REM 26 Jan 2066 INFO "Url: https://en.wikipedia.org/wiki/Dog_(zodiac)" MSG %(Chinese New Year) (%(Dog))
REM 14 Feb 2067 INFO "Url: https://en.wikipedia.org/wiki/Pig_(zodiac)" MSG %(Chinese New Year) (%(Pig))
REM 3 Feb 2068 INFO "Url: https://en.wikipedia.org/wiki/Rat_(zodiac)" MSG %(Chinese New Year) (%(Rat))
REM 23 Jan 2069 INFO "Url: https://en.wikipedia.org/wiki/Ox_(zodiac)" MSG %(Chinese New Year) (%(Ox))
REM 11 Feb 2070 INFO "Url: https://en.wikipedia.org/wiki/Tiger_(zodiac)" MSG %(Chinese New Year) (%(Tiger))
REM 31 Jan 2071 INFO "Url: https://en.wikipedia.org/wiki/Rabbit_(zodiac)" MSG %(Chinese New Year) (%(Rabbit))
REM 19 Feb 2072 INFO "Url: https://en.wikipedia.org/wiki/Dragon_(zodiac)" MSG %(Chinese New Year) (%(Dragon))
REM 7 Feb 2073 INFO "Url: https://en.wikipedia.org/wiki/Snake_(zodiac)" MSG %(Chinese New Year) (%(Snake))
REM 27 Jan 2074 INFO "Url: https://en.wikipedia.org/wiki/Horse_(zodiac)" MSG %(Chinese New Year) (%(Horse))
REM 15 Feb 2075 INFO "Url: https://en.wikipedia.org/wiki/Goat_(zodiac)" MSG %(Chinese New Year) (%(Goat))
REM 5 Feb 2076 INFO "Url: https://en.wikipedia.org/wiki/Monkey_(zodiac)" MSG %(Chinese New Year) (%(Monkey))
REM 24 Jan 2077 INFO "Url: https://en.wikipedia.org/wiki/Rooster_(zodiac)" MSG %(Chinese New Year) (%(Rooster))
REM 12 Feb 2078 INFO "Url: https://en.wikipedia.org/wiki/Dog_(zodiac)" MSG %(Chinese New Year) (%(Dog))
REM 2 Feb 2079 INFO "Url: https://en.wikipedia.org/wiki/Pig_(zodiac)" MSG %(Chinese New Year) (%(Pig))
REM 22 Jan 2080 INFO "Url: https://en.wikipedia.org/wiki/Rat_(zodiac)" MSG %(Chinese New Year) (%(Rat))
REM 9 Feb 2081 INFO "Url: https://en.wikipedia.org/wiki/Ox_(zodiac)" MSG %(Chinese New Year) (%(Ox))
REM 29 Jan 2082 INFO "Url: https://en.wikipedia.org/wiki/Tiger_(zodiac)" MSG %(Chinese New Year) (%(Tiger))
REM 17 Feb 2083 INFO "Url: https://en.wikipedia.org/wiki/Rabbit_(zodiac)" MSG %(Chinese New Year) (%(Rabbit))
REM 6 Feb 2084 INFO "Url: https://en.wikipedia.org/wiki/Dragon_(zodiac)" MSG %(Chinese New Year) (%(Dragon))
REM 26 Jan 2085 INFO "Url: https://en.wikipedia.org/wiki/Snake_(zodiac)" MSG %(Chinese New Year) (%(Snake))
REM 14 Feb 2086 INFO "Url: https://en.wikipedia.org/wiki/Horse_(zodiac)" MSG %(Chinese New Year) (%(Horse))
REM 3 Feb 2087 INFO "Url: https://en.wikipedia.org/wiki/Goat_(zodiac)" MSG %(Chinese New Year) (%(Goat))
REM 24 Jan 2088 INFO "Url: https://en.wikipedia.org/wiki/Monkey_(zodiac)" MSG %(Chinese New Year) (%(Monkey))
REM 10 Feb 2089 INFO "Url: https://en.wikipedia.org/wiki/Rooster_(zodiac)" MSG %(Chinese New Year) (%(Rooster))
REM 30 Jan 2090 INFO "Url: https://en.wikipedia.org/wiki/Dog_(zodiac)" MSG %(Chinese New Year) (%(Dog))
REM 18 Feb 2091 INFO "Url: https://en.wikipedia.org/wiki/Pig_(zodiac)" MSG %(Chinese New Year) (%(Pig))
REM 7 Feb 2092 INFO "Url: https://en.wikipedia.org/wiki/Rat_(zodiac)" MSG %(Chinese New Year) (%(Rat))
REM 27 Jan 2093 INFO "Url: https://en.wikipedia.org/wiki/Ox_(zodiac)" MSG %(Chinese New Year) (%(Ox))
REM 15 Feb 2094 INFO "Url: https://en.wikipedia.org/wiki/Tiger_(zodiac)" MSG %(Chinese New Year) (%(Tiger))
REM 5 Feb 2095 INFO "Url: https://en.wikipedia.org/wiki/Rabbit_(zodiac)" MSG %(Chinese New Year) (%(Rabbit))
REM 25 Jan 2096 INFO "Url: https://en.wikipedia.org/wiki/Dragon_(zodiac)" MSG %(Chinese New Year) (%(Dragon))
REM 12 Feb 2097 INFO "Url: https://en.wikipedia.org/wiki/Snake_(zodiac)" MSG %(Chinese New Year) (%(Snake))
REM 1 Feb 2098 INFO "Url: https://en.wikipedia.org/wiki/Horse_(zodiac)" MSG %(Chinese New Year) (%(Horse))
REM 21 Jan 2099 INFO "Url: https://en.wikipedia.org/wiki/Goat_(zodiac)" MSG %(Chinese New Year) (%(Goat))
REM 9 Feb 2100 INFO "Url: https://en.wikipedia.org/wiki/Monkey_(zodiac)" MSG %(Chinese New Year) (%(Monkey))

View File

@@ -3431,9 +3431,11 @@ in unwanted reminders being purged in Purge Mode. See also the section
Returns the current date and time as a DATETIME object. This may be the
actual date and time, or may be the date and time supplied on the command line.
.TP
.B date(i_y, i_m, i_d)
.B date(i_y, si_m, i_d)
The \fBdate()\fR function returns a \fBDATE\fR object with the year,
month and day components specified by \fIy\fR, \fIm\fR and \fId\fR.
The month can be specified as an integer from 1 to 12, or a string
that is the name of a month.
.TP
.B datepart(dq_datetime)
Returns a \fBDATE\fR object representing the date portion of
@@ -3450,11 +3452,13 @@ If you supply three arguments, the first
must be a DATE and the second and third must be INTs. The second and
third arguments are interpreted as hours and minutes and converted to a TIME.
.PP
If you supply four arguments, the first three must be INTs, interpreted
as the year, month and day. The fourth argument must be a TIME.
If you supply four arguments, they are interpreted as year, month, day
and time. Year and day must be INTs. Month may be an INT from 0 to 12
or a string naming a month. Time must be a TIME.
.PP
Finally, if you supply five arguments, they must all be INTs and are
interpreted as year, month, day, hour and minute.
interpreted as year, month, day, hour and minute. (Actually, month
can also be a string that is the name of a month.)
.RE
.TP
.B dawn([dq_date])
@@ -3467,8 +3471,12 @@ This function takes a \fBDATE\fR or \fBDATETIME\fR as an argument, and
returns an \fBINT\fR that is the day-of-month component of
\fIdate\fR.
.TP
.B daysinmon(i_m, i_y)
Returns the number of days in month \fIm\fR (1-12) of the year \fIy\fR.
.B daysinmon(si_m, i_y)\fR or \fB daysinmon(dq_date)\fR
Returns the number of days in month \fIm\fR (1-12) of the year
\fIy\fR. The first argument can either be an integer from 1 to 12, or
a string that is the name of a month. If given a single DATE or
DATETIME argument, returns the number of days in the month containing
the argument.
.TP
.B defined(s_var)
Returns 1 if the variable named by \fIvar\fR is defined, or 0 if it is not.
@@ -3774,10 +3782,20 @@ functions. It is available starting with version 03.00.07 of \fBRemind\fR.
.B minute(tq_time)
Returns the minute component of \fItime\fR.
.TP
.B mon(dqi_arg)
.B mon(dqis_arg)
If \fIarg\fR is of \fBDATE\fR or \fBDATETIME\fR type, returns a string
that names the month component of the date. If \fIarg\fR is an
\fBINT\fR from 1 to 12, returns a string that names the month.
\fBINT\fR from 1 to 12, returns a string that names the month. If \fIarg\fR
is a \fBSTRING\fR, returns the name of the month. This last case might
sound silly, but for example:
.RS
.PP
.nf
mon("Mar")
.fi
.PP
will return "March", the full name of the month.
.RE
.TP
.B monnum(dq_date)\fR or \fBmonnum(s_str)\fR
Returns an \fBINT\fR from 1 to 12, representing the month component of
@@ -6773,12 +6791,13 @@ date of the scanning\fR that
satisfies the trigger. In addition, there is one special case in which
\fBtrigvalid()\fR returns 1 and \fBtrigdate()\fR returns a meaningful result:
.PP
If the \fBREM\fR or \fBIFTRIG\fR command did not contain an \fBUNTIL\fR
clause, and contained all of the \fIday\fR, \fImonth\fR and \fIyear\fR
components, then \fBRemind\fR will correctly compute a trigger date, even
if it happens to be before the start of scanning.
Note that this behaviour is not true for
If the \fBREM\fR or \fBIFTRIG\fR command did not contain an
\fBUNTIL\fR or \fBSATISFY\fR clause, and contained all of the
\fIday\fR, \fImonth\fR and \fIyear\fR components, then \fBRemind\fR
will correctly compute a trigger date, even if it happens to be before
the start of scanning. Note that this behaviour is not true for
versions of \fBRemind\fR prior to 03.00.01.
.SH FILES
.PP
The traditional location of your reminders file or directory is:

View File

@@ -4,7 +4,7 @@ REM2HTML
rem2html is a Perl script that transforms the output of `remind -pp
...' to HTML. Type `perl rem2html --help' for usage information.
rem2html requires the Perl modules `JSON::Any' and `Getopt::Long'. It
rem2html requires the Perl modules `JSON::MaybeXS' and `Getopt::Long'. It
will not be installed unless you have those modules as well as Perl
itself.

View File

@@ -757,7 +757,7 @@ InitMoonsAndShades(void)
static void
SetShadeEntry(int dse, char const *shade)
{
int y, m, d;
int d;
int r, g, b;
/* Don't bother if we're not doing SHADE specials */
if (!UseBGVTColors) {
@@ -774,7 +774,7 @@ SetShadeEntry(int dse, char const *shade)
if (r < 0 || g < 0 || b < 0 || r > 255 || g > 255 || b > 255) {
return;
}
FromDSE(dse, &y, &m, &d);
FromDSE(dse, NULL, NULL, &d);
bgcolor[d][0] = r;
bgcolor[d][1] = g;
bgcolor[d][2] = b;
@@ -784,7 +784,7 @@ static void
SetMoonEntry(int dse, char const *moon)
{
int phase;
int y, m, d;
int d;
char msg[28];
/* Don't bother unless it's utf-8 */
@@ -803,7 +803,7 @@ SetMoonEntry(int dse, char const *moon)
/* Bad phase */
return;
}
FromDSE(dse, &y, &m, &d);
FromDSE(dse, NULL, NULL, &d);
if (msg[0]) {
snprintf(moons[d], sizeof(moons[d]), "%s %s", moonphase_emojis[phase], msg);
} else {
@@ -1476,13 +1476,13 @@ static void PrintCentered(char const *s, int width, char *pad)
static int WriteOneCalLine(int start_dse, int wd)
{
int done = 1, i;
int y, m, d;
int d;
gon();
DRAW(tb);
goff();
for (i=0; i<7; i++) {
FromDSE(start_dse+i, &y, &m, &d);
FromDSE(start_dse+i, NULL, NULL, &d);
d -= wd;
if (CalColumn[i]) {
Backgroundize(ColToDay[i]);

View File

@@ -1554,6 +1554,8 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
}
if (dse == -1) {
free_expr_tree(sat_node);
LastTrigValid = 0;
LastTriggerDate = -1;
return E_EXPIRED;
}
r = evaluate_expression(sat_node, NULL, &v, &nonconst);

View File

@@ -23,11 +23,11 @@
#define E_MISS_END 1
#define E_MISS_QUOTE 2
#define E_OP_STK_OVER 3
/* #define E_VA_STK_OVER 4 */
#define E_CANT_PARSE_MONTH 4
#define E_MISS_RIGHT_PAREN 5
#define E_UNDEF_FUNC 6
#define E_ILLEGAL_CHAR 7
/* #define E_EXPECTING_BINOP 8 */
#define E_CANT_PARSE_WKDAY 8
#define E_NO_MEM 9
#define E_BAD_NUMBER 10
/* #define E_OP_STK_UNDER 11 */
@@ -151,11 +151,11 @@ EXTERN char *ErrMsg[]
/* E_MISS_END */ "Missing ']'",
/* E_MISS_QUOTE */ "Missing quote",
/* E_OP_STK_OVER */ "Expression too complex",
/* E_VA_STK_OVER */ "",
/* E_CANT_PARSE_MONTH */ "Invalid month name",
/* E_MISS_RIGHT_PAREN */ "Missing ')'",
/* E_UNDEF_FUNC */ "Undefined function",
/* E_ILLEGAL_CHAR */ "Illegal character",
/* E_EXPECTING_BINOP */ "Expecting binary operator",
/* E_CANT_PARSE_WKDAY*/ "Invalid weekday name",
/* E_NO_MEM */ "Out of memory",
/* E_BAD_NUMBER */ "Ill-formed number",
/* E_OP_STK_UNDER */ "",

View File

@@ -231,6 +231,8 @@ static int CacheHebYear, CacheHebMon, CacheHebDay;
#define HASDATE(x) ((x).type & DATE_TYPE)
#define HASTIME(x) ((x).type & TIME_TYPE)
#define GETMON(x) get_month(&(ARG(x)))
/* Macro for copying a value while destroying original copy */
#define DCOPYVAL(x, y) ( (x) = (y), (y).type = ERR_TYPE )
@@ -267,7 +269,7 @@ BuiltinFunc Func[] = {
{ "datetime", 2, 5, 1, FDateTime, NULL },
{ "dawn", 0, 1, 0, FDawn, NULL },
{ "day", 1, 1, 1, FDay, NULL },
{ "daysinmon", 2, 2, 1, FDaysinmon, NULL },
{ "daysinmon", 1, 2, 1, FDaysinmon, NULL },
{ "defined", 1, 1, 0, FDefined, NULL },
{ "dosubst", 1, 3, 0, FDosubst, NULL },
{ "dusk", 0, 1, 0, FDusk, NULL },
@@ -378,6 +380,26 @@ BuiltinFunc Func[] = {
/* Need a variable here - Func[] array not really visible to outside. */
int NumFuncs = sizeof(Func) / sizeof(BuiltinFunc) ;
static int get_month(Value *v)
{
Token tok;
if (v->type == INT_TYPE) {
if (v->v.val < 1) return -E_2LOW;
if (v->v.val > 12) return -E_2HIGH;
return v->v.val - 1;
}
if (v->type == STR_TYPE) {
FindToken(v->v.str, &tok);
if (tok.type != T_Month) {
return -E_CANT_PARSE_MONTH;
}
return tok.val;
}
return -E_BAD_TYPE;
}
/***************************************************************/
/* */
/* RetStrVal */
@@ -463,29 +485,27 @@ static int FBaseyr(func_info *info)
static int FDate(func_info *info)
{
int y, m, d;
int ytemp, mtemp, dtemp;
/* Any arg can be a date (in which case we use the corresponding
component) or an integer */
if (HASDATE(ARG(0))) {
FromDSE(DATEPART(ARG(0)), &ytemp, &mtemp, &dtemp);
y = ytemp;
FromDSE(DATEPART(ARG(0)), &y, NULL, NULL);
} else {
ASSERT_TYPE(0, INT_TYPE);
y = ARGV(0);
}
if (HASDATE(ARG(1))) {
FromDSE(DATEPART(ARG(1)), &ytemp, &mtemp, &dtemp);
m = mtemp;
FromDSE(DATEPART(ARG(1)), NULL, &m, NULL);
} else {
ASSERT_TYPE(1, INT_TYPE);
m = ARGV(1) - 1;
m = GETMON(1);
if (m < 0) {
return -m;
}
}
if (HASDATE(ARG(2))) {
FromDSE(DATEPART(ARG(2)), &ytemp, &mtemp, &dtemp);
d = dtemp;
FromDSE(DATEPART(ARG(2)), NULL, NULL, &d);
} else {
ASSERT_TYPE(2, INT_TYPE);
d = ARGV(2);
@@ -530,11 +550,11 @@ static int FDateTime(func_info *info)
return OK;
case 4:
if (ARG(0).type != INT_TYPE ||
ARG(1).type != INT_TYPE ||
ARG(2).type != INT_TYPE ||
ARG(3).type != TIME_TYPE) return E_BAD_TYPE;
y = ARGV(0);
m = ARGV(1) - 1;
m = GETMON(1);
if (m < 0) return -m;
d = ARGV(2);
if (!DateOK(y, m, d)) return E_BAD_DATE;
@@ -542,13 +562,13 @@ static int FDateTime(func_info *info)
return OK;
case 5:
if (ARG(0).type != INT_TYPE ||
ARG(1).type != INT_TYPE ||
ARG(2).type != INT_TYPE ||
ARG(3).type != INT_TYPE ||
ARG(4).type != INT_TYPE) return E_BAD_TYPE;
y = ARGV(0);
m = ARGV(1) - 1;
m = GETMON(1);
if (m < 0) return -m;
d = ARGV(2);
if (!DateOK(y, m, d)) return E_BAD_DATE;
@@ -759,7 +779,7 @@ static int FMonnum(func_info *info)
/* Convert a month name to a month number */
FindToken(ARG(0).v.str, &tok);
if (tok.type != T_Month) {
return E_BAD_TYPE;
return E_CANT_PARSE_MONTH;
}
RetVal.type = INT_TYPE;
RETVAL = tok.val + 1;
@@ -811,7 +831,7 @@ static int FWkdaynum(func_info *info)
/* Convert a day name to a day number */
FindToken(ARG(0).v.str, &tok);
if (tok.type != T_WkDay) {
return E_BAD_TYPE;
return E_CANT_PARSE_WKDAY;
}
RetVal.type = INT_TYPE;
RETVAL = (tok.val + 1) % 7;
@@ -848,12 +868,11 @@ static int FMon(func_info *info)
char const *s;
int y, m, d, v;
if (!HASDATE(ARG(0)) && ARG(0).type != INT_TYPE) return E_BAD_TYPE;
if (!HASDATE(ARG(0)) && ARG(0).type != INT_TYPE && ARG(0).type != STR_TYPE) return E_BAD_TYPE;
if (ARG(0).type == INT_TYPE) {
m = ARGV(0) - 1;
if (m < 0) return E_2LOW;
if (m > 11) return E_2HIGH;
if (ARG(0).type == INT_TYPE || ARG(0).type == STR_TYPE) {
m = GETMON(0);
if (m < 0) return -m;
} else {
v = DATEPART(ARG(0));
if (v == CacheDse)
@@ -2008,19 +2027,29 @@ static int FTrigdatetime(func_info *info)
/* */
/* FDaysinmon */
/* */
/* Returns the number of days in mon,yr */
/* Returns the number of days in mon,yr OR month containing */
/* given date. */
/* */
/***************************************************************/
static int FDaysinmon(func_info *info)
{
if (ARG(0).type != INT_TYPE || ARG(1).type != INT_TYPE) return E_BAD_TYPE;
int y, m;
if (ARGV(0) > 12 || ARGV(0) < 1 ||
ARGV(1) < BASE || ARGV(1) > BASE+YR_RANGE)
return E_DOMAIN_ERR;
if (Nargs == 1) {
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
FromDSE(DATEPART(ARG(0)), &y, &m, NULL);
} else {
if (ARG(1).type != INT_TYPE) return E_BAD_TYPE;
m = GETMON(0);
if (m < 0) return -m;
y = ARGV(1);
if (y < BASE) return E_2LOW;
if (y > BASE + YR_RANGE) return E_2HIGH;
}
RetVal.type = INT_TYPE;
RETVAL = DaysInMonth(ARGV(0)-1, ARGV(1));
RETVAL = DaysInMonth(m, y);
return OK;
}
@@ -2033,13 +2062,13 @@ static int FDaysinmon(func_info *info)
/***************************************************************/
static int FIsleap(func_info *info)
{
int y, m, d;
int y;
if (ARG(0).type != INT_TYPE && !HASDATE(ARG(0))) return E_BAD_TYPE;
/* If it's a date, extract the year */
if (HASDATE(ARG(0)))
FromDSE(DATEPART(ARG(0)), &y, &m, &d);
FromDSE(DATEPART(ARG(0)), &y, NULL, NULL);
else
y = ARGV(0);
@@ -2825,7 +2854,7 @@ static int FEasterdate(func_info *info)
int base;
if (Nargs == 0) {
base = DSEToday;
FromDSE(DSEToday, &y, &m, &d);
FromDSE(DSEToday, &y, NULL, NULL);
} else {
if (ARG(0).type == INT_TYPE) {
base = -1;
@@ -2834,7 +2863,7 @@ static int FEasterdate(func_info *info)
else if (y > BASE+YR_RANGE) return E_2HIGH;
} else if (HASDATE(ARG(0))) {
base = DATEPART(ARG(0));
FromDSE(DATEPART(ARG(0)), &y, &m, &d); /* We just want the year */
FromDSE(DATEPART(ARG(0)), &y, NULL, NULL); /* We just want the year */
} else return E_BAD_TYPE;
}
@@ -2878,7 +2907,7 @@ static int FOrthodoxeaster(func_info *info)
int base = -1;
if (Nargs == 0) {
base = DSEToday;
FromDSE(DSEToday, &y, &m, &d);
FromDSE(DSEToday, &y, NULL, NULL);
} else {
if (ARG(0).type == INT_TYPE) {
y = ARGV(0);
@@ -2886,7 +2915,7 @@ static int FOrthodoxeaster(func_info *info)
else if (y > BASE+YR_RANGE) return E_2HIGH;
} else if (HASDATE(ARG(0))) {
base = DATEPART(ARG(0));
FromDSE(DATEPART(ARG(0)), &y, &m, &d); /* We just want the year */
FromDSE(DATEPART(ARG(0)), &y, NULL, NULL); /* We just want the year */
} else return E_BAD_TYPE;
}
@@ -3914,7 +3943,7 @@ FSlide(func_info *info)
for (i=localargs; i<Nargs; i++) {
if (ARG(i).type != STR_TYPE) return E_BAD_TYPE;
FindToken(ARG(i).v.str, &tok);
if (tok.type != T_WkDay) return E_UNKNOWN_TOKEN;
if (tok.type != T_WkDay) return E_CANT_PARSE_WKDAY;
localomit |= (1 << tok.val);
}
@@ -3972,7 +4001,7 @@ FNonomitted(func_info *info)
for (i=localargs; i<Nargs; i++) {
if (ARG(i).type != STR_TYPE) return E_BAD_TYPE;
FindToken(ARG(i).v.str, &tok);
if (tok.type != T_WkDay) return E_UNKNOWN_TOKEN;
if (tok.type != T_WkDay) return E_CANT_PARSE_WKDAY;
localomit |= (1 << tok.val);
}

View File

@@ -459,6 +459,15 @@ void FromDSE(int dse, int *y, int *m, int *d)
try_yr--;
try_dse -= DaysInYear(try_yr);
}
if (y) {
*y = try_yr;
}
/* If all we want is the year, we can quit here */
if (!d && !m) {
return;
}
dse -= try_dse;
t = DaysInMonth(try_mon, try_yr);
@@ -467,9 +476,6 @@ void FromDSE(int dse, int *y, int *m, int *d)
try_mon++;
t = DaysInMonth(try_mon, try_yr);
}
if (y) {
*y = try_yr;
}
if (m) {
*m = try_mon;
}
@@ -1994,9 +2000,11 @@ SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigt
{
SaveLastTrigger(t);
SaveLastTimeTrig(tt);
LastTriggerDate = trigdate;
if (trigdate != -1) {
LastTriggerDate = trigdate;
LastTrigValid = valid;
}
LastTriggerTime = trigtime;
LastTrigValid = valid;
}
void

View File

@@ -242,7 +242,7 @@ int IsOmitted(int dse, int localomit, char const *omitfunc, int *omit)
return OK;
}
FromDSE(dse, &y, &m, &d);
FromDSE(dse, NULL, &m, &d);
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d)) {
*omit = 1;
return OK;

View File

@@ -27,11 +27,11 @@
executes 'return' if an initial non-numeric char is found. */
#define PARSENUM(var, string) \
if (!isdigit(*(string))) return; \
var = 0; \
(var) = 0; \
while (isdigit(*(string))) { \
var *= 10; \
var += *(string) - '0'; \
string++; \
(var) *= 10; \
(var) += *(string) - '0'; \
(string)++; \
}
/* The big array holding all recognized (literal) tokens in reminder file.

View File

@@ -541,6 +541,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
trig->expired = 0;
if (save_in_globals) {
LastTrigValid = 0;
LastTriggerDate = -1;
}
/* Assume everything works */
@@ -579,7 +580,6 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
while (nattempts++ < TRIG_ATTEMPTS) {
result = GetNextTriggerDate(trig, start, err, &nextstart);
/* If there's an error, die immediately */
if (*err) return -1;
if (result == -1) {
@@ -635,8 +635,9 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
trig->rep == NO_REP) {
trig->expired = 1;
if (DebugFlag & DB_PRTTRIG) {
fprintf(ErrFp, "%s(%s): %s\n",
GetCurrentFilename(), line_range(LineNoStart, LineNo), GetErr(E_EXPIRED));
FromDSE(result, &y, &m, &d);
fprintf(ErrFp, "%s(%s): %s: %04d-%02d-%02d\n",
GetCurrentFilename(), line_range(LineNoStart, LineNo), GetErr(E_EXPIRED), y, m+1, d);
}
if (save_in_globals) {
LastTriggerDate = result;

View File

@@ -285,7 +285,7 @@ static int trig_until_func(int do_set, Value *val)
static int trig_day_func(int do_set, Value *val)
{
int y, m, d;
int d;
UNUSED(do_set);
val->type = INT_TYPE;
if (!LastTrigValid) {
@@ -293,7 +293,7 @@ static int trig_day_func(int do_set, Value *val)
return OK;
}
FromDSE(LastTriggerDate, &y, &m, &d);
FromDSE(LastTriggerDate, NULL, NULL, &d);
val->v.val = d;
return OK;
}
@@ -312,7 +312,7 @@ static int timet_is_64_func(int do_set, Value *val)
static int trig_mon_func(int do_set, Value *val)
{
int y, m, d;
int m;
UNUSED(do_set);
val->type = INT_TYPE;
if (!LastTrigValid) {
@@ -320,14 +320,14 @@ static int trig_mon_func(int do_set, Value *val)
return OK;
}
FromDSE(LastTriggerDate, &y, &m, &d);
FromDSE(LastTriggerDate, NULL, &m, NULL);
val->v.val = m+1;
return OK;
}
static int trig_year_func(int do_set, Value *val)
{
int y, m, d;
int y;
UNUSED(do_set);
val->type = INT_TYPE;
if (!LastTrigValid) {
@@ -335,7 +335,7 @@ static int trig_year_func(int do_set, Value *val)
return OK;
}
FromDSE(LastTriggerDate, &y, &m, &d);
FromDSE(LastTriggerDate, &y, NULL, NULL);
val->v.val = y;
return OK;
}
@@ -362,30 +362,30 @@ static int today_date_func(int do_set, Value *val)
}
static int today_day_func(int do_set, Value *val)
{
int y, m, d;
int d;
UNUSED(do_set);
val->type = INT_TYPE;
FromDSE(DSEToday, &y, &m, &d);
FromDSE(DSEToday, NULL, NULL, &d);
val->v.val = d;
return OK;
}
static int today_mon_func(int do_set, Value *val)
{
int y, m, d;
int m;
UNUSED(do_set);
val->type = INT_TYPE;
FromDSE(DSEToday, &y, &m, &d);
FromDSE(DSEToday, NULL, &m, NULL);
val->v.val = m+1;
return OK;
}
static int today_year_func(int do_set, Value *val)
{
int y, m, d;
int y;
UNUSED(do_set);
val->type = INT_TYPE;
FromDSE(DSEToday, &y, &m, &d);
FromDSE(DSEToday, &y, NULL, NULL);
val->v.val = y;
return OK;
}

View File

@@ -428,7 +428,7 @@ Leaving UserFN _i(29, "Adar A", 1991-02-16, 5756) => Invalid Hebrew date
# This causes a parse error on version 03.01.01
REM 1990-01-01 SATISFY 1
../tests/test.rem(90): Expired
../tests/test.rem(90): Expired: 1990-01-01
# Test each possible case of the basic reminders.
@@ -494,7 +494,7 @@ REM May 1992 MSG May 1992
../tests/test.rem(121): Trig = Friday, 1 May, 1992
REM 1 Jan 1991 MSG 1 Jan 1991
../tests/test.rem(123): Expired
../tests/test.rem(123): Expired: 1991-01-01
REM 16 Feb 1991 MSG 16 Feb 1991
../tests/test.rem(124): Trig = Saturday, 16 February, 1991
16 Feb 1991
@@ -1042,7 +1042,7 @@ set a057 value("a05"+"6")
"a05" + "6" => "a056"
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
set a058 version()
version() => "05.04.01"
version() => "05.04.02"
set a059 wkday(today())
today() => 1991-02-16
wkday(1991-02-16) => "Saturday"
@@ -2605,7 +2605,7 @@ a056 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a007 "1991-02-16"
a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a008 "11:44"
a058 "05.04.01"
a058 "05.04.02"
a059 "Saturday"
a010 12
a060 6
@@ -4115,7 +4115,7 @@ trig("Mon", "Tue", "Wed") => ../tests/test.rem(849): Trig = Monday, 18 February,
../tests/test.rem(849): Trig = Tuesday, 19 February, 1991
../tests/test.rem(849): Trig = Wednesday, 20 February, 1991
1990-01-01
../tests/test.rem(849): Expired
../tests/test.rem(849): Expired: 1990-01-01
# Multitrig
REM [multitrig("10", "17")] MSG multitrig-1
@@ -4151,7 +4151,7 @@ REM [multitrig("15 SCANFROM -7", "14 SCANFROM -7")] MSG multitrig-6
multitrig("15 SCANFROM -7", "14 SCANFROM -7") => ../tests/test.rem(857): Trig = Friday, 15 February, 1991
../tests/test.rem(857): Trig = Thursday, 14 February, 1991
1991-02-14
../tests/test.rem(857): Expired
../tests/test.rem(857): Expired: 1991-02-14
REM [multitrig("15 SCANFROM -7", "14 SCANFROM -7")] SCANFROM -7 MSG multitrig-7
multitrig("15 SCANFROM -7", "14 SCANFROM -7") => ../tests/test.rem(858): Trig = Friday, 15 February, 1991
../tests/test.rem(858): Trig = Thursday, 14 February, 1991
@@ -5075,12 +5075,12 @@ htmlstriptags("<img src=\"foo\">") => ""
# $ParseUntriggered
REM 2 Jan 1990 MSG ["bad_expr" / 2]
../tests/test.rem(971): Expired
../tests/test.rem(971): Expired: 1990-01-02
"bad_expr" / 2 => Type mismatch
../tests/test.rem(971): `/': Type mismatch
SET $ParseUntriggered 0
REM 2 Jan 1990 MSG ["bad_expr" / 2]
../tests/test.rem(973): Expired
../tests/test.rem(973): Expired: 1990-01-02
SET $ParseUntriggered 1
# String multiplication
@@ -5639,8 +5639,8 @@ REM SATISFY ""
REM SATISFY [version() > "01.00.00"]
../tests/test.rem(1055): SATISFY: expression has no reference to trigdate() or $T...
../tests/test.rem(1055): Trig = Saturday, 16 February, 1991
version() => "05.04.01"
"05.04.01" > "01.00.00" => 1
version() => "05.04.02"
"05.04.02" > "01.00.00" => 1
../tests/test.rem(1055): Trig(satisfied) = Saturday, 16 February, 1991
REM SATISFY [max(x, max(x, 1, 2, 3), 4, 5, 6) * 5]
../tests/test.rem(1056): SATISFY: expression has no reference to trigdate() or $T...
@@ -16362,8 +16362,8 @@ set a monnum("Dec")
monnum("Dec") => 12
set a monnum("not a month")
monnum("not a month") => Type mismatch
../tests/test.rem(1491): monnum(): Type mismatch
monnum("not a month") => Invalid month name
../tests/test.rem(1491): monnum(): Invalid month name
# Test wkdaynum("string")
set a wkdaynum("Sun")
@@ -16397,8 +16397,8 @@ set a wkdaynum("saturday")
wkdaynum("saturday") => 6
set a wkdaynum("cabbage")
wkdaynum("cabbage") => Type mismatch
../tests/test.rem(1510): wkdaynum(): Type mismatch
wkdaynum("cabbage") => Invalid weekday name
../tests/test.rem(1510): wkdaynum(): Invalid weekday name
# Test non-constant debugging
DEBUG +n
@@ -16577,6 +16577,35 @@ Base: 1991-02-09
Base: 1991-02-09
../tests/test.rem(1611): Expired
../tests/test.rem(1612): Expired
trigvalid = 1; trigdate = 1991-01-14
trigvalid = 0; trigdate = 0
daysinmon(2, 2000) => 29
daysinmon(2, 2001) => 28
daysinmon(3, 2000) => 31
daysinmon(3, 2001) => 31
daysinmon("Feb", 2000) => 29
daysinmon("Feb", 2001) => 28
daysinmon("March", 2000) => 31
daysinmon("March", 2001) => 31
daysinmon("Cabbage", 2001) => Invalid month name
../tests/test.rem(1639): daysinmon(): Invalid month name
daysinmon(2000-02-14) => 29
daysinmon(2001-02-14) => 28
daysinmon(2000-04-14) => 30
daysinmon(2001-04-14) => 30
date(2020, "April", 15) => 2020-04-15
date(2020, "Carrot", 12) => Invalid month name
../tests/test.rem(1647): date(): Invalid month name
datetime(2020, "April", 13, 04:44) => 2020-04-13@04:44
datetime(2020, "April", 13, 4, 44) => 2020-04-13@04:44
datetime(2020, "Lettuce", 13, 04:44) => Invalid month name
../tests/test.rem(1650): datetime(): Invalid month name
datetime(2020, "Lettuce", 13, 4, 44) => Invalid month name
../tests/test.rem(1651): datetime(): Invalid month name
wkdaynum("Tue") => 2
wkdaynum("Wednesday") => 3
wkdaynum("telephone") => Invalid weekday name
../tests/test.rem(1655): wkdaynum(): Invalid weekday name
Variable hash table statistics:
Entries: 100143; Buckets: 87719; Non-empty Buckets: 66301
Maxlen: 5; Minlen: 0; Avglen: 1.142; Stddev: 0.878; Avg nonempty len: 1.510
@@ -23639,7 +23668,7 @@ SECURITY: Won't read world-writable file or directory!
Error reading include_dir/ww: Can't open file
SECURITY: Won't read world-writable file or directory!
Error reading include_dir/ww: No files matching *.rem
05.04.01
05.04.02
Enabling test mode: This is meant for the acceptance test.
Do not use --test in production.
In test mode, the system time is fixed at 2025-01-06@19:00
@@ -23693,7 +23722,7 @@ REM 29 Feb MSG two
REM 29 2024 MSG three
-stdin-(4): Trig = Friday, 29 March, 2024
REM 29 Feb 2024 MSG four
-stdin-(5): Expired
-stdin-(5): Expired: 2024-02-29
REM Thursday 29 MSG One
-stdin-(6): Trig = Thursday, 4 April, 2024
REM Thursday 29 Feb MSG two
@@ -23701,7 +23730,7 @@ REM Thursday 29 Feb MSG two
REM Thursday 29 2024 MSG three
-stdin-(8): Trig = Thursday, 4 April, 2024
REM Thursday 29 Feb 2024 MSG four
-stdin-(9): Expired
-stdin-(9): Expired: 2024-02-29
REM Wednesday 29 MSG One
-stdin-(10): Trig = Wednesday, 6 March, 2024
REM Wednesday 29 Feb MSG two
@@ -24844,10 +24873,11 @@ TRANSLATE "Ok" ""
TRANSLATE "Missing ']'" ""
TRANSLATE "Missing quote" ""
TRANSLATE "Expression too complex" ""
TRANSLATE "Invalid month name" ""
TRANSLATE "Missing ')'" ""
TRANSLATE "Undefined function" ""
TRANSLATE "Illegal character" ""
TRANSLATE "Expecting binary operator" ""
TRANSLATE "Invalid weekday name" ""
TRANSLATE "Out of memory" ""
TRANSLATE "Ill-formed number" ""
TRANSLATE "Can't coerce" ""

View File

@@ -1612,6 +1612,49 @@ REM SECOND SATURDAY +300 UNTIL 1991-02-02 MSG [$T]
REM SECOND SATURDAY +300 UNTIL 1991-02-16 MSG [$T]
DEBUG -t
# Fully-specified trigger date in the past
REM 14 Jan 1991 MSG In the past
set a trigvalid()
set b trigdate()
REM MSG trigvalid = [a]; trigdate = [b]
# SATISFY clause that's never satisfied...
REM 14 Jan 1991 SATISFY [$Ty == 2022] MSG I can't get no satisfaction
set a trigvalid()
set b trigdate()
REM MSG trigvalid = [a]; trigdate = [b]
DEBUG +x
set a daysinmon(2, 2000)
set a daysinmon(2, 2001)
set a daysinmon(3, 2000)
set a daysinmon(3, 2001)
set a daysinmon("Feb", 2000)
set a daysinmon("Feb", 2001)
set a daysinmon("March", 2000)
set a daysinmon("March", 2001)
set a daysinmon("Cabbage", 2001)
set a daysinmon('2000-02-14')
set a daysinmon('2001-02-14')
set a daysinmon('2000-04-14')
set a daysinmon('2001-04-14')
set a date(2020, "April", 15)
set a date(2020, "Carrot", 12)
set a datetime(2020, "April", 13, 4:44)
set a datetime(2020, "April", 13, 4, 44)
set a datetime(2020, "Lettuce", 13, 4:44)
set a datetime(2020, "Lettuce", 13, 4, 44)
set a wkdaynum("Tue")
set a wkdaynum("Wednesday")
set a wkdaynum("telephone")
DEBUG -x
# Output expression-node stats
DEBUG +h