mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 22:38:37 +02:00
Compare commits
42 Commits
05.04.00-B
...
05.04.02
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ab8897577 | ||
|
|
9613417a2e | ||
|
|
f808a2963d | ||
|
|
96a4dc3189 | ||
|
|
3c60285466 | ||
|
|
6fed350e1f | ||
|
|
9f220555af | ||
|
|
005ccef953 | ||
|
|
578c98c865 | ||
|
|
64bf3381c6 | ||
|
|
02ade6fc58 | ||
|
|
2954fca8d8 | ||
|
|
8356dacf2a | ||
|
|
4fd145cf4e | ||
|
|
1af2bdf8f1 | ||
|
|
9b98e65e01 | ||
|
|
0f83b98698 | ||
|
|
4fd62f9894 | ||
|
|
cc06592fe0 | ||
|
|
21d28ebfc3 | ||
|
|
b300422cdb | ||
|
|
37e09f4671 | ||
|
|
b6e53341c8 | ||
|
|
896fcf1d7f | ||
|
|
72155329f2 | ||
|
|
36c7db510a | ||
|
|
d4aa73747d | ||
|
|
3ed657b708 | ||
|
|
0441c0263b | ||
|
|
c40d4ee672 | ||
|
|
96f2d6537a | ||
|
|
dc777c95df | ||
|
|
3090d77346 | ||
|
|
157d2821f3 | ||
|
|
71d2da19a8 | ||
|
|
516b9c81b3 | ||
|
|
58d0e38f1a | ||
|
|
68d487ade9 | ||
|
|
9d42879170 | ||
|
|
db70aabc97 | ||
|
|
c8f55ef60b | ||
|
|
44b50fc6be |
33
README.md
33
README.md
@@ -55,6 +55,39 @@ edit custom.h on your behalf:
|
||||
|
||||
`wish ./build.tk`
|
||||
|
||||
## Usage
|
||||
|
||||
Remind is a large and complex program. You can read the full manual page
|
||||
with:
|
||||
|
||||
`man remind`
|
||||
|
||||
after installation. However, the man page is long and detailed and is
|
||||
more of a reference than an introduction. You can get an overview
|
||||
with a [slide deck](https://dianne.skoll.ca/projects/remind/download/remind-oclug.pdf)
|
||||
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
18
configure
vendored
@@ -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.00.
|
||||
# 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.00'
|
||||
PACKAGE_STRING='remind 05.04.00'
|
||||
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.00 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.00:";;
|
||||
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.00
|
||||
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.00, 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.00, 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.00
|
||||
remind config.status 05.04.02
|
||||
configured by $0, generated by GNU Autoconf 2.71,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT(remind, 05.04.00, , , 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'
|
||||
|
||||
@@ -1,6 +1,41 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* VERSION 5.4 Patch 0 - 2025-??-??
|
||||
* 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
|
||||
yield a trigger date after its UNTIL date, rather than recognizing it
|
||||
as having expired. This has been fixed. Bug found by Ian! D. Allen.
|
||||
|
||||
- BUG FIX: rem2pdf: Support the COLOUR special (as well as COLOR).
|
||||
|
||||
- MINOR IMPROVEMENT: Add include/utils/add-html-anchors.rem. You can
|
||||
INCLUDE this file to get HTML anchors added to every calendar day
|
||||
by rem2html.
|
||||
|
||||
- DOCUMENTATION: Add NOTE-ABOUT-AI.txt
|
||||
|
||||
* VERSION 5.4 Patch 0 - 2025-06-03
|
||||
|
||||
- MAJOR IMPROVEMENT: remind: Track which expressions and variables
|
||||
Remind can prove to its satisfaction are "constant" - that is, that
|
||||
@@ -26,6 +61,20 @@ CHANGES TO REMIND
|
||||
corresponding $Tb system variable. See the remind(1) man page for
|
||||
details.
|
||||
|
||||
- MINOR IMPROVEMENT: remind: make value("var", default) evaluate the
|
||||
second argument lazily: If "var" is defined, then the second
|
||||
argument is never evaluated.
|
||||
|
||||
- MINOR IMPROVEMENT: remind: Add syntax for redefining a function without
|
||||
issuing a warning. The syntax:
|
||||
|
||||
FSET - func(x) expr
|
||||
|
||||
is equivalent to:
|
||||
|
||||
FUNSET func
|
||||
FSET func(x) expr
|
||||
|
||||
- MINOR IMPROVEMENT: include/holidays: Update a bunch of files to use
|
||||
isany(n, a, b, c) rather than (n == a || n == b || n == c)
|
||||
|
||||
@@ -1500,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.
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -14,9 +14,6 @@ FSET _h2(x, y) HEBDATE(x, y, $U-7)
|
||||
FSET _PastSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)+1)
|
||||
FSET _BackTwoFri(x, y) IIF(WKDAYNUM(_h2(x,y))!=5, _h2(x,y), _h2(x,y)-2)
|
||||
FSET _BackTwoSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)-2)
|
||||
# Default values in case InIsrael and Reform are not set
|
||||
SET InIsrael VALUE("InIsrael", 0)
|
||||
SET Reform VALUE("Reform", 0)
|
||||
|
||||
REM [hebdate(1, "Tishrey")] INFO "Url: https://en.wikipedia.org/wiki/Rosh_Hashanah" MSG Rosh Hashana 1
|
||||
|
||||
|
||||
5
include/utils/add-html-anchors.rem
Normal file
5
include/utils/add-html-anchors.rem
Normal file
@@ -0,0 +1,5 @@
|
||||
# Add HTML anchors to each day box.
|
||||
# This adds anchors: <a id="YYYY-MM-DD" name="YYYY-MM-DD"></a>
|
||||
# to each calendar box in an HTML calendar.
|
||||
|
||||
REM SPECIAL HTML <a id="[$T]" name="[$T]"></a>
|
||||
@@ -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
|
||||
@@ -4595,7 +4613,9 @@ an error results.
|
||||
.PP
|
||||
However, if you supply a second argument, it is returned if the \fIvarname\fR
|
||||
is not defined. The expression value("XY", 0) will return 0 if XY is not
|
||||
defined, and the value of XY if it is defined.
|
||||
defined, and the value of XY if it is defined. Note that \fBvalue\fR
|
||||
evaluates the second argument lazily; it is \fInot\fR evaluated if
|
||||
\fIvarname\fR is defined.
|
||||
.RE
|
||||
.TP
|
||||
.B version()
|
||||
@@ -5074,7 +5094,18 @@ function, the command fails with an error message and does nothing.
|
||||
If you define a user-defined function and then later on redefine it,
|
||||
\fBRemind\fR will issue a warning. If you do not want this warning,
|
||||
then use \fBFUNSET\fR to remove the existing definition before you
|
||||
redefine the function.
|
||||
redefine the function. Alternatively, you can use a "-" token before
|
||||
the function name to suppress "redefined function" warnings, as in the
|
||||
following example:
|
||||
.PP
|
||||
.nf
|
||||
FSET - f(x) 2*x
|
||||
# You must have space before and after the "-"
|
||||
# This will NOT work:
|
||||
# FSET -f(x) 2*x
|
||||
.fi
|
||||
.PP
|
||||
to define a function and suppress any "redefined function" warning.
|
||||
.PP
|
||||
.SH PRECISE SCHEDULING
|
||||
.PP
|
||||
@@ -6760,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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -265,6 +265,7 @@ while(1) {
|
||||
}
|
||||
my ($obj, $err) = Remind::PDF->create_from_stream(*STDIN,
|
||||
{color => 1,
|
||||
colour => 1,
|
||||
shade => 1,
|
||||
moon => 1,
|
||||
pango => 1,
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */ "",
|
||||
|
||||
226
src/funcs.c
226
src/funcs.c
@@ -59,7 +59,9 @@
|
||||
#define Nargs (info->nargs)
|
||||
#define RetVal (info->retval)
|
||||
|
||||
#define DBG(x) do { if (DebugFlag & DB_PRTEXPR) { x; } } while(0)
|
||||
#define DBGX (DebugFlag & DB_PRTEXPR)
|
||||
|
||||
#define DBG(x) do { if (DBGX) { x; } } while(0)
|
||||
/* Debugging helpers for "choose()", "iif(), etc. */
|
||||
#define PUT(x) DBufPuts(&DebugBuf, x)
|
||||
#define OUT() do { fprintf(ErrFp, "%s\n", DBufValue(&DebugBuf)); DBufFree(&DebugBuf); } while(0)
|
||||
@@ -193,7 +195,7 @@ static int FTypeof (func_info *);
|
||||
static int FTzconvert (func_info *);
|
||||
static int FUTCToLocal (func_info *);
|
||||
static int FUpper (func_info *);
|
||||
static int FValue (func_info *);
|
||||
static int FValue (expr_node *, Value *, Value *, int *);
|
||||
static int FVersion (func_info *);
|
||||
static int FWeekno (func_info *);
|
||||
static int FWkday (func_info *);
|
||||
@@ -229,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 )
|
||||
|
||||
@@ -265,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 },
|
||||
@@ -365,7 +369,7 @@ BuiltinFunc Func[] = {
|
||||
{ "tzconvert", 2, 3, 0, FTzconvert, NULL },
|
||||
{ "upper", 1, 1, 1, FUpper, NULL },
|
||||
{ "utctolocal", 1, 1, 1, FUTCToLocal, NULL },
|
||||
{ "value", 1, 2, 0, FValue, NULL },
|
||||
{ "value", 1, 2, 1, NULL, FValue }, /* NEW-STYLE */
|
||||
{ "version", 0, 0, 1, FVersion, NULL },
|
||||
{ "weekno", 0, 3, 0, FWeekno, NULL },
|
||||
{ "wkday", 1, 1, 1, FWkday, NULL },
|
||||
@@ -376,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 */
|
||||
@@ -461,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);
|
||||
@@ -528,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;
|
||||
@@ -540,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;
|
||||
|
||||
@@ -757,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;
|
||||
@@ -809,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;
|
||||
@@ -846,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)
|
||||
@@ -1299,7 +1320,7 @@ static int FIsconst(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
ans->type = INT_TYPE;
|
||||
ans->v.val = (my_nonconst ? 0 : 1);
|
||||
DBG(PUT(PrintValue(&junk, NULL)));
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
PUT(") => ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
OUT();
|
||||
@@ -1366,7 +1387,7 @@ static int FIsAny(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
break;
|
||||
}
|
||||
DestroyValue(v);
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
while(cur->sibling) {
|
||||
cur = cur->sibling;
|
||||
PUT(", ?");
|
||||
@@ -1403,7 +1424,7 @@ static int FCatch(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
SuppressErrorOutputInCatch = old_suppress;
|
||||
|
||||
if (r == OK) {
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
PUT(PrintValue(ans, NULL));
|
||||
PUT(", ?) => ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
@@ -1414,14 +1435,14 @@ static int FCatch(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
|
||||
/* Save the catch error */
|
||||
LastCatchError = r;
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
PUT("*");
|
||||
PUT(GetErr(r));
|
||||
PUT("*, ");
|
||||
}
|
||||
r = evaluate_expr_node(cur->sibling, locals, ans, nonconst);
|
||||
if (r == OK) {
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
PUT(PrintValue(ans, NULL));
|
||||
PUT(") => ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
@@ -1429,7 +1450,7 @@ static int FCatch(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
}
|
||||
return r;
|
||||
}
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
PUT("*");
|
||||
PUT(GetErr(r));
|
||||
PUT("*) => ");
|
||||
@@ -1478,7 +1499,7 @@ static int FChoose(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
}
|
||||
DBG(PUT(PrintValue(&v, NULL)));
|
||||
if (v.type != INT_TYPE) {
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
cur = cur->sibling;
|
||||
while(cur) {
|
||||
PUT(", ?");
|
||||
@@ -1488,6 +1509,7 @@ static int FChoose(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
PUT(GetErr(E_BAD_TYPE));
|
||||
OUT();
|
||||
}
|
||||
DestroyValue(v);
|
||||
Eprint("choose(): %s", GetErr(E_BAD_TYPE));
|
||||
return E_BAD_TYPE;
|
||||
}
|
||||
@@ -1505,7 +1527,7 @@ static int FChoose(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
DBG(DBufFree(&DebugBuf));
|
||||
return r;
|
||||
}
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
PUT(", ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
cur = cur->sibling;
|
||||
@@ -1695,26 +1717,92 @@ static int FGetenv(func_info *info)
|
||||
/* it is returned if variable is undefined. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int FValue(func_info *info)
|
||||
static int FValue(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
{
|
||||
DynamicBuffer DebugBuf;
|
||||
expr_node *cur;
|
||||
int r;
|
||||
Value varname;
|
||||
Var *v;
|
||||
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
switch(Nargs) {
|
||||
case 1:
|
||||
return GetVarValue(ARGSTR(0), &RetVal);
|
||||
DBG(DBufInit(&DebugBuf));
|
||||
|
||||
case 2:
|
||||
v = FindVar(ARGSTR(0), 0);
|
||||
if (!v) {
|
||||
DCOPYVAL(RetVal, ARG(1));
|
||||
return OK;
|
||||
} else {
|
||||
v->used_since_set = 1;
|
||||
return CopyValue(&RetVal, &v->v);
|
||||
cur = node->child;
|
||||
r = evaluate_expr_node(cur, locals, &varname, nonconst);
|
||||
if (r != OK) {
|
||||
DBG(DBufFree(&DebugBuf));
|
||||
return r;
|
||||
}
|
||||
|
||||
DBG(PUT("value("));
|
||||
DBG(PUT(PrintValue(&varname, NULL)));
|
||||
if (node->num_kids == 1) {
|
||||
DBG(PUT(") => "));
|
||||
} else {
|
||||
DBG(PUT(", "));
|
||||
}
|
||||
if (varname.type != STR_TYPE) {
|
||||
if (DBGX) {
|
||||
if (node->num_kids == 2) {
|
||||
PUT("?) => ");
|
||||
}
|
||||
PUT(GetErr(E_BAD_TYPE));
|
||||
OUT();
|
||||
}
|
||||
DestroyValue(varname);
|
||||
return E_BAD_TYPE;
|
||||
}
|
||||
|
||||
v = FindVar(varname.v.str, 0);
|
||||
if (!v) {
|
||||
r = E_NOSUCH_VAR;
|
||||
} else {
|
||||
r = OK;
|
||||
v->used_since_set = 1;
|
||||
CopyValue(ans, &v->v);
|
||||
if (!v->is_constant) {
|
||||
nonconst_debug(*nonconst, tr("Global variable `%s' makes expression non-constant"), varname.v.str);
|
||||
*nonconst = 1;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
if (r == OK || node->num_kids == 1) {
|
||||
DestroyValue(varname);
|
||||
if (DBGX) {
|
||||
if (node->num_kids == 2) {
|
||||
PUT("?) => ");
|
||||
}
|
||||
if (r != OK) {
|
||||
PUT(GetErr(r));
|
||||
} else {
|
||||
PUT(PrintValue(ans, NULL));
|
||||
}
|
||||
OUT();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Variable does not exist. We have to mark the result of value()
|
||||
as non-constant because the nonexistence of a variable may depend
|
||||
on today's date (for example) */
|
||||
nonconst_debug(*nonconst, tr("Nonexistence of global variable `%s' makes value() non-constant"), varname.v.str);
|
||||
DestroyValue(varname);
|
||||
*nonconst = 1;
|
||||
r = evaluate_expr_node(cur->sibling, locals, ans, nonconst);
|
||||
if (DBGX) {
|
||||
if (node->num_kids == 2) {
|
||||
if (r != OK) {
|
||||
PUT(GetErr(r));
|
||||
PUT(") => ");
|
||||
PUT(GetErr(r));
|
||||
} else {
|
||||
PUT(PrintValue(ans, NULL));
|
||||
PUT(") => ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
}
|
||||
OUT();
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -1939,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;
|
||||
}
|
||||
|
||||
@@ -1964,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);
|
||||
|
||||
@@ -2216,7 +2314,7 @@ static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
cur = node->child;
|
||||
|
||||
if (!(node->num_kids % 2)) {
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
r = 0;
|
||||
while(cur) {
|
||||
if (r) PUT(", ");
|
||||
@@ -2239,7 +2337,7 @@ static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
DBG(DBufFree(&DebugBuf));
|
||||
return r;
|
||||
}
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
if (done) PUT(", ");
|
||||
done = 1;
|
||||
PUT(PrintValue(&v, NULL));
|
||||
@@ -2247,7 +2345,7 @@ static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
|
||||
if (truthy(&v)) {
|
||||
r = evaluate_expr_node(cur->sibling, locals, ans, nonconst);
|
||||
if (r == OK && (DebugFlag & DB_PRTEXPR)) {
|
||||
if (r == OK && DBGX) {
|
||||
PUT(", ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
cur = cur->sibling->sibling;
|
||||
@@ -2268,7 +2366,7 @@ static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
|
||||
/* Return the last arg */
|
||||
r = evaluate_expr_node(cur, locals, ans, nonconst);
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
if (done) PUT(", ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
PUT(") => ");
|
||||
@@ -2756,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;
|
||||
@@ -2765,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;
|
||||
}
|
||||
|
||||
@@ -2809,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);
|
||||
@@ -2817,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;
|
||||
}
|
||||
|
||||
@@ -3845,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);
|
||||
}
|
||||
|
||||
@@ -3903,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* HASHTAB_STATS.C */
|
||||
/* HASHTAB.C */
|
||||
/* */
|
||||
/* Implementation of hash table. */
|
||||
/* */
|
||||
|
||||
22
src/main.c
22
src/main.c
@@ -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;
|
||||
}
|
||||
@@ -935,6 +941,10 @@ void Eprint(char const *fmt, ...)
|
||||
return;
|
||||
}
|
||||
|
||||
if (should_ignore_line()) {
|
||||
return;
|
||||
}
|
||||
|
||||
char const *fname = GetCurrentFilename();
|
||||
if (!fname) {
|
||||
return;
|
||||
@@ -1990,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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -12,12 +12,6 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* Solaris needs this to get select() prototype */
|
||||
#ifdef __sun__
|
||||
#define __EXTENSIONS__ 1
|
||||
#endif
|
||||
|
||||
/* We only want object code generated if we have queued reminders */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -310,15 +310,15 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
{
|
||||
int simple, mod, omit;
|
||||
|
||||
/* First: Have we passed the UNTIL date? */
|
||||
/* First: Have we passed the UNTIL date? */
|
||||
if (trig->until != NO_UNTIL &&
|
||||
trig->until < start) {
|
||||
trig->expired = 1;
|
||||
return -1; /* expired */
|
||||
}
|
||||
|
||||
/* Next: If it's an "AFTER"-type skip, back up
|
||||
until we're at the start of a block of holidays */
|
||||
/* Next: If it's an "AFTER"-type skip, back up
|
||||
until we're at the start of a block of holidays */
|
||||
if (trig->skip == AFTER_SKIP) {
|
||||
int iter = 0;
|
||||
while (iter++ <= MaxSatIter) {
|
||||
@@ -339,16 +339,16 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the next simple trigger */
|
||||
/* Find the next simple trigger */
|
||||
simple = NextSimpleTrig(start, trig, err);
|
||||
|
||||
/* Problems? */
|
||||
/* Problems? */
|
||||
if (*err || (simple == -1)) return -1;
|
||||
|
||||
/* Suggested starting point for next attempt */
|
||||
/* Suggested starting point for next attempt */
|
||||
*nextstart = simple+1;
|
||||
|
||||
/* If there's a BACK, back up... */
|
||||
/* If there's a BACK, back up... */
|
||||
if (trig->back != NO_BACK) {
|
||||
mod = trig->back;
|
||||
if (mod < 0) {
|
||||
@@ -376,7 +376,7 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
}
|
||||
}
|
||||
|
||||
/* If there's a REP, calculate the next occurrence */
|
||||
/* If there's a REP, calculate the next occurrence */
|
||||
if (trig->rep != NO_REP) {
|
||||
if (simple < start) {
|
||||
mod = (start - simple) / trig->rep;
|
||||
@@ -385,7 +385,7 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
}
|
||||
}
|
||||
|
||||
/* If it's a "BEFORE"-type skip, back up */
|
||||
/* If it's a "BEFORE"-type skip, back up */
|
||||
if (trig->skip == BEFORE_SKIP) {
|
||||
int iter = 0;
|
||||
while(iter++ <= MaxSatIter) {
|
||||
@@ -406,7 +406,7 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
}
|
||||
}
|
||||
|
||||
/* If it's an "AFTER"-type skip, jump ahead */
|
||||
/* If it's an "AFTER"-type skip, jump ahead */
|
||||
if (trig->skip == AFTER_SKIP) {
|
||||
int iter = 0;
|
||||
while (iter++ <= MaxSatIter) {
|
||||
@@ -423,7 +423,12 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the date */
|
||||
/* If we've passed the UNTIL, then it's expired */
|
||||
if (trig->until != NO_UNTIL && simple > trig->until) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return the date */
|
||||
return simple;
|
||||
}
|
||||
|
||||
@@ -536,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 */
|
||||
@@ -574,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) {
|
||||
@@ -630,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;
|
||||
|
||||
@@ -181,12 +181,34 @@ int DoFset(ParsePtr p)
|
||||
Var *locals = NULL;
|
||||
Var local_array[MAX_FUNC_ARGS];
|
||||
int orig_namelen;
|
||||
int suppress_redefined_function_warning = 0;
|
||||
int ch;
|
||||
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
|
||||
|
||||
ch = ParseNonSpaceChar(p, &r, 1);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
if (ch == '-') {
|
||||
r = ParseToken(p, &buf);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
if (strcmp(DBufValue(&buf), "-")) {
|
||||
DBufFree(&buf);
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
suppress_redefined_function_warning = 1;
|
||||
DBufFree(&buf);
|
||||
}
|
||||
|
||||
/* Get the function name */
|
||||
if ( (r=ParseIdentifier(p, &buf)) ) return r;
|
||||
if ( (r=ParseIdentifier(p, &buf)) ) {
|
||||
return r;
|
||||
}
|
||||
if (*DBufValue(&buf) == '$') {
|
||||
DBufFree(&buf);
|
||||
return E_BAD_ID;
|
||||
@@ -222,8 +244,10 @@ int DoFset(ParsePtr p)
|
||||
return OK;
|
||||
}
|
||||
/* Warn about redefinition */
|
||||
Wprint(tr("Function `%s' redefined: previously defined at %s(%s)"),
|
||||
existing->name, existing->filename, line_range(existing->lineno_start, existing->lineno));
|
||||
if (!suppress_redefined_function_warning) {
|
||||
Wprint(tr("Function `%s' redefined: previously defined at %s(%s)"),
|
||||
existing->name, existing->filename, line_range(existing->lineno_start, existing->lineno));
|
||||
}
|
||||
}
|
||||
|
||||
/* Should be followed by '(' */
|
||||
|
||||
49
src/var.c
49
src/var.c
@@ -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;
|
||||
}
|
||||
@@ -560,6 +560,7 @@ Var *FindVar(char const *str, int create)
|
||||
v->v.type = INT_TYPE;
|
||||
v->v.v.val = 0;
|
||||
v->preserve = 0;
|
||||
v->is_constant = 1;
|
||||
v->filename = "";
|
||||
v->lineno = 0;
|
||||
StrnCpy(v->name, str, VAR_NAME_LEN);
|
||||
@@ -660,7 +661,13 @@ int DoSet (Parser *p)
|
||||
Var *var;
|
||||
|
||||
r = ParseIdentifier(p, &buf);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
DBufFree(&buf);
|
||||
if (ignoring) {
|
||||
return OK;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
if (ignoring) {
|
||||
/* We're only here to mark a variable as non-const */
|
||||
@@ -907,7 +914,6 @@ int PreserveVar(char const *name)
|
||||
v = FindVar(name, 1);
|
||||
if (!v) return E_NO_MEM;
|
||||
v->preserve = 1;
|
||||
|
||||
/* Assume we're gonna use the variable */
|
||||
v->used_since_set = 1;
|
||||
return OK;
|
||||
@@ -925,11 +931,10 @@ int DoPreserve (Parser *p)
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
|
||||
r = ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (!DBufLen(&buf)) {
|
||||
r = ParseIdentifier(p, &buf);
|
||||
if (r) {
|
||||
DBufFree(&buf);
|
||||
return E_EOLN;
|
||||
return r;
|
||||
}
|
||||
|
||||
r = PreserveVar(DBufValue(&buf));
|
||||
@@ -938,12 +943,14 @@ int DoPreserve (Parser *p)
|
||||
|
||||
/* Keep going... */
|
||||
while(1) {
|
||||
r = ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (!DBufLen(&buf)) {
|
||||
r = ParseIdentifier(p, &buf);
|
||||
if (r == E_EOLN) {
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
}
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
r = PreserveVar(DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
|
||||
@@ -65,8 +65,8 @@ FSET not_const(x) x+nonconst(a)
|
||||
REM [const(5)] Jan 1992 MSG expired... should be commented out
|
||||
REM [const(a)] Jan 1992 MSG expired... should be commented out
|
||||
REM [not_const(5)] Jan 1992 MSG nonconstant expression
|
||||
REM [value("a")] Jan 1992 MSG nonconstant expression
|
||||
|
||||
REM [value("a")] Jan 1992 MSG constant expression
|
||||
REM [value("__cabbage", 1)] Jan 1992 MSG non-constant expression
|
||||
IF 0
|
||||
# A comment in a false IF block
|
||||
#!P This should be nuked
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
# If you're writing a back-end, test it by feeding it the output
|
||||
# of: remind -pp test-for-backends.rem
|
||||
|
||||
# All back-ends should endeavour to support: WEEK, SHADE, MOON, and
|
||||
# COLOR/COLOUR. They may support other back-end-specific SPECIALs.
|
||||
|
||||
# Color and shade
|
||||
REM 1 SPECIAL COLOR 128 0 0 Red
|
||||
REM 2 SPECIAL COLOUR 0 128 0 British Green
|
||||
@@ -17,11 +20,18 @@ REM [moondate(3)] SPECIAL MOON 3 -1 -1 [moontime(3)]
|
||||
# Week
|
||||
REM Monday SPECIAL WEEK (W[weekno()])
|
||||
|
||||
# PostScript
|
||||
REM Wed PS Border Border 2 div moveto /Helvetica-Oblique findfont 6 scalefont setfont (oof!) show
|
||||
# A normal reminder
|
||||
REM 16 MSG A normal reminder
|
||||
|
||||
# PostScript - currently only supported by rem2ps
|
||||
REM Wed PS Border Border 2 div moveto /Helvetica-Oblique findfont 6 scalefont setfont (oof PostScript!) show
|
||||
|
||||
# A SPECIAL that should be ignored
|
||||
REM 15 SPECIAL RANDOM-STUFF ignore me and be happy
|
||||
|
||||
# A normal reminder
|
||||
REM 16 MSG A normal reminder
|
||||
# HTML - currently only supported by rem2html
|
||||
REM 17 SPECIAL HTML I am <b>bold</b> HTML
|
||||
|
||||
# Pango - currently only supported by rem2pdf
|
||||
REM 18 SPECIAL PANGO I am <b>bold</b> PANGO
|
||||
|
||||
|
||||
105
tests/test.cmp
105
tests/test.cmp
@@ -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
|
||||
@@ -800,8 +800,7 @@ Leaving UserFN _ofunc(1991-02-28) => 0
|
||||
../tests/test.rem(224): Trig = Thursday, 28 February, 1991
|
||||
|
||||
# omitfunc ignores local/global omits
|
||||
fset _ofunc(x) 0
|
||||
../tests/test.rem(227): Function `_ofunc' redefined: previously defined at ../tests/test.rem(222)
|
||||
fset - _ofunc(x) 0
|
||||
OMIT 1 March
|
||||
OMIT 2 March 1991
|
||||
REM 1 March OMIT Sun OMITFUNC _ofunc AFTER MSG Should trigger 1 March
|
||||
@@ -1043,7 +1042,7 @@ set a057 value("a05"+"6")
|
||||
"a05" + "6" => "a056"
|
||||
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
set a058 version()
|
||||
version() => "05.04.00"
|
||||
version() => "05.04.02"
|
||||
set a059 wkday(today())
|
||||
today() => 1991-02-16
|
||||
wkday(1991-02-16) => "Saturday"
|
||||
@@ -2606,7 +2605,7 @@ a056 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
a007 "1991-02-16"
|
||||
a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
a008 "11:44"
|
||||
a058 "05.04.00"
|
||||
a058 "05.04.02"
|
||||
a059 "Saturday"
|
||||
a010 12
|
||||
a060 6
|
||||
@@ -3154,7 +3153,7 @@ REM Mon 1992 UNTIL 1991-01-01 MSG Not diagnosed - not fully-specified start
|
||||
../tests/test.rem(561): Expired
|
||||
REM 1992-01-01 *1 UNTIL 1991-12-31 MSG Diagnosed
|
||||
../tests/test.rem(562): Warning: UNTIL/THROUGH date earlier than start date
|
||||
../tests/test.rem(562): Trig = Wednesday, 1 January, 1992
|
||||
../tests/test.rem(562): Expired
|
||||
set x '1992-01-01'
|
||||
MSG [isconst(x)]
|
||||
../tests/test.rem(564): Trig = Saturday, 16 February, 1991
|
||||
@@ -3165,7 +3164,7 @@ isconst(1992-01-01) => 1
|
||||
REM [x] *1 UNTIL 1991-12-31 MSG Diagnosed
|
||||
x => 1992-01-01
|
||||
../tests/test.rem(565): Warning: UNTIL/THROUGH date earlier than start date
|
||||
../tests/test.rem(565): Trig = Wednesday, 1 January, 1992
|
||||
../tests/test.rem(565): Expired
|
||||
|
||||
set x nonconst('1992-01-01')
|
||||
nonconst(1992-01-01) => 1992-01-01
|
||||
@@ -3177,7 +3176,7 @@ isconst(1992-01-01) => 0
|
||||
|
||||
REM [x] *1 UNTIL 1991-12-31 MSG Not diagnosed - nonconst expression
|
||||
x => 1992-01-01
|
||||
../tests/test.rem(569): Trig = Wednesday, 1 January, 1992
|
||||
../tests/test.rem(569): Expired
|
||||
|
||||
REM MON FROM 1992-01-01 UNTIL 1991-12-31 MSG Diagnosed
|
||||
../tests/test.rem(571): Warning: UNTIL/THROUGH date earlier than FROM date
|
||||
@@ -4116,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
|
||||
@@ -4152,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
|
||||
@@ -5076,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
|
||||
@@ -5640,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.00"
|
||||
"05.04.00" > "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...
|
||||
@@ -16363,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")
|
||||
@@ -16398,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
|
||||
@@ -16554,12 +16553,59 @@ shell("ls") => RUN disabled
|
||||
../tests/test.rem(1588): shell(): RUN disabled
|
||||
RUN disabled
|
||||
|
||||
# "value" should use lazy evaluation
|
||||
set a value(4:33)
|
||||
value(04:33) => Type mismatch
|
||||
../tests/test.rem(1591): Type mismatch
|
||||
set a value('2020-01-01', 42)
|
||||
value(2020-01-01, ?) => Type mismatch
|
||||
../tests/test.rem(1592): Type mismatch
|
||||
set a value("nosuchvar")
|
||||
value("nosuchvar") => Undefined variable
|
||||
../tests/test.rem(1593): Undefined variable
|
||||
set a value("nosuchvar", 42)
|
||||
value("nosuchvar", 42) => 42
|
||||
set a value("a", 42)
|
||||
value("a", ?) => 42
|
||||
set a value("a")
|
||||
value("a") => 42
|
||||
DEBUG -x
|
||||
|
||||
DEBUG -e
|
||||
../tests/test.rem(1596): eval(): Too many recursive function calls
|
||||
../tests/test.rem(1603): eval(): Too many recursive function calls
|
||||
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
|
||||
@@ -20399,10 +20445,11 @@ FSET not_const(x) x+nonconst(a)
|
||||
#!P: Next line may have expired, but contains non-constant expression
|
||||
#!P: or a relative SCANFROM clause
|
||||
REM [not_const(5)] Jan 1992 MSG nonconstant expression
|
||||
#!P: Next line has expired, but contains expression... please verify
|
||||
#!P: Expired: REM [value("a")] Jan 1992 MSG constant expression
|
||||
#!P: Next line may have expired, but contains non-constant expression
|
||||
#!P: or a relative SCANFROM clause
|
||||
REM [value("a")] Jan 1992 MSG nonconstant expression
|
||||
|
||||
REM [value("__cabbage", 1)] Jan 1992 MSG non-constant expression
|
||||
#!P: The next IF evaluated false...
|
||||
#!P: REM statements in IF block not checked for purging.
|
||||
IF 0
|
||||
@@ -20516,8 +20563,8 @@ FSET not_const(x) x+nonconst(a)
|
||||
#!P: Expired: REM [const(5)] Jan 1992 MSG expired... should be commented out
|
||||
#!P: Expired: REM [const(a)] Jan 1992 MSG expired... should be commented out
|
||||
REM [not_const(5)] Jan 1992 MSG nonconstant expression
|
||||
REM [value("a")] Jan 1992 MSG nonconstant expression
|
||||
|
||||
#!P: Expired: REM [value("a")] Jan 1992 MSG constant expression
|
||||
REM [value("__cabbage", 1)] Jan 1992 MSG non-constant expression
|
||||
IF 0
|
||||
# A comment in a false IF block
|
||||
ENDIF
|
||||
@@ -23621,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.00
|
||||
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
|
||||
@@ -23675,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
|
||||
@@ -23683,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
|
||||
@@ -24826,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" ""
|
||||
@@ -24955,6 +25003,7 @@ TRANSLATE "No Adar A in %d" ""
|
||||
TRANSLATE "No substition function `%s' defined" ""
|
||||
TRANSLATE "Non-constant built-in function `%s' makes expression non-constant" ""
|
||||
TRANSLATE "Non-constant expression converted to constant by `const' built-in function" ""
|
||||
TRANSLATE "Nonexistence of global variable `%s' makes value() non-constant" ""
|
||||
TRANSLATE "Not setting $OnceFile: Already processed a reminder with a ONCE clause" ""
|
||||
TRANSLATE "OMIT: UNTIL not allowed; did you mean THROUGH?" ""
|
||||
TRANSLATE "OMITFUNC counts as a non-constant expression" ""
|
||||
|
||||
@@ -224,7 +224,7 @@ REM 1 March OMITFUNC _ofunc AFTER MSG OmitFunc Test
|
||||
REM 8 March OMITFUNC _ofunc -1 MSG OmitFunc Test 2
|
||||
|
||||
# omitfunc ignores local/global omits
|
||||
fset _ofunc(x) 0
|
||||
fset - _ofunc(x) 0
|
||||
OMIT 1 March
|
||||
OMIT 2 March 1991
|
||||
REM 1 March OMIT Sun OMITFUNC _ofunc AFTER MSG Should trigger 1 March
|
||||
@@ -1587,6 +1587,13 @@ FUNSET i
|
||||
set a "eval(\"1\")+ shell(\"ls\")"
|
||||
set b eval(a)
|
||||
|
||||
# "value" should use lazy evaluation
|
||||
set a value(4:33)
|
||||
set a value('2020-01-01', 42)
|
||||
set a value("nosuchvar")
|
||||
set a value("nosuchvar", 42)
|
||||
set a value("a", 42)
|
||||
set a value("a")
|
||||
DEBUG -x
|
||||
|
||||
DEBUG -e
|
||||
@@ -1599,6 +1606,55 @@ set a eval(a)
|
||||
REM 9 Feb 1991 *7 MSG Base: [trigbase()]
|
||||
REM 9 Feb 1991 *1 MSG Base: [$Tb]
|
||||
|
||||
# The UNTIL bug
|
||||
DEBUG +t
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user