mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-17 23:08:40 +02:00
Compare commits
106 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9dea59206 | ||
|
|
46aa144b65 | ||
|
|
914971308d | ||
|
|
a22e81040f | ||
|
|
72f74f03cf | ||
|
|
d0e45e727e | ||
|
|
ce2b2e80da | ||
|
|
11771b7d3d | ||
|
|
01cb028532 | ||
|
|
58b6f43b9c | ||
|
|
1dedb667e8 | ||
|
|
8a96236788 | ||
|
|
2a13163659 | ||
|
|
336a9684d4 | ||
|
|
86945c6e18 | ||
|
|
684280db5e | ||
|
|
d801408933 | ||
|
|
79b3da3820 | ||
|
|
ed021d3f46 | ||
|
|
27d0fda280 | ||
|
|
ef12da4ec6 | ||
|
|
7b098e95ad | ||
|
|
7d13f4b09e | ||
|
|
cecdfe6ade | ||
|
|
216bbd6378 | ||
|
|
30e2e9c633 | ||
|
|
bf2aabd610 | ||
|
|
c019221d15 | ||
|
|
b7bd6faf07 | ||
|
|
80d58220fe | ||
|
|
cd8624e176 | ||
|
|
8515fb7ddd | ||
|
|
84f9f4ae0a | ||
|
|
e201ebcfa4 | ||
|
|
4e15c3ec35 | ||
|
|
1adccf9b1f | ||
|
|
a1aa5c2ad9 | ||
|
|
1e0d650737 | ||
|
|
553d092ca8 | ||
|
|
dc62841517 | ||
|
|
326e7bfc53 | ||
|
|
b9dc7c16ad | ||
|
|
abd54b016b | ||
|
|
db02b54067 | ||
|
|
40a78dfbbb | ||
|
|
c860b46baa | ||
|
|
1458ba8856 | ||
|
|
7b9b6ebc96 | ||
|
|
7ee4073c7a | ||
|
|
8c072cd9b6 | ||
|
|
b794a45c3f | ||
|
|
98e491ed1d | ||
|
|
c397cc06da | ||
|
|
8616236b3c | ||
|
|
702704af1a | ||
|
|
a0d1b19050 | ||
|
|
a5c8ae491c | ||
|
|
b3cf741d15 | ||
|
|
0b28dde9c7 | ||
|
|
5a3980b5b8 | ||
|
|
a8e33118d6 | ||
|
|
2223277f64 | ||
|
|
c72413e3c1 | ||
|
|
fa1033db6f | ||
|
|
61e3edd2ac | ||
|
|
093c97ff91 | ||
|
|
6e64b175aa | ||
|
|
09dba4bc94 | ||
|
|
2e443ac5b7 | ||
|
|
59a8c88178 | ||
|
|
40eab03d84 | ||
|
|
e993bf59cf | ||
|
|
c6de5a2c8f | ||
|
|
51cc939d0c | ||
|
|
c857192e6d | ||
|
|
4591c2b181 | ||
|
|
7843a1b2ba | ||
|
|
649481cf01 | ||
|
|
c253bdfcbe | ||
|
|
1910808fd7 | ||
|
|
1d8cb9749e | ||
|
|
e3f9380fcd | ||
|
|
326c3f59b0 | ||
|
|
03f1c5a047 | ||
|
|
02122491c3 | ||
|
|
735f6f5686 | ||
|
|
ac033d75c0 | ||
|
|
e2185e773a | ||
|
|
d9ae417e01 | ||
|
|
e1d0948538 | ||
|
|
357ddf285a | ||
|
|
41859fc484 | ||
|
|
07275e71b0 | ||
|
|
f68521cb95 | ||
|
|
526610bdd2 | ||
|
|
973e3448ae | ||
|
|
9a3f28f6fc | ||
|
|
a3e32d2dc4 | ||
|
|
a8b78eff00 | ||
|
|
460db83298 | ||
|
|
4560712778 | ||
|
|
ce8803dde9 | ||
|
|
60ca5d45e3 | ||
|
|
4454613d00 | ||
|
|
0704808500 | ||
|
|
166b1ac499 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -33,3 +33,4 @@ src/version.h
|
|||||||
tests/test.out
|
tests/test.out
|
||||||
www/Makefile
|
www/Makefile
|
||||||
gmon.out
|
gmon.out
|
||||||
|
tests/once.timestamp
|
||||||
|
|||||||
18
configure
vendored
18
configure
vendored
@@ -1,6 +1,6 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.71 for remind 05.00.00.
|
# Generated by GNU Autoconf 2.71 for remind 05.00.05.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
|
# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
|
||||||
@@ -608,8 +608,8 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='remind'
|
PACKAGE_NAME='remind'
|
||||||
PACKAGE_TARNAME='remind'
|
PACKAGE_TARNAME='remind'
|
||||||
PACKAGE_VERSION='05.00.00'
|
PACKAGE_VERSION='05.00.05'
|
||||||
PACKAGE_STRING='remind 05.00.00'
|
PACKAGE_STRING='remind 05.00.05'
|
||||||
PACKAGE_BUGREPORT=''
|
PACKAGE_BUGREPORT=''
|
||||||
PACKAGE_URL='https://dianne.skoll.ca/projects/remind/'
|
PACKAGE_URL='https://dianne.skoll.ca/projects/remind/'
|
||||||
|
|
||||||
@@ -1264,7 +1264,7 @@ if test "$ac_init_help" = "long"; then
|
|||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# 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.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures remind 05.00.00 to adapt to many kinds of systems.
|
\`configure' configures remind 05.00.05 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@@ -1326,7 +1326,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of remind 05.00.00:";;
|
short | recursive ) echo "Configuration of remind 05.00.05:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@@ -1414,7 +1414,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
remind configure 05.00.00
|
remind configure 05.00.05
|
||||||
generated by GNU Autoconf 2.71
|
generated by GNU Autoconf 2.71
|
||||||
|
|
||||||
Copyright (C) 2021 Free Software Foundation, Inc.
|
Copyright (C) 2021 Free Software Foundation, Inc.
|
||||||
@@ -1864,7 +1864,7 @@ cat >config.log <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by remind $as_me 05.00.00, which was
|
It was created by remind $as_me 05.00.05, which was
|
||||||
generated by GNU Autoconf 2.71. Invocation command line was
|
generated by GNU Autoconf 2.71. Invocation command line was
|
||||||
|
|
||||||
$ $0$ac_configure_args_raw
|
$ $0$ac_configure_args_raw
|
||||||
@@ -4703,7 +4703,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by remind $as_me 05.00.00, which was
|
This file was extended by remind $as_me 05.00.05, which was
|
||||||
generated by GNU Autoconf 2.71. Invocation command line was
|
generated by GNU Autoconf 2.71. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@@ -4768,7 +4768,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config='$ac_cs_config_escaped'
|
ac_cs_config='$ac_cs_config_escaped'
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
remind config.status 05.00.00
|
remind config.status 05.00.05
|
||||||
configured by $0, generated by GNU Autoconf 2.71,
|
configured by $0, generated by GNU Autoconf 2.71,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_INIT(remind, 05.00.00, , , https://dianne.skoll.ca/projects/remind/)
|
AC_INIT(remind, 05.00.05, , , https://dianne.skoll.ca/projects/remind/)
|
||||||
AC_CONFIG_SRCDIR([src/queue.c])
|
AC_CONFIG_SRCDIR([src/queue.c])
|
||||||
|
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ foreach $yearkey (sort keys %{$events} ) {
|
|||||||
if ($start->hour > 0) {
|
if ($start->hour > 0) {
|
||||||
print " AT ";
|
print " AT ";
|
||||||
print $start->strftime("%H:%M");
|
print $start->strftime("%H:%M");
|
||||||
print " SCHED _sfun MSG %a %2 ";
|
print " +15 MSG %a %2 ";
|
||||||
} else {
|
} else {
|
||||||
print " MSG %a ";
|
print " MSG %a ";
|
||||||
}
|
}
|
||||||
|
|||||||
120
docs/WHATSNEW
120
docs/WHATSNEW
@@ -1,5 +1,125 @@
|
|||||||
CHANGES TO REMIND
|
CHANGES TO REMIND
|
||||||
|
|
||||||
|
* VERSION 5.0 Patch 5 - 2024-09-02
|
||||||
|
|
||||||
|
* CHANGE: remind: When using the "-c" option and with the SHADE special
|
||||||
|
enabled, shade the entire calendar box including the line containing the
|
||||||
|
day number.
|
||||||
|
|
||||||
|
* IMPROVEMENT: remind: Better error messages when diagnosing certain
|
||||||
|
errors in expressions.
|
||||||
|
|
||||||
|
* IMPROVEMENT: include/holidays/jewish.rem: Remove unnecessary _h()
|
||||||
|
function definition.
|
||||||
|
|
||||||
|
* BUG FIX: remind: In a couple of spots when we parsed a character, we did
|
||||||
|
not check for an error return. This has been fixed.
|
||||||
|
|
||||||
|
* BUG FIX: remind: Fix edge-case bugs in "remind -c" output formatting.
|
||||||
|
|
||||||
|
* BUG FIX: make test: Fix a test that was broken for all of September 2024.
|
||||||
|
|
||||||
|
* BUG FIX: remind: Fix a couple of potential file-descriptor leaks.
|
||||||
|
|
||||||
|
* BUG FIX: contrib/ical2rem.pl: Replace "SCHED _sfun" with "+15" to
|
||||||
|
hard-code 15-minutes advance warning rather than using an undefined
|
||||||
|
scheduling function. If this is not what you want, you should edit
|
||||||
|
ical2rem.pl to suit your taste; it's not officially part of Remind and
|
||||||
|
is meant more as a starting point for you to customize than a finished
|
||||||
|
product.
|
||||||
|
|
||||||
|
* DOCUMENTATION FIX: Remove obsolete info from Remind man page.
|
||||||
|
|
||||||
|
* VERSION 5.0 Patch 4 - 2024-08-29
|
||||||
|
|
||||||
|
* IMPROVEMENT: remind: When checking if a SATISFY expression refers to the
|
||||||
|
trigger date, look recursively at any user-defined functions it calls.
|
||||||
|
This reduces spurious warnings.
|
||||||
|
|
||||||
|
* CHANGE: remind: Allow any type to be used as the test argument for IIF.
|
||||||
|
|
||||||
|
* IMPROVEMENT: remind man page: Clarify how various types are treated
|
||||||
|
in boolean context.
|
||||||
|
|
||||||
|
* VERSION 5.0 Patch 3 - 2024-08-28
|
||||||
|
|
||||||
|
* IMPROVEMENT: remind: Preserve newlines ("%_" sequences) in calendar
|
||||||
|
mode in most cases. See the remind man page for details.
|
||||||
|
|
||||||
|
* IMPROVEMENT: rem2pdf: rem2pdf can now produce PostScript and
|
||||||
|
Encapsulated PostScript output in addition to PDF and SVG.
|
||||||
|
|
||||||
|
* IMPROVEMENT: remind: Emit warnings if a subst_XXX function takes the
|
||||||
|
wrong number of arguments, or for custom sequences, if the function
|
||||||
|
is not defined.
|
||||||
|
|
||||||
|
* IMPROVEMENT: remind: Emit warnings if WARN/SCHED/OMITFUNC functions
|
||||||
|
do not reference their argument.
|
||||||
|
|
||||||
|
* IMPROVEMENT: remind: Allow strings to be used with logical
|
||||||
|
operators. The empty string "" is considered false and all other
|
||||||
|
strings are considered true.
|
||||||
|
|
||||||
|
* IMPROVEMENT: remind: Emit warnings for lines that are implicitly
|
||||||
|
treated as REM commands; add warnings for REM commands that are
|
||||||
|
implicitly treated as MSG-type reminders.
|
||||||
|
|
||||||
|
* IMPROVEMENT: remind: Add an optional fourth argument to the built-in
|
||||||
|
ampm() function that specifies not to suppress a leading zero in the
|
||||||
|
hour component.
|
||||||
|
|
||||||
|
* IMPROVEMENT: remind: If a SATISFY expression is not constant and
|
||||||
|
doesn't reference the trigger date somehow, issue a warning.
|
||||||
|
|
||||||
|
* IMPROVEMENT: remind: Add a warning if a user-defined function is
|
||||||
|
redefined. If you do have a use-case that requires you to redefine
|
||||||
|
a function, simply FUNSET it first before FSETting it for the second
|
||||||
|
time.
|
||||||
|
|
||||||
|
* DOCUMENTATION FIX: Clarify man pages and remove some information that
|
||||||
|
has become incorrect as Remind has evolved.
|
||||||
|
|
||||||
|
* BUG FIX: Fix typos in man pages
|
||||||
|
|
||||||
|
* VERSION 5.0 Patch 2 - 2024-07-26
|
||||||
|
|
||||||
|
* IMPROVEMENT: Remind: Revamp how ONCE works. You can now set a
|
||||||
|
special variable $OnceFile to be the path to a timestamp file. The
|
||||||
|
ONCE directive uses this timestamp file to track when it was last
|
||||||
|
run rather than the access date of the main reminder script. This
|
||||||
|
is more reliable because it doesn't rely on the atime of a file
|
||||||
|
(which might not be maintained accurately) and is not affected if
|
||||||
|
you edit your reminder script.
|
||||||
|
|
||||||
|
* CHANGE: Taking input from stdin no longer implies the "-o" option; ONCE can
|
||||||
|
work if you set $OnceFile
|
||||||
|
|
||||||
|
* CHANGE: Any of the -c, -n, -p and -s options implicitly enable the
|
||||||
|
-o option. As before, specifying a repeat factor *N or a date that
|
||||||
|
is not today on the command-line also implies -o.
|
||||||
|
|
||||||
|
* MINOR NEW FEATURE: Rem2PDF: Add the "--svg" command-line option to produce
|
||||||
|
SVG output rather than PDF.
|
||||||
|
|
||||||
|
* MINOR IMPROVEMENT: Remind: Improve the storage efficiency of short
|
||||||
|
string constants in compiled expression trees.
|
||||||
|
|
||||||
|
* MINOR IMPROVEMENT: Remind: Remove some obsolete macro definitions
|
||||||
|
|
||||||
|
* VERSION 5.0 Patch 1 - 2024-06-08
|
||||||
|
|
||||||
|
* MINOR IMPROVEMENT: Add short-circuit evaluation to the isany() function,
|
||||||
|
which now only evaluates those arguments absolutely necessary to determine
|
||||||
|
the result.
|
||||||
|
|
||||||
|
* BUG FIX: Mark weekno() as a non-constant function (the zero-argument form
|
||||||
|
depends on external conditions.)
|
||||||
|
|
||||||
|
* BUG FIX: Fix a couple of memory leaks.
|
||||||
|
|
||||||
|
* BUG FIX: Don't rely on support for unnamed function parameters; this caused
|
||||||
|
compilation failures with older versions of gcc.
|
||||||
|
|
||||||
* VERSION 5.0 Patch 0 - 2024-06-06
|
* VERSION 5.0 Patch 0 - 2024-06-06
|
||||||
|
|
||||||
* MAJOR CHANGE: The expression evaluation engine has been completely replaced
|
* MAJOR CHANGE: The expression evaluation engine has been completely replaced
|
||||||
|
|||||||
@@ -6,6 +6,11 @@
|
|||||||
# Cut and paste as desired! Also, near the end, there are a bunch of #
|
# Cut and paste as desired! Also, near the end, there are a bunch of #
|
||||||
# holiday definitions for the U.S. #
|
# holiday definitions for the U.S. #
|
||||||
# #
|
# #
|
||||||
|
# *** NOTE *** #
|
||||||
|
# #
|
||||||
|
# This file is simply a grab-bag of examples. It is NOT meant to be #
|
||||||
|
# included as-is in a live reminder file. #
|
||||||
|
# #
|
||||||
# Some examples provided by George M. Sipe <gsipe@pyratl.ga.pyramid.com> #
|
# Some examples provided by George M. Sipe <gsipe@pyratl.ga.pyramid.com> #
|
||||||
# #
|
# #
|
||||||
# U.S. holidays provided by Dave Rickel <drickel@sjc.mentorg.com> #
|
# U.S. holidays provided by Dave Rickel <drickel@sjc.mentorg.com> #
|
||||||
@@ -305,51 +310,51 @@ FSET _PastMon(x, y) IIF(WKDAYNUM(_h2(x,y))!=1, _h2(x,y), _h2(x,y)+1)
|
|||||||
SET InIsrael VALUE("InIsrael", 0)
|
SET InIsrael VALUE("InIsrael", 0)
|
||||||
SET Reform VALUE("Reform", 0)
|
SET Reform VALUE("Reform", 0)
|
||||||
|
|
||||||
[_h(1, "Tishrey")] ++4 MSG %"Rosh Hashana 1%" is %b.
|
REM [_h(1, "Tishrey")] ++4 MSG %"Rosh Hashana 1%" is %b.
|
||||||
|
|
||||||
# No RH-2 or Tzom Gedalia in Reform
|
# No RH-2 or Tzom Gedalia in Reform
|
||||||
IF !Reform
|
IF !Reform
|
||||||
[_h(2, "Tishrey")] ++4 MSG %"Rosh Hashana 2%" is %b.
|
REM [_h(2, "Tishrey")] ++4 MSG %"Rosh Hashana 2%" is %b.
|
||||||
[_PastSat(3, "Tishrey")] ++4 MSG %"Tzom Gedalia%" is %b.
|
REM [_PastSat(3, "Tishrey")] ++4 MSG %"Tzom Gedalia%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(10, "Tishrey")] ++4 MSG %"Yom Kippur%" is %b.
|
REM [_h(10, "Tishrey")] ++4 MSG %"Yom Kippur%" is %b.
|
||||||
[_h(15, "Tishrey")] ++4 MSG %"Sukkot 1%" is %b.
|
REM [_h(15, "Tishrey")] ++4 MSG %"Sukkot 1%" is %b.
|
||||||
|
|
||||||
IF !InIsrael
|
IF !InIsrael
|
||||||
[_h(16, "Tishrey")] MSG %"Sukkot 2%"
|
REM [_h(16, "Tishrey")] MSG %"Sukkot 2%"
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(21, "Tishrey")] ++4 MSG %"Hoshana Rabba%" is %b.
|
REM [_h(21, "Tishrey")] ++4 MSG %"Hoshana Rabba%" is %b.
|
||||||
[_h(22, "Tishrey")] ++4 MSG %"Shemini Atzeret%" is %b.
|
REM [_h(22, "Tishrey")] ++4 MSG %"Shemini Atzeret%" is %b.
|
||||||
|
|
||||||
IF InIsrael
|
IF InIsrael
|
||||||
[_h(22, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
REM [_h(22, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
||||||
ELSE
|
ELSE
|
||||||
[_h(23, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
REM [_h(23, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
# Because Kislev can change length, we must be more careful about Chanukah
|
# Because Kislev can change length, we must be more careful about Chanukah
|
||||||
FSET _chan(x) HEBDATE(24, "Kislev", $U-9)+x
|
FSET _chan(x) HEBDATE(24, "Kislev", $U-9)+x
|
||||||
[_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
|
REM [_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
|
||||||
[_chan(2)] MSG %"Chanukah 2%"
|
REM [_chan(2)] MSG %"Chanukah 2%"
|
||||||
[_chan(3)] MSG %"Chanukah 3%"
|
REM [_chan(3)] MSG %"Chanukah 3%"
|
||||||
[_chan(4)] MSG %"Chanukah 4%"
|
REM [_chan(4)] MSG %"Chanukah 4%"
|
||||||
[_chan(5)] MSG %"Chanukah 5%"
|
REM [_chan(5)] MSG %"Chanukah 5%"
|
||||||
[_chan(6)] MSG %"Chanukah 6%"
|
REM [_chan(6)] MSG %"Chanukah 6%"
|
||||||
[_chan(7)] MSG %"Chanukah 7%"
|
REM [_chan(7)] MSG %"Chanukah 7%"
|
||||||
[_chan(8)] MSG %"Chanukah 8%"
|
REM [_chan(8)] MSG %"Chanukah 8%"
|
||||||
|
|
||||||
# Not sure about Reform's position on the next one.
|
# Not sure about Reform's position on the next one.
|
||||||
IF !Reform
|
IF !Reform
|
||||||
# 10 Tevet will never be a Saturday, so whether or not to
|
# 10 Tevet will never be a Saturday, so whether or not to
|
||||||
# move it is moot. (Thanks to Art Werschulz.)
|
# move it is moot. (Thanks to Art Werschulz.)
|
||||||
[_h(10, "Tevet")] MSG %"Tzom Tevet%" is %b.
|
REM [_h(10, "Tevet")] MSG %"Tzom Tevet%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(15, "Shvat")] ++4 MSG %"Tu B'Shvat%" is %b.
|
REM [_h(15, "Shvat")] ++4 MSG %"Tu B'Shvat%" is %b.
|
||||||
[_h(14, "Adar A")] ++4 MSG %"Purim Katan%" is %b.
|
REM [_h(14, "Adar A")] ++4 MSG %"Purim Katan%" is %b.
|
||||||
[_h(15, "Adar A")] ++4 MSG %"Shushan Purim Katan%" is %b.
|
REM [_h(15, "Adar A")] ++4 MSG %"Shushan Purim Katan%" is %b.
|
||||||
|
|
||||||
# If Purim is on Sunday, then Fast of Esther is 11 Adar.
|
# If Purim is on Sunday, then Fast of Esther is 11 Adar.
|
||||||
IF WKDAYNUM(_h2(13, "Adar")) != 6
|
IF WKDAYNUM(_h2(13, "Adar")) != 6
|
||||||
@@ -357,18 +362,18 @@ IF WKDAYNUM(_h2(13, "Adar")) != 6
|
|||||||
ELSE
|
ELSE
|
||||||
REM [_h2(11, "Adar")] ++4 MSG %"Fast of Esther%" is %b.
|
REM [_h2(11, "Adar")] ++4 MSG %"Fast of Esther%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
[_h(14, "Adar")] ++4 MSG %"Purim%" is %b.
|
REM [_h(14, "Adar")] ++4 MSG %"Purim%" is %b.
|
||||||
[_h(15, "Adar")] ++4 MSG %"Shushan Purim%" is %b.
|
REM [_h(15, "Adar")] ++4 MSG %"Shushan Purim%" is %b.
|
||||||
[_h(15, "Nisan")] ++4 MSG %"Pesach%" is %b.
|
REM [_h(15, "Nisan")] ++4 MSG %"Pesach%" is %b.
|
||||||
|
|
||||||
IF !InIsrael
|
IF !InIsrael
|
||||||
[_h(16, "Nisan")] MSG %"Pesach 2%"
|
REM [_h(16, "Nisan")] MSG %"Pesach 2%"
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(21, "Nisan")] MSG %"Pesach 7%"
|
REM [_h(21, "Nisan")] MSG %"Pesach 7%"
|
||||||
|
|
||||||
IF !InIsrael && !Reform
|
IF !InIsrael && !Reform
|
||||||
[_h(22, "Nisan")] MSG %"Pesach 8%"
|
REM [_h(22, "Nisan")] MSG %"Pesach 8%"
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
REM [_PastSun(27, "Nisan")] SATISFY 1
|
REM [_PastSun(27, "Nisan")] SATISFY 1
|
||||||
@@ -384,36 +389,36 @@ ENDIF
|
|||||||
# Thursday. If 4 Iyar is a Sunday, then Yom Hazikaron
|
# Thursday. If 4 Iyar is a Sunday, then Yom Hazikaron
|
||||||
# moves to 5 Iyar and Yom Ha'atzmaut to 6 Iyar.
|
# moves to 5 Iyar and Yom Ha'atzmaut to 6 Iyar.
|
||||||
IF WKDAYNUM(_h2(4, "Iyar")) == 4 || WKDAYNUM(_h2(4, "Iyar")) == 5
|
IF WKDAYNUM(_h2(4, "Iyar")) == 4 || WKDAYNUM(_h2(4, "Iyar")) == 5
|
||||||
[_h(2, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
REM [_h(2, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
||||||
[_h(3, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
REM [_h(3, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||||
ELSE
|
ELSE
|
||||||
IF WKDAYNUM(_h2(4, "Iyar")) == 0
|
IF WKDAYNUM(_h2(4, "Iyar")) == 0
|
||||||
[_h(5, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
REM [_h(5, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
||||||
[_h(6, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
REM [_h(6, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||||
ELSE
|
ELSE
|
||||||
[_h(4, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
REM [_h(4, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
||||||
[_h(5, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
REM [_h(5, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
# Not sure about Reform's position on Lag B'Omer
|
# Not sure about Reform's position on Lag B'Omer
|
||||||
IF !Reform
|
IF !Reform
|
||||||
[_h(18, "Iyar")] ++4 MSG %"Lag B'Omer%" is %b.
|
REM [_h(18, "Iyar")] ++4 MSG %"Lag B'Omer%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(28, "Iyar")] ++4 MSG %"Yom Yerushalayim%" is %b.
|
REM [_h(28, "Iyar")] ++4 MSG %"Yom Yerushalayim%" is %b.
|
||||||
[_h(6, "Sivan")] ++4 MSG %"Shavuot%" is %b.
|
REM [_h(6, "Sivan")] ++4 MSG %"Shavuot%" is %b.
|
||||||
|
|
||||||
IF !InIsrael && !Reform
|
IF !InIsrael && !Reform
|
||||||
[_h(7, "Sivan")] MSG %"Shavuot 2%"
|
REM [_h(7, "Sivan")] MSG %"Shavuot 2%"
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
# Fairly sure Reform Jews don't observe the next two
|
# Fairly sure Reform Jews don't observe the next two
|
||||||
IF !Reform
|
IF !Reform
|
||||||
# Tzom Tamuz and Tish'a B'Av are moved to Sunday if they normally
|
# Tzom Tamuz and Tish'a B'Av are moved to Sunday if they normally
|
||||||
# fall on a Saturday
|
# fall on a Saturday
|
||||||
[_PastSat(17, "Tamuz")] ++4 MSG %"Tzom Tammuz%" is %b.
|
REM [_PastSat(17, "Tamuz")] ++4 MSG %"Tzom Tammuz%" is %b.
|
||||||
[_PastSat(9, "Av")] ++4 MSG %"Tish'a B'Av%" is %b.
|
REM [_PastSat(9, "Av")] ++4 MSG %"Tish'a B'Av%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
# Counting the omer - do the whole spiel, i.e:
|
# Counting the omer - do the whole spiel, i.e:
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ REM 28 Oct MSG ΟΧΙ
|
|||||||
REM 25 Dec MSG ΧΡΙΣΤΟΥΓΕΝΝΑ
|
REM 25 Dec MSG ΧΡΙΣΤΟΥΓΕΝΝΑ
|
||||||
REM 26 Dec MSG ΧΡΙΣΤΟΥΓΕΝΝΑ2
|
REM 26 Dec MSG ΧΡΙΣΤΟΥΓΕΝΝΑ2
|
||||||
|
|
||||||
REM [orthodoxeaster($Uy)+1] ΔΕΥΤΕΡΑ ΤΟΥ ΠΑΣΧΑ
|
REM [orthodoxeaster($Uy)+1] MSG ΔΕΥΤΕΡΑ ΤΟΥ ΠΑΣΧΑ
|
||||||
|
|
||||||
|
|
||||||
# May first is a national holiday except if Sunday, day of great week (week before easter) or Monday after easter, then
|
# May first is a national holiday except if Sunday, day of great week (week before easter) or Monday after easter, then
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ SET InIsrael value("InIsrael", 0)
|
|||||||
SET Reform value("Reform", 0)
|
SET Reform value("Reform", 0)
|
||||||
|
|
||||||
# Convenient function definition to save typing
|
# Convenient function definition to save typing
|
||||||
FSET _h(x, y) HEBDATE(x,y)
|
|
||||||
FSET _h2(x, y) HEBDATE(x, y, $U-7)
|
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 _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 _BackTwoFri(x, y) IIF(WKDAYNUM(_h2(x,y))!=5, _h2(x,y), _h2(x,y)-2)
|
||||||
@@ -19,50 +18,50 @@ FSET _BackTwoSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)-2)
|
|||||||
SET InIsrael VALUE("InIsrael", 0)
|
SET InIsrael VALUE("InIsrael", 0)
|
||||||
SET Reform VALUE("Reform", 0)
|
SET Reform VALUE("Reform", 0)
|
||||||
|
|
||||||
[_h(1, "Tishrey")] ++4 MSG %"Rosh Hashana 1%" is %b.
|
REM [hebdate(1, "Tishrey")] ++4 MSG %"Rosh Hashana 1%" is %b.
|
||||||
|
|
||||||
# No RH-2 or Tzom Gedalia in Reform
|
# No RH-2 or Tzom Gedalia in Reform
|
||||||
IF !Reform
|
IF !Reform
|
||||||
[_h(2, "Tishrey")] ++4 MSG %"Rosh Hashana 2%" is %b.
|
REM [hebdate(2, "Tishrey")] ++4 MSG %"Rosh Hashana 2%" is %b.
|
||||||
[_PastSat(3, "Tishrey")] ++4 MSG %"Tzom Gedalia%" is %b.
|
REM [_PastSat(3, "Tishrey")] ++4 MSG %"Tzom Gedalia%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(10, "Tishrey")] ++4 MSG %"Yom Kippur%" is %b.
|
REM [hebdate(10, "Tishrey")] ++4 MSG %"Yom Kippur%" is %b.
|
||||||
[_h(15, "Tishrey")] ++4 MSG %"Sukkot 1%" is %b.
|
REM [hebdate(15, "Tishrey")] ++4 MSG %"Sukkot 1%" is %b.
|
||||||
|
|
||||||
IF !InIsrael
|
IF !InIsrael
|
||||||
[_h(16, "Tishrey")] MSG %"Sukkot 2%"
|
REM [hebdate(16, "Tishrey")] MSG %"Sukkot 2%"
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(21, "Tishrey")] ++4 MSG %"Hoshana Rabba%" is %b.
|
REM [hebdate(21, "Tishrey")] ++4 MSG %"Hoshana Rabba%" is %b.
|
||||||
[_h(22, "Tishrey")] ++4 MSG %"Shemini Atzeret%" is %b.
|
REM [hebdate(22, "Tishrey")] ++4 MSG %"Shemini Atzeret%" is %b.
|
||||||
|
|
||||||
IF InIsrael
|
IF InIsrael
|
||||||
[_h(22, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
REM [hebdate(22, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
||||||
ELSE
|
ELSE
|
||||||
[_h(23, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
REM [hebdate(23, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
# Because Kislev can change length, we must be more careful about Chanukah
|
# Because Kislev can change length, we must be more careful about Chanukah
|
||||||
FSET _chan(x) HEBDATE(24, "Kislev", $U-9)+x
|
FSET _chan(x) HEBDATE(24, "Kislev", $U-9)+x
|
||||||
[_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
|
REM [_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
|
||||||
[_chan(2)] MSG %"Chanukah 2%"
|
REM [_chan(2)] MSG %"Chanukah 2%"
|
||||||
[_chan(3)] MSG %"Chanukah 3%"
|
REM [_chan(3)] MSG %"Chanukah 3%"
|
||||||
[_chan(4)] MSG %"Chanukah 4%"
|
REM [_chan(4)] MSG %"Chanukah 4%"
|
||||||
[_chan(5)] MSG %"Chanukah 5%"
|
REM [_chan(5)] MSG %"Chanukah 5%"
|
||||||
[_chan(6)] MSG %"Chanukah 6%"
|
REM [_chan(6)] MSG %"Chanukah 6%"
|
||||||
[_chan(7)] MSG %"Chanukah 7%"
|
REM [_chan(7)] MSG %"Chanukah 7%"
|
||||||
[_chan(8)] MSG %"Chanukah 8%"
|
REM [_chan(8)] MSG %"Chanukah 8%"
|
||||||
|
|
||||||
# Not sure about Reform's position on the next one.
|
# Not sure about Reform's position on the next one.
|
||||||
IF !Reform
|
IF !Reform
|
||||||
# 10 Tevet will never be a Saturday, so whether or not to
|
# 10 Tevet will never be a Saturday, so whether or not to
|
||||||
# move it is moot. (Thanks to Art Werschulz.)
|
# move it is moot. (Thanks to Art Werschulz.)
|
||||||
[_h(10, "Tevet")] MSG %"Tzom Tevet%" is %b.
|
REM [hebdate(10, "Tevet")] MSG %"Tzom Tevet%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(15, "Shvat")] ++4 MSG %"Tu B'Shvat%" is %b.
|
REM [hebdate(15, "Shvat")] ++4 MSG %"Tu B'Shvat%" is %b.
|
||||||
[_h(14, "Adar A")] ++4 MSG %"Purim Katan%" is %b.
|
REM [hebdate(14, "Adar A")] ++4 MSG %"Purim Katan%" is %b.
|
||||||
|
|
||||||
# If Purim is on Sunday, then Fast of Esther is 11 Adar.
|
# If Purim is on Sunday, then Fast of Esther is 11 Adar.
|
||||||
IF WKDAYNUM(_h2(13, "Adar")) != 6
|
IF WKDAYNUM(_h2(13, "Adar")) != 6
|
||||||
@@ -70,39 +69,39 @@ IF WKDAYNUM(_h2(13, "Adar")) != 6
|
|||||||
ELSE
|
ELSE
|
||||||
REM [_h2(11, "Adar")] ++4 MSG %"Fast of Esther%" is %b.
|
REM [_h2(11, "Adar")] ++4 MSG %"Fast of Esther%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
[_h(14, "Adar")] ++4 MSG %"Purim%" is %b.
|
REM [hebdate(14, "Adar")] ++4 MSG %"Purim%" is %b.
|
||||||
[_h(15, "Nisan")] ++4 MSG %"Pesach%" is %b.
|
REM [hebdate(15, "Nisan")] ++4 MSG %"Pesach%" is %b.
|
||||||
|
|
||||||
IF !InIsrael
|
IF !InIsrael
|
||||||
[_h(16, "Nisan")] MSG %"Pesach 2%"
|
REM [hebdate(16, "Nisan")] MSG %"Pesach 2%"
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(21, "Nisan")] MSG %"Pesach 7%"
|
REM [hebdate(21, "Nisan")] MSG %"Pesach 7%"
|
||||||
|
|
||||||
IF !InIsrael && !Reform
|
IF !InIsrael && !Reform
|
||||||
[_h(22, "Nisan")] MSG %"Pesach 8%"
|
REM [hebdate(22, "Nisan")] MSG %"Pesach 8%"
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(27, "Nisan")] ++4 MSG %"Yom HaShoah%" is %b.
|
REM [hebdate(27, "Nisan")] ++4 MSG %"Yom HaShoah%" is %b.
|
||||||
[_BackTwoFri(4, "Iyar")] ++4 MSG %"Yom HaZikaron%" is %b.
|
REM [_BackTwoFri(4, "Iyar")] ++4 MSG %"Yom HaZikaron%" is %b.
|
||||||
[_BackTwoSat(5, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
REM [_BackTwoSat(5, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||||
|
|
||||||
# Not sure about Reform's position on Lag B'Omer
|
# Not sure about Reform's position on Lag B'Omer
|
||||||
IF !Reform
|
IF !Reform
|
||||||
[_h(18, "Iyar")] ++4 MSG %"Lag B'Omer%" is %b.
|
REM [hebdate(18, "Iyar")] ++4 MSG %"Lag B'Omer%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(28, "Iyar")] ++4 MSG %"Yom Yerushalayim%" is %b.
|
REM [hebdate(28, "Iyar")] ++4 MSG %"Yom Yerushalayim%" is %b.
|
||||||
[_h(6, "Sivan")] ++4 MSG %"Shavuot%" is %b.
|
REM [hebdate(6, "Sivan")] ++4 MSG %"Shavuot%" is %b.
|
||||||
|
|
||||||
IF !InIsrael && !Reform
|
IF !InIsrael && !Reform
|
||||||
[_h(7, "Sivan")] MSG %"Shavuot 2%"
|
REM [hebdate(7, "Sivan")] MSG %"Shavuot 2%"
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
# Fairly sure Reform Jews don't observe the next two
|
# Fairly sure Reform Jews don't observe the next two
|
||||||
IF !Reform
|
IF !Reform
|
||||||
# Tzom Tamuz and Tish'a B'Av are moved to Sunday if they normally
|
# Tzom Tamuz and Tish'a B'Av are moved to Sunday if they normally
|
||||||
# fall on a Saturday
|
# fall on a Saturday
|
||||||
[_PastSat(17, "Tamuz")] ++4 MSG %"Tzom Tammuz%" is %b.
|
REM [_PastSat(17, "Tamuz")] ++4 MSG %"Tzom Tammuz%" is %b.
|
||||||
[_PastSat(9, "Av")] ++4 MSG %"Tish'a B'Av%" is %b.
|
REM [_PastSat(9, "Av")] ++4 MSG %"Tish'a B'Av%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|||||||
@@ -525,9 +525,9 @@ contains the back value. If the "back" value was \-n, the value will
|
|||||||
be positive; if it was \-\-n, the value will be negative.
|
be positive; if it was \-\-n, the value will be negative.
|
||||||
.TP
|
.TP
|
||||||
.B delta \fIn\fR
|
.B delta \fIn\fR
|
||||||
If the reminder contained a "delta" clause (\+n or \+\+n), this key
|
If the reminder contained a "delta" clause (+n or ++n), this key
|
||||||
contains the delta value. If the "delta" value was \+n, the value will
|
contains the delta value. If the "delta" value was +n, the value will
|
||||||
be positive; if it was \+\+n, the value will be negative.
|
be positive; if it was ++n, the value will be negative.
|
||||||
.TP
|
.TP
|
||||||
.B rep \fIn\fR
|
.B rep \fIn\fR
|
||||||
If the reminder contained a "repeat" clause (*n), this key contains
|
If the reminder contained a "repeat" clause (*n), this key contains
|
||||||
|
|||||||
220
man/remind.1.in
220
man/remind.1.in
@@ -11,8 +11,8 @@ reminder or alarm can consist of a message sent to standard output, or
|
|||||||
a program to be executed.
|
a program to be executed.
|
||||||
.PP
|
.PP
|
||||||
If \fIfilename\fR is specified as a single dash '-', then \fBRemind\fR
|
If \fIfilename\fR is specified as a single dash '-', then \fBRemind\fR
|
||||||
takes its input from standard input. This also implicitly enables
|
takes its input from standard input.
|
||||||
the \fB\-o\fR option, described below.
|
|
||||||
.PP
|
.PP
|
||||||
If \fIfilename\fR happens to
|
If \fIfilename\fR happens to
|
||||||
be a directory rather than a plain file, then \fBRemind\fR reads all of
|
be a directory rather than a plain file, then \fBRemind\fR reads all of
|
||||||
@@ -32,7 +32,8 @@ ignore them for now and skip to the section "REMINDER FILES".
|
|||||||
The \fB\-n\fR option causes \fBRemind\fR to print the \fBnext\fR occurrence
|
The \fB\-n\fR option causes \fBRemind\fR to print the \fBnext\fR occurrence
|
||||||
of each reminder in a simple calendar format. You can sort this by
|
of each reminder in a simple calendar format. You can sort this by
|
||||||
date by piping the output through \fBsort(1)\fR. Note that the \fB\-n\fR
|
date by piping the output through \fBsort(1)\fR. Note that the \fB\-n\fR
|
||||||
option causes any \fB\-g\fR option to be \fIignored\fR.
|
option causes any \fB\-g\fR option to be \fIignored\fR and also implicitly
|
||||||
|
enables the \fB\-o\fR option.
|
||||||
.TP
|
.TP
|
||||||
.B \-j\fR[\fIn\fR]
|
.B \-j\fR[\fIn\fR]
|
||||||
Runs \fBRemind\fR in "purge" mode to get rid of expired reminders.
|
Runs \fBRemind\fR in "purge" mode to get rid of expired reminders.
|
||||||
@@ -47,7 +48,7 @@ The \fB\-c\fR option causes \fBRemind\fR to produce a calendar that is
|
|||||||
sent to standard output. If you supply a number \fIn\fR, then a
|
sent to standard output. If you supply a number \fIn\fR, then a
|
||||||
calendar will be generated for \fIn\fR months, starting with the
|
calendar will be generated for \fIn\fR months, starting with the
|
||||||
current month. By default, a calendar for only the current month is
|
current month. By default, a calendar for only the current month is
|
||||||
produced.
|
produced. This option implicitly enables the \fB\-o\fR option.
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
You can precede \fIn\fR (if any) with a set of flags. The flags
|
You can precede \fIn\fR (if any) with a set of flags. The flags
|
||||||
@@ -173,7 +174,7 @@ The \fB\-s\fR option is very similar to the \fB\-c\fR option, except
|
|||||||
that the output calendar is not formatted. It is listed in a "simple
|
that the output calendar is not formatted. It is listed in a "simple
|
||||||
format" that can be used as input for more sophisticated calendar-drawing
|
format" that can be used as input for more sophisticated calendar-drawing
|
||||||
programs. If \fIn\fR starts with "+", then it is interpreted as a number
|
programs. If \fIn\fR starts with "+", then it is interpreted as a number
|
||||||
of weeks.
|
of weeks. This option also implicitly enables the \fB\-o\fR option.
|
||||||
|
|
||||||
If you immediately follow the \fBs\fR with the letter
|
If you immediately follow the \fBs\fR with the letter
|
||||||
\fBa\fR, then \fBRemind\fR displays reminders on the calendar on the
|
\fBa\fR, then \fBRemind\fR displays reminders on the calendar on the
|
||||||
@@ -200,6 +201,9 @@ letter with this option, then the normal calendar-mode substitution filter
|
|||||||
is disabled and the %"...%" sequences are preserved in the output.
|
is disabled and the %"...%" sequences are preserved in the output.
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
|
The \fB\-p\fR, \fB\-pp\fR and \fB\-ppp\fR options implicitly enable
|
||||||
|
the \fB\-o\fR option.
|
||||||
|
.PP
|
||||||
Note that the \fB\-pp\fR or \fB\-ppp\fR options also enable the \fB\-l\fR
|
Note that the \fB\-pp\fR or \fB\-ppp\fR options also enable the \fB\-l\fR
|
||||||
option.
|
option.
|
||||||
.RE
|
.RE
|
||||||
@@ -223,7 +227,11 @@ error, and to print a security message if a script tests the
|
|||||||
$RunOff system variable.
|
$RunOff system variable.
|
||||||
.TP
|
.TP
|
||||||
.B \-o
|
.B \-o
|
||||||
The \fB\-o\fR option causes \fBRemind\fR to ignore all \fBONCE\fR directives.
|
The \fB\-o\fR option causes \fBRemind\fR to ignore all \fBONCE\fR
|
||||||
|
directives. Note that \fBONCE\fR is also ignored if any of the
|
||||||
|
\fB\-c\fR, \fB\-n\fR, \fB\-p\fR, or \fB\-s\fR options is used, if a
|
||||||
|
repetition factor \fB*n\fR is used, or if a date other than today's
|
||||||
|
date is specified on the command-line.
|
||||||
.TP
|
.TP
|
||||||
.B \-t
|
.B \-t
|
||||||
The \fB\-t\fR option causes \fBRemind\fR to trigger all non-expired reminders,
|
The \fB\-t\fR option causes \fBRemind\fR to trigger all non-expired reminders,
|
||||||
@@ -232,13 +240,13 @@ regardless of the \fIdelta\fR supplied for each reminder.
|
|||||||
.B \-t\fR\fIn\fR
|
.B \-t\fR\fIn\fR
|
||||||
If you supply a number \fIn\fR after the \fB\-t\fR option, then
|
If you supply a number \fIn\fR after the \fB\-t\fR option, then
|
||||||
\fBRemind\fR pretends that echo \fBREM\fR command has a delta
|
\fBRemind\fR pretends that echo \fBREM\fR command has a delta
|
||||||
of \+\+\fIn\fR, regardless of any existing delta.
|
of ++\fIn\fR, regardless of any existing delta.
|
||||||
.TP
|
.TP
|
||||||
.B \-tz\fR
|
.B \-tz\fR
|
||||||
If you supply the letter \fBz\fR after the \fB\-t\fR option, then
|
If you supply the letter \fBz\fR after the \fB\-t\fR option, then
|
||||||
\fBRemind\fR sets all REM statements' deltas to zero, regardless of the
|
\fBRemind\fR sets all REM statements' deltas to zero, regardless of the
|
||||||
value supplied in the REM statement itself. In effect, this disables
|
value supplied in the REM statement itself. In effect, this disables
|
||||||
all deltas of the form \fB\+\fIn\fR and \fB\+\+\fIn\fR.
|
all deltas of the form \fB+\fIn\fR and \fB++\fIn\fR.
|
||||||
.TP
|
.TP
|
||||||
.B \-tt\fR[\fIn\fR]
|
.B \-tt\fR[\fIn\fR]
|
||||||
The \fB-tt\fR option causes \fBRemind\fR to assume a default delta of
|
The \fB-tt\fR option causes \fBRemind\fR to assume a default delta of
|
||||||
@@ -455,7 +463,7 @@ information.
|
|||||||
\fBRemind\fR supports the following long options, which \fIare\fR
|
\fBRemind\fR supports the following long options, which \fIare\fR
|
||||||
case-sensitive:
|
case-sensitive:
|
||||||
|
|
||||||
.RP
|
.PP
|
||||||
.B \-\-version
|
.B \-\-version
|
||||||
The \fB\-\-version\fR option causes \fBRemind\fR to print its version number
|
The \fB\-\-version\fR option causes \fBRemind\fR to print its version number
|
||||||
to standard output and then exit.
|
to standard output and then exit.
|
||||||
@@ -547,12 +555,15 @@ Its syntax is:
|
|||||||
The parts of the \fBREM\fR command can be specified in any order, except
|
The parts of the \fBREM\fR command can be specified in any order, except
|
||||||
that the \fIbody\fR must come immediately after the \fBMSG\fR,
|
that the \fIbody\fR must come immediately after the \fBMSG\fR,
|
||||||
\fBRUN\fR, \fBCAL\fR, \fBPS\fR, \fBPSFILE\fR or \fBSATISFY\fR keyword.
|
\fBRUN\fR, \fBCAL\fR, \fBPS\fR, \fBPSFILE\fR or \fBSATISFY\fR keyword.
|
||||||
|
The portion of the \fBREM\fR command before the \fBMSG\fR, \fBMSF\fR
|
||||||
|
\fBRUN\fR, \fBCAL\fR or \fBSATISFY\fR clause is called a
|
||||||
|
\fItrigger\fR.
|
||||||
.PP
|
.PP
|
||||||
The \fBREM\fR token is optional, providing that the remainder
|
In earlier versions of \fBRemind\fR, the \fBREM\fR token was optional
|
||||||
of the command cannot be mistaken for another \fBRemind\fR command
|
providing that the remainder of the command cannot be mistaken for
|
||||||
such as \fBOMIT\fR or \fBRUN\fR. The portion of the \fBREM\fR command
|
another \fBRemind\fR command. However, this use is deprecated and will
|
||||||
before the \fBMSG\fR, \fBMSF\fR \fBRUN\fR, \fBCAL\fR or \fBSATISFY\fR clause
|
now cause a warning to be issued. All of your reminder lines should
|
||||||
is called a \fItrigger\fR.
|
be written to start with the REM command.
|
||||||
.PP
|
.PP
|
||||||
.B "MSG, MSF, RUN, CAL, SPECIAL, PS and PSFILE"
|
.B "MSG, MSF, RUN, CAL, SPECIAL, PS and PSFILE"
|
||||||
.PP
|
.PP
|
||||||
@@ -565,14 +576,16 @@ used the \fB\-k\fR command-line option, then \fBMSG\fR-type reminders are
|
|||||||
passed to the appropriate program. Note that the options \fB\-c\fR,
|
passed to the appropriate program. Note that the options \fB\-c\fR,
|
||||||
\fB\-s\fR, \fB\-p\fR and \fB\-n\fR disable the \fB\-k\fR option.
|
\fB\-s\fR, \fB\-p\fR and \fB\-n\fR disable the \fB\-k\fR option.
|
||||||
.PP
|
.PP
|
||||||
Note that you can omit the reminder type, in which case it
|
Earlier versions of \fBRemind\fR let you omit the reminder type,
|
||||||
defaults to \fBMSG\fR. So you can write:
|
in which case it defaulted to \fBMSG\fR. However, this usage is
|
||||||
|
deprecated and will cause a warning. Something like:
|
||||||
.PP
|
.PP
|
||||||
.nf
|
.nf
|
||||||
6 January Dianne's Birthday
|
REM 6 January Dianne's Birthday
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
although this is not recommended.
|
will issue the warning "Missing REM type; assuming MSG"
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
The \fBMSF\fR keyword is almost the same as the \fBMSG\fR keyword,
|
The \fBMSF\fR keyword is almost the same as the \fBMSG\fR keyword,
|
||||||
except that the reminder is formatted to fit into a paragraph-like
|
except that the reminder is formatted to fit into a paragraph-like
|
||||||
@@ -1019,26 +1032,35 @@ overrides that.
|
|||||||
.B THE ONCE KEYWORD
|
.B THE ONCE KEYWORD
|
||||||
.PP
|
.PP
|
||||||
Sometimes, it is necessary to ensure that reminders are run only once
|
Sometimes, it is necessary to ensure that reminders are run only once
|
||||||
on a given day. For example, if you have a reminder that makes a backup
|
on a given day. For example, compare the following two reminders:
|
||||||
of your files every Friday:
|
|
||||||
.PP
|
.PP
|
||||||
.nf
|
.nf
|
||||||
REM Fri RUN do_backup
|
REM Fri RUN do_backup
|
||||||
|
REM Fri ONCE RUN do_backup
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
(Here, \fIdo_backup\fR is assumed to be a program or shell script that
|
The first will be run every time you invoke \fBRemind\fR on a Friday,
|
||||||
does the work.) If you run \fBRemind\fR from your .login script, for
|
whereas the second will be run only the first time you invoke
|
||||||
example, and log in several times per day, the \fIdo_backup\fR program
|
\fBRemind\fR on a given Friday.
|
||||||
will be run each time you log in. If, however, you use the \fBONCE\fR
|
.PP
|
||||||
keyword in the reminder, the \fBRemind\fR checks the last access date of
|
If you run \fBRemind\fR from your .login script, for example, and log
|
||||||
the reminder script. If it is the same as the current date, \fBRemind\fR
|
in several times per day, the \fIdo_backup\fR program in the first
|
||||||
assumes that it has already been run, and will not issue reminders containing
|
reminder will be run each time you log in. If, however, you use the
|
||||||
the \fBONCE\fR keyword.
|
\fBONCE\fR keyword in the reminder, the \fBRemind\fR checks the last
|
||||||
|
access date of the reminder script. If it is the same as the current
|
||||||
|
date, \fBRemind\fR assumes that it has already been run, and will not
|
||||||
|
issue reminders containing the \fBONCE\fR keyword.
|
||||||
.PP
|
.PP
|
||||||
Note that if you view or edit your reminder script, the last access date
|
Note that if you view or edit your reminder script, the last access date
|
||||||
will be updated, and the \fBONCE\fR keyword will not operate properly.
|
will be updated, and the \fBONCE\fR keyword will not operate properly.
|
||||||
|
You can fix this by setting a timestamp file for \fBRemind\fR to track
|
||||||
|
the last-run date; see the documentation of \fB$OnceFile\fR in the
|
||||||
|
\fBSYSTEM VARIABLES\fR section. If you use standard input as your
|
||||||
|
\fBRemind\fR input file, then you \fImust\fR use \fB$OnceFile\fR for the
|
||||||
|
\fBONCE\fR keyword to work properly.
|
||||||
|
.PP
|
||||||
If you start \fBRemind\fR with the \fB\-o\fR option, then the \fBONCE\fR
|
If you start \fBRemind\fR with the \fB\-o\fR option, then the \fBONCE\fR
|
||||||
keyword will be ignored.
|
keyword will be ignored and any \fB$OnceFile\fR will be ignored.
|
||||||
.PP
|
.PP
|
||||||
.B LOCALLY OMITTING WEEKDAYS
|
.B LOCALLY OMITTING WEEKDAYS
|
||||||
.PP
|
.PP
|
||||||
@@ -1548,7 +1570,35 @@ is replaced with "\fIyy\fR", the last two digits of the year.
|
|||||||
.TP
|
.TP
|
||||||
.B %_
|
.B %_
|
||||||
(percent-underscore) is replaced with a newline. You can use this to
|
(percent-underscore) is replaced with a newline. You can use this to
|
||||||
achieve multi-line reminders.
|
achieve multi-line reminders. Note that calendar back-ends vary in
|
||||||
|
how they handle multi-line reminders:
|
||||||
|
.RS
|
||||||
|
.TP
|
||||||
|
.B o
|
||||||
|
Running \fBremind -c\fR preserves newlines in the terminal calendar output.
|
||||||
|
.TP
|
||||||
|
.B o
|
||||||
|
\fBrem2pdf\fR preserves newlines if \fBremind\fR is invoked with the \fB\-pp\fR
|
||||||
|
or \fB\-ppp\fR option.
|
||||||
|
.TP
|
||||||
|
.B o
|
||||||
|
\fBrem2html\fR preserves newlines if \fBremind\fR is invoked with the
|
||||||
|
\fB\-pp\fR option.
|
||||||
|
.TP
|
||||||
|
.B o
|
||||||
|
\fBtkremind\fR preserves newlines.\fR
|
||||||
|
.TP
|
||||||
|
.B o
|
||||||
|
\fBrem2ps\fR converts newlines to spaces. But \fBrem2ps\fR is deprecated;
|
||||||
|
use \fBrem2pdf\fR instead.
|
||||||
|
.TP
|
||||||
|
.B o
|
||||||
|
The "simple calendar" formats (ie, \fBremind\fR's \fB\-s\fR, \fB\-n\fR and
|
||||||
|
\fB\-p\fR options) convert newlines to spaces.
|
||||||
|
.PP
|
||||||
|
All calendar back-ends collapse multiple spaces to a single space and
|
||||||
|
multiple newlines to a single newline.
|
||||||
|
.RE
|
||||||
.TP
|
.TP
|
||||||
.B %1
|
.B %1
|
||||||
is replaced with "now", "\fIm\fR minutes from now", "\fIm\fR minutes ago",
|
is replaced with "now", "\fIm\fR minutes from now", "\fIm\fR minutes ago",
|
||||||
@@ -1682,7 +1732,7 @@ or:
|
|||||||
The \fBOMIT\fR command is used to "globally" omit certain days
|
The \fBOMIT\fR command is used to "globally" omit certain days
|
||||||
(usually holidays). These globally-omitted days are skipped by the
|
(usually holidays). These globally-omitted days are skipped by the
|
||||||
"\-" and "+" forms of \fIback\fR and \fIdelta\fR, but not by the
|
"\-" and "+" forms of \fIback\fR and \fIdelta\fR, but not by the
|
||||||
"\-\-" and "\+\+" forms. Some examples:
|
"\-\-" and "++" forms. Some examples:
|
||||||
.PP
|
.PP
|
||||||
.nf
|
.nf
|
||||||
OMIT Saturday Sunday
|
OMIT Saturday Sunday
|
||||||
@@ -1978,6 +2028,10 @@ your INCLUDECMD uses expression-pasting that results in differences depending
|
|||||||
on the value of \fBtoday()\fR, then each \fIunique\fR version of the
|
on the value of \fBtoday()\fR, then each \fIunique\fR version of the
|
||||||
command will be executed once.
|
command will be executed once.
|
||||||
.PP
|
.PP
|
||||||
|
If a given reminder file contains more than one identical
|
||||||
|
\fBINCLUDECMD\fR, only the first one will actually be executed. All
|
||||||
|
subsequent identical ones will use the cached output from the first one.
|
||||||
|
.PP
|
||||||
|
|
||||||
.SH THE BANNER COMMAND
|
.SH THE BANNER COMMAND
|
||||||
.PP
|
.PP
|
||||||
@@ -2161,11 +2215,11 @@ and time separator characters for \fBDATE\fR and \fBTIME\fR constants apply
|
|||||||
also to \fBDATETIME\fR constants.
|
also to \fBDATETIME\fR constants.
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
.B ZERO VALUES
|
.B ZERO VALUES AND TRUE/FALSE
|
||||||
.PP
|
.PP
|
||||||
The non-string types all have an associated \fIzero\fR value, which is
|
All types have an associated \fIzero value\fR, which is treated as
|
||||||
treated as "false" by the IF command and the logical operators. The
|
\fIfalse\fR by the IF command, the IIF function, and the logical
|
||||||
zero values are:
|
operators. The zero values are:
|
||||||
.PP
|
.PP
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
@@ -2176,10 +2230,11 @@ zero values are:
|
|||||||
\fBTIME\fR - 00:00
|
\fBTIME\fR - 00:00
|
||||||
.PP
|
.PP
|
||||||
\fBDATETIME\fR - '1990-01-01@00:00'
|
\fBDATETIME\fR - '1990-01-01@00:00'
|
||||||
|
.PP
|
||||||
|
\fBSTRING\fR - "" (the empty string)
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
Additionally, for the purpose of the IF command (but \fInot\fR the
|
Any value other than the \fIzero value\fR is treated as \fItrue\fR.
|
||||||
logical operators) the empty string "" is considered a false value.
|
|
||||||
.PP
|
.PP
|
||||||
.B OPERATORS
|
.B OPERATORS
|
||||||
.PP
|
.PP
|
||||||
@@ -2202,8 +2257,8 @@ C operators.
|
|||||||
.PP
|
.PP
|
||||||
.TP
|
.TP
|
||||||
.B !
|
.B !
|
||||||
Logical negation. Can be applied to an \fBINT\fR type. If the operand
|
Logical negation. Can be applied to any type. If the operand
|
||||||
is non-zero, returns zero. Otherwise, returns 1.
|
is non-zero, returns 0. Otherwise, returns 1.
|
||||||
.TP
|
.TP
|
||||||
.B \-
|
.B \-
|
||||||
Unary minus. Can be applied to an \fBINT\fR. Returns the negative
|
Unary minus. Can be applied to an \fBINT\fR. Returns the negative
|
||||||
@@ -2307,15 +2362,16 @@ If the operands are not of the same type, == returns 0 and != returns
|
|||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
.B &&
|
.B &&
|
||||||
This is the logical AND operator. Neither of its operands can be
|
This is the logical AND operator. Returns the second operand if both
|
||||||
\fBSTRING\fR type. Returns the second operand if both operands are
|
operands are non-zero. Otherwise, returns whichever operand is zero.
|
||||||
non-zero. Otherwise, returns whichever operand is zero.
|
Operands can be any type and "zero" is interpreted as appropriate for
|
||||||
|
each operand's type.
|
||||||
.TP
|
.TP
|
||||||
.B ||
|
.B ||
|
||||||
This is the logical OR operator. Neither of its operands can be
|
This is the logical OR operator. It returns the first operand that is
|
||||||
\fBSTRING\fR type. It returns the first operand that is non-zero; if
|
non-zero; if both operands are zero, then returns the second operand.
|
||||||
both operands are zero, then returns the second operand.
|
Operands can be any type and "zero" is interpreted as appropriate for
|
||||||
|
each operand's type.
|
||||||
.PP
|
.PP
|
||||||
.B NOTES
|
.B NOTES
|
||||||
.PP
|
.PP
|
||||||
@@ -2532,9 +2588,9 @@ truncated - the width limit will be ignored.
|
|||||||
If non-zero, then the \fB\-h\fR option was supplied on the command line.
|
If non-zero, then the \fB\-h\fR option was supplied on the command line.
|
||||||
.TP
|
.TP
|
||||||
.B $IgnoreOnce (read-only)
|
.B $IgnoreOnce (read-only)
|
||||||
If non-zero, then the \fB\-o\fR option was supplied on the command line,
|
If non-zero, then the \fB\-o\fR option was supplied on the command
|
||||||
or a date different from today's true date was supplied. If non-zero,
|
line, or implicitly enabled for some other reason. In this case,
|
||||||
then \fBONCE\fR directives will be ignored.
|
\fBONCE\fR directives will be ignored.
|
||||||
.TP
|
.TP
|
||||||
.B $InfDelta (read-only)
|
.B $InfDelta (read-only)
|
||||||
If non-zero, then the \fB\-t\fR option was supplied on the command line,
|
If non-zero, then the \fB\-t\fR option was supplied on the command line,
|
||||||
@@ -2691,6 +2747,20 @@ by \fBREM\fR commands; triggers in \fBIFTRIG\fR commands do
|
|||||||
not affect it.
|
not affect it.
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
|
.B $OnceFile (STRING type)
|
||||||
|
If you set this variable to a non-empty string, then rather than using
|
||||||
|
the file access date to determine whether or not to run a ONCE-type
|
||||||
|
reminder, \fBRemind\fR will maintain a timestamp in the file \fB$OnceFile\fR.
|
||||||
|
This is more reliable than using the access date of the reminder file.
|
||||||
|
.RS
|
||||||
|
.PP
|
||||||
|
If \fB$OnceFile\fR does not exist, then it will be created the first time
|
||||||
|
a \fBONCE\fR keyword is processed. The file must be writable by the
|
||||||
|
current user. If you try to set \fB$OnceFile\fR \fIafter\fR a \fBONCE\fR
|
||||||
|
reminder has already been processed, \fBRemind\fR will issue a warning
|
||||||
|
and ignore the attempt to set \fB$OnceFile\fR.
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
.B $ParseUntriggered
|
.B $ParseUntriggered
|
||||||
A flag indicating whether or not \fBRemind\fR should fully parse \fBREM\fR
|
A flag indicating whether or not \fBRemind\fR should fully parse \fBREM\fR
|
||||||
statements that are not triggered. 0 means to skip parsing them and 1
|
statements that are not triggered. 0 means to skip parsing them and 1
|
||||||
@@ -2869,18 +2939,25 @@ is supplied, only the date component is used.
|
|||||||
Returns the time of "astronomical twilight" on the specified \fIdate\fR. If
|
Returns the time of "astronomical twilight" on the specified \fIdate\fR. If
|
||||||
\fIdate\fR is omitted, defaults to \fBtoday()\fR.
|
\fIdate\fR is omitted, defaults to \fBtoday()\fR.
|
||||||
.TP
|
.TP
|
||||||
.B ampm(tq_time [,s_am [,s_pm]])
|
.B ampm(tq_time [,s_am [,s_pm [,i_lz]]])
|
||||||
Returns a \fBSTRING\fR that is the result of converting \fItime\fR
|
Returns a \fBSTRING\fR that is the result of converting \fItime\fR
|
||||||
(which is either a \fBTIME\fR or a \fBDATETIME\fR object) to "AM/PM"
|
(which is either a \fBTIME\fR or a \fBDATETIME\fR object) to "AM/PM"
|
||||||
format. The optional arguments \fIam\fR and \fIpm\fR are the strings
|
format. The optional arguments \fIam\fR and \fIpm\fR are the strings
|
||||||
to append in the AM and PM case, respectively; they default to "AM"
|
to append in the AM and PM case, respectively; they default to "AM"
|
||||||
and "PM". The function obeys the system variables $DateSep,
|
and "PM". The optional argument \fIlz\fR specifies whether or not
|
||||||
$TimeSep and $DateTimeSep when formatting its output. For example:
|
the hour should be padded to two digits with a leading zero. If \fIlz\fR is
|
||||||
|
zero, then a leading 0 is not added; otherwise, the hour is padded out to
|
||||||
|
two digits with a leading zero. If not supplied, \fIlz\fR defaults to zero.
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
|
The function obeys the system variables $DateSep, $TimeSep and
|
||||||
|
$DateTimeSep when formatting its output. Here are some examples of
|
||||||
|
its output:
|
||||||
|
.PP
|
||||||
.nf
|
.nf
|
||||||
ampm(0:22) returns "12:22AM"
|
ampm(0:22) returns "12:22AM"
|
||||||
ampm(17:45, "am", "pm") returns "5:45pm"
|
ampm(17:45, "am", "pm") returns "5:45pm"
|
||||||
|
ampm(17:45, "am", "pm", 1) returns "05:45pm"
|
||||||
ampm('2020-03-14@21:34') returns "2020-03-14@9:34PM"
|
ampm('2020-03-14@21:34') returns "2020-03-14@9:34PM"
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
@@ -3240,14 +3317,14 @@ out. The stripping algorithm is fairly naive; the function starts
|
|||||||
stripping characters when it encounters a "<" and it stops stripping
|
stripping characters when it encounters a "<" and it stops stripping
|
||||||
when it encounters a ">".
|
when it encounters a ">".
|
||||||
.TP
|
.TP
|
||||||
.B iif(si_test1, x_arg1, [si_test2, x_arg2,...], x_default)
|
.B iif(x_test1, x_arg1, [x_test2, x_arg2,...], x_default)
|
||||||
If \fItest1\fR is not zero or the null string, returns \fIarg1\fR.
|
If \fItest1\fR is true, returns \fIarg1\fR. Otherwise, if \fItest2\fR
|
||||||
Otherwise, if \fItest2\fR is not zero or the null string, returns
|
is true, returns \fIarg2\fR, and so on. If all of the \fItest\fR
|
||||||
\fIarg2\fR, and so on. If all of the \fItest\fR arguments are false,
|
arguments are false, returns \fIdefault\fR. Note that all arguments
|
||||||
returns \fIdefault\fR. Note that all arguments are \fIalways\fR evaluated.
|
are \fIalways\fR evaluated. This function accepts an odd number of
|
||||||
This function accepts an odd number of arguments - note that prior to version
|
arguments - note that prior to version 03.00.05 of \fBRemind\fR, it
|
||||||
03.00.05 of \fBRemind\fR, it accepted 3 arguments only. The 3-argument
|
accepted 3 arguments only. The 3-argument version of \fBiif()\fR is
|
||||||
version of \fBiif()\fR is compatible with previous versions of \fBRemind\fR.
|
compatible with previous versions of \fBRemind\fR.
|
||||||
.TP
|
.TP
|
||||||
.B index(s_search, s_target [,i_start)
|
.B index(s_search, s_target [,i_start)
|
||||||
Returns an \fBINT\fR that is the location of \fItarget\fR in the
|
Returns an \fBINT\fR that is the location of \fItarget\fR in the
|
||||||
@@ -4462,11 +4539,10 @@ The above sequence sets y to 1, which is the global value of x.
|
|||||||
.TP
|
.TP
|
||||||
o
|
o
|
||||||
User-defined functions may call other functions, including other user-defined
|
User-defined functions may call other functions, including other user-defined
|
||||||
functions. However, recursive calls are not allowed.
|
functions. Recursive calls are allowed, but they must terminate (for
|
||||||
.TP
|
example, by using a short-circuit operator or function that breaks the
|
||||||
o
|
recursion) or an error will result after a certain maximum number of
|
||||||
User-defined functions are not syntax-checked when they are defined; parsing
|
recursive calls (by default, 1000.)
|
||||||
occurs only when they are called.
|
|
||||||
.TP
|
.TP
|
||||||
o
|
o
|
||||||
If a user-defined function has the same name as a built-in function,
|
If a user-defined function has the same name as a built-in function,
|
||||||
@@ -4488,6 +4564,11 @@ or thirdfunc will exist. \fBRemind\fR does not issue an error if you
|
|||||||
try to \fBFUNSET\fR a nonexistent user-defined function; it simply
|
try to \fBFUNSET\fR a nonexistent user-defined function; it simply
|
||||||
does nothing in that case.
|
does nothing in that case.
|
||||||
.PP
|
.PP
|
||||||
|
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.
|
||||||
|
.PP
|
||||||
.SH PRECISE SCHEDULING
|
.SH PRECISE SCHEDULING
|
||||||
.PP
|
.PP
|
||||||
The \fBWARN\fR keyword allows precise control over advance warning in
|
The \fBWARN\fR keyword allows precise control over advance warning in
|
||||||
@@ -4621,8 +4702,11 @@ the error message "Can't compute trigger" is issued. Otherwise,
|
|||||||
\fBtrigvalid()\fR is set to 1.
|
\fBtrigvalid()\fR is set to 1.
|
||||||
.PP
|
.PP
|
||||||
This is really useful only if \fIexpr\fR involves a call to the
|
This is really useful only if \fIexpr\fR involves a call to the
|
||||||
\fBtrigdate()\fR or related functions; otherwise, \fIexpr\fR will not change as
|
\fBtrigdate()\fR or related functions or system variables; otherwise,
|
||||||
\fBRemind\fR iterates.
|
\fIexpr\fR will not change as \fBRemind\fR iterates. In fact, if
|
||||||
|
\fIexpr\fR is not a constant and does not call \fBtrigdate()\fR or
|
||||||
|
related functions or system variables, then \fBRemind\fR will issue a
|
||||||
|
warning.
|
||||||
.PP
|
.PP
|
||||||
An example of the usefulness of \fBSATISFY\fR: Suppose you wish to
|
An example of the usefulness of \fBSATISFY\fR: Suppose you wish to
|
||||||
be warned of every Friday the 13th. Your first attempt may be:
|
be warned of every Friday the 13th. Your first attempt may be:
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ Useful strings might be "emacs +%d %s" or "gvim +%d %s"
|
|||||||
.TP
|
.TP
|
||||||
.B Extra Argument for Remind
|
.B Extra Argument for Remind
|
||||||
This specifies any extra arguments that should be passed to Remind
|
This specifies any extra arguments that should be passed to Remind
|
||||||
when \BTkRemind\fR invokes \fBremind\fR. Unless you know what
|
when \fBTkRemind\fR invokes \fBremind\fR. Unless you know what
|
||||||
you are doing, leave this blank.
|
you are doing, leave this blank.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -374,19 +374,37 @@ sub parse_input
|
|||||||
($1 % 256), ($1 % 256), ($1 % 256));
|
($1 % 256), ($1 % 256), ($1 % 256));
|
||||||
}
|
}
|
||||||
} elsif ($special eq 'COLOR' || $special eq 'COLOUR') {
|
} elsif ($special eq 'COLOR' || $special eq 'COLOUR') {
|
||||||
if ($body =~ /(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/) {
|
if ($body =~ /(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/s) {
|
||||||
my($r, $g, $b, $text) = ($1, $2, $3, $4);
|
my($r, $g, $b, $text) = ($1, $2, $3, $4);
|
||||||
my $color = sprintf("style=\"color: #%02X%02X%02X;\"",
|
my $color = sprintf("style=\"color: #%02X%02X%02X;\"",
|
||||||
$r % 256, $g % 256, $b % 256);
|
$r % 256, $g % 256, $b % 256);
|
||||||
push(@{$days->[$d]}, "<p$class $color>" . escape_html($text) . '</p>');
|
push(@{$days->[$d]}, "<p$class $color>" . fix_whitespace(escape_html($text)) . '</p>');
|
||||||
}
|
}
|
||||||
} elsif ($special eq '*') {
|
} elsif ($special eq '*') {
|
||||||
push(@{$days->[$d]}, "<p$class>" . escape_html($body) . '</p>');
|
push(@{$days->[$d]}, "<p$class>" . fix_whitespace(escape_html($body)) . '</p>');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $found_data;
|
return $found_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub fix_whitespace
|
||||||
|
{
|
||||||
|
my ($text) = @_;
|
||||||
|
|
||||||
|
# Collapse multiple spaces/tabs to a single space
|
||||||
|
$text =~ s/[ \t]+/ /gs;
|
||||||
|
|
||||||
|
# Remove whitespace before/after newlines
|
||||||
|
$text =~ s/\s+\n/\n/gs;
|
||||||
|
$text =~ s/\n\s+/\n/gs;
|
||||||
|
# Collapse multiple newlines to a single newline
|
||||||
|
$text =~ s/\n+/\n/gs;
|
||||||
|
|
||||||
|
# Convert newlines to <br />
|
||||||
|
$text =~ s|\n|<br />|g;
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
|
||||||
sub small_calendar
|
sub small_calendar
|
||||||
{
|
{
|
||||||
my($month, $monlen, $url, $first_col) = @_;
|
my($month, $monlen, $url, $first_col) = @_;
|
||||||
|
|||||||
@@ -60,7 +60,9 @@ my $settings = {
|
|||||||
margin_bottom => 36,
|
margin_bottom => 36,
|
||||||
margin_left => 36,
|
margin_left => 36,
|
||||||
margin_right => 36,
|
margin_right => 36,
|
||||||
|
svg => 0,
|
||||||
|
ps => 0,
|
||||||
|
eps => 0,
|
||||||
verbose => 0,
|
verbose => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -80,6 +82,9 @@ Options:
|
|||||||
|
|
||||||
--landscape, -l Print in landscape orientation
|
--landscape, -l Print in landscape orientation
|
||||||
--small-calendars=N Choose location for small calendars
|
--small-calendars=N Choose location for small calendars
|
||||||
|
--svg Output SVG instead of PDF
|
||||||
|
--ps Output PostScript instead of PDF
|
||||||
|
--eps Output encapsulated PostScript instead of PDF
|
||||||
-cN Synonym for --small-calendars=N
|
-cN Synonym for --small-calendars=N
|
||||||
--left-numbers, -x Print day numbers on the left
|
--left-numbers, -x Print day numbers on the left
|
||||||
--fill-page, -e Fill the entire page
|
--fill-page, -e Fill the entire page
|
||||||
@@ -112,6 +117,9 @@ Getopt::Long::Configure('bundling_values');
|
|||||||
my $ret = GetOptions('landscape|l' => \$settings->{landscape},
|
my $ret = GetOptions('landscape|l' => \$settings->{landscape},
|
||||||
'small-calendars|c=i' => \$settings->{small_calendars},
|
'small-calendars|c=i' => \$settings->{small_calendars},
|
||||||
'left-numbers|x' => \$settings->{numbers_on_left},
|
'left-numbers|x' => \$settings->{numbers_on_left},
|
||||||
|
'svg' => \$settings->{svg},
|
||||||
|
'ps' => \$settings->{ps},
|
||||||
|
'eps' => \$settings->{eps},
|
||||||
'fill-page|e' => \$settings->{fill_entire_page},
|
'fill-page|e' => \$settings->{fill_entire_page},
|
||||||
'media|m=s' => \$settings->{media},
|
'media|m=s' => \$settings->{media},
|
||||||
'width|w=i' => \$settings->{width},
|
'width|w=i' => \$settings->{width},
|
||||||
@@ -176,6 +184,17 @@ if ($settings->{landscape}) {
|
|||||||
$settings->{height} = $tmp;
|
$settings->{height} = $tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($settings->{svg} && $settings->{ps} ||
|
||||||
|
$settings->{svg} && $settings->{eps} ||
|
||||||
|
$settings->{eps} && $settings->{ps}) {
|
||||||
|
print STDERR "Only one of --eps, --ps or --svg may be used.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($settings->{eps}) {
|
||||||
|
$settings->{ps} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
# Don't read from a terminal
|
# Don't read from a terminal
|
||||||
if (-t STDIN) { ## no critic
|
if (-t STDIN) { ## no critic
|
||||||
print STDERR "I can't read data from a terminal. Please run like this:\n";
|
print STDERR "I can't read data from a terminal. Please run like this:\n";
|
||||||
@@ -187,8 +206,25 @@ my $done_one = 0;
|
|||||||
|
|
||||||
my $errored_out = 0;
|
my $errored_out = 0;
|
||||||
|
|
||||||
my $surface = Cairo::PdfSurface->create_for_stream(sub { print $_[1] unless $errored_out; }, undef,
|
my $surface;
|
||||||
$settings->{width}, $settings->{height});
|
if ($settings->{svg}) {
|
||||||
|
$surface = Cairo::SvgSurface->create_for_stream(sub { print $_[1] unless $errored_out; }, undef,
|
||||||
|
$settings->{width}, $settings->{height});
|
||||||
|
} elsif ($settings->{ps}) {
|
||||||
|
if ($settings->{landscape}) {
|
||||||
|
$surface = Cairo::PsSurface->create_for_stream(sub { print $_[1] unless $errored_out; }, undef,
|
||||||
|
$settings->{height}, $settings->{width});
|
||||||
|
} else {
|
||||||
|
$surface = Cairo::PsSurface->create_for_stream(sub { print $_[1] unless $errored_out; }, undef,
|
||||||
|
$settings->{width}, $settings->{height});
|
||||||
|
}
|
||||||
|
if ($settings->{eps}) {
|
||||||
|
$surface->set_eps(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$surface = Cairo::PdfSurface->create_for_stream(sub { print $_[1] unless $errored_out; }, undef,
|
||||||
|
$settings->{width}, $settings->{height});
|
||||||
|
}
|
||||||
|
|
||||||
# set_metadata not available in older versions of Cairo
|
# set_metadata not available in older versions of Cairo
|
||||||
eval { $surface->set_metadata('title', 'Calendar'); };
|
eval { $surface->set_metadata('title', 'Calendar'); };
|
||||||
@@ -196,10 +232,26 @@ eval { $surface->set_metadata('author', 'Remind (https://dianne.skoll.ca/project
|
|||||||
eval { $surface->set_metadata('creator', 'rem2pdf (https://dianne.skoll.ca/projects/remind/)'); };
|
eval { $surface->set_metadata('creator', 'rem2pdf (https://dianne.skoll.ca/projects/remind/)'); };
|
||||||
eval { $surface->set_metadata('subject', 'Calendar'); };
|
eval { $surface->set_metadata('subject', 'Calendar'); };
|
||||||
|
|
||||||
|
if ($settings->{ps}) {
|
||||||
|
$surface->dsc_comment('%%Title: Calendar');
|
||||||
|
$surface->dsc_comment('%%Producer: rem2pdf (https://dianne.skoll.ca/projects/remind/)');
|
||||||
|
$surface->dsc_comment('%%PageOrientation: ' . (($settings->{landscape}) ? 'Landscape' : 'Portrait'));
|
||||||
|
$surface->dsc_begin_setup();
|
||||||
|
}
|
||||||
|
|
||||||
my $cr = Cairo::Context->create($surface);
|
my $cr = Cairo::Context->create($surface);
|
||||||
$cr->set_line_width($settings->{line_thickness});
|
$cr->set_line_width($settings->{line_thickness});
|
||||||
|
if ($settings->{ps} && $settings->{landscape}) {
|
||||||
|
$cr->translate(0, $settings->{width});
|
||||||
|
$cr->rotate(-1.5707963267949); # Rotate -90 degrees
|
||||||
|
}
|
||||||
|
|
||||||
|
my $warned = 0;
|
||||||
while(1) {
|
while(1) {
|
||||||
|
if ($settings->{ps}) {
|
||||||
|
$surface->dsc_begin_page_setup();
|
||||||
|
$surface->dsc_comment('%%PageOrientation: ' . (($settings->{landscape}) ? 'Landscape' : 'Portrait'));
|
||||||
|
}
|
||||||
my ($obj, $err) = Remind::PDF->create_from_stream(*STDIN,
|
my ($obj, $err) = Remind::PDF->create_from_stream(*STDIN,
|
||||||
{color => 1,
|
{color => 1,
|
||||||
shade => 1,
|
shade => 1,
|
||||||
@@ -215,8 +267,15 @@ while(1) {
|
|||||||
}
|
}
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
$done_one = 1;
|
if (($settings->{eps} || $settings->{svg}) && $done_one) {
|
||||||
|
if (!$warned) {
|
||||||
|
print STDERR "WARNING: --eps and --svg can only output one page; ignoring subsequent\nmonths in a multi-month calendar.\n";
|
||||||
|
$warned = 1;
|
||||||
|
}
|
||||||
|
next;
|
||||||
|
}
|
||||||
$obj->render($cr, $settings);
|
$obj->render($cr, $settings);
|
||||||
|
$done_one = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
$surface->finish();
|
$surface->finish();
|
||||||
@@ -273,17 +332,22 @@ __END__
|
|||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
rem2pdf - draw a PDF calendar from Remind output
|
rem2pdf - draw a PDF, SVG or PostScript calendar from Remind output
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
remind -pp [options] file | rem2pdf [options] > output.pdf
|
remind -pp [options] file | rem2pdf [options] > output.pdf
|
||||||
|
remind -pp [options] file | rem2pdf --svg [options] > output.svg
|
||||||
|
remind -pp [options] file | rem2pdf --ps [options] > output.ps
|
||||||
|
remind -pp [options] file | rem2pdf --eps [options] > output.eps
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
B<rem2pdf> reads the standard input, which should be the results of
|
B<rem2pdf> reads the standard input, which should be the results of
|
||||||
running B<remind> with the B<-p>, B<-pp> or B<-ppp> options. It emits
|
running B<remind> with the B<-p>, B<-pp> or B<-ppp> options. It emits
|
||||||
PDF code that draws a calendar to standard output.
|
PDF, SVG or PostScript code that draws a calendar to standard output. (The
|
||||||
|
addition of support for SVG and PostScript means that rem2pdf is increasingly
|
||||||
|
misnamed...)
|
||||||
|
|
||||||
B<rem2pdf> uses the Pango text formatting library (L<https://pango.gnome.org/>)
|
B<rem2pdf> uses the Pango text formatting library (L<https://pango.gnome.org/>)
|
||||||
and the Cairo graphics library (L<https://www.cairographics.org/>) to produce
|
and the Cairo graphics library (L<https://www.cairographics.org/>) to produce
|
||||||
@@ -298,6 +362,22 @@ output at all.
|
|||||||
|
|
||||||
=over
|
=over
|
||||||
|
|
||||||
|
=item --ps
|
||||||
|
|
||||||
|
Output PostScript instead of PDF.
|
||||||
|
|
||||||
|
=item --eps
|
||||||
|
|
||||||
|
Output Encapsulated PostScript instead of PDF. In this case, you
|
||||||
|
should feed C<rem2pdf> only one month's worth of calendar data,
|
||||||
|
because it cannot create a multi-page encapsulated PostScript file.
|
||||||
|
|
||||||
|
=item --svg
|
||||||
|
|
||||||
|
Output SVG instead of PDF. In this case, you should feed C<rem2pdf>
|
||||||
|
only one month's worth of calendar data, because it cannot create
|
||||||
|
a multi-page SVG file.
|
||||||
|
|
||||||
=item --landscape, -l
|
=item --landscape, -l
|
||||||
|
|
||||||
Print the calendar in landscape orientation. Essentially, this swaps
|
Print the calendar in landscape orientation. Essentially, this swaps
|
||||||
|
|||||||
@@ -1008,7 +1008,17 @@ as were read from the C<remind -ppp> stream
|
|||||||
sub render
|
sub render
|
||||||
{
|
{
|
||||||
my ($self, $cr, $settings) = @_;
|
my ($self, $cr, $settings) = @_;
|
||||||
|
my $done = 0;
|
||||||
|
my $warned = 0;
|
||||||
foreach my $e (@{$self->{entries}}) {
|
foreach my $e (@{$self->{entries}}) {
|
||||||
|
if ($settings->{svg} && $done) {
|
||||||
|
if (!$warned) {
|
||||||
|
print STDERR "WARNING: --svg can only output one page; ignoring subsequent\nmonths in a multi-month calendar.\n";
|
||||||
|
$warned = 1;
|
||||||
|
}
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
$done = 1;
|
||||||
$e->render($cr, $settings);
|
$e->render($cr, $settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,6 +85,18 @@ sub render
|
|||||||
} else {
|
} else {
|
||||||
$body = $self->{body};
|
$body = $self->{body};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Clean up the body:
|
||||||
|
|
||||||
|
# Collapse multiple spaces/tabs to a single space
|
||||||
|
$body =~ s/[ \t]+/ /gs;
|
||||||
|
|
||||||
|
# Remove whitespace before/after newlines
|
||||||
|
$body =~ s/\s+\n/\n/gs;
|
||||||
|
$body =~ s/\n\s+/\n/gs;
|
||||||
|
# Collapse multiple newlines to a single newline
|
||||||
|
$body =~ s/\n+/\n/gs;
|
||||||
|
|
||||||
$layout->set_text(Encode::decode('UTF-8', $body));
|
$layout->set_text(Encode::decode('UTF-8', $body));
|
||||||
my $desc = Pango::FontDescription->from_string($settings->{entry_font} . ' ' . $settings->{entry_size} . 'px');
|
my $desc = Pango::FontDescription->from_string($settings->{entry_font} . ' ' . $settings->{entry_size} . 'px');
|
||||||
$layout->set_font_description($desc);
|
$layout->set_font_description($desc);
|
||||||
|
|||||||
@@ -319,7 +319,7 @@ set Option(PrintMargins) 36pt
|
|||||||
set OptDescr(PrintSmallCalendars) "(0/1) If 1, print small calendars in PostScript output"
|
set OptDescr(PrintSmallCalendars) "(0/1) If 1, print small calendars in PostScript output"
|
||||||
set Option(PrintSmallCalendars) 1
|
set Option(PrintSmallCalendars) 1
|
||||||
|
|
||||||
set OptDescr(PrintFormat) "Print format: pdf or ps"
|
set OptDescr(PrintFormat) "Print format: pdf, ps or ps1 - ps1 means PostScript using rem2pdf"
|
||||||
set Option(PrintFormat) ps
|
set Option(PrintFormat) ps
|
||||||
|
|
||||||
set WarningHeaders [list "# Lines starting with REM TAG TKTAGnnn ... were created by tkremind" "# Do not edit them by hand or results may be unpredictable."]
|
set WarningHeaders [list "# Lines starting with REM TAG TKTAGnnn ... were created by tkremind" "# Do not edit them by hand or results may be unpredictable."]
|
||||||
@@ -1217,6 +1217,13 @@ proc FillCalWindow {} {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
.cal.t$n configure -state normal
|
.cal.t$n configure -state normal
|
||||||
|
|
||||||
|
# Canonicalize spaces and newlines
|
||||||
|
set stuff [regsub -all {[ \t]+} $stuff " "]
|
||||||
|
set stuff [regsub -all {[ \t]+\n} $stuff "\n"]
|
||||||
|
set stuff [regsub -all {\n[ \t]} $stuff "\n"]
|
||||||
|
set stuff [regsub -all {\n+} $stuff "\n"]
|
||||||
|
|
||||||
if {[regexp {TKTAG([0-9]+)} $tag all tagno] && "$fntag" != "x"} {
|
if {[regexp {TKTAG([0-9]+)} $tag all tagno] && "$fntag" != "x"} {
|
||||||
.cal.t$n insert end [string trim $stuff] [list REM TAGGED "TKTAG$tagno" "date_$date" $extratags $fntag]
|
.cal.t$n insert end [string trim $stuff] [list REM TAGGED "TKTAG$tagno" "date_$date" $extratags $fntag]
|
||||||
.cal.t$n tag bind "TKTAG$tagno" <Enter> "TaggedEnter .cal.t$n"
|
.cal.t$n tag bind "TKTAG$tagno" <Enter> "TaggedEnter .cal.t$n"
|
||||||
@@ -1333,7 +1340,8 @@ proc DoPrint {} {
|
|||||||
frame .p.ff -relief sunken -bd 2
|
frame .p.ff -relief sunken -bd 2
|
||||||
label .p.format -text "Output Format:"
|
label .p.format -text "Output Format:"
|
||||||
radiobutton .p.pdf -text "PDF" -variable Option(PrintFormat) -value pdf
|
radiobutton .p.pdf -text "PDF" -variable Option(PrintFormat) -value pdf
|
||||||
radiobutton .p.ps -text "PostScript" -variable Option(PrintFormat) -value ps
|
radiobutton .p.ps -text "PostScript (using rem2ps)" -variable Option(PrintFormat) -value ps
|
||||||
|
radiobutton .p.ps1 -text "PostScript (using rem2pdf)" -variable Option(PrintFormat) -value ps1
|
||||||
}
|
}
|
||||||
|
|
||||||
label .p.size -text "Paper Size:"
|
label .p.size -text "Paper Size:"
|
||||||
@@ -1350,7 +1358,7 @@ proc DoPrint {} {
|
|||||||
radiobutton .p.portrait -text "Portrait" -variable Option(PrintOrient) -value portrait
|
radiobutton .p.portrait -text "Portrait" -variable Option(PrintOrient) -value portrait
|
||||||
|
|
||||||
checkbutton .p.fill -text "Fill page" -variable Option(PrintFill)
|
checkbutton .p.fill -text "Fill page" -variable Option(PrintFill)
|
||||||
checkbutton .p.wrap -text "Use at most 5 rows (PDF only)" -variable Option(WrapCal)
|
checkbutton .p.wrap -text "Use at most 5 rows (rem2pdf only)" -variable Option(WrapCal)
|
||||||
checkbutton .p.right -text "Day numbers at top-right" -variable Option(PrintDaysRight)
|
checkbutton .p.right -text "Day numbers at top-right" -variable Option(PrintDaysRight)
|
||||||
checkbutton .p.encoding -text "ISO 8859-1 PostScript encoding" -variable Option(PrintEncoding)
|
checkbutton .p.encoding -text "ISO 8859-1 PostScript encoding" -variable Option(PrintEncoding)
|
||||||
checkbutton .p.calendars -text "Print small calendars" -variable Option(PrintSmallCalendars)
|
checkbutton .p.calendars -text "Print small calendars" -variable Option(PrintSmallCalendars)
|
||||||
@@ -1374,7 +1382,7 @@ proc DoPrint {} {
|
|||||||
pack .p.tofile .p.filename .p.browse -in .p.f11 -side left -fill none -expand 0 -anchor w
|
pack .p.tofile .p.filename .p.browse -in .p.f11 -side left -fill none -expand 0 -anchor w
|
||||||
pack .p.tocmd .p.command -in .p.f12 -side left -fill none -expand 0 -anchor w
|
pack .p.tocmd .p.command -in .p.f12 -side left -fill none -expand 0 -anchor w
|
||||||
if { $HaveRem2PDF } {
|
if { $HaveRem2PDF } {
|
||||||
pack .p.format .p.pdf .p.ps -in .p.ff -side top -fill none -expand 0 -anchor w
|
pack .p.format .p.pdf .p.ps .p.ps1 -in .p.ff -side top -fill none -expand 0 -anchor w
|
||||||
}
|
}
|
||||||
pack .p.size .p.letter .p.a4 -in .p.f2 -side top -fill none -expand 0 -anchor w
|
pack .p.size .p.letter .p.a4 -in .p.f2 -side top -fill none -expand 0 -anchor w
|
||||||
pack .p.margin .p.24pt .p.36pt .p.48pt -in .p.f2a -side top -anchor w -fill none -expand 0
|
pack .p.margin .p.24pt .p.36pt .p.48pt -in .p.f2a -side top -anchor w -fill none -expand 0
|
||||||
@@ -1422,6 +1430,9 @@ proc DoPrint {} {
|
|||||||
if {$HaveRem2PDF && $Option(PrintFormat) == "pdf"} {
|
if {$HaveRem2PDF && $Option(PrintFormat) == "pdf"} {
|
||||||
set p [regsub @EXTRA@ $PSCmd "-itkpdf=1 $Option(ExtraRemindArgs)"]
|
set p [regsub @EXTRA@ $PSCmd "-itkpdf=1 $Option(ExtraRemindArgs)"]
|
||||||
set cmd "$p 1 [lindex $MonthNames $CurMonth] $CurYear | $Rem2PDF"
|
set cmd "$p 1 [lindex $MonthNames $CurMonth] $CurYear | $Rem2PDF"
|
||||||
|
} elseif {$HaveRem2PDF && $Option(PrintFormat) == "ps1"} {
|
||||||
|
set p [regsub @EXTRA@ $PSCmd "-itkpdf=1 $Option(ExtraRemindArgs)"]
|
||||||
|
set cmd "$p 1 [lindex $MonthNames $CurMonth] $CurYear | $Rem2PDF --ps"
|
||||||
} else {
|
} else {
|
||||||
set p [regsub @EXTRA@ $PSCmd $Option(ExtraRemindArgs)]
|
set p [regsub @EXTRA@ $PSCmd $Option(ExtraRemindArgs)]
|
||||||
set cmd "$p 1 [lindex $MonthNames $CurMonth] $CurYear | $Rem2PS"
|
set cmd "$p 1 [lindex $MonthNames $CurMonth] $CurYear | $Rem2PS"
|
||||||
@@ -1463,7 +1474,7 @@ proc DoPrint {} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if {$Option(WrapCal)} {
|
if {$Option(WrapCal)} {
|
||||||
if {$Option(PrintFormat) == "pdf"} {
|
if {$Option(PrintFormat) == "pdf" || $Option(PrintFormat) == "ps1"} {
|
||||||
append cmd " --wrap"
|
append cmd " --wrap"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -338,6 +338,7 @@ UnBackgroundize(int d)
|
|||||||
printf("%s", Decolorize());
|
printf("%s", Decolorize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef REM_USE_WCHAR
|
||||||
static void
|
static void
|
||||||
send_lrm(void)
|
send_lrm(void)
|
||||||
{
|
{
|
||||||
@@ -352,6 +353,7 @@ send_lrm(void)
|
|||||||
printf("\xE2\x80\x8E");
|
printf("\xE2\x80\x8E");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static char const *
|
static char const *
|
||||||
despace(char const *s)
|
despace(char const *s)
|
||||||
@@ -526,9 +528,9 @@ get_month_abbrev(char const *mon)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef REM_USE_WCHAR
|
||||||
static int make_wchar_versions(CalEntry *e)
|
static int make_wchar_versions(CalEntry *e)
|
||||||
{
|
{
|
||||||
#ifdef REM_USE_WCHAR
|
|
||||||
size_t len;
|
size_t len;
|
||||||
wchar_t *buf;
|
wchar_t *buf;
|
||||||
len = mbstowcs(NULL, e->text, 0);
|
len = mbstowcs(NULL, e->text, 0);
|
||||||
@@ -542,10 +544,8 @@ static int make_wchar_versions(CalEntry *e)
|
|||||||
e->wc_text = buf;
|
e->wc_text = buf;
|
||||||
e->wc_pos = buf;
|
e->wc_pos = buf;
|
||||||
return 1;
|
return 1;
|
||||||
#else
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void gon(void)
|
static void gon(void)
|
||||||
{
|
{
|
||||||
@@ -758,13 +758,11 @@ SetMoonEntry(int dse, char const *moon)
|
|||||||
if (sscanf(moon, "%d %*d %*d %27[^\x01]", &phase, msg) < 4) {
|
if (sscanf(moon, "%d %*d %*d %27[^\x01]", &phase, msg) < 4) {
|
||||||
if (sscanf(moon, "%d", &phase) != 1) {
|
if (sscanf(moon, "%d", &phase) != 1) {
|
||||||
/* Malformed MOON special; ignore */
|
/* Malformed MOON special; ignore */
|
||||||
fprintf(stderr, "Oops 1\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (phase < 0 || phase > 3) {
|
if (phase < 0 || phase > 3) {
|
||||||
/* Bad phase */
|
/* Bad phase */
|
||||||
fprintf(stderr, "Oops 2\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FromDSE(dse, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
@@ -902,13 +900,17 @@ static void DoCalendarOneWeek(int nleft)
|
|||||||
if (UseVTColors) {
|
if (UseVTColors) {
|
||||||
printf("\x1B[1m"); /* Bold */
|
printf("\x1B[1m"); /* Bold */
|
||||||
}
|
}
|
||||||
|
Backgroundize(d);
|
||||||
PrintLeft(buf, ColSpaces-1, '*');
|
PrintLeft(buf, ColSpaces-1, '*');
|
||||||
|
putchar(' ');
|
||||||
|
UnBackgroundize(d);
|
||||||
if (UseVTColors) {
|
if (UseVTColors) {
|
||||||
printf("\x1B[0m"); /* Normal */
|
printf("\x1B[0m"); /* Normal */
|
||||||
}
|
}
|
||||||
putchar(' ');
|
|
||||||
} else {
|
} else {
|
||||||
|
Backgroundize(d);
|
||||||
PrintLeft(buf, ColSpaces, ' ');
|
PrintLeft(buf, ColSpaces, ' ');
|
||||||
|
UnBackgroundize(d);
|
||||||
}
|
}
|
||||||
gon();
|
gon();
|
||||||
DRAW(tb);
|
DRAW(tb);
|
||||||
@@ -1124,13 +1126,17 @@ static int WriteCalendarRow(void)
|
|||||||
if (UseVTColors) {
|
if (UseVTColors) {
|
||||||
printf("\x1B[1m"); /* Bold */
|
printf("\x1B[1m"); /* Bold */
|
||||||
}
|
}
|
||||||
|
Backgroundize(d+i-wd);
|
||||||
PrintLeft(buf, ColSpaces-1, '*');
|
PrintLeft(buf, ColSpaces-1, '*');
|
||||||
|
putchar(' ');
|
||||||
if (UseVTColors) {
|
if (UseVTColors) {
|
||||||
printf("\x1B[0m"); /* Normal */
|
printf("\x1B[0m"); /* Normal */
|
||||||
}
|
}
|
||||||
putchar(' ');
|
UnBackgroundize(d+i-wd);
|
||||||
} else {
|
} else {
|
||||||
|
Backgroundize(d+i-wd);
|
||||||
PrintLeft(buf, ColSpaces, ' ');
|
PrintLeft(buf, ColSpaces, ' ');
|
||||||
|
UnBackgroundize(d+i-wd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gon();
|
gon();
|
||||||
@@ -1198,15 +1204,17 @@ static void PrintLeft(char const *s, int width, char pad)
|
|||||||
{
|
{
|
||||||
#ifndef REM_USE_WCHAR
|
#ifndef REM_USE_WCHAR
|
||||||
int len = strlen(s);
|
int len = strlen(s);
|
||||||
printf("%s", s);
|
int i;
|
||||||
while (len++ < width) putchar(pad);
|
for (i=0; i<len && i<width; i++) {
|
||||||
|
fputc(*(s+i), stdout);
|
||||||
|
}
|
||||||
|
while (i++ < width) putchar(pad);
|
||||||
#else
|
#else
|
||||||
size_t len = mbstowcs(NULL, s, 0);
|
size_t len = mbstowcs(NULL, s, 0);
|
||||||
int i;
|
int i;
|
||||||
wchar_t static_buf[128];
|
wchar_t static_buf[128];
|
||||||
wchar_t *buf;
|
wchar_t *buf;
|
||||||
wchar_t *ws;
|
wchar_t *ws;
|
||||||
int display_len;
|
|
||||||
|
|
||||||
if (!len) {
|
if (!len) {
|
||||||
for (i=0; i<width; i++) {
|
for (i=0; i<width; i++) {
|
||||||
@@ -1225,13 +1233,16 @@ static void PrintLeft(char const *s, int width, char pad)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(void) mbstowcs(buf, s, len+1);
|
(void) mbstowcs(buf, s, len+1);
|
||||||
display_len = wcswidth(buf, len+1);
|
|
||||||
|
|
||||||
ws = buf;
|
ws = buf;
|
||||||
for (i=0; i<width;) {
|
i=0;
|
||||||
|
while (i<width) {
|
||||||
if (*ws) {
|
if (*ws) {
|
||||||
|
if (i + wcwidth(*ws) > width) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i += wcwidth(*ws);
|
||||||
PutWideChar(*ws++, NULL);
|
PutWideChar(*ws++, NULL);
|
||||||
i+= wcwidth(*ws);
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1244,7 +1255,10 @@ static void PrintLeft(char const *s, int width, char pad)
|
|||||||
/* Possibly send lrm control sequence */
|
/* Possibly send lrm control sequence */
|
||||||
send_lrm();
|
send_lrm();
|
||||||
|
|
||||||
for (i=display_len; i<width; i++) fputc(pad, stdout);
|
while (i<width) {
|
||||||
|
fputc(pad, stdout);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
if (buf != static_buf) free(buf);
|
if (buf != static_buf) free(buf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1265,7 +1279,7 @@ static void PrintCentered(char const *s, int width, char *pad)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<d; i++) fputs(pad, stdout);
|
for (i=0; i<d; i++) fputs(pad, stdout);
|
||||||
for (i=0; i<width; i++) {
|
for (i=0; i<width-d; i++) {
|
||||||
if (*s) {
|
if (*s) {
|
||||||
if (isspace(*s)) {
|
if (isspace(*s)) {
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
@@ -1309,13 +1323,14 @@ static void PrintCentered(char const *s, int width, char *pad)
|
|||||||
if (d < 0) d = 0;
|
if (d < 0) d = 0;
|
||||||
ws = buf;
|
ws = buf;
|
||||||
for (i=0; i<d; i++) fputs(pad, stdout);
|
for (i=0; i<d; i++) fputs(pad, stdout);
|
||||||
for (i=0; i<width; i++) {
|
i=0;
|
||||||
|
while (i+d < width) {
|
||||||
if (*ws) {
|
if (*ws) {
|
||||||
PutWideChar(*ws++, NULL);
|
if (i+d + wcwidth(*ws) > width) {
|
||||||
if (wcwidth(*ws) == 0) {
|
break;
|
||||||
/* Don't count this character... it's zero-width */
|
|
||||||
i--;
|
|
||||||
}
|
}
|
||||||
|
i += wcwidth(*ws);
|
||||||
|
PutWideChar(*ws++, NULL);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1327,7 +1342,10 @@ static void PrintCentered(char const *s, int width, char *pad)
|
|||||||
/* Possibly send lrm control sequence */
|
/* Possibly send lrm control sequence */
|
||||||
send_lrm();
|
send_lrm();
|
||||||
|
|
||||||
for (i=d+display_len; i<width; i++) fputs(pad, stdout);
|
while (i+d<width) {
|
||||||
|
fputs(pad, stdout);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
if (buf != static_buf) free(buf);
|
if (buf != static_buf) free(buf);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1414,7 +1432,7 @@ static int WriteOneColLine(int col)
|
|||||||
/* Find the last space char within the column. */
|
/* Find the last space char within the column. */
|
||||||
width = 0;
|
width = 0;
|
||||||
while (width <= ColSpaces) {
|
while (width <= ColSpaces) {
|
||||||
if (!*ws) {
|
if (!*ws || *ws == '\n') {
|
||||||
wspace = ws;
|
wspace = ws;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1520,7 +1538,7 @@ static int WriteOneColLine(int col)
|
|||||||
|
|
||||||
/* Find the last space char within the column. */
|
/* Find the last space char within the column. */
|
||||||
while (s - e->pos <= ColSpaces) {
|
while (s - e->pos <= ColSpaces) {
|
||||||
if (!*s) {space = s; break;}
|
if (!*s || *s == '\n') {space = s; break;}
|
||||||
if (isspace(*s)) space = s;
|
if (isspace(*s)) space = s;
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
@@ -1683,7 +1701,10 @@ static void GenerateCalEntries(int col)
|
|||||||
/* Note: Since the parser hasn't been used yet, we don't */
|
/* Note: Since the parser hasn't been used yet, we don't */
|
||||||
/* need to destroy it here. */
|
/* need to destroy it here. */
|
||||||
|
|
||||||
default: CreateParser(CurLine, &p);
|
default:
|
||||||
|
Wprint("Unrecognized command; interpreting as REM");
|
||||||
|
WarnedAboutImplicit = 1;
|
||||||
|
CreateParser(CurLine, &p);
|
||||||
r=DoCalRem(&p, col);
|
r=DoCalRem(&p, col);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2142,7 +2163,9 @@ static int DoCalRem(ParsePtr p, int col)
|
|||||||
FreeTrig(&trig);
|
FreeTrig(&trig);
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
|
#ifdef REM_USE_WCHAR
|
||||||
make_wchar_versions(e);
|
make_wchar_versions(e);
|
||||||
|
#endif
|
||||||
DBufInit(&(e->tags));
|
DBufInit(&(e->tags));
|
||||||
DBufPuts(&(e->tags), DBufValue(&(trig.tags)));
|
DBufPuts(&(e->tags), DBufValue(&(trig.tags)));
|
||||||
if (SynthesizeTags) {
|
if (SynthesizeTags) {
|
||||||
|
|||||||
18
src/custom.h
18
src/custom.h
@@ -20,7 +20,7 @@
|
|||||||
/* western hemisphere. */
|
/* western hemisphere. */
|
||||||
/* */
|
/* */
|
||||||
/* The default values are initially set to the city hall in Ottawa, */
|
/* The default values are initially set to the city hall in Ottawa, */
|
||||||
/* Ontario, Canada. */
|
/* Ontario, Canada. */
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
#define DEFAULT_LATITUDE 45.420556
|
#define DEFAULT_LATITUDE 45.420556
|
||||||
#define DEFAULT_LONGITUDE -75.689722
|
#define DEFAULT_LONGITUDE -75.689722
|
||||||
@@ -68,12 +68,6 @@
|
|||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
/* WANT_SHELL_ESCAPING: Define this if you want special shell */
|
|
||||||
/* characters to be escaped with a backslash for the -k option. */
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
#define WANT_SHELL_ESCAPING 1
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
/* BASE: The base year for date calculation. NOTE! January 1 of the */
|
/* BASE: The base year for date calculation. NOTE! January 1 of the */
|
||||||
/* base year MUST be a Monday, else Remind will not work! */
|
/* base year MUST be a Monday, else Remind will not work! */
|
||||||
@@ -109,16 +103,6 @@
|
|||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
#define MAX_STR_LEN 65535
|
#define MAX_STR_LEN 65535
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
/* OP_STACK_SIZE: The size of the operator stack for expr. parsing */
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
#define OP_STACK_SIZE 100
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
/* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
#define VAL_STACK_SIZE 100
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
/* western hemisphere. */
|
/* western hemisphere. */
|
||||||
/* */
|
/* */
|
||||||
/* The default values are initially set to the city hall in Ottawa, */
|
/* The default values are initially set to the city hall in Ottawa, */
|
||||||
/* Ontario, Canada. */
|
/* Ontario, Canada. */
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
#define DEFAULT_LATITUDE 45.420556
|
#define DEFAULT_LATITUDE 45.420556
|
||||||
#define DEFAULT_LONGITUDE -75.689722
|
#define DEFAULT_LONGITUDE -75.689722
|
||||||
@@ -68,12 +68,6 @@
|
|||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
/* WANT_SHELL_ESCAPING: Define this if you want special shell */
|
|
||||||
/* characters to be escaped with a backslash for the -k option. */
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
#define WANT_SHELL_ESCAPING 1
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
/* BASE: The base year for date calculation. NOTE! January 1 of the */
|
/* BASE: The base year for date calculation. NOTE! January 1 of the */
|
||||||
/* base year MUST be a Monday, else Remind will not work! */
|
/* base year MUST be a Monday, else Remind will not work! */
|
||||||
@@ -109,16 +103,6 @@
|
|||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
#define MAX_STR_LEN 65535
|
#define MAX_STR_LEN 65535
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
/* OP_STACK_SIZE: The size of the operator stack for expr. parsing */
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
#define OP_STACK_SIZE 100
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
/* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
#define VAL_STACK_SIZE 100
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
|
|||||||
163
src/dorem.c
163
src/dorem.c
@@ -32,6 +32,152 @@ static int ParseUntil (ParsePtr s, Trigger *t, int type);
|
|||||||
static int ShouldTriggerBasedOnWarn (Trigger *t, int dse, int *err);
|
static int ShouldTriggerBasedOnWarn (Trigger *t, int dse, int *err);
|
||||||
static int ComputeTrigDuration(TimeTrig *t);
|
static int ComputeTrigDuration(TimeTrig *t);
|
||||||
|
|
||||||
|
static int
|
||||||
|
ensure_expr_references_first_local_arg(expr_node *node)
|
||||||
|
{
|
||||||
|
expr_node *other;
|
||||||
|
|
||||||
|
if (!node) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (node->type == N_LOCAL_VAR && node->u.arg == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (ensure_expr_references_first_local_arg(node->child)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
other = node->sibling;
|
||||||
|
while (other) {
|
||||||
|
if (ensure_expr_references_first_local_arg(other)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
other = other->sibling;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_trigger_function(char const *fname, char const *type)
|
||||||
|
{
|
||||||
|
UserFunc *f;
|
||||||
|
if (!*fname) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
f = FindUserFunc(fname);
|
||||||
|
if (!f) {
|
||||||
|
if (strcmp(type, "WARN")) {
|
||||||
|
/* Undefined WARN functions are diagnosed elsewhere... */
|
||||||
|
Wprint("Undefined %s function: `%s'", type, fname);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (f->nargs != 1) {
|
||||||
|
Wprint("%s function `%s' defined at %s:%d should take 1 argument but actually takes %d", type, fname, f->filename, f->lineno, f->nargs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ensure_expr_references_first_local_arg(f->node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Wprint("%s function `%s' defined at %s:%d does not use its argument", type, fname, f->filename, f->lineno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ensure_satnode_mentions_trigdate_aux(expr_node *node, int *mentioned)
|
||||||
|
{
|
||||||
|
char const *name;
|
||||||
|
expr_node *other;
|
||||||
|
UserFunc *f;
|
||||||
|
|
||||||
|
if (!node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (*mentioned) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->type == N_BUILTIN_FUNC) {
|
||||||
|
name = node->u.builtin_func->name;
|
||||||
|
if (!strcmp(name, "trigdate") ||
|
||||||
|
!strcmp(name, "trigdatetime")) {
|
||||||
|
*mentioned = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (node->type == N_SHORT_SYSVAR || node->type == N_SYSVAR) {
|
||||||
|
if (node->type == N_SHORT_SYSVAR) {
|
||||||
|
name = node->u.name;
|
||||||
|
} else {
|
||||||
|
name = node->u.value.v.str;
|
||||||
|
}
|
||||||
|
if (!StrCmpi(name, "T") ||
|
||||||
|
!StrCmpi(name, "Td") ||
|
||||||
|
!StrCmpi(name, "Tm") ||
|
||||||
|
!StrCmpi(name, "Tw") ||
|
||||||
|
!StrCmpi(name, "Ty")) {
|
||||||
|
*mentioned = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (node->type == N_SHORT_USER_FUNC || node->type == N_USER_FUNC) {
|
||||||
|
if (node->type == N_SHORT_USER_FUNC) {
|
||||||
|
name = node->u.name;
|
||||||
|
} else {
|
||||||
|
name = node->u.value.v.str;
|
||||||
|
}
|
||||||
|
f = FindUserFunc(name);
|
||||||
|
if (f && !f->recurse_flag) {
|
||||||
|
f->recurse_flag = 1;
|
||||||
|
ensure_satnode_mentions_trigdate_aux(f->node, mentioned);
|
||||||
|
f->recurse_flag = 0;
|
||||||
|
if (*mentioned) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ensure_satnode_mentions_trigdate_aux(node->child, mentioned);
|
||||||
|
if (*mentioned) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
other = node->sibling;
|
||||||
|
while (other) {
|
||||||
|
ensure_satnode_mentions_trigdate_aux(other, mentioned);
|
||||||
|
if (*mentioned) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
other = other->sibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ensure_satnode_mentions_trigdate(expr_node *node)
|
||||||
|
{
|
||||||
|
int mentioned = 0;
|
||||||
|
char const *str;
|
||||||
|
if (node->type == N_CONSTANT || node->type == N_SHORT_STR) {
|
||||||
|
if (node->type == N_CONSTANT) {
|
||||||
|
if (node->u.value.type == INT_TYPE) {
|
||||||
|
if (node->u.value.v.val == 0) {
|
||||||
|
Wprint("SATISFY: constant 0 will never be true");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (node->u.value.type != STR_TYPE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
str = node->u.value.v.str;
|
||||||
|
} else {
|
||||||
|
str = node->u.name;
|
||||||
|
}
|
||||||
|
if (!*str) {
|
||||||
|
Wprint("SATISFY: constant \"\" will never be true");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_satnode_mentions_trigdate_aux(node, &mentioned);
|
||||||
|
if (!mentioned) {
|
||||||
|
Wprint("SATISFY: expression has no reference to trigdate() or $T...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ComputeTrigDuration(TimeTrig *t)
|
ComputeTrigDuration(TimeTrig *t)
|
||||||
{
|
{
|
||||||
@@ -182,7 +328,7 @@ int DoRem(ParsePtr p)
|
|||||||
if (dse == DSEToday &&
|
if (dse == DSEToday &&
|
||||||
!(!IgnoreOnce &&
|
!(!IgnoreOnce &&
|
||||||
trig.once != NO_ONCE &&
|
trig.once != NO_ONCE &&
|
||||||
FileAccessDate == DSEToday))
|
GetOnceDate() == DSEToday))
|
||||||
QueueReminder(p, &trig, &tim, trig.sched);
|
QueueReminder(p, &trig, &tim, trig.sched);
|
||||||
/* If we're in daemon mode, do nothing over here */
|
/* If we're in daemon mode, do nothing over here */
|
||||||
if (Daemon) {
|
if (Daemon) {
|
||||||
@@ -540,6 +686,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
|||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
trig->typ = MSG_TYPE;
|
trig->typ = MSG_TYPE;
|
||||||
if (s->isnested) return E_CANT_NEST_RTYPE;
|
if (s->isnested) return E_CANT_NEST_RTYPE;
|
||||||
|
if (!WarnedAboutImplicit) {
|
||||||
|
Wprint("Missing REM type; assuming MSG");
|
||||||
|
WarnedAboutImplicit = 1;
|
||||||
|
}
|
||||||
parsing = 0;
|
parsing = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -591,6 +741,11 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
|||||||
trig->scanfrom = DSEToday;
|
trig->scanfrom = DSEToday;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check that any SCHED / WARN / OMITFUNC functions refer to
|
||||||
|
their arguments */
|
||||||
|
check_trigger_function(trig->sched, "SCHED");
|
||||||
|
check_trigger_function(trig->warn, "WARN");
|
||||||
|
check_trigger_function(trig->omitfunc, "OMITFUNC");
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1191,7 +1346,7 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int dse, int *err)
|
|||||||
*err = 0;
|
*err = 0;
|
||||||
|
|
||||||
/* Handle the ONCE modifier in the reminder. */
|
/* Handle the ONCE modifier in the reminder. */
|
||||||
if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == DSEToday)
|
if (!IgnoreOnce && t->once !=NO_ONCE && GetOnceDate() == DSEToday)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (dse < DSEToday) return 0;
|
if (dse < DSEToday) return 0;
|
||||||
@@ -1283,6 +1438,10 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
|||||||
if (!sat_node) {
|
if (!sat_node) {
|
||||||
return E_SWERR;
|
return E_SWERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Diagnose if SAT_NODE does not reference trigdate */
|
||||||
|
ensure_satnode_mentions_trigdate(sat_node);
|
||||||
|
|
||||||
iter = 0;
|
iter = 0;
|
||||||
start = trig->scanfrom;
|
start = trig->scanfrom;
|
||||||
while (iter++ < MaxSatIter) {
|
while (iter++ < MaxSatIter) {
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#define L_IN_DOSUBST
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -32,6 +31,19 @@
|
|||||||
|
|
||||||
#define SHIP_OUT(s) if(DBufPuts(dbuf, s) != OK) return E_NO_MEM
|
#define SHIP_OUT(s) if(DBufPuts(dbuf, s) != OK) return E_NO_MEM
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_subst_args(UserFunc *f, int n)
|
||||||
|
{
|
||||||
|
if (!f) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (f->nargs == n) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
Wprint("Function `%s' defined at %s:%d should take %d argument%s, but actually takes %d",
|
||||||
|
f->name, f->filename, f->lineno, n, (n == 1 ? "" : "s"), f->nargs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* DoSubst */
|
/* DoSubst */
|
||||||
@@ -68,6 +80,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
int altmode;
|
int altmode;
|
||||||
int r;
|
int r;
|
||||||
Value v;
|
Value v;
|
||||||
|
UserFunc *func;
|
||||||
|
|
||||||
FromDSE(dse, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
|
|
||||||
@@ -101,7 +114,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
L_AMPM_OVERRIDE (pm, h)
|
L_AMPM_OVERRIDE (pm, h)
|
||||||
#else
|
#else
|
||||||
r = -1;
|
r = -1;
|
||||||
if (UserFuncExists("subst_ampm") == 1) {
|
func = FindUserFunc("subst_ampm");
|
||||||
|
if (func && check_subst_args(func, 1)) {
|
||||||
snprintf(s, sizeof(s), "subst_ampm(%d)", h);
|
snprintf(s, sizeof(s), "subst_ampm(%d)", h);
|
||||||
expr = (char const *) s;
|
expr = (char const *) s;
|
||||||
r = EvalExpr(&expr, &v, NULL);
|
r = EvalExpr(&expr, &v, NULL);
|
||||||
@@ -130,7 +144,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
L_AMPM_OVERRIDE (cpm, ch)
|
L_AMPM_OVERRIDE (cpm, ch)
|
||||||
#else
|
#else
|
||||||
r = -1;
|
r = -1;
|
||||||
if (UserFuncExists("subst_ampm") == 1) {
|
func = FindUserFunc("subst_ampm");
|
||||||
|
if (func && check_subst_args(func, 1)) {
|
||||||
snprintf(s, sizeof(s), "subst_ampm(%d)", ch);
|
snprintf(s, sizeof(s), "subst_ampm(%d)", ch);
|
||||||
expr = (char const *) s;
|
expr = (char const *) s;
|
||||||
r = EvalExpr(&expr, &v, NULL);
|
r = EvalExpr(&expr, &v, NULL);
|
||||||
@@ -141,6 +156,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
} else {
|
} else {
|
||||||
r = -1;
|
r = -1;
|
||||||
}
|
}
|
||||||
|
DestroyValue(v);
|
||||||
} else {
|
} else {
|
||||||
Eprint("%s", ErrMsg[r]);
|
Eprint("%s", ErrMsg[r]);
|
||||||
}
|
}
|
||||||
@@ -154,7 +170,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
#ifdef L_ORDINAL_OVERRIDE
|
#ifdef L_ORDINAL_OVERRIDE
|
||||||
L_ORDINAL_OVERRIDE;
|
L_ORDINAL_OVERRIDE;
|
||||||
#else
|
#else
|
||||||
if (UserFuncExists("subst_ordinal") == 1) {
|
func = FindUserFunc("subst_ordinal");
|
||||||
|
if (func && check_subst_args(func, 1)) {
|
||||||
snprintf(s, sizeof(s), "subst_ordinal(%d)", d);
|
snprintf(s, sizeof(s), "subst_ordinal(%d)", d);
|
||||||
expr = (char const *) s;
|
expr = (char const *) s;
|
||||||
r = EvalExpr(&expr, &v, NULL);
|
r = EvalExpr(&expr, &v, NULL);
|
||||||
@@ -165,6 +182,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
} else {
|
} else {
|
||||||
r = -1;
|
r = -1;
|
||||||
}
|
}
|
||||||
|
DestroyValue(v);
|
||||||
} else {
|
} else {
|
||||||
Eprint("%s", ErrMsg[r]);
|
Eprint("%s", ErrMsg[r]);
|
||||||
}
|
}
|
||||||
@@ -249,7 +267,13 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
if (!c) {
|
if (!c) {
|
||||||
Wprint("Warning: Unterminated %%{...} substitution sequence");
|
Wprint("Warning: Unterminated %%{...} substitution sequence");
|
||||||
}
|
}
|
||||||
if (UserFuncExists(s) != 3) {
|
func = FindUserFunc(s);
|
||||||
|
if (!func) {
|
||||||
|
Wprint("No substition function `%s' defined", s);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!check_subst_args(func, 3)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
snprintf(ss, sizeof(s) - (ss-s), "(%d,'%04d-%02d-%02d',%02d:%02d)",
|
snprintf(ss, sizeof(s) - (ss-s), "(%d,'%04d-%02d-%02d',%02d:%02d)",
|
||||||
@@ -269,7 +293,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
}
|
}
|
||||||
done = 0;
|
done = 0;
|
||||||
snprintf(uf, sizeof(uf), "subst_%c", tolower(c));
|
snprintf(uf, sizeof(uf), "subst_%c", tolower(c));
|
||||||
if (UserFuncExists(uf) == 3) {
|
func = FindUserFunc(uf);
|
||||||
|
if (func && check_subst_args(func, 3)) {
|
||||||
snprintf(s, sizeof(s), "subst_%c(%d,'%04d-%02d-%02d',%02d:%02d)",
|
snprintf(s, sizeof(s), "subst_%c(%d,'%04d-%02d-%02d',%02d:%02d)",
|
||||||
tolower(c), altmode ? 1 : 0, y, m+1, d, h, min);
|
tolower(c), altmode ? 1 : 0, y, m+1, d, h, min);
|
||||||
expr = (char const *) s;
|
expr = (char const *) s;
|
||||||
@@ -344,7 +369,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
|
|
||||||
if (!done) {
|
if (!done) {
|
||||||
snprintf(uf, sizeof(uf), "subst_%cx", tolower(c));
|
snprintf(uf, sizeof(uf), "subst_%cx", tolower(c));
|
||||||
if (UserFuncExists(uf) == 3) {
|
func = FindUserFunc(uf);
|
||||||
|
if (func && check_subst_args(func, 3)) {
|
||||||
snprintf(s, sizeof(s), "subst_%cx(%d,'%04d-%02d-%02d',%02d:%02d)",
|
snprintf(s, sizeof(s), "subst_%cx(%d,'%04d-%02d-%02d',%02d:%02d)",
|
||||||
tolower(c), altmode ? 1 : 0, y, m+1, d, h, min);
|
tolower(c), altmode ? 1 : 0, y, m+1, d, h, min);
|
||||||
expr = (char const *) s;
|
expr = (char const *) s;
|
||||||
@@ -796,7 +822,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '_':
|
case '_':
|
||||||
if (PsCal == PSCAL_LEVEL2 || PsCal == PSCAL_LEVEL3 || (mode != CAL_MODE && mode != ADVANCE_MODE && !(MsgCommand && *MsgCommand))) {
|
if (PsCal == PSCAL_LEVEL2 || PsCal == PSCAL_LEVEL3 || DoCalendar || (mode != CAL_MODE && mode != ADVANCE_MODE && !(MsgCommand && *MsgCommand))) {
|
||||||
snprintf(s, sizeof(s), "%s", NL);
|
snprintf(s, sizeof(s), "%s", NL);
|
||||||
} else {
|
} else {
|
||||||
snprintf(s, sizeof(s), " ");
|
snprintf(s, sizeof(s), " ");
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ EXTERN char *ErrMsg[]
|
|||||||
/* E_ERR_READING */ "Error reading",
|
/* E_ERR_READING */ "Error reading",
|
||||||
/* E_EXPECTING_EOL */ "Expecting end-of-line",
|
/* E_EXPECTING_EOL */ "Expecting end-of-line",
|
||||||
/* E_BAD_HEBDATE */ "Invalid Hebrew date",
|
/* E_BAD_HEBDATE */ "Invalid Hebrew date",
|
||||||
/* E_IIF_ODD */ "IIF needs odd number of arguments",
|
/* E_IIF_ODD */ "iif(): odd number of arguments required",
|
||||||
/* E_MISS_ENDIF */ "Warning: Missing ENDIF",
|
/* E_MISS_ENDIF */ "Warning: Missing ENDIF",
|
||||||
/* E_EXPECT_COMMA */ "Expecting comma",
|
/* E_EXPECT_COMMA */ "Expecting comma",
|
||||||
/* E_WD_TWICE */ "Weekday specified twice",
|
/* E_WD_TWICE */ "Weekday specified twice",
|
||||||
@@ -241,7 +241,7 @@ EXTERN char *ErrMsg[]
|
|||||||
/* E_NOREMINDERS */ "No reminders.",
|
/* E_NOREMINDERS */ "No reminders.",
|
||||||
/* M_QUEUED */ "%d reminder(s) queued for later today.\n",
|
/* M_QUEUED */ "%d reminder(s) queued for later today.\n",
|
||||||
/* E_EXPECTING_NUMBER */ "Expecting number",
|
/* E_EXPECTING_NUMBER */ "Expecting number",
|
||||||
/* M_BAD_WARN_FUNC */ "Bad function in WARN clause",
|
/* M_BAD_WARN_FUNC */ "Undefined WARN function",
|
||||||
/* E_CANT_CONVERT_TZ */ "Can't convert between time zones",
|
/* E_CANT_CONVERT_TZ */ "Can't convert between time zones",
|
||||||
/* E_NO_MATCHING_REMS */ "No files matching *.rem",
|
/* E_NO_MATCHING_REMS */ "No files matching *.rem",
|
||||||
/* E_STRING_TOO_LONG */ "String too long",
|
/* E_STRING_TOO_LONG */ "String too long",
|
||||||
|
|||||||
140
src/expr.c
140
src/expr.c
@@ -39,6 +39,7 @@
|
|||||||
6) N_USER_FUNC: A reference to a user-defined function
|
6) N_USER_FUNC: A reference to a user-defined function
|
||||||
7) N_OPERATOR: A reference to an operator such as "+" or "&&"
|
7) N_OPERATOR: A reference to an operator such as "+" or "&&"
|
||||||
8) N_ERROR: A node resulting from a parse error
|
8) N_ERROR: A node resulting from a parse error
|
||||||
|
9) N_SHORT_STR: A string constant short enough to store in u.name
|
||||||
|
|
||||||
Additional types are N_SHORT_VAR, N_SHORT_SYSVAR, and N_SHORT_USER_FUNC
|
Additional types are N_SHORT_VAR, N_SHORT_SYSVAR, and N_SHORT_USER_FUNC
|
||||||
which behave identically to N_VARIABLE, N_SYSVAR and N_USER_FUNC
|
which behave identically to N_VARIABLE, N_SYSVAR and N_USER_FUNC
|
||||||
@@ -167,8 +168,8 @@ static expr_node *expr_node_free_list = NULL;
|
|||||||
#define STACK_ARGS_MAX 5
|
#define STACK_ARGS_MAX 5
|
||||||
|
|
||||||
/* Maximum parse level before we bail (to avoid SEGV from filling stack)*/
|
/* Maximum parse level before we bail (to avoid SEGV from filling stack)*/
|
||||||
|
|
||||||
#define MAX_PARSE_LEVEL 2000
|
#define MAX_PARSE_LEVEL 2000
|
||||||
|
|
||||||
static int parse_level_high_water = 0;
|
static int parse_level_high_water = 0;
|
||||||
#define CHECK_PARSE_LEVEL() do { if (level > parse_level_high_water) { parse_level_high_water = level; if (level > MAX_PARSE_LEVEL) { *r = E_OP_STK_OVER; return NULL; } } } while(0)
|
#define CHECK_PARSE_LEVEL() do { if (level > parse_level_high_water) { parse_level_high_water = level; if (level > MAX_PARSE_LEVEL) { *r = E_OP_STK_OVER; return NULL; } } } while(0)
|
||||||
|
|
||||||
@@ -198,7 +199,6 @@ static UserFunc *CurrentUserFunc = NULL;
|
|||||||
/* How many expr_node objects to allocate at a time */
|
/* How many expr_node objects to allocate at a time */
|
||||||
#define ALLOC_CHUNK 64
|
#define ALLOC_CHUNK 64
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* alloc_expr_node - allocate an expr_node object */
|
/* alloc_expr_node - allocate an expr_node object */
|
||||||
@@ -425,8 +425,14 @@ eval_builtin(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
|||||||
Value stack_args[STACK_ARGS_MAX];
|
Value stack_args[STACK_ARGS_MAX];
|
||||||
|
|
||||||
/* Check that we have the right number of argumens */
|
/* Check that we have the right number of argumens */
|
||||||
if (node->num_kids < f->minargs) return E_2FEW_ARGS;
|
if (node->num_kids < f->minargs) {
|
||||||
if (node->num_kids > f->maxargs && f->maxargs != NO_MAX) return E_2MANY_ARGS;
|
Eprint("%s(): %s", f->name, ErrMsg[E_2FEW_ARGS]);
|
||||||
|
return E_2FEW_ARGS;
|
||||||
|
}
|
||||||
|
if (node->num_kids > f->maxargs && f->maxargs != NO_MAX) {
|
||||||
|
Eprint("%s(): %s", f->name, ErrMsg[E_2MANY_ARGS]);
|
||||||
|
return E_2MANY_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
/* If this is a new-style function that knows about expr_nodes,
|
/* If this is a new-style function that knows about expr_nodes,
|
||||||
let it evaluate itself */
|
let it evaluate itself */
|
||||||
@@ -585,7 +591,7 @@ debug_exit_userfunc(expr_node *node, Value *ans, int r, Value *locals, int nargs
|
|||||||
/* eval_userfunc - evaluate a user-defined function */
|
/* eval_userfunc - evaluate a user-defined function */
|
||||||
/* */
|
/* */
|
||||||
/* This function sets up a local value array by evaluating */
|
/* This function sets up a local value array by evaluating */
|
||||||
/* all of its children, and then evaluated the expr_node */
|
/* all of its children, and then evaluates the expr_node */
|
||||||
/* tree associated with the user-defined function. */
|
/* tree associated with the user-defined function. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -622,10 +628,12 @@ eval_userfunc(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
|||||||
/* Make sure we have the right number of arguments */
|
/* Make sure we have the right number of arguments */
|
||||||
if (node->num_kids < f->nargs) {
|
if (node->num_kids < f->nargs) {
|
||||||
DBG(fprintf(ErrFp, "%s(...) => %s\n", fname, ErrMsg[E_2FEW_ARGS]));
|
DBG(fprintf(ErrFp, "%s(...) => %s\n", fname, ErrMsg[E_2FEW_ARGS]));
|
||||||
|
Eprint("%s(): %s", f->name, ErrMsg[E_2FEW_ARGS]);
|
||||||
return E_2FEW_ARGS;
|
return E_2FEW_ARGS;
|
||||||
}
|
}
|
||||||
if (node->num_kids > f->nargs) {
|
if (node->num_kids > f->nargs) {
|
||||||
DBG(fprintf(ErrFp, "%s(...) => %s\n", fname, ErrMsg[E_2MANY_ARGS]));
|
DBG(fprintf(ErrFp, "%s(...) => %s\n", fname, ErrMsg[E_2MANY_ARGS]));
|
||||||
|
Eprint("%s(): %s", f->name, ErrMsg[E_2MANY_ARGS]);
|
||||||
return E_2MANY_ARGS;
|
return E_2MANY_ARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,10 +737,26 @@ evaluate_expression(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
|||||||
alarm(ExpressionEvaluationTimeLimit);
|
alarm(ExpressionEvaluationTimeLimit);
|
||||||
}
|
}
|
||||||
r = evaluate_expr_node(node, locals, ans, nonconst);
|
r = evaluate_expr_node(node, locals, ans, nonconst);
|
||||||
alarm(0);
|
if (ExpressionEvaluationTimeLimit > 0) {
|
||||||
|
alarm(0);
|
||||||
|
ExpressionTimeLimitExceeded = 0;
|
||||||
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CopyShortStr(Value *ans, expr_node *node)
|
||||||
|
{
|
||||||
|
size_t len = strlen(node->u.name);
|
||||||
|
ans->v.str = malloc(len+1);
|
||||||
|
if (!ans->v.str) {
|
||||||
|
ans->type = ERR_TYPE;
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
strcpy(ans->v.str, node->u.name);
|
||||||
|
ans->type = STR_TYPE;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* evaluate_expr_node - evaluate an expression */
|
/* evaluate_expr_node - evaluate an expression */
|
||||||
@@ -773,6 +797,9 @@ evaluate_expr_node(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
|||||||
ans->type = ERR_TYPE;
|
ans->type = ERR_TYPE;
|
||||||
return E_SWERR;
|
return E_SWERR;
|
||||||
|
|
||||||
|
case N_SHORT_STR:
|
||||||
|
return CopyShortStr(ans, node);
|
||||||
|
|
||||||
case N_CONSTANT:
|
case N_CONSTANT:
|
||||||
/* Constant node? Just return a copy of the constant */
|
/* Constant node? Just return a copy of the constant */
|
||||||
return CopyValue(ans, &(node->u.value));
|
return CopyValue(ans, &(node->u.value));
|
||||||
@@ -1348,7 +1375,7 @@ static int divide_or_mod(expr_node *node, Value *locals, Value *ans, int *noncon
|
|||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* domod - evaluate the "%" operator */
|
/* do_mod - evaluate the "%" operator */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int do_mod(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
static int do_mod(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||||
@@ -1378,14 +1405,10 @@ static int logical_not(expr_node *node, Value *locals, Value *ans, int *nonconst
|
|||||||
|
|
||||||
r = evaluate_expr_node(node->child, locals, &v1, nonconst);
|
r = evaluate_expr_node(node->child, locals, &v1, nonconst);
|
||||||
if (r != OK) return r;
|
if (r != OK) return r;
|
||||||
if (v1.type != INT_TYPE) {
|
|
||||||
DBG(debug_evaluation_unop(ans, E_BAD_TYPE, &v1, "!"));
|
|
||||||
DestroyValue(v1);
|
|
||||||
return E_BAD_TYPE;
|
|
||||||
}
|
|
||||||
ans->type = INT_TYPE;
|
ans->type = INT_TYPE;
|
||||||
ans->v.val = !(v1.v.val);
|
ans->v.val = !truthy(&v1);
|
||||||
DBG(debug_evaluation_unop(ans, OK, &v1, "!"));
|
DBG(debug_evaluation_unop(ans, OK, &v1, "!"));
|
||||||
|
DestroyValue(v1);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1433,22 +1456,16 @@ static int logical_binop(expr_node *node, Value *locals, Value *ans, int *noncon
|
|||||||
/* Bail on error */
|
/* Bail on error */
|
||||||
if (r != OK) return r;
|
if (r != OK) return r;
|
||||||
|
|
||||||
if (v.type == STR_TYPE) {
|
|
||||||
DBG(debug_evaluation_binop(ans, E_BAD_TYPE, &v, NULL, opname));
|
|
||||||
DestroyValue(v);
|
|
||||||
return E_BAD_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_and) {
|
if (is_and) {
|
||||||
/* If first arg is false, return it */
|
/* If first arg is false, return it */
|
||||||
if (!v.v.val) {
|
if (!truthy(&v)) {
|
||||||
*ans = v;
|
*ans = v;
|
||||||
DBG(debug_evaluation_binop(ans, OK, &v, NULL, opname));
|
DBG(debug_evaluation_binop(ans, OK, &v, NULL, opname));
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* If first arg is true, return it */
|
/* If first arg is true, return it */
|
||||||
if (v.v.val) {
|
if (truthy(&v)) {
|
||||||
*ans = v;
|
*ans = v;
|
||||||
DBG(debug_evaluation_binop(ans, OK, &v, NULL, opname));
|
DBG(debug_evaluation_binop(ans, OK, &v, NULL, opname));
|
||||||
return OK;
|
return OK;
|
||||||
@@ -1457,12 +1474,8 @@ static int logical_binop(expr_node *node, Value *locals, Value *ans, int *noncon
|
|||||||
|
|
||||||
/* Otherwise, evaluate and return second arg */
|
/* Otherwise, evaluate and return second arg */
|
||||||
r = evaluate_expr_node(node->child->sibling, locals, ans, nonconst);
|
r = evaluate_expr_node(node->child->sibling, locals, ans, nonconst);
|
||||||
if (r == OK && ans->type == STR_TYPE) {
|
|
||||||
DBG(debug_evaluation_binop(ans, E_BAD_TYPE, &v, ans, opname));
|
|
||||||
DestroyValue(*ans);
|
|
||||||
return E_BAD_TYPE;
|
|
||||||
}
|
|
||||||
DBG(debug_evaluation_binop(ans, r, &v, ans, opname));
|
DBG(debug_evaluation_binop(ans, r, &v, ans, opname));
|
||||||
|
DestroyValue(v);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1542,9 +1555,10 @@ static int parse_expr_token_aux(DynamicBuffer *buf, char const **in)
|
|||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
(*in)++;
|
(*in)++;
|
||||||
}
|
} else {
|
||||||
return OK;
|
return E_PARSE_ERR;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
case '!':
|
case '!':
|
||||||
case '>':
|
case '>':
|
||||||
case '<':
|
case '<':
|
||||||
@@ -1765,6 +1779,7 @@ static expr_node * parse_function_call(char const **e, int *r, Var *locals, int
|
|||||||
expr_node *node;
|
expr_node *node;
|
||||||
expr_node *arg;
|
expr_node *arg;
|
||||||
char *s;
|
char *s;
|
||||||
|
char const *ptr;
|
||||||
CHECK_PARSE_LEVEL();
|
CHECK_PARSE_LEVEL();
|
||||||
|
|
||||||
node = alloc_expr_node(r);
|
node = alloc_expr_node(r);
|
||||||
@@ -1837,6 +1852,7 @@ static expr_node * parse_function_call(char const **e, int *r, Var *locals, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (TOKEN_IS(")")) {
|
if (TOKEN_IS(")")) {
|
||||||
|
ptr = *e;
|
||||||
*r = GET_TOKEN();
|
*r = GET_TOKEN();
|
||||||
if (*r != OK) {
|
if (*r != OK) {
|
||||||
return free_expr_tree(node);
|
return free_expr_tree(node);
|
||||||
@@ -1845,8 +1861,14 @@ static expr_node * parse_function_call(char const **e, int *r, Var *locals, int
|
|||||||
/* Check args for builtin funcs */
|
/* Check args for builtin funcs */
|
||||||
if (node->type == N_BUILTIN_FUNC) {
|
if (node->type == N_BUILTIN_FUNC) {
|
||||||
f = node->u.builtin_func;
|
f = node->u.builtin_func;
|
||||||
if (node->num_kids < f->minargs) *r = E_2FEW_ARGS;
|
if (node->num_kids < f->minargs) {
|
||||||
if (node->num_kids > f->maxargs && f->maxargs != NO_MAX) *r = E_2MANY_ARGS;
|
*e = ptr;
|
||||||
|
*r = E_2FEW_ARGS;
|
||||||
|
}
|
||||||
|
if (node->num_kids > f->maxargs && f->maxargs != NO_MAX) {
|
||||||
|
*e = ptr;
|
||||||
|
*r = E_2MANY_ARGS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (*r != OK) {
|
if (*r != OK) {
|
||||||
if (node->type == N_BUILTIN_FUNC) {
|
if (node->type == N_BUILTIN_FUNC) {
|
||||||
@@ -1870,6 +1892,7 @@ static int set_constant_value(expr_node *atom)
|
|||||||
size_t len;
|
size_t len;
|
||||||
char const *s = DBufValue(&ExprBuf);
|
char const *s = DBufValue(&ExprBuf);
|
||||||
atom->u.value.type = ERR_TYPE;
|
atom->u.value.type = ERR_TYPE;
|
||||||
|
atom->type = N_CONSTANT;
|
||||||
|
|
||||||
if (!*s) {
|
if (!*s) {
|
||||||
Eprint("%s", ErrMsg[E_EOLN]);
|
Eprint("%s", ErrMsg[E_EOLN]);
|
||||||
@@ -1878,6 +1901,12 @@ static int set_constant_value(expr_node *atom)
|
|||||||
ampm = 0;
|
ampm = 0;
|
||||||
if (*s == '\"') { /* It's a literal string "*/
|
if (*s == '\"') { /* It's a literal string "*/
|
||||||
len = strlen(s)-1;
|
len = strlen(s)-1;
|
||||||
|
if (len <= SHORT_NAME_BUF) {
|
||||||
|
atom->type = N_SHORT_STR;
|
||||||
|
strncpy(atom->u.name, s+1, len-1);
|
||||||
|
atom->u.name[len-1] = 0;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
atom->u.value.type = STR_TYPE;
|
atom->u.value.type = STR_TYPE;
|
||||||
atom->u.value.v.str = malloc(len);
|
atom->u.value.v.str = malloc(len);
|
||||||
if (! atom->u.value.v.str) {
|
if (! atom->u.value.v.str) {
|
||||||
@@ -2013,9 +2042,7 @@ static int make_atom(expr_node *atom, Var *locals)
|
|||||||
|
|
||||||
/* Constant */
|
/* Constant */
|
||||||
r = set_constant_value(atom);
|
r = set_constant_value(atom);
|
||||||
if (r == OK) {
|
if (r != OK) {
|
||||||
atom->type = N_CONSTANT;
|
|
||||||
} else {
|
|
||||||
atom->type = N_ERROR;
|
atom->type = N_ERROR;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
@@ -2143,22 +2170,6 @@ static expr_node *parse_factor(char const **e, int *r, Var *locals, int level)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the child is a constant int, optimize! */
|
|
||||||
if (node->type == N_CONSTANT &&
|
|
||||||
node->u.value.type == INT_TYPE) {
|
|
||||||
if (op == '-') {
|
|
||||||
if (node->u.value.v.val == INT_MIN) {
|
|
||||||
*r = E_2LOW;
|
|
||||||
return free_expr_tree(node);
|
|
||||||
}
|
|
||||||
node->u.value.v.val = -node->u.value.v.val;
|
|
||||||
} else {
|
|
||||||
node->u.value.v.val = !node->u.value.v.val;
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Not a constant int; we need to add a node */
|
|
||||||
factor_node = alloc_expr_node(r);
|
factor_node = alloc_expr_node(r);
|
||||||
if (!factor_node) {
|
if (!factor_node) {
|
||||||
free_expr_tree(node);
|
free_expr_tree(node);
|
||||||
@@ -2500,15 +2511,23 @@ expr_node *parse_expression(char const **e, int *r, Var *locals)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (*r == E_EXPECT_COMMA ||
|
if (*r == E_EXPECT_COMMA ||
|
||||||
*r == E_PARSE_ERR ||
|
|
||||||
*r == E_MISS_RIGHT_PAREN ||
|
*r == E_MISS_RIGHT_PAREN ||
|
||||||
*r == E_EXPECTING_EOL ||
|
*r == E_EXPECTING_EOL ||
|
||||||
|
*r == E_2MANY_ARGS ||
|
||||||
|
*r == E_2FEW_ARGS ||
|
||||||
*r == E_PARSE_ERR ||
|
*r == E_PARSE_ERR ||
|
||||||
*r == E_EOLN ||
|
*r == E_EOLN ||
|
||||||
*r == E_ILLEGAL_CHAR) {
|
*r == E_ILLEGAL_CHAR) {
|
||||||
orig = o2;
|
orig = o2;
|
||||||
while (*orig) {
|
while (*orig) {
|
||||||
fprintf(ErrFp, "%c", *orig++);
|
if (*orig == '\n') {
|
||||||
|
fprintf(ErrFp, " ");
|
||||||
|
orig++;
|
||||||
|
} else if (*orig == ']' && ! *(orig+1)) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
fprintf(ErrFp, "%c", *orig++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fprintf(ErrFp, "\n");
|
fprintf(ErrFp, "\n");
|
||||||
orig = o2;
|
orig = o2;
|
||||||
@@ -2557,6 +2576,9 @@ void print_expr_tree(expr_node *node, FILE *fp)
|
|||||||
case N_CONSTANT:
|
case N_CONSTANT:
|
||||||
PrintValue(&(node->u.value), fp);
|
PrintValue(&(node->u.value), fp);
|
||||||
return;
|
return;
|
||||||
|
case N_SHORT_STR:
|
||||||
|
fprintf(fp, "\"%s\"", node->u.name);
|
||||||
|
return;
|
||||||
case N_SHORT_VAR:
|
case N_SHORT_VAR:
|
||||||
fprintf(fp, "%s", node->u.name);
|
fprintf(fp, "%s", node->u.name);
|
||||||
return;
|
return;
|
||||||
@@ -3049,3 +3071,17 @@ void print_expr_nodes_stats(void)
|
|||||||
fprintf(stderr, " Expression nodes leaked: %d\n", ExprNodesUsed);
|
fprintf(stderr, " Expression nodes leaked: %d\n", ExprNodesUsed);
|
||||||
fprintf(stderr, " Parse level high-water: %d\n", parse_level_high_water);
|
fprintf(stderr, " Parse level high-water: %d\n", parse_level_high_water);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return 1 if a value is "true" for its type, 0 if "false" */
|
||||||
|
int truthy(Value const *v)
|
||||||
|
{
|
||||||
|
if (v->type == STR_TYPE) {
|
||||||
|
if (v->v.str && *(v->v.str)) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (v->v.val != 0);
|
||||||
|
}
|
||||||
|
|||||||
15
src/files.c
15
src/files.c
@@ -102,6 +102,13 @@ static int CheckSafetyAux (struct stat *statbuf);
|
|||||||
static int PopFile (void);
|
static int PopFile (void);
|
||||||
static int IncludeCmd(char const *);
|
static int IncludeCmd(char const *);
|
||||||
|
|
||||||
|
static void
|
||||||
|
got_a_fresh_line(void)
|
||||||
|
{
|
||||||
|
FreshLine = 1;
|
||||||
|
WarnedAboutImplicit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void set_cloexec(FILE *fp)
|
void set_cloexec(FILE *fp)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
@@ -182,7 +189,7 @@ int ReadLine(void)
|
|||||||
CurLine = CLine->text;
|
CurLine = CLine->text;
|
||||||
LineNo = CLine->LineNo;
|
LineNo = CLine->LineNo;
|
||||||
CLine = CLine->next;
|
CLine = CLine->next;
|
||||||
FreshLine = 1;
|
got_a_fresh_line();
|
||||||
clear_callstack();
|
clear_callstack();
|
||||||
if (DebugFlag & DB_ECHO_LINE) OutputLine(ErrFp);
|
if (DebugFlag & DB_ECHO_LINE) OutputLine(ErrFp);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -283,7 +290,7 @@ static int ReadLineFromFile(int use_pclose)
|
|||||||
CurLine = DBufValue(&LineBuffer);
|
CurLine = DBufValue(&LineBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
FreshLine = 1;
|
got_a_fresh_line();
|
||||||
clear_callstack();
|
clear_callstack();
|
||||||
if (DebugFlag & DB_ECHO_LINE) OutputLine(ErrFp);
|
if (DebugFlag & DB_ECHO_LINE) OutputLine(ErrFp);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -849,7 +856,7 @@ static int IncludeCmd(char const *cmd)
|
|||||||
char const *fname;
|
char const *fname;
|
||||||
int old_flag;
|
int old_flag;
|
||||||
|
|
||||||
FreshLine = 1;
|
got_a_fresh_line();
|
||||||
clear_callstack();
|
clear_callstack();
|
||||||
if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE;
|
if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE;
|
||||||
i = &IStack[IStackPtr];
|
i = &IStack[IStackPtr];
|
||||||
@@ -968,7 +975,7 @@ int IncludeFile(char const *fname)
|
|||||||
int oldRunDisabled;
|
int oldRunDisabled;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
|
||||||
FreshLine = 1;
|
got_a_fresh_line();
|
||||||
clear_callstack();
|
clear_callstack();
|
||||||
if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE;
|
if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE;
|
||||||
i = &IStack[IStackPtr];
|
i = &IStack[IStackPtr];
|
||||||
|
|||||||
150
src/funcs.c
150
src/funcs.c
@@ -60,6 +60,9 @@
|
|||||||
#define RetVal (info->retval)
|
#define RetVal (info->retval)
|
||||||
|
|
||||||
#define DBG(x) do { if (DebugFlag & DB_PRTEXPR) { x; } } while(0)
|
#define DBG(x) do { if (DebugFlag & DB_PRTEXPR) { 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)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
solstice_equinox_for_year(int y, int which);
|
solstice_equinox_for_year(int y, int which);
|
||||||
@@ -104,7 +107,7 @@ static int FHtmlEscape (func_info *);
|
|||||||
static int FHtmlStriptags (func_info *);
|
static int FHtmlStriptags (func_info *);
|
||||||
static int FIif (expr_node *, Value *, Value *, int *);
|
static int FIif (expr_node *, Value *, Value *, int *);
|
||||||
static int FIndex (func_info *);
|
static int FIndex (func_info *);
|
||||||
static int FIsAny (func_info *);
|
static int FIsAny (expr_node *, Value *, Value *, int *);
|
||||||
static int FIsdst (func_info *);
|
static int FIsdst (func_info *);
|
||||||
static int FIsleap (func_info *);
|
static int FIsleap (func_info *);
|
||||||
static int FIsomitted (func_info *);
|
static int FIsomitted (func_info *);
|
||||||
@@ -228,7 +231,7 @@ BuiltinFunc Func[] = {
|
|||||||
{ "access", 2, 2, 0, FAccess, NULL },
|
{ "access", 2, 2, 0, FAccess, NULL },
|
||||||
{ "adawn", 0, 1, 0, FADawn, NULL},
|
{ "adawn", 0, 1, 0, FADawn, NULL},
|
||||||
{ "adusk", 0, 1, 0, FADusk, NULL},
|
{ "adusk", 0, 1, 0, FADusk, NULL},
|
||||||
{ "ampm", 1, 3, 1, FAmpm, NULL },
|
{ "ampm", 1, 4, 1, FAmpm, NULL },
|
||||||
{ "ansicolor", 1, 5, 1, FAnsicolor, NULL },
|
{ "ansicolor", 1, 5, 1, FAnsicolor, NULL },
|
||||||
{ "args", 1, 1, 0, FArgs, NULL },
|
{ "args", 1, 1, 0, FArgs, NULL },
|
||||||
{ "asc", 1, 1, 1, FAsc, NULL },
|
{ "asc", 1, 1, 1, FAsc, NULL },
|
||||||
@@ -263,7 +266,7 @@ BuiltinFunc Func[] = {
|
|||||||
{ "htmlstriptags",1, 1, 1, FHtmlStriptags, NULL },
|
{ "htmlstriptags",1, 1, 1, FHtmlStriptags, NULL },
|
||||||
{ "iif", 1, NO_MAX, 1, NULL, FIif }, /*NEW-STYLE*/
|
{ "iif", 1, NO_MAX, 1, NULL, FIif }, /*NEW-STYLE*/
|
||||||
{ "index", 2, 3, 1, FIndex, NULL },
|
{ "index", 2, 3, 1, FIndex, NULL },
|
||||||
{ "isany", 1, NO_MAX, 1, FIsAny, NULL },
|
{ "isany", 1, NO_MAX, 1, NULL, FIsAny }, /*NEW-STYLE*/
|
||||||
{ "isdst", 0, 2, 0, FIsdst, NULL },
|
{ "isdst", 0, 2, 0, FIsdst, NULL },
|
||||||
{ "isleap", 1, 1, 1, FIsleap, NULL },
|
{ "isleap", 1, 1, 1, FIsleap, NULL },
|
||||||
{ "isomitted", 1, 1, 0, FIsomitted, NULL },
|
{ "isomitted", 1, 1, 0, FIsomitted, NULL },
|
||||||
@@ -335,7 +338,7 @@ BuiltinFunc Func[] = {
|
|||||||
{ "utctolocal", 1, 1, 1, FUTCToLocal, NULL },
|
{ "utctolocal", 1, 1, 1, FUTCToLocal, NULL },
|
||||||
{ "value", 1, 2, 0, FValue, NULL },
|
{ "value", 1, 2, 0, FValue, NULL },
|
||||||
{ "version", 0, 0, 1, FVersion, NULL },
|
{ "version", 0, 0, 1, FVersion, NULL },
|
||||||
{ "weekno", 0, 3, 1, FWeekno, NULL },
|
{ "weekno", 0, 3, 0, FWeekno, NULL },
|
||||||
{ "wkday", 1, 1, 1, FWkday, NULL },
|
{ "wkday", 1, 1, 1, FWkday, NULL },
|
||||||
{ "wkdaynum", 1, 1, 1, FWkdaynum, NULL },
|
{ "wkdaynum", 1, 1, 1, FWkdaynum, NULL },
|
||||||
{ "year", 1, 1, 1, FYear, NULL }
|
{ "year", 1, 1, 1, FYear, NULL }
|
||||||
@@ -376,10 +379,9 @@ static int RetStrVal(char const *s, func_info *info)
|
|||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int FStrlen(func_info *info)
|
static int FStrlen(func_info *info)
|
||||||
{
|
{
|
||||||
Value *v = &ARG(0);
|
ASSERT_TYPE(0, STR_TYPE);
|
||||||
if (v->type != STR_TYPE) return E_BAD_TYPE;
|
|
||||||
RetVal.type = INT_TYPE;
|
RetVal.type = INT_TYPE;
|
||||||
size_t l = strlen(v->v.str);
|
size_t l = strlen(ARGSTR(0));
|
||||||
if (l > INT_MAX) return E_2HIGH;
|
if (l > INT_MAX) return E_2HIGH;
|
||||||
RETVAL = (int) l;
|
RETVAL = (int) l;
|
||||||
return OK;
|
return OK;
|
||||||
@@ -943,6 +945,8 @@ static int FAmpm(func_info *info)
|
|||||||
char const *pm = "PM";
|
char const *pm = "PM";
|
||||||
char const *ampm = NULL;
|
char const *ampm = NULL;
|
||||||
|
|
||||||
|
int include_leading_zero = 0;
|
||||||
|
|
||||||
char outbuf[128];
|
char outbuf[128];
|
||||||
|
|
||||||
if (ARG(0).type != DATETIME_TYPE && ARG(0).type != TIME_TYPE) {
|
if (ARG(0).type != DATETIME_TYPE && ARG(0).type != TIME_TYPE) {
|
||||||
@@ -957,6 +961,10 @@ static int FAmpm(func_info *info)
|
|||||||
if (Nargs >= 3) {
|
if (Nargs >= 3) {
|
||||||
ASSERT_TYPE(2, STR_TYPE);
|
ASSERT_TYPE(2, STR_TYPE);
|
||||||
pm = ARGSTR(2);
|
pm = ARGSTR(2);
|
||||||
|
if (Nargs >= 4) {
|
||||||
|
ASSERT_TYPE(3, INT_TYPE);
|
||||||
|
include_leading_zero = ARGV(3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
h = TIMEPART(ARG(0)) / 60;
|
h = TIMEPART(ARG(0)) / 60;
|
||||||
@@ -971,9 +979,17 @@ static int FAmpm(func_info *info)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ARG(0).type == DATETIME_TYPE) {
|
if (ARG(0).type == DATETIME_TYPE) {
|
||||||
snprintf(outbuf, sizeof(outbuf), "%04d%c%02d%c%02d%c%d%c%02d", yr, DateSep, mo+1, DateSep, da, DateTimeSep, h, TimeSep, m);
|
if (include_leading_zero) {
|
||||||
|
snprintf(outbuf, sizeof(outbuf), "%04d%c%02d%c%02d%c%02d%c%02d", yr, DateSep, mo+1, DateSep, da, DateTimeSep, h, TimeSep, m);
|
||||||
|
} else {
|
||||||
|
snprintf(outbuf, sizeof(outbuf), "%04d%c%02d%c%02d%c%d%c%02d", yr, DateSep, mo+1, DateSep, da, DateTimeSep, h, TimeSep, m);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
snprintf(outbuf, sizeof(outbuf), "%d%c%02d", h, TimeSep, m);
|
if (include_leading_zero) {
|
||||||
|
snprintf(outbuf, sizeof(outbuf), "%02d%c%02d", h, TimeSep, m);
|
||||||
|
} else {
|
||||||
|
snprintf(outbuf, sizeof(outbuf), "%d%c%02d", h, TimeSep, m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ampm = am;
|
ampm = am;
|
||||||
@@ -982,9 +998,17 @@ static int FAmpm(func_info *info)
|
|||||||
h -= 12;
|
h -= 12;
|
||||||
}
|
}
|
||||||
if (ARG(0).type == DATETIME_TYPE) {
|
if (ARG(0).type == DATETIME_TYPE) {
|
||||||
snprintf(outbuf, sizeof(outbuf), "%04d%c%02d%c%02d%c%d%c%02d", yr, DateSep, mo+1, DateSep, da, DateTimeSep, h, TimeSep, m);
|
if (include_leading_zero) {
|
||||||
|
snprintf(outbuf, sizeof(outbuf), "%04d%c%02d%c%02d%c%02d%c%02d", yr, DateSep, mo+1, DateSep, da, DateTimeSep, h, TimeSep, m);
|
||||||
|
} else {
|
||||||
|
snprintf(outbuf, sizeof(outbuf), "%04d%c%02d%c%02d%c%d%c%02d", yr, DateSep, mo+1, DateSep, da, DateTimeSep, h, TimeSep, m);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
snprintf(outbuf, sizeof(outbuf), "%d%c%02d", h, TimeSep, m);
|
if (include_leading_zero) {
|
||||||
|
snprintf(outbuf, sizeof(outbuf), "%02d%c%02d", h, TimeSep, m);
|
||||||
|
} else {
|
||||||
|
snprintf(outbuf, sizeof(outbuf), "%d%c%02d", h, TimeSep, m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ampm = pm;
|
ampm = pm;
|
||||||
}
|
}
|
||||||
@@ -1034,8 +1058,8 @@ static int FOrd(func_info *info)
|
|||||||
/* */
|
/* */
|
||||||
/* FPad - Pad a string to min length */
|
/* FPad - Pad a string to min length */
|
||||||
/* */
|
/* */
|
||||||
/* pad("1", "0", 4) --> "0004" */
|
/* pad("1", "0", 4) --> "0001" */
|
||||||
/* pad("1", "0", 4, 1) --> "4000" */
|
/* pad("1", "0", 4, 1) --> "1000" */
|
||||||
/* pad("foo", "bar", 7) -> "barbfoo" */
|
/* pad("foo", "bar", 7) -> "barbfoo" */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -1159,32 +1183,70 @@ static int FPlural(func_info *info)
|
|||||||
/* otherwise. */
|
/* otherwise. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int FIsAny(func_info *info)
|
static int FIsAny(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||||
{
|
{
|
||||||
int i;
|
DynamicBuffer DebugBuf;
|
||||||
RetVal.type = INT_TYPE;
|
expr_node *cur;
|
||||||
RETVAL = 0;
|
int r;
|
||||||
for (i=1; i<Nargs; i++) {
|
|
||||||
if (ARG(0).type == ARG(i).type) {
|
Value v;
|
||||||
if (ARG(0).type == STR_TYPE) {
|
Value candidate;
|
||||||
if (!strcmp(ARGSTR(0), ARGSTR(i))) {
|
|
||||||
RETVAL = 1;
|
ans->type = INT_TYPE;
|
||||||
return OK;
|
ans->v.val = 0;
|
||||||
}
|
|
||||||
} else {
|
DBG(DBufInit(&DebugBuf));
|
||||||
if (ARGV(0) == ARGV(i)) {
|
DBG(PUT("isany("));
|
||||||
RETVAL = 1;
|
|
||||||
return OK;
|
cur = node->child;
|
||||||
}
|
r = evaluate_expr_node(cur, locals, &v, nonconst);
|
||||||
|
if (r != OK) {
|
||||||
|
DBG(DBufFree(&DebugBuf));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
DBG(PUT(PrintValue(&v, NULL)));
|
||||||
|
while(cur->sibling) {
|
||||||
|
cur = cur->sibling;
|
||||||
|
r = evaluate_expr_node(cur, locals, &candidate, nonconst);
|
||||||
|
if (r != OK) {
|
||||||
|
DestroyValue(v);
|
||||||
|
DBG(DBufFree(&DebugBuf));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
DBG(PUT(", "));
|
||||||
|
DBG(PUT(PrintValue(&candidate, NULL)));
|
||||||
|
if (candidate.type != v.type) {
|
||||||
|
DestroyValue(candidate);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (v.type == STR_TYPE) {
|
||||||
|
if (strcmp(v.v.str, candidate.v.str)) {
|
||||||
|
DestroyValue(candidate);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (v.v.val != candidate.v.val) {
|
||||||
|
DestroyValue(candidate);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DestroyValue(candidate);
|
||||||
|
ans->v.val = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DestroyValue(v);
|
||||||
|
if (DebugFlag & DB_PRTEXPR) {
|
||||||
|
while(cur->sibling) {
|
||||||
|
cur = cur->sibling;
|
||||||
|
PUT(", ?");
|
||||||
|
}
|
||||||
|
PUT(") => ");
|
||||||
|
PUT(PrintValue(ans, NULL));
|
||||||
|
OUT();
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Debugging helpers for "choose()" and "iif() */
|
|
||||||
#define PUT(x) DBufPuts(&DebugBuf, x)
|
|
||||||
#define OUT() do { fprintf(ErrFp, "%s\n", DBufValue(&DebugBuf)); DBufFree(&DebugBuf); } while(0)
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* FChoose */
|
/* FChoose */
|
||||||
@@ -1200,7 +1262,7 @@ static int FChoose(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
|||||||
int r;
|
int r;
|
||||||
int n;
|
int n;
|
||||||
int nargs = node->num_kids;
|
int nargs = node->num_kids;
|
||||||
Value(v);
|
Value v;
|
||||||
DBG(DBufInit(&DebugBuf));
|
DBG(DBufInit(&DebugBuf));
|
||||||
DBG(PUT("choose("));
|
DBG(PUT("choose("));
|
||||||
|
|
||||||
@@ -1222,6 +1284,7 @@ static int FChoose(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
|||||||
PUT(ErrMsg[E_BAD_TYPE]);
|
PUT(ErrMsg[E_BAD_TYPE]);
|
||||||
OUT();
|
OUT();
|
||||||
}
|
}
|
||||||
|
Eprint("choose(): %s", ErrMsg[E_BAD_TYPE]);
|
||||||
return E_BAD_TYPE;
|
return E_BAD_TYPE;
|
||||||
}
|
}
|
||||||
n = v.v.val;
|
n = v.v.val;
|
||||||
@@ -1912,7 +1975,6 @@ static int FIndex(func_info *info)
|
|||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||||
{
|
{
|
||||||
int istrue;
|
|
||||||
int r;
|
int r;
|
||||||
int done;
|
int done;
|
||||||
Value v;
|
Value v;
|
||||||
@@ -1952,26 +2014,8 @@ static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
|||||||
done = 1;
|
done = 1;
|
||||||
PUT(PrintValue(&v, NULL));
|
PUT(PrintValue(&v, NULL));
|
||||||
}
|
}
|
||||||
if (v.type != STR_TYPE && v.type != INT_TYPE) {
|
|
||||||
if (DebugFlag & DB_PRTEXPR) {
|
|
||||||
cur = cur->sibling;
|
|
||||||
while(cur) {
|
|
||||||
PUT(", ?");
|
|
||||||
cur = cur->sibling;
|
|
||||||
}
|
|
||||||
PUT(") => ");
|
|
||||||
PUT(ErrMsg[E_BAD_TYPE]);
|
|
||||||
OUT();
|
|
||||||
}
|
|
||||||
return E_BAD_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v.type == INT_TYPE) {
|
if (truthy(&v)) {
|
||||||
istrue = v.v.val;
|
|
||||||
} else {
|
|
||||||
istrue = *(v.v.str);
|
|
||||||
}
|
|
||||||
if (istrue) {
|
|
||||||
r = evaluate_expr_node(cur->sibling, locals, ans, nonconst);
|
r = evaluate_expr_node(cur->sibling, locals, ans, nonconst);
|
||||||
if (r == OK && (DebugFlag & DB_PRTEXPR)) {
|
if (r == OK && (DebugFlag & DB_PRTEXPR)) {
|
||||||
PUT(", ");
|
PUT(", ");
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ EXTERN int CurMon;
|
|||||||
EXTERN int CurYear;
|
EXTERN int CurYear;
|
||||||
EXTERN int LineNo;
|
EXTERN int LineNo;
|
||||||
EXTERN int FreshLine;
|
EXTERN int FreshLine;
|
||||||
|
EXTERN int WarnedAboutImplicit;
|
||||||
EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS];
|
EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS];
|
||||||
|
|
||||||
EXTERN INIT( int MaxLateMinutes, 0);
|
EXTERN INIT( int MaxLateMinutes, 0);
|
||||||
@@ -78,9 +79,12 @@ EXTERN INIT( int ExpressionEvaluationDisabled, 0);
|
|||||||
EXTERN INIT( int ExpressionEvaluationTimeLimit, 0);
|
EXTERN INIT( int ExpressionEvaluationTimeLimit, 0);
|
||||||
EXTERN INIT( volatile sig_atomic_t ExpressionTimeLimitExceeded, 0);
|
EXTERN INIT( volatile sig_atomic_t ExpressionTimeLimitExceeded, 0);
|
||||||
EXTERN INIT( int IgnoreOnce, 0);
|
EXTERN INIT( int IgnoreOnce, 0);
|
||||||
EXTERN INIT( int SortByTime, 0);
|
EXTERN INIT( char const *OnceFile, NULL);
|
||||||
EXTERN INIT( int SortByDate, 0);
|
EXTERN INIT( int OnceDate, -1);
|
||||||
EXTERN INIT( int SortByPrio, 0);
|
EXTERN INIT( int ProcessedOnce, 0);
|
||||||
|
EXTERN INIT( int SortByTime, SORT_NONE);
|
||||||
|
EXTERN INIT( int SortByDate, SORT_NONE);
|
||||||
|
EXTERN INIT( int SortByPrio, SORT_NONE);
|
||||||
EXTERN INIT( int UntimedBeforeTimed, 0);
|
EXTERN INIT( int UntimedBeforeTimed, 0);
|
||||||
EXTERN INIT( int DefaultPrio, NO_PRIORITY);
|
EXTERN INIT( int DefaultPrio, NO_PRIORITY);
|
||||||
EXTERN INIT( int SysTime, -1);
|
EXTERN INIT( int SysTime, -1);
|
||||||
|
|||||||
@@ -241,7 +241,6 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
arg++;
|
arg++;
|
||||||
if (!*arg) {
|
if (!*arg) {
|
||||||
UseStdin = 1;
|
UseStdin = 1;
|
||||||
IgnoreOnce = 1;
|
|
||||||
i--;
|
i--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -324,6 +323,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
NextMode = 1;
|
NextMode = 1;
|
||||||
DontQueue = 1;
|
DontQueue = 1;
|
||||||
Daemon = 0;
|
Daemon = 0;
|
||||||
|
IgnoreOnce = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
@@ -457,6 +457,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
case 'C':
|
case 'C':
|
||||||
|
IgnoreOnce = 1;
|
||||||
DoCalendar = 1;
|
DoCalendar = 1;
|
||||||
weeks = 0;
|
weeks = 0;
|
||||||
/* Parse the flags */
|
/* Parse the flags */
|
||||||
@@ -501,6 +502,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
case 's':
|
case 's':
|
||||||
case 'S':
|
case 'S':
|
||||||
DoSimpleCalendar = 1;
|
DoSimpleCalendar = 1;
|
||||||
|
IgnoreOnce = 1;
|
||||||
weeks = 0;
|
weeks = 0;
|
||||||
while(*arg) {
|
while(*arg) {
|
||||||
if (*arg == 'a' || *arg == 'A') {
|
if (*arg == 'a' || *arg == 'A') {
|
||||||
@@ -527,6 +529,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
case 'p':
|
case 'p':
|
||||||
case 'P':
|
case 'P':
|
||||||
DoSimpleCalendar = 1;
|
DoSimpleCalendar = 1;
|
||||||
|
IgnoreOnce = 1;
|
||||||
PsCal = PSCAL_LEVEL1;
|
PsCal = PSCAL_LEVEL1;
|
||||||
while (*arg == 'a' || *arg == 'A' ||
|
while (*arg == 'a' || *arg == 'A' ||
|
||||||
*arg == 'q' || *arg == 'Q' ||
|
*arg == 'q' || *arg == 'Q' ||
|
||||||
@@ -720,6 +723,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
|
|
||||||
if (rep > 0) {
|
if (rep > 0) {
|
||||||
Iterations = rep;
|
Iterations = rep;
|
||||||
|
IgnoreOnce = 1;
|
||||||
DontQueue = 1;
|
DontQueue = 1;
|
||||||
Daemon = 0;
|
Daemon = 0;
|
||||||
}
|
}
|
||||||
@@ -1115,6 +1119,8 @@ guess_terminal_background(int *r, int *g, int *b)
|
|||||||
|
|
||||||
if (n != 8) {
|
if (n != 8) {
|
||||||
/* write failed... WTF? Not much we can do */
|
/* write failed... WTF? Not much we can do */
|
||||||
|
tty_reset(ttyfd);
|
||||||
|
close(ttyfd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1138,6 +1144,7 @@ guess_terminal_background(int *r, int *g, int *b)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tty_reset(ttyfd);
|
tty_reset(ttyfd);
|
||||||
|
close(ttyfd);
|
||||||
buf[n+1] = 0;
|
buf[n+1] = 0;
|
||||||
if (n < 25) {
|
if (n < 25) {
|
||||||
/* Too short */
|
/* Too short */
|
||||||
|
|||||||
66
src/main.c
66
src/main.c
@@ -68,17 +68,24 @@ exitfunc(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sigalrm(int)
|
static void sigalrm(int sig)
|
||||||
{
|
{
|
||||||
|
UNUSED(sig);
|
||||||
if (ExpressionEvaluationTimeLimit) {
|
if (ExpressionEvaluationTimeLimit) {
|
||||||
ExpressionTimeLimitExceeded = 1;
|
ExpressionTimeLimitExceeded = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sigxcpu(int)
|
static void sigxcpu(int sig)
|
||||||
{
|
{
|
||||||
write(STDERR_FILENO, "\n\nmax-execution-time exceeded.\n\n", 32);
|
|
||||||
_exit(1);
|
UNUSED(sig);
|
||||||
|
int r = write(STDERR_FILENO, "\n\nmax-execution-time exceeded.\n\n", 32);
|
||||||
|
|
||||||
|
/* Pretend to use r to avoid compiler warning */
|
||||||
|
/* cppcheck-suppress duplicateExpression */
|
||||||
|
/* cppcheck-suppress knownArgument */
|
||||||
|
_exit(1 + (r-r));
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -235,7 +242,8 @@ static void DoReminders(void)
|
|||||||
if (!UseStdin) {
|
if (!UseStdin) {
|
||||||
FileAccessDate = GetAccessDate(InitialFile);
|
FileAccessDate = GetAccessDate(InitialFile);
|
||||||
} else {
|
} else {
|
||||||
FileAccessDate = DSEToday;
|
FileAccessDate = DSEToday - 1;
|
||||||
|
if (FileAccessDate < 0) FileAccessDate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FileAccessDate < 0) {
|
if (FileAccessDate < 0) {
|
||||||
@@ -345,9 +353,16 @@ static void DoReminders(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
/* If we don't recognize the command, do a REM by default */
|
/* If we don't recognize the command, do a REM by default, but warn */
|
||||||
|
|
||||||
default: DestroyParser(&p); CreateParser(CurLine, &p); purge_handled = 1; r=DoRem(&p); break;
|
default:
|
||||||
|
Wprint("Unrecognized command; interpreting as REM");
|
||||||
|
WarnedAboutImplicit = 1;
|
||||||
|
DestroyParser(&p);
|
||||||
|
CreateParser(CurLine, &p);
|
||||||
|
purge_handled = 1;
|
||||||
|
r=DoRem(&p);
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (r && (!Hush || r != E_RUN_DISABLED)) {
|
if (r && (!Hush || r != E_RUN_DISABLED)) {
|
||||||
@@ -1886,3 +1901,40 @@ get_month_name(int mon)
|
|||||||
if (DynamicMonthName[mon]) return DynamicMonthName[mon];
|
if (DynamicMonthName[mon]) return DynamicMonthName[mon];
|
||||||
return MonthName[mon];
|
return MonthName[mon];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int GetOnceDateFromFile(void)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
int once_date = 0;
|
||||||
|
|
||||||
|
fp = fopen(OnceFile, "r");
|
||||||
|
if (fp) {
|
||||||
|
if (fscanf(fp, "%d", &once_date) != 1) {
|
||||||
|
once_date = 0;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
/* Save today to file */
|
||||||
|
fp = fopen(OnceFile, "w");
|
||||||
|
if (!fp) {
|
||||||
|
Wprint("Warning: Unable to save ONCE timestamp to %s: %s",
|
||||||
|
OnceFile, strerror(errno));
|
||||||
|
return once_date;
|
||||||
|
}
|
||||||
|
fprintf(fp, "%d\n# This is a timestamp file used by Remind to track ONCE reminders.\n# Do not edit or delete it.\n", DSEToday);
|
||||||
|
fclose(fp);
|
||||||
|
return once_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetOnceDate(void)
|
||||||
|
{
|
||||||
|
ProcessedOnce = 1;
|
||||||
|
if (IgnoreOnce || !OnceFile || !*OnceFile) {
|
||||||
|
return FileAccessDate;
|
||||||
|
}
|
||||||
|
if (OnceDate < 0) {
|
||||||
|
OnceDate = GetOnceDateFromFile();
|
||||||
|
}
|
||||||
|
return OnceDate;
|
||||||
|
}
|
||||||
|
|||||||
14
src/moon.c
14
src/moon.c
@@ -100,21 +100,12 @@ static double phase (double, double *, double *, double *, double *, double *, d
|
|||||||
#define mmlong 64.975464 /* Moon's mean lonigitude at the epoch */
|
#define mmlong 64.975464 /* Moon's mean lonigitude at the epoch */
|
||||||
#define mmlongp 349.383063 /* Mean longitude of the perigee at the
|
#define mmlongp 349.383063 /* Mean longitude of the perigee at the
|
||||||
epoch */
|
epoch */
|
||||||
#define mlnode 151.950429 /* Mean longitude of the node at the
|
|
||||||
epoch */
|
|
||||||
#define minc 5.145396 /* Inclination of the Moon's orbit */
|
|
||||||
#define mecc 0.054900 /* Eccentricity of the Moon's orbit */
|
#define mecc 0.054900 /* Eccentricity of the Moon's orbit */
|
||||||
#define mangsiz 0.5181 /* Moon's angular size at distance a
|
#define mangsiz 0.5181 /* Moon's angular size at distance a
|
||||||
from Earth */
|
from Earth */
|
||||||
#define msmax 384401.0 /* Semi-major axis of Moon's orbit in km */
|
#define msmax 384401.0 /* Semi-major axis of Moon's orbit in km */
|
||||||
#define mparallax 0.9507 /* Parallax at distance a from Earth */
|
|
||||||
#define synmonth 29.53058868 /* Synodic month (new Moon to new Moon) */
|
#define synmonth 29.53058868 /* Synodic month (new Moon to new Moon) */
|
||||||
#define lunatbase 2423436.0 /* Base date for E. W. Brown's numbered
|
|
||||||
series of lunations (1923 January 16) */
|
|
||||||
|
|
||||||
/* Properties of the Earth */
|
|
||||||
|
|
||||||
#define earthrad 6378.16 /* Radius of Earth in kilometres */
|
|
||||||
#ifdef PI
|
#ifdef PI
|
||||||
#undef PI
|
#undef PI
|
||||||
#endif
|
#endif
|
||||||
@@ -123,11 +114,6 @@ static double phase (double, double *, double *, double *, double *, double *, d
|
|||||||
|
|
||||||
/* Handy mathematical functions */
|
/* Handy mathematical functions */
|
||||||
|
|
||||||
#ifdef sgn
|
|
||||||
#undef sgn
|
|
||||||
#endif
|
|
||||||
#define sgn(x) (((x) < 0) ? -1 : ((x) > 0 ? 1 : 0)) /* Extract sign */
|
|
||||||
|
|
||||||
#ifdef abs
|
#ifdef abs
|
||||||
#undef abs
|
#undef abs
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ expr_node *parse_expression(char const **e, int *r, Var *locals);
|
|||||||
|
|
||||||
int evaluate_expression(expr_node *node, Value *locals, Value *ans, int *nonconst);
|
int evaluate_expression(expr_node *node, Value *locals, Value *ans, int *nonconst);
|
||||||
int evaluate_expr_node(expr_node *node, Value *locals, Value *ans, int *nonconst);
|
int evaluate_expr_node(expr_node *node, Value *locals, Value *ans, int *nonconst);
|
||||||
|
int truthy(Value const *v);
|
||||||
|
|
||||||
void print_expr_tree(expr_node *node, FILE *fp);
|
void print_expr_tree(expr_node *node, FILE *fp);
|
||||||
void unlimit_execution_time(void);
|
void unlimit_execution_time(void);
|
||||||
expr_node *free_expr_tree(expr_node *node);
|
expr_node *free_expr_tree(expr_node *node);
|
||||||
@@ -225,6 +227,7 @@ void pop_call(void);
|
|||||||
void FixSpecialType(Trigger *trig);
|
void FixSpecialType(Trigger *trig);
|
||||||
void WriteJSONTrigger(Trigger const *t, int include_tags, int today);
|
void WriteJSONTrigger(Trigger const *t, int include_tags, int today);
|
||||||
void WriteJSONTimeTrigger(TimeTrig const *tt);
|
void WriteJSONTimeTrigger(TimeTrig const *tt);
|
||||||
|
int GetOnceDate(void);
|
||||||
#ifdef REM_USE_WCHAR
|
#ifdef REM_USE_WCHAR
|
||||||
#define _XOPEN_SOURCE 600
|
#define _XOPEN_SOURCE 600
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ enum expr_node_type
|
|||||||
N_FREE,
|
N_FREE,
|
||||||
N_ERROR,
|
N_ERROR,
|
||||||
N_CONSTANT,
|
N_CONSTANT,
|
||||||
|
N_SHORT_STR,
|
||||||
N_LOCAL_VAR,
|
N_LOCAL_VAR,
|
||||||
N_SHORT_VAR,
|
N_SHORT_VAR,
|
||||||
N_VARIABLE,
|
N_VARIABLE,
|
||||||
@@ -316,5 +317,6 @@ typedef struct udf_struct {
|
|||||||
int nargs;
|
int nargs;
|
||||||
char const *filename;
|
char const *filename;
|
||||||
int lineno;
|
int lineno;
|
||||||
|
int recurse_flag;
|
||||||
} UserFunc;
|
} UserFunc;
|
||||||
|
|
||||||
|
|||||||
@@ -115,17 +115,6 @@ int DoFset(ParsePtr p)
|
|||||||
}
|
}
|
||||||
orig_namelen = buf.len;
|
orig_namelen = buf.len;
|
||||||
|
|
||||||
/* Should be followed by '(' */
|
|
||||||
c = ParseNonSpaceChar(p, &r, 0);
|
|
||||||
if (r) {
|
|
||||||
DBufFree(&buf);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
if (c != '(') {
|
|
||||||
DBufFree(&buf);
|
|
||||||
return E_PARSE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert to lower-case */
|
/* Convert to lower-case */
|
||||||
strtolower(DBufValue(&buf));
|
strtolower(DBufValue(&buf));
|
||||||
|
|
||||||
@@ -140,7 +129,22 @@ int DoFset(ParsePtr p)
|
|||||||
/* We already have it! Our work here is done. */
|
/* We already have it! Our work here is done. */
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
/* Warn about redefinition */
|
||||||
|
Wprint("Function %s redefined (previously defined at %s:%d)",
|
||||||
|
existing->name, existing->filename, existing->lineno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Should be followed by '(' */
|
||||||
|
c = ParseNonSpaceChar(p, &r, 0);
|
||||||
|
if (r) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if (c != '(') {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_PARSE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
func = NEW(UserFunc);
|
func = NEW(UserFunc);
|
||||||
if (!func) {
|
if (!func) {
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
@@ -156,6 +160,7 @@ int DoFset(ParsePtr p)
|
|||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
func->lineno = LineNo;
|
func->lineno = LineNo;
|
||||||
|
func->recurse_flag = 0;
|
||||||
StrnCpy(func->name, DBufValue(&buf), VAR_NAME_LEN);
|
StrnCpy(func->name, DBufValue(&buf), VAR_NAME_LEN);
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
if (!Hush) {
|
if (!Hush) {
|
||||||
@@ -202,6 +207,11 @@ int DoFset(ParsePtr p)
|
|||||||
local_array[i+1].next = NULL;
|
local_array[i+1].next = NULL;
|
||||||
func->nargs++;
|
func->nargs++;
|
||||||
c = ParseNonSpaceChar(p, &r, 0);
|
c = ParseNonSpaceChar(p, &r, 0);
|
||||||
|
if (r) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
DestroyUserFunc(func);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
if (c == ')') break;
|
if (c == ')') break;
|
||||||
else if (c != ',') {
|
else if (c != ',') {
|
||||||
DestroyUserFunc(func);
|
DestroyUserFunc(func);
|
||||||
@@ -212,6 +222,10 @@ int DoFset(ParsePtr p)
|
|||||||
|
|
||||||
/* Allow an optional = sign: FSET f(x) = x*x */
|
/* Allow an optional = sign: FSET f(x) = x*x */
|
||||||
c = ParseNonSpaceChar(p, &r, 1);
|
c = ParseNonSpaceChar(p, &r, 1);
|
||||||
|
if (r) {
|
||||||
|
DestroyUserFunc(func);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
if (c == '=') {
|
if (c == '=') {
|
||||||
(void) ParseNonSpaceChar(p, &r, 0);
|
(void) ParseNonSpaceChar(p, &r, 0);
|
||||||
}
|
}
|
||||||
@@ -236,14 +250,15 @@ int DoFset(ParsePtr p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
c = ParseNonSpaceChar(p, &r, 1);
|
c = ParseNonSpaceChar(p, &r, 1);
|
||||||
if (c != 0) {
|
if (c != 0 || r != 0) {
|
||||||
DestroyUserFunc(func);
|
DestroyUserFunc(func);
|
||||||
|
if (r != 0) return r;
|
||||||
return E_EXPECTING_EOL;
|
return E_EXPECTING_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the argument names */
|
/* Save the argument names */
|
||||||
if (func->nargs) {
|
if (func->nargs) {
|
||||||
func->args = calloc(sizeof(char *), func->nargs);
|
func->args = calloc(func->nargs, sizeof(char *));
|
||||||
for (i=0; i<func->nargs; i++) {
|
for (i=0; i<func->nargs; i++) {
|
||||||
func->args[i] = StrDup(local_array[i].name);
|
func->args[i] = StrDup(local_array[i].name);
|
||||||
if (!func->args[i]) {
|
if (!func->args[i]) {
|
||||||
|
|||||||
42
src/var.c
42
src/var.c
@@ -164,6 +164,40 @@ static int latitude_func(int do_set, Value *val)
|
|||||||
return latitude_longitude_func(do_set, val, &Latitude, -90.0, 90.0);
|
return latitude_longitude_func(do_set, val, &Latitude, -90.0, 90.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int oncefile_func(int do_set, Value *val)
|
||||||
|
{
|
||||||
|
if (do_set) {
|
||||||
|
if (val->type != STR_TYPE) return E_BAD_TYPE;
|
||||||
|
if (! (*val->v.str) && (!OnceFile || !*OnceFile)) {
|
||||||
|
/* Trying to set already-empty string to empty string */
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
if (OnceFile && !strcmp(OnceFile, val->v.str)) {
|
||||||
|
/* Trying to set to the exact same value */
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ProcessedOnce) {
|
||||||
|
Wprint("Not setting $OnceFile: Already processed a reminder with a ONCE clause");
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
if (OnceFile) {
|
||||||
|
free( (void *) OnceFile);
|
||||||
|
}
|
||||||
|
OnceFile = StrDup(val->v.str);
|
||||||
|
if (!OnceFile) return E_NO_MEM;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
if (!OnceFile) {
|
||||||
|
val->v.str = StrDup("");
|
||||||
|
} else {
|
||||||
|
val->v.str = StrDup(OnceFile);
|
||||||
|
}
|
||||||
|
if (!val->v.str) return E_NO_MEM;
|
||||||
|
val->type = STR_TYPE;
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
}
|
||||||
static int terminal_bg_func(int do_set, Value *val)
|
static int terminal_bg_func(int do_set, Value *val)
|
||||||
{
|
{
|
||||||
UNUSED(do_set);
|
UNUSED(do_set);
|
||||||
@@ -553,7 +587,7 @@ int DoSet (Parser *p)
|
|||||||
{
|
{
|
||||||
Value v;
|
Value v;
|
||||||
int r;
|
int r;
|
||||||
|
int ch;
|
||||||
DynamicBuffer buf;
|
DynamicBuffer buf;
|
||||||
DynamicBuffer buf2;
|
DynamicBuffer buf2;
|
||||||
DBufInit(&buf);
|
DBufInit(&buf);
|
||||||
@@ -563,8 +597,11 @@ int DoSet (Parser *p)
|
|||||||
if (r) return r;
|
if (r) return r;
|
||||||
|
|
||||||
/* Allow optional equals-sign: SET var = value */
|
/* Allow optional equals-sign: SET var = value */
|
||||||
if (ParseNonSpaceChar(p, &r, 1) == '=') {
|
ch = ParseNonSpaceChar(p, &r, 1);
|
||||||
|
if (r) return r;
|
||||||
|
if (ch == '=') {
|
||||||
ParseNonSpaceChar(p, &r, 0);
|
ParseNonSpaceChar(p, &r, 0);
|
||||||
|
if (r) return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->isnested) {
|
if (p->isnested) {
|
||||||
@@ -883,6 +920,7 @@ static SysVar SysVarArr[] = {
|
|||||||
{"NumTrig", 0, INT_TYPE, &NumTriggered, 0, 0 },
|
{"NumTrig", 0, INT_TYPE, &NumTriggered, 0, 0 },
|
||||||
{"October", 1, STR_TYPE, &DynamicMonthName[9], 0, 0 },
|
{"October", 1, STR_TYPE, &DynamicMonthName[9], 0, 0 },
|
||||||
{"On", 1, STR_TYPE, &DynamicOn, 0, 0 },
|
{"On", 1, STR_TYPE, &DynamicOn, 0, 0 },
|
||||||
|
{"OnceFile", 1, SPECIAL_TYPE, oncefile_func, 0, 0 },
|
||||||
{"ParseUntriggered", 1, INT_TYPE, &ParseUntriggered, 0, 1 },
|
{"ParseUntriggered", 1, INT_TYPE, &ParseUntriggered, 0, 1 },
|
||||||
{"Pm", 1, STR_TYPE, &DynamicPm, 0, 0 },
|
{"Pm", 1, STR_TYPE, &DynamicPm, 0, 0 },
|
||||||
{"PrefixLineNo", 0, INT_TYPE, &DoPrefixLineNo, 0, 0 },
|
{"PrefixLineNo", 0, INT_TYPE, &DoPrefixLineNo, 0, 0 },
|
||||||
|
|||||||
@@ -49,3 +49,7 @@ set a 15:00 - 14:44
|
|||||||
set a (1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+1))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
|
set a (1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+1))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
|
||||||
|
|
||||||
set a (1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+1)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
|
set a (1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+1)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
|
||||||
|
|
||||||
|
set a isany(1)
|
||||||
|
set a isany(1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6)
|
||||||
|
set a isany("foo", 1 + 1, 2:00 + 1, '2021-01-01' + 1, '2021-01-01@14:00' + 1, "f" + "oo", "fo" + "o")
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ FSET msgprefix(x) "Priority: " + x + "; Filename: " + filename() + ": "
|
|||||||
|
|
||||||
REM at 23:56 MSG foo
|
REM at 23:56 MSG foo
|
||||||
REM PRIORITY 42 at 23:57 MSG bar
|
REM PRIORITY 42 at 23:57 MSG bar
|
||||||
REM PRIORITY 999 at 23:58 MSQ quux
|
REM PRIORITY 999 at 23:58 MSG quux
|
||||||
DO queue2.rem
|
DO queue2.rem
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ set $LatMin 24
|
|||||||
set $LatSec 0
|
set $LatSec 0
|
||||||
|
|
||||||
IF $PSCAL
|
IF $PSCAL
|
||||||
[trigger(moondate(0))] SPECIAL MOON 0 -1 -1 [moontime(0)]
|
REM [trigger(moondate(0))] SPECIAL MOON 0 -1 -1 [moontime(0)]
|
||||||
[trigger(moondate(1))] SPECIAL MOON 1 -1 -1 [moontime(1)]
|
REM [trigger(moondate(1))] SPECIAL MOON 1 -1 -1 [moontime(1)]
|
||||||
[trigger(moondate(2))] SPECIAL MOON 2 -1 -1 [moontime(2)]
|
REM [trigger(moondate(2))] SPECIAL MOON 2 -1 -1 [moontime(2)]
|
||||||
[trigger(moondate(3))] SPECIAL MOON 3 -1 -1 [moontime(3)]
|
REM [trigger(moondate(3))] SPECIAL MOON 3 -1 -1 [moontime(3)]
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
REM 4 PS (First-Bit-Of-PS)
|
REM 4 PS (First-Bit-Of-PS)
|
||||||
|
|||||||
7
tests/test-once.rem
Normal file
7
tests/test-once.rem
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
BANNER %
|
||||||
|
SET $OnceFile "../tests/once.timestamp"
|
||||||
|
|
||||||
|
REM ONCE MSG This should only be issued once per day.
|
||||||
|
|
||||||
|
SET $OnceFile "../tests/once.timestamp"
|
||||||
|
SET $OnceFile "../tests/once-again.timestamp"
|
||||||
@@ -569,8 +569,34 @@ EOF
|
|||||||
|
|
||||||
../src/remind ../tests/if1.rem 2020-03-03 >> ../tests/test.out 2>&1
|
../src/remind ../tests/if1.rem 2020-03-03 >> ../tests/test.out 2>&1
|
||||||
|
|
||||||
|
# Test ONCE with a timestamp file
|
||||||
|
rm -f ../tests/once.timestamp
|
||||||
|
../src/remind ../tests/test-once.rem >> ../tests/test.out 2>&1
|
||||||
|
../src/remind ../tests/test-once.rem >> ../tests/test.out 2>&1
|
||||||
|
../src/remind ../tests/test-once.rem >> ../tests/test.out 2>&1
|
||||||
|
tail +2 ../tests/once.timestamp >> ../tests/test.out 2>&1
|
||||||
|
rm -f ../tests/once.timestamp
|
||||||
|
|
||||||
|
../src/remind - < ../tests/test-once.rem >> ../tests/test.out 2>&1
|
||||||
|
../src/remind - < ../tests/test-once.rem >> ../tests/test.out 2>&1
|
||||||
|
../src/remind - < ../tests/test-once.rem >> ../tests/test.out 2>&1
|
||||||
|
tail +2 ../tests/once.timestamp >> ../tests/test.out 2>&1
|
||||||
|
rm -f ../tests/once.timestamp
|
||||||
|
|
||||||
|
# Newlines in calendar output
|
||||||
|
(echo 'REM 16 MSG foo%_bar%_baz wookie quux apple %_ %_ %_ blech'; echo "REM 16 MSG ANOTHER") | ../src/remind -c -w80 - 1 sep 1990 >> ../tests/test.out 2>&1
|
||||||
|
|
||||||
# Remove references to SysInclude, which is build-specific
|
# Remove references to SysInclude, which is build-specific
|
||||||
grep -F -v '$SysInclude' < ../tests/test.out > ../tests/test.out.1 && mv -f ../tests/test.out.1 ../tests/test.out
|
grep -F -v '$SysInclude' < ../tests/test.out > ../tests/test.out.1 && mv -f ../tests/test.out.1 ../tests/test.out
|
||||||
|
|
||||||
|
# If "man" accepts the --warnings flag, test all the man pages.
|
||||||
|
man man | grep -e --warnings > /dev/null 2>&1
|
||||||
|
if test $? = 0 ; then
|
||||||
|
for i in ../man/*.1 ; do
|
||||||
|
man --warnings=w $i 2>>../tests/test.out 1>/dev/null
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
cmp -s ../tests/test.out ../tests/test.cmp
|
cmp -s ../tests/test.out ../tests/test.cmp
|
||||||
if [ "$?" = "0" ]; then
|
if [ "$?" = "0" ]; then
|
||||||
echo "Remind: Acceptance test PASSED"
|
echo "Remind: Acceptance test PASSED"
|
||||||
|
|||||||
1266
tests/test.cmp
1266
tests/test.cmp
File diff suppressed because one or more lines are too long
246
tests/test.rem
246
tests/test.rem
@@ -33,7 +33,7 @@ fset _h(x, y) trigger(hebdate(x,y))
|
|||||||
|
|
||||||
# Test case from Remind mailing list
|
# Test case from Remind mailing list
|
||||||
set mltest "a b"
|
set mltest "a b"
|
||||||
INCLUDECMD printf 'REM %s\n' [mltest]
|
INCLUDECMD printf 'REM MSG %s\n' [mltest]
|
||||||
|
|
||||||
# Disabling RUN in an !includecmd
|
# Disabling RUN in an !includecmd
|
||||||
INCLUDECMD !echo MSG foo
|
INCLUDECMD !echo MSG foo
|
||||||
@@ -49,38 +49,38 @@ INCLUDECMD echo MSG foo
|
|||||||
RUN ON
|
RUN ON
|
||||||
INCLUDECMD echo MSG foo
|
INCLUDECMD echo MSG foo
|
||||||
|
|
||||||
[_h(1, "Tishrey")] MSG Rosh Hashana 1
|
REM [_h(1, "Tishrey")] MSG Rosh Hashana 1
|
||||||
[_h(2, "Tishrey")] MSG Rosh Hashana 2
|
REM [_h(2, "Tishrey")] MSG Rosh Hashana 2
|
||||||
[_h(3, "Tishrey")] MSG Tzom Gedalia
|
REM [_h(3, "Tishrey")] MSG Tzom Gedalia
|
||||||
[_h(10, "Tishrey")] MSG Yom Kippur
|
REM [_h(10, "Tishrey")] MSG Yom Kippur
|
||||||
[_h(15, "Tishrey")] MSG Sukkot 1
|
REM [_h(15, "Tishrey")] MSG Sukkot 1
|
||||||
[_h(25, "Kislev")] MSG Channuka
|
REM [_h(25, "Kislev")] MSG Channuka
|
||||||
[_h(10, "Tevet")] MSG Asara B'Tevet
|
REM [_h(10, "Tevet")] MSG Asara B'Tevet
|
||||||
[_h(15, "Shvat")] MSG Tu B'Shvat
|
REM [_h(15, "Shvat")] MSG Tu B'Shvat
|
||||||
[_h(15, "Adar A")] MSG Purim Katan
|
REM [_h(15, "Adar A")] MSG Purim Katan
|
||||||
[_h(14, "Adar")] MSG Purim
|
REM [_h(14, "Adar")] MSG Purim
|
||||||
[_h(15, "Nisan")] MSG Pesach
|
REM [_h(15, "Nisan")] MSG Pesach
|
||||||
[_h(27, "Nisan")] MSG Yom HaShoah
|
REM [_h(27, "Nisan")] MSG Yom HaShoah
|
||||||
[_h(4, "Iyar")] MSG Yom HaZikaron
|
REM [_h(4, "Iyar")] MSG Yom HaZikaron
|
||||||
[_h(5, "Iyar")] MSG Yom Ha'atzmaut
|
REM [_h(5, "Iyar")] MSG Yom Ha'atzmaut
|
||||||
[_h(28, "Iyar")] MSG Yom Yerushalayim
|
REM [_h(28, "Iyar")] MSG Yom Yerushalayim
|
||||||
[_h(6, "Sivan")] MSG Shavuot
|
REM [_h(6, "Sivan")] MSG Shavuot
|
||||||
[_h(9, "Av")] MSG Tish'a B'Av
|
REM [_h(9, "Av")] MSG Tish'a B'Av
|
||||||
|
|
||||||
# Test some jahrzeit cases
|
# Test some jahrzeit cases
|
||||||
fset _i(x,y,z,a) trigger(hebdate(x,y,z,a))
|
fset _i(x,y,z,a) trigger(hebdate(x,y,z,a))
|
||||||
[_i(30, "Heshvan", today(), 5759)] MSG Complete-Complete
|
REM [_i(30, "Heshvan", today(), 5759)] MSG Complete-Complete
|
||||||
[_i(30, "Heshvan", today(), 5760)] MSG Complete-Defective
|
REM [_i(30, "Heshvan", today(), 5760)] MSG Complete-Defective
|
||||||
[_i(30, "Heshvan", today(), 5761)] MSG Illegal
|
REM [_i(30, "Heshvan", today(), 5761)] MSG Illegal
|
||||||
|
|
||||||
[_i(30, "Kislev", today(), 5759)] MSG Complete-Complete
|
REM [_i(30, "Kislev", today(), 5759)] MSG Complete-Complete
|
||||||
[_i(30, "Kislev", today(), 5760)] MSG Complete-Defective
|
REM [_i(30, "Kislev", today(), 5760)] MSG Complete-Defective
|
||||||
[_i(30, "Kislev", today(), 5761)] MSG Illegal
|
REM [_i(30, "Kislev", today(), 5761)] MSG Illegal
|
||||||
|
|
||||||
[_i(30, "Adar A", today(), 5755)] MSG Leap
|
REM [_i(30, "Adar A", today(), 5755)] MSG Leap
|
||||||
[_i(30, "Adar A", today(), 5756)] MSG Illegal
|
REM [_i(30, "Adar A", today(), 5756)] MSG Illegal
|
||||||
[_i(29, "Adar A", today(), 5755)] MSG Leap
|
REM [_i(29, "Adar A", today(), 5755)] MSG Leap
|
||||||
[_i(29, "Adar A", today(), 5756)] MSG Illegal
|
REM [_i(29, "Adar A", today(), 5756)] MSG Illegal
|
||||||
|
|
||||||
# This causes a parse error on version 03.01.01
|
# This causes a parse error on version 03.01.01
|
||||||
REM 1990-01-01 SATISFY 1
|
REM 1990-01-01 SATISFY 1
|
||||||
@@ -238,8 +238,8 @@ CLEAR-OMIT-CONTEXT
|
|||||||
|
|
||||||
REM tag ill,egal MSG bad tag
|
REM tag ill,egal MSG bad tag
|
||||||
REM MSG The tags are: [trigtags()]
|
REM MSG The tags are: [trigtags()]
|
||||||
REM TAG foo The tags are: [trigtags()]
|
REM TAG foo MSG The tags are: [trigtags()]
|
||||||
REM TAG foo TAG bar TAG quux TAG znort TAG cabbage The tags are: [trigtags()]
|
REM TAG foo TAG bar TAG quux TAG znort TAG cabbage MSG The tags are: [trigtags()]
|
||||||
REM MSG The tags are: [trigtags()]
|
REM MSG The tags are: [trigtags()]
|
||||||
|
|
||||||
# Test ADDOMIT
|
# Test ADDOMIT
|
||||||
@@ -559,11 +559,11 @@ REM 1992-01-01 *1 UNTIL 1991-12-31 MSG Diagnosed
|
|||||||
set x '1992-01-01'
|
set x '1992-01-01'
|
||||||
REM [x] *1 UNTIL 1991-12-31 MSG Not diagnosed - nonconst expression
|
REM [x] *1 UNTIL 1991-12-31 MSG Not diagnosed - nonconst expression
|
||||||
|
|
||||||
REM MON FROM 1992-01-01 UNTIL 1991-12-31 Diagnosed
|
REM MON FROM 1992-01-01 UNTIL 1991-12-31 MSG Diagnosed
|
||||||
REM MON SCANFROM 1992-01-01 UNTIL 1991-12-31 Diagnosed
|
REM MON SCANFROM 1992-01-01 UNTIL 1991-12-31 MSG Diagnosed
|
||||||
|
|
||||||
REM MON FROM [x] UNTIL 1991-12-31 Not diagnosed
|
REM MON FROM [x] UNTIL 1991-12-31 MSG Not diagnosed
|
||||||
REM MON SCANFROM [x] UNTIL 1991-12-31 Not diagnosed
|
REM MON SCANFROM [x] UNTIL 1991-12-31 MSG Not diagnosed
|
||||||
|
|
||||||
REM 1992-01-01 UNTIL 1992-02-02 MSG Diagnosed
|
REM 1992-01-01 UNTIL 1992-02-02 MSG Diagnosed
|
||||||
REM [x] UNTIL 1992-02-02 MSG Diagnosed
|
REM [x] UNTIL 1992-02-02 MSG Diagnosed
|
||||||
@@ -575,7 +575,7 @@ OMIT December 25 MSG X
|
|||||||
OMIT 26 Dec 2010 THROUGH 27 Dec 2010 MSG This is not legal
|
OMIT 26 Dec 2010 THROUGH 27 Dec 2010 MSG This is not legal
|
||||||
OMIT DUMP
|
OMIT DUMP
|
||||||
# Regression test for bugfix in Hebrew calendar Adar jahrzeit
|
# Regression test for bugfix in Hebrew calendar Adar jahrzeit
|
||||||
[_i(14, "Adar", today(), 5761)] MSG Purim
|
REM [_i(14, "Adar", today(), 5761)] MSG Purim
|
||||||
|
|
||||||
# Regression test for bug found by Larry Hynes
|
# Regression test for bug found by Larry Hynes
|
||||||
REM SATISFY [day(trigdate()-25) == 14] MSG Foo
|
REM SATISFY [day(trigdate()-25) == 14] MSG Foo
|
||||||
@@ -708,6 +708,56 @@ set x ampm(21:12) + ""
|
|||||||
set x ampm(22:12) + ""
|
set x ampm(22:12) + ""
|
||||||
set x ampm(23:12) + ""
|
set x ampm(23:12) + ""
|
||||||
|
|
||||||
|
set x ampm(0:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(1:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(2:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(3:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(4:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(5:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(6:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(7:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(8:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(9:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(10:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(11:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(12:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(13:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(14:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(15:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(16:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(17:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(18:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(19:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(20:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(21:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(22:12,"AM", "PM", 1) + ""
|
||||||
|
set x ampm(23:12,"AM", "PM", 1) + ""
|
||||||
|
|
||||||
|
set x ampm(0:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(0:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(2:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(3:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(4:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(5:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(6:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(7:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(8:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(9:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(00:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(00:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(02:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(03:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(04:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(05:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(06:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(07:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(08:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(09:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(20:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(20:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(22:02,"AM", "PM", 0) + ""
|
||||||
|
set x ampm(23:02,"AM", "PM", 0) + ""
|
||||||
|
|
||||||
# Coerce with am/pm
|
# Coerce with am/pm
|
||||||
set x coerce("TIME", "12:45am")
|
set x coerce("TIME", "12:45am")
|
||||||
set x coerce("TIME", "12:45")
|
set x coerce("TIME", "12:45")
|
||||||
@@ -777,7 +827,7 @@ ENDIF
|
|||||||
# Trig with a good warnfunc
|
# Trig with a good warnfunc
|
||||||
FSET w(x) choose(x, 5, 3, 1, 0)
|
FSET w(x) choose(x, 5, 3, 1, 0)
|
||||||
|
|
||||||
Short-circuit operators
|
# Short-circuit operators
|
||||||
IF trig("sun warn w") || trig("thu warn w")
|
IF trig("sun warn w") || trig("thu warn w")
|
||||||
REM [trig()] +5 MSG Foo %b
|
REM [trig()] +5 MSG Foo %b
|
||||||
ENDIF
|
ENDIF
|
||||||
@@ -872,6 +922,16 @@ REM MSG Here: %{custom}
|
|||||||
REM MSG There: %*{custom}
|
REM MSG There: %*{custom}
|
||||||
REM MSG Bad: %{custom
|
REM MSG Bad: %{custom
|
||||||
|
|
||||||
|
REM MSG Undefined: %{nopity_nope_nope}
|
||||||
|
|
||||||
|
# Bad substitution functions
|
||||||
|
FSET subst_bad() "foo"
|
||||||
|
REM MSG %{bad}
|
||||||
|
|
||||||
|
FSET subst_ampm(a, b, c, d, e, f, g) "wookie"
|
||||||
|
|
||||||
|
REM AT 11:00 MSG %2
|
||||||
|
|
||||||
# Test FUNSET
|
# Test FUNSET
|
||||||
FSET square(x) x*x
|
FSET square(x) x*x
|
||||||
SET a square(5)
|
SET a square(5)
|
||||||
@@ -945,6 +1005,120 @@ REM Tue AT 10:00 DURATION [trigtime()] MSG blort
|
|||||||
# Make sure shellescape does not mangle UTF-8 characters
|
# Make sure shellescape does not mangle UTF-8 characters
|
||||||
msg [shellescape("😆")]
|
msg [shellescape("😆")]
|
||||||
|
|
||||||
|
This should be diagnosed as implicitly being REM
|
||||||
|
REM This should be diganosed as implicitly being MSG-type
|
||||||
|
|
||||||
|
# Check that user-defined functions with too many arguments are
|
||||||
|
# correctly diagnosed.
|
||||||
|
|
||||||
|
# This should be OK
|
||||||
|
FSET f(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63) 3
|
||||||
|
|
||||||
|
# This should give an error
|
||||||
|
FSET f(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63, a64) 3
|
||||||
|
|
||||||
|
# Check that SATISFY expressions that don't reference trigdate are diagnosed
|
||||||
|
|
||||||
|
# These should all NOT be diagnosed
|
||||||
|
set x 3
|
||||||
|
REM SATISFY 1
|
||||||
|
REM SATISFY trigdate() > '1990-01-01'
|
||||||
|
REM AT 23:59 SATISFY trigdatetime() > '1990-01-01@12:00'
|
||||||
|
REM SATISFY $T > '1990-01-01'
|
||||||
|
REM SATISFY $Ty > 1990
|
||||||
|
REM SATISFY $Tm > 0
|
||||||
|
REM SATISFY $Td > 0
|
||||||
|
REM SATISFY $Tw > -1
|
||||||
|
REM SATISFY [max(x, max(x, 1, 2, 3), 4, 5, 6) * max(5, $Td)]
|
||||||
|
|
||||||
|
FSET references_t(x) $T != x
|
||||||
|
REM SATISFY references_t($U)
|
||||||
|
|
||||||
|
FSET recursive_t(x) iif(x==0, recursive_t(1), references_t($U))
|
||||||
|
|
||||||
|
REM SATISFY recursive_t(0)
|
||||||
|
REM SATISFY recursive_t(2)
|
||||||
|
|
||||||
|
# These should be diagnosed
|
||||||
|
REM SATISFY 0
|
||||||
|
REM SATSIFY ""
|
||||||
|
REM SATISFY [version() > "01.00.00"]
|
||||||
|
REM SATISFY [max(x, max(x, 1, 2, 3), 4, 5, 6) * 5]
|
||||||
|
|
||||||
|
FSET gg(x) 0
|
||||||
|
REM WARN gg MSG Wookie
|
||||||
|
REM AT 11:00 SCHED gg MSG blork
|
||||||
|
REM OMITFUNC gg MSG hehe
|
||||||
|
|
||||||
|
FSET gg(x,y,z) 0
|
||||||
|
REM WARN gg MSG Wookie
|
||||||
|
REM AT 11:00 SCHED gg MSG blork
|
||||||
|
REM OMITFUNC gg MSG hehe
|
||||||
|
|
||||||
|
FSET gg() 0
|
||||||
|
REM WARN gg MSG Wookie
|
||||||
|
REM AT 11:00 SCHED gg MSG blork
|
||||||
|
REM OMITFUNC gg MSG hehe
|
||||||
|
|
||||||
|
FSET gg(x) x-x
|
||||||
|
REM WARN gg MSG Wookie
|
||||||
|
REM AT 11:00 SCHED gg MSG blork
|
||||||
|
REM OMITFUNC gg MSG hehe
|
||||||
|
|
||||||
|
REM WARN not_defined MSG Wookie
|
||||||
|
REM AT 11:00 SCHED not_defined MSG blork
|
||||||
|
REM OMITFUNC not_defined MSG hehe
|
||||||
|
|
||||||
|
### Strings in logical operators
|
||||||
|
SET logstr "" && 7
|
||||||
|
SET logstr "foo" && 7
|
||||||
|
SET logstr "" && ""
|
||||||
|
SET logstr "foo" && ""
|
||||||
|
SET logstr "" && "bar"
|
||||||
|
SET logstr "foo" && "bar"
|
||||||
|
SET logstr "" && '2023-02-01'
|
||||||
|
SET logstr "foo" && '2023-02-01'
|
||||||
|
|
||||||
|
SET logstr "" || 7
|
||||||
|
SET logstr "foo" || 7
|
||||||
|
SET logstr "" || ""
|
||||||
|
SET logstr "foo" || ""
|
||||||
|
SET logstr "" || "bar"
|
||||||
|
SET logstr "foo" || "bar"
|
||||||
|
SET logstr "" || '2023-02-01'
|
||||||
|
SET logstr "foo" || '2023-02-01'
|
||||||
|
|
||||||
|
set xyz ! 0
|
||||||
|
set xyz ! 1
|
||||||
|
set xyz ! 2
|
||||||
|
|
||||||
|
set xyz ! date(baseyr(), 1, 1)
|
||||||
|
set xyz ! date(baseyr(), 1, 2)
|
||||||
|
set xyz ! '2024-01-01'
|
||||||
|
|
||||||
|
set xyz ! datetime(baseyr(), 1, 1, 00:00)
|
||||||
|
set xyz ! datetime(baseyr(), 1, 1, 00:01)
|
||||||
|
set xyz ! datetime(baseyr(), 1, 2, 12:30)
|
||||||
|
set xyz ! '2024-01-01@11:47'
|
||||||
|
|
||||||
|
set xyz ! 00:00
|
||||||
|
set xyz ! 00:01
|
||||||
|
set xyz ! 23:59
|
||||||
|
|
||||||
|
set xyz ! ""
|
||||||
|
set xyz ! "foo"
|
||||||
|
set xyz ! "0"
|
||||||
|
|
||||||
|
# Test error messages for function calls with too many / too few args
|
||||||
|
|
||||||
|
set zxk version(1)
|
||||||
|
set zxk max()
|
||||||
|
|
||||||
|
fset dooby(x) 1
|
||||||
|
set zxk dooby()
|
||||||
|
set zxk dooby(1, 2)
|
||||||
|
set zxk dooby(1)
|
||||||
|
|
||||||
# Don't want Remind to queue reminders
|
# Don't want Remind to queue reminders
|
||||||
EXIT
|
EXIT
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
MSG ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский
|
REM MSG ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский
|
||||||
MSG עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית
|
REM MSG עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית
|
||||||
|
|
||||||
Wed MSG With tabs and spaces
|
REM Wed MSG With tabs and spaces
|
||||||
|
|
||||||
REM [moondate(0)] MSG 🌑
|
REM [moondate(0)] MSG 🌑
|
||||||
REM [moondate(1)] MSG 🌓 woo
|
REM [moondate(1)] MSG 🌓 woo
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[moondate(0)] SPECIAL MOON 0
|
REM [moondate(0)] SPECIAL MOON 0
|
||||||
[moondate(1)] SPECIAL MOON 1
|
REM [moondate(1)] SPECIAL MOON 1
|
||||||
[moondate(2)] SPECIAL MOON 2
|
REM [moondate(2)] SPECIAL MOON 2
|
||||||
[moondate(3)] SPECIAL MOON 3
|
REM [moondate(3)] SPECIAL MOON 3
|
||||||
REM Monday SPECIAL WEEK (W[weekno()])
|
REM Monday SPECIAL WEEK (W[weekno()])
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ IF !$PSCAL
|
|||||||
|
|
||||||
FSET msgsuffix(x) "<P>"
|
FSET msgsuffix(x) "<P>"
|
||||||
|
|
||||||
MSG The Hebrew date for today, %d %m, %y, is [_hstr(today())]. %
|
REM MSG The Hebrew date for today, %d %m, %y, is [_hstr(today())]. %
|
||||||
MSG And the Hebrew date for tomorrow is [_hstr(today()+1)]. %
|
REM MSG And the Hebrew date for tomorrow is [_hstr(today()+1)]. %
|
||||||
|
|
||||||
fset msgprefix(x) iif($NumTrig==OldTrig, "<H2>Upcoming Holidays</H2>"+char(13,10),"")
|
fset msgprefix(x) iif($NumTrig==OldTrig, "<H2>Upcoming Holidays</H2>"+char(13,10),"")
|
||||||
set oldtrig $numtrig
|
set oldtrig $numtrig
|
||||||
@@ -51,40 +51,40 @@ FSET _PastSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, \
|
|||||||
SET InIsrael VALUE("InIsrael", 0)
|
SET InIsrael VALUE("InIsrael", 0)
|
||||||
SET Reform VALUE("Reform", 0)
|
SET Reform VALUE("Reform", 0)
|
||||||
|
|
||||||
[_h(1, "Tishrey")] ++12 MSG %"Rosh Hashana 1%" is %b.
|
REM [_h(1, "Tishrey")] ++12 MSG %"Rosh Hashana 1%" is %b.
|
||||||
|
|
||||||
# No RH-2 or Tzom Gedalia in Reform
|
# No RH-2 or Tzom Gedalia in Reform
|
||||||
IF !Reform
|
IF !Reform
|
||||||
[_h(2, "Tishrey")] ++12 MSG %"Rosh Hashana 2%" is %b.
|
REM [_h(2, "Tishrey")] ++12 MSG %"Rosh Hashana 2%" is %b.
|
||||||
[_PastSat(3, "Tishrey")] ++12 MSG %"Tzom Gedalia%" is %b.
|
REM [_PastSat(3, "Tishrey")] ++12 MSG %"Tzom Gedalia%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(10, "Tishrey")] ++12 MSG %"Yom Kippur%" is %b.
|
REM [_h(10, "Tishrey")] ++12 MSG %"Yom Kippur%" is %b.
|
||||||
[_h(15, "Tishrey")] ++12 MSG %"Sukkot 1%" is %b.
|
REM [_h(15, "Tishrey")] ++12 MSG %"Sukkot 1%" is %b.
|
||||||
|
|
||||||
IF !InIsrael
|
IF !InIsrael
|
||||||
[_h(16, "Tishrey")] MSG %"Sukkot 2%"
|
REM [_h(16, "Tishrey")] MSG %"Sukkot 2%"
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(21, "Tishrey")] ++12 MSG %"Hoshana Rabba%" is %b.
|
REM [_h(21, "Tishrey")] ++12 MSG %"Hoshana Rabba%" is %b.
|
||||||
[_h(22, "Tishrey")] ++12 MSG %"Shemini Atzeret%" is %b.
|
REM [_h(22, "Tishrey")] ++12 MSG %"Shemini Atzeret%" is %b.
|
||||||
|
|
||||||
IF InIsrael
|
IF InIsrael
|
||||||
[_h(22, "Tishrey")] ++12 MSG %"Simchat Torah%" is %b.
|
REM [_h(22, "Tishrey")] ++12 MSG %"Simchat Torah%" is %b.
|
||||||
ELSE
|
ELSE
|
||||||
[_h(23, "Tishrey")] ++12 MSG %"Simchat Torah%" is %b.
|
REM [_h(23, "Tishrey")] ++12 MSG %"Simchat Torah%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
# Because Kislev can change length, we must be more careful about Chanukah
|
# Because Kislev can change length, we must be more careful about Chanukah
|
||||||
FSET _chan(x) TRIGGER(HEBDATE(24, "Kislev", today()-9)+x)
|
FSET _chan(x) TRIGGER(HEBDATE(24, "Kislev", today()-9)+x)
|
||||||
[_chan(1)] ++12 MSG %"Chanukah 1%" is %b.
|
REM [_chan(1)] ++12 MSG %"Chanukah 1%" is %b.
|
||||||
[_chan(2)] MSG %"Chanukah 2%"
|
REM [_chan(2)] MSG %"Chanukah 2%"
|
||||||
[_chan(3)] MSG %"Chanukah 3%"
|
REM [_chan(3)] MSG %"Chanukah 3%"
|
||||||
[_chan(4)] MSG %"Chanukah 4%"
|
REM [_chan(4)] MSG %"Chanukah 4%"
|
||||||
[_chan(5)] MSG %"Chanukah 5%"
|
REM [_chan(5)] MSG %"Chanukah 5%"
|
||||||
[_chan(6)] MSG %"Chanukah 6%"
|
REM [_chan(6)] MSG %"Chanukah 6%"
|
||||||
[_chan(7)] MSG %"Chanukah 7%"
|
REM [_chan(7)] MSG %"Chanukah 7%"
|
||||||
[_chan(8)] MSG %"Chanukah 8%"
|
REM [_chan(8)] MSG %"Chanukah 8%"
|
||||||
|
|
||||||
# Not sure about Reform's position on the next one.
|
# Not sure about Reform's position on the next one.
|
||||||
IF !Reform
|
IF !Reform
|
||||||
@@ -92,8 +92,8 @@ IF !Reform
|
|||||||
REM [_PastSat(10, "Tevet")] MSG %"Tzom Tevet%" is %b.
|
REM [_PastSat(10, "Tevet")] MSG %"Tzom Tevet%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(15, "Shvat")] ++12 MSG %"Tu B'Shvat%" is %b.
|
REM [_h(15, "Shvat")] ++12 MSG %"Tu B'Shvat%" is %b.
|
||||||
[_h(15, "Adar A")] ++12 MSG %"Purim Katan%" is %b.
|
REM [_h(15, "Adar A")] ++12 MSG %"Purim Katan%" is %b.
|
||||||
|
|
||||||
# If Purim is on Sunday, then Fast of Esther is 11 Adar.
|
# If Purim is on Sunday, then Fast of Esther is 11 Adar.
|
||||||
IF WKDAYNUM(_h2(13, "Adar")) != 6
|
IF WKDAYNUM(_h2(13, "Adar")) != 6
|
||||||
@@ -101,41 +101,41 @@ IF WKDAYNUM(_h2(13, "Adar")) != 6
|
|||||||
ELSE
|
ELSE
|
||||||
REM [TRIGGER(_h2(11, "Adar"))] ++12 MSG %"Fast of Esther%" is %b.
|
REM [TRIGGER(_h2(11, "Adar"))] ++12 MSG %"Fast of Esther%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
[_h(14, "Adar")] ++12 MSG %"Purim%" is %b.
|
REM [_h(14, "Adar")] ++12 MSG %"Purim%" is %b.
|
||||||
[_h(15, "Nisan")] ++12 MSG %"Pesach%" is %b.
|
REM [_h(15, "Nisan")] ++12 MSG %"Pesach%" is %b.
|
||||||
|
|
||||||
IF !InIsrael
|
IF !InIsrael
|
||||||
[_h(16, "Nisan")] MSG %"Pesach 2%" is %b.
|
REM [_h(16, "Nisan")] MSG %"Pesach 2%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(21, "Nisan")] MSG %"Pesach 7%" is %b.
|
REM [_h(21, "Nisan")] MSG %"Pesach 7%" is %b.
|
||||||
|
|
||||||
IF !InIsrael && !Reform
|
IF !InIsrael && !Reform
|
||||||
[_h(22, "Nisan")] MSG %"Pesach 8%" is %b.
|
REM [_h(22, "Nisan")] MSG %"Pesach 8%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(27, "Nisan")] ++12 MSG %"Yom HaShoah%" is %b.
|
REM [_h(27, "Nisan")] ++12 MSG %"Yom HaShoah%" is %b.
|
||||||
[_h(4, "Iyar")] ++12 MSG %"Yom HaZikaron%" is %b.
|
REM [_h(4, "Iyar")] ++12 MSG %"Yom HaZikaron%" is %b.
|
||||||
[_h(5, "Iyar")] ++12 MSG %"Yom Ha'atzmaut%" is %b.
|
REM [_h(5, "Iyar")] ++12 MSG %"Yom Ha'atzmaut%" is %b.
|
||||||
|
|
||||||
# Not sure about Reform's position on Lag B'Omer
|
# Not sure about Reform's position on Lag B'Omer
|
||||||
IF !Reform
|
IF !Reform
|
||||||
[_h(18, "Iyar")] ++12 MSG %"Lag B'Omer%" is %b.
|
REM [_h(18, "Iyar")] ++12 MSG %"Lag B'Omer%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
[_h(28, "Iyar")] ++12 MSG %"Yom Yerushalayim%" is %b.
|
REM [_h(28, "Iyar")] ++12 MSG %"Yom Yerushalayim%" is %b.
|
||||||
[_h(6, "Sivan")] ++12 MSG %"Shavuot%" is %b.
|
REM [_h(6, "Sivan")] ++12 MSG %"Shavuot%" is %b.
|
||||||
|
|
||||||
IF !InIsrael && !Reform
|
IF !InIsrael && !Reform
|
||||||
[_h(7, "Sivan")] MSG %"Shavuot 2%" is %b.
|
REM [_h(7, "Sivan")] MSG %"Shavuot 2%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
# Fairly sure Reform Jews don't observe the next two
|
# Fairly sure Reform Jews don't observe the next two
|
||||||
IF !Reform
|
IF !Reform
|
||||||
# Tzom Tamuz and Tish'a B'Av are moved to Sunday if they normally
|
# Tzom Tamuz and Tish'a B'Av are moved to Sunday if they normally
|
||||||
# fall on a Saturday
|
# fall on a Saturday
|
||||||
[_PastSat(17, "Tamuz")] ++12 MSG %"Tzom Tammuz%" is %b.
|
REM [_PastSat(17, "Tamuz")] ++12 MSG %"Tzom Tammuz%" is %b.
|
||||||
[_PastSat(9, "Av")] ++12 MSG %"Tish'a B'Av%" is %b.
|
REM [_PastSat(9, "Av")] ++12 MSG %"Tish'a B'Av%" is %b.
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
fset msgprefix(x) ""
|
fset msgprefix(x) ""
|
||||||
|
|||||||
Reference in New Issue
Block a user