mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 06:18:47 +02:00
Compare commits
35 Commits
05.03.01
...
05.03.05-B
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abb8cbb1bf | ||
|
|
ee4e3e9073 | ||
|
|
220014e60f | ||
|
|
3d0d07ce29 | ||
|
|
38615adb41 | ||
|
|
3d8f0e3907 | ||
|
|
160f85a1f8 | ||
|
|
5cb062166c | ||
|
|
81fa6c667f | ||
|
|
190dfa3a8f | ||
|
|
a22c674846 | ||
|
|
ba224445b1 | ||
|
|
6aeee47bfa | ||
|
|
c506fa4613 | ||
|
|
04404a252e | ||
|
|
be746f9fa7 | ||
|
|
2393a86970 | ||
|
|
143ad08b3f | ||
|
|
44afdfcb44 | ||
|
|
4b905dbc02 | ||
|
|
0f76750e05 | ||
|
|
b32f56134e | ||
|
|
60b0b468df | ||
|
|
52ce99af80 | ||
|
|
5915eb4973 | ||
|
|
aa8d23fd87 | ||
|
|
917d943953 | ||
|
|
9ade3876b2 | ||
|
|
471ecff267 | ||
|
|
762bf97473 | ||
|
|
563f3ea088 | ||
|
|
939078428f | ||
|
|
5acbb907b4 | ||
|
|
21ecc28ea4 | ||
|
|
b37a7cd993 |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1,2 +0,0 @@
|
||||
|
||||
liberapay: dskoll
|
||||
7
.github/README.md
vendored
7
.github/README.md
vendored
@@ -1,7 +0,0 @@
|
||||
# Remind has moved
|
||||
|
||||
For various reasons, I have decided to move Remind off GitHub. This repo
|
||||
will be archived. To create merge requests or issues, please visit
|
||||
Remind's new home at https://salsa.debian.org/dskoll/remind
|
||||
|
||||
-- Dianne Skoll
|
||||
29
.github/workflows/github-action.yml
vendored
29
.github/workflows/github-action.yml
vendored
@@ -1,29 +0,0 @@
|
||||
# language: bash
|
||||
---
|
||||
|
||||
name: Remind unit tests
|
||||
|
||||
on:
|
||||
push
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Remind
|
||||
uses: actions/checkout@v2
|
||||
- name: Add test user
|
||||
run: |
|
||||
sudo adduser --home /home/testuser --gecos 'Test User' --disabled-password testuser
|
||||
- name: Fix ownership
|
||||
run: |
|
||||
sudo chown -R testuser .
|
||||
- name: Build
|
||||
run: |
|
||||
sudo su -c './configure && make' testuser
|
||||
- name: Run Tests
|
||||
run: |
|
||||
sudo su -c 'make test' testuser
|
||||
- name: Fix up permissions so GitHub does not complain
|
||||
run: |
|
||||
sudo chmod -R a+rwX .
|
||||
18
configure
vendored
18
configure
vendored
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.71 for remind 05.03.01.
|
||||
# Generated by GNU Autoconf 2.71 for remind 05.03.05.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
|
||||
@@ -608,8 +608,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='remind'
|
||||
PACKAGE_TARNAME='remind'
|
||||
PACKAGE_VERSION='05.03.01'
|
||||
PACKAGE_STRING='remind 05.03.01'
|
||||
PACKAGE_VERSION='05.03.05'
|
||||
PACKAGE_STRING='remind 05.03.05'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL='https://dianne.skoll.ca/projects/remind/'
|
||||
|
||||
@@ -1265,7 +1265,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures remind 05.03.01 to adapt to many kinds of systems.
|
||||
\`configure' configures remind 05.03.05 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1327,7 +1327,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of remind 05.03.01:";;
|
||||
short | recursive ) echo "Configuration of remind 05.03.05:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1415,7 +1415,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
remind configure 05.03.01
|
||||
remind configure 05.03.05
|
||||
generated by GNU Autoconf 2.71
|
||||
|
||||
Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
@@ -1865,7 +1865,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by remind $as_me 05.03.01, which was
|
||||
It was created by remind $as_me 05.03.05, which was
|
||||
generated by GNU Autoconf 2.71. Invocation command line was
|
||||
|
||||
$ $0$ac_configure_args_raw
|
||||
@@ -4710,7 +4710,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by remind $as_me 05.03.01, which was
|
||||
This file was extended by remind $as_me 05.03.05, which was
|
||||
generated by GNU Autoconf 2.71. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -4775,7 +4775,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config='$ac_cs_config_escaped'
|
||||
ac_cs_version="\\
|
||||
remind config.status 05.03.01
|
||||
remind config.status 05.03.05
|
||||
configured by $0, generated by GNU Autoconf 2.71,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT(remind, 05.03.01, , , https://dianne.skoll.ca/projects/remind/)
|
||||
AC_INIT(remind, 05.03.05, , , https://dianne.skoll.ca/projects/remind/)
|
||||
AC_CONFIG_SRCDIR([src/queue.c])
|
||||
|
||||
cat <<'EOF'
|
||||
|
||||
@@ -1,5 +1,53 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* VERSION 5.3 Patch 5 - 2025-03-??
|
||||
|
||||
- NEW FEATURE: remind: Add moonrise, moonset, moonrisedir and moonsetdir
|
||||
functions. The first two functions calculate the time of the next
|
||||
moonrise and moonset, and the second two calculate in which direction
|
||||
the moon will rise or set. See the examples/astro script for examples
|
||||
of how to use the moonrise/moonset functions.
|
||||
|
||||
- CODE CLEANUPS: remind: Some minor code cleanups with no user-visible effects.
|
||||
|
||||
- BUG FIX: remind: The %2 and %@ sequences would print "0:34am" for the
|
||||
time 00:34, instead of the correct "12:34am". This has been fixed.
|
||||
|
||||
- BUG FIX: TkRemind: Fix bug that broke the ability to open a text editor
|
||||
on a reminder from the Queue... listing.
|
||||
|
||||
* VERSION 5.3 Patch 4 - 2025-03-09
|
||||
|
||||
- BUG FIX: remind: "make test" could fail if Remind was built in a locale
|
||||
other than "C". This has been fixed.
|
||||
|
||||
- BUG FIX: Fix a typo in the remind man page.
|
||||
|
||||
* VERSION 5.3 Patch 3 - 2025-03-03
|
||||
|
||||
- NEW FEATURE: remind: If a command spans more than one line (because of
|
||||
backslash line continuation) output both the starting and ending line
|
||||
number in error messages.
|
||||
|
||||
- NEW FEATURE: remind: In the JSON -pp and -ppp output, include a new key
|
||||
lineno_start to specify the starting line of a multi-line reminder.
|
||||
The existing lineno key specifies the ending line; this is maintained
|
||||
for backward-compatibility.
|
||||
|
||||
- MINOR IMPROVEMENT: include/holidays/misc.rem: Add a few new holidays and
|
||||
URL INFO strings.
|
||||
|
||||
- CHANGE: remind: Issue a warning if a time-related subsitution sequence
|
||||
is used with a non-timed REM command.
|
||||
|
||||
- BUG FIX: remind: Fix a memory leak.
|
||||
|
||||
* VERSION 5.3 Patch 2 - 2025-02-09
|
||||
|
||||
- CHANGE: remind: Revert a change to the way "-y" tags are generated that
|
||||
was introduced in 05.03.01. The change broke a library that depended
|
||||
on it being generated in the old way.
|
||||
|
||||
* VERSION 5.3 Patch 1 - 2025-02-07
|
||||
|
||||
- IMPROVEMENT: TkRemind: When we pop up a timed reminder, make any "Url:"
|
||||
|
||||
@@ -32,6 +32,24 @@ EOF
|
||||
|
||||
remind -g "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
|
||||
SET $AddBlankLines 0
|
||||
FSET angle_to_direction(x) \
|
||||
IIF(x > 348 && x <= 11, "North", \
|
||||
x > 11 && x <= 34, "North North-East", \
|
||||
x > 34 && x <= 56, "North-East", \
|
||||
x > 56 && x <= 79, "East North-East", \
|
||||
x > 79 && x <= 101, "East", \
|
||||
x > 101 && x <= 124, "East South-East", \
|
||||
x > 124 && x <= 146, "South-East", \
|
||||
x > 146 && x <= 169, "South South-East", \
|
||||
x > 169 && x <= 191, "South", \
|
||||
x > 191 && x <= 214, "South South-West", \
|
||||
x > 214 && x <= 236, "South-West", \
|
||||
x > 236 && x <= 259, "West South-West", \
|
||||
x > 259 && x <= 281, "West", \
|
||||
x > 281 && x <= 304, "West North-West", \
|
||||
x > 304 && x <= 326, "North-West", \
|
||||
"North North-West")
|
||||
|
||||
BANNER %
|
||||
IF $TerminalBackground == 0
|
||||
REM [moondatetime(0)] +60 SPECIAL COLOR 255 255 0 New moon: 🌑 [$T] %3 (%b)
|
||||
@@ -48,6 +66,50 @@ EOF
|
||||
|
||||
echo ""
|
||||
|
||||
remind -g "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
|
||||
SET $AddBlankLines 0
|
||||
FSET angle_to_direction(x) \
|
||||
IIF(x > 348 && x <= 11, "North", \
|
||||
x > 11 && x <= 34, "North North-East", \
|
||||
x > 34 && x <= 56, "North-East", \
|
||||
x > 56 && x <= 79, "East North-East", \
|
||||
x > 79 && x <= 101, "East", \
|
||||
x > 101 && x <= 124, "East South-East", \
|
||||
x > 124 && x <= 146, "South-East", \
|
||||
x > 146 && x <= 169, "South South-East", \
|
||||
x > 169 && x <= 191, "South", \
|
||||
x > 191 && x <= 214, "South South-West", \
|
||||
x > 214 && x <= 236, "South-West", \
|
||||
x > 236 && x <= 259, "West South-West", \
|
||||
x > 259 && x <= 281, "West", \
|
||||
x > 281 && x <= 304, "West North-West", \
|
||||
x > 304 && x <= 326, "North-West", \
|
||||
"North North-West")
|
||||
|
||||
BANNER %
|
||||
set mr moonrise()
|
||||
set ms moonset()
|
||||
set mr_a moonrisedir()
|
||||
set ms_a moonsetdir()
|
||||
|
||||
IF mr < ms
|
||||
REM NOQUEUE [mr] MSG The moon rises %3 in the [angle_to_direction(mr_a)] ([mr_a] degrees)
|
||||
REM NOQUEUE [ms] MSG The moon sets %3 in the [angle_to_direction(ms_a)] ([ms_a] degrees)
|
||||
ELSE
|
||||
REM NOQUEUE [ms] MSG The moon sets %3 in the [angle_to_direction(ms_a)] ([ms_a] degrees)
|
||||
REM NOQUEUE [mr] MSG The moon rises %3 in the [angle_to_direction(mr_a)] ([mr_a] degrees)
|
||||
ENDIF
|
||||
|
||||
IF (datepart(mr) != today())
|
||||
REM MSG There is no moonrise today
|
||||
ENDIF
|
||||
IF (datepart(ms) != today())
|
||||
REM MSG There is no moonset today
|
||||
ENDIF
|
||||
EOF
|
||||
|
||||
echo ""
|
||||
|
||||
remind -g "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
|
||||
SET $AddBlankLines 0
|
||||
BANNER %
|
||||
|
||||
9
include/holidays/misc.rem
Normal file
9
include/holidays/misc.rem
Normal file
@@ -0,0 +1,9 @@
|
||||
# Miscellaneous holidays
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
REM 1 February INFO "Url: https://en.wikipedia.org/wiki/Black_History_Month" MSG Start of Black History Month
|
||||
REM 1 March INFO "Url: https://en.wikipedia.org/wiki/Women%27s_History_Month" MSG Start of Women's History Month
|
||||
REM 8 March INFO "Url: https://en.wikipedia.org/wiki/International_Women%27s_Day" MSG International Women's Day
|
||||
REM Thu 1 May INFO "Url: https://en.wikipedia.org/wiki/National_Day_of_Reason" MSG National Day of Reason
|
||||
REM 23 March INFO "Url: https://www.atheistrepublic.com/atheist-day" MSG Atheist Day
|
||||
@@ -86,3 +86,6 @@ TRANSLATE "Sunrise" "Zonsopgang"
|
||||
TRANSLATE "Sunset" "Zonsondergang"
|
||||
|
||||
TRANSLATE "No reminders." "Geen herinneringen."
|
||||
|
||||
TRANSLATE "Daylight Saving Time Begins" "Daglicht-sparende tijd begint"
|
||||
TRANSLATE "Daylight Saving Time Ends" "Daglicht-sparende tijd eindigt"
|
||||
|
||||
@@ -492,6 +492,13 @@ The filename in which the reminder was found.
|
||||
.B lineno \fIn\fR
|
||||
The line number within the file on which the reminder was found.
|
||||
.TP
|
||||
.B lineno_start \fIn\fR
|
||||
If a reminder spans multiple lines because of backslash
|
||||
line-continuation, then the \fBlineno\fR entry is the \fIlast\fR line
|
||||
of the reminder; the \fBlineno_start\fR entry is the \fIfirst\fR line. If
|
||||
a reminder does \fInot\fR span multiple lines, then only the \fBlineno\fR
|
||||
entry is present; the \fBlineno_start\fR entry is absent in that case.
|
||||
.TP
|
||||
.B nonconst_expr 1
|
||||
If the reminder contained a non-constant expression that had to be evaluated
|
||||
to determine the trigger date, this key will be present with the value 1.
|
||||
|
||||
@@ -3711,6 +3711,43 @@ which default to \fBtoday()\fR and midnight, respectively. The returned
|
||||
value is an integer from 0 to 359, representing the phase of the moon
|
||||
in degrees. 0 is a new moon, 180 is a full moon, 90 is first-quarter, etc.
|
||||
.TP
|
||||
.B moonrise([d_date])
|
||||
This function returns a DATETIME result giving the date and time of the
|
||||
first moonrise on or after midnight on \fIdate\fR. If \fIdate\fR is not
|
||||
supplied, it defaults to \fBtoday()\fR.
|
||||
.RS
|
||||
.PP
|
||||
Note that it is not uncommon for a day to have no moonrise, so the date
|
||||
part of the return value may not be the same as the \fIdate\fR argument.
|
||||
So if you want a calendar of moonrise times, you could use something
|
||||
like this:
|
||||
.PP
|
||||
.nf
|
||||
SET mr moonrise()
|
||||
IF datepart(mr) == today()
|
||||
REM NOQUEUE [mr] MSG Moon rises at %3.
|
||||
ELSE
|
||||
REM MSG No moonrise today
|
||||
ENDIF
|
||||
.fi
|
||||
.PP
|
||||
.RE
|
||||
.TP
|
||||
.B moonrisedir([d_date])
|
||||
This function returns an INT result giving the direction from which
|
||||
the moon will rise on the first moonrise on or after midnight on
|
||||
\fIdate\fR. If \fIdate\fR is not supplied, it defaults to
|
||||
\fBtoday()\fR. The return value ranges from 0 to 359, where 0 is North,
|
||||
90 is East, 180 is South and 270 is West.
|
||||
.TP
|
||||
.B moonset([d_date])
|
||||
This function is analogous to \fBmoonrise()\fR but returns the DATETIME of
|
||||
the next moonset on or after midnight on \fIdate\fR.
|
||||
.TP
|
||||
.B moonsetdir([d_date])
|
||||
This function is analogous to \fBmoonrisedir()\fR but returns the
|
||||
direction of moonset.
|
||||
.TP
|
||||
.B multitrig(s_trig1 [,s_trig2, [... s_trigN]])
|
||||
\fBmultitrig\fR evaluates each string as a trigger, similar to \fBevaltrig\fR,
|
||||
and returns the \fIearliest\fR trigger date that is on or after \fBtoday()\fR.
|
||||
@@ -3787,7 +3824,7 @@ are effectively swapped, so counting always begins from the older
|
||||
date.
|
||||
.PP
|
||||
If the third argument to \fBnonomitted\fR is an \fBINT\fR, then it must
|
||||
be greater than zero, and is consider to be the \fIstep\fR by which
|
||||
be greater than zero, and is considered to be the \fIstep\fR by which
|
||||
\fBnonomitted\fR counts. For example the following expression:
|
||||
.PP
|
||||
.nf
|
||||
@@ -6460,14 +6497,15 @@ Do not hard-code the above directory in your reminder files. Instead,
|
||||
use the value of the $SysInclude system variable.
|
||||
.SH AUTHOR
|
||||
.PP
|
||||
Dianne Skoll <dianne@skoll.ca> wrote \fBRemind\fR. The moon code was
|
||||
copied largely unmodified from "moontool" by John Walker. The sunrise
|
||||
and sunset functions use ideas from programs by Michael Schwartz and
|
||||
Marc T. Kaufman. The Hebrew calendar support was taken from "hdate"
|
||||
by Amos Shapir. OS/2 support was done by Darrel Hankerson, Russ
|
||||
Herman, and Norman Walsh. The supported languages and their
|
||||
translators are listed below. Languages marked "complete" support
|
||||
error messages in that language; all others only support the
|
||||
Dianne Skoll <dianne@skoll.ca> wrote \fBRemind\fR. The moon phase
|
||||
code was copied largely unmodified from "moontool" by John Walker.
|
||||
The moonrise/moonset code comes from
|
||||
https://github.com/signetica/MoonRise by Stephen R. Schmitt and Cyrus
|
||||
Rahman. The sunrise and sunset functions use ideas from programs by
|
||||
Michael Schwartz and Marc T. Kaufman. The Hebrew calendar support was
|
||||
taken from "hdate" by Amos Shapir. The supported languages and
|
||||
their translators are listed below. Languages marked "complete"
|
||||
support error messages in that language; all others only support the
|
||||
substitution filter mechanism and month/day names.
|
||||
.PP
|
||||
\fBGerman\fR --
|
||||
|
||||
@@ -15,7 +15,7 @@ all: Makefile
|
||||
OK=1; \
|
||||
for m in $(PERLMODS_NEEDED) ; \
|
||||
do \
|
||||
$(PERL) -M$$m -e 1 > /dev/null 2>&1; \
|
||||
$(PERL) -M$$m -e 1 ; \
|
||||
if test $$? != 0 ; then echo "Missing Perl module: $$m"; OK=0; fi; \
|
||||
done; \
|
||||
if test "$$OK" != "1" ; then echo "Not building rem2pdf because of missing perl module(s)"; exit 0; fi; \
|
||||
@@ -27,7 +27,7 @@ install:
|
||||
echo "Not installing rem2pdf; Perl is required"; exit 0; fi; \
|
||||
for m in $(PERLMODS_NEEDED) ; \
|
||||
do \
|
||||
$(PERL) -M$$m -e 1 > /dev/null 2>&1; \
|
||||
$(PERL) -M$$m -e 1 ; \
|
||||
if test $$? != 0 ; then echo "Not installing rem2pdf; missing $$m"; exit 0; fi; \
|
||||
done; \
|
||||
echo "Installing rem2pdf"; \
|
||||
|
||||
@@ -1212,7 +1212,12 @@ proc FillCalWindow {} {
|
||||
set fname [dict get $obj filename]
|
||||
# Don't make INCLUDECMD output editable
|
||||
if {![string match "*|" $fname]} {
|
||||
set fntag [string cat "FILE_" [dict get $obj lineno] "_" $fname]
|
||||
if {[dict exists $obj lineno_start]} {
|
||||
set l [dict get $obj lineno_start]
|
||||
} else {
|
||||
set l [dict get $obj lineno]
|
||||
}
|
||||
set fntag [string cat "FILE_" $l "_" $fname]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2867,7 +2872,11 @@ proc ShowQueue { queue } {
|
||||
set fntag ""
|
||||
catch {
|
||||
set fname [dict get $q filename]
|
||||
set lineno [dict get $q lineno]
|
||||
if {[dict exists $q lineno_start]} {
|
||||
set lineno [dict get $q lineno_start]
|
||||
} else {
|
||||
set lineno [dict get $q lineno]
|
||||
}
|
||||
set fntag [string cat "FILE_" $lineno "_" $fname]
|
||||
}
|
||||
if { "$fntag" != "" } {
|
||||
@@ -4624,7 +4633,7 @@ proc ShowErrors {} {
|
||||
set l [split $RemindErrors "\n"]
|
||||
set i 0
|
||||
foreach line $l {
|
||||
if {[regexp {^(.*)\(([0-9]+)\)} $line dummy fname lineno]} {
|
||||
if {[regexp {^(.*)\(([0-9]+)} $line dummy fname lineno]} {
|
||||
incr i
|
||||
set fntag [string cat "FILE_" $lineno "_" $fname]
|
||||
$w.t insert end $line [list ERR "ERR$i" $fntag]
|
||||
|
||||
@@ -48,7 +48,7 @@ test: all
|
||||
xlat.c: $(REMINDSRCS)
|
||||
@echo "#include <stddef.h>" > xlat.c
|
||||
@echo "char const *translatables[] = {" >> xlat.c
|
||||
@cat $(REMINDSRCS) | grep 'tr(".*")' | sed -e 's/.*tr."/"/' -e 's/").*/"/' | sort | uniq | grep -E -v '^"(am|at|from now|hour|minute|now|on|pm|today|tomorrow|was)"$$' | sed -e 's/^/ /' -e 's/$$/,/' >> xlat.c
|
||||
@cat $(REMINDSRCS) | grep 'tr(".*")' | sed -e 's/.*tr."/"/' -e 's/").*/"/' | LANG=C LC_ALL=C sort | uniq | grep -E -v '^"(am|at|from now|hour|minute|now|on|pm|today|tomorrow|was)"$$' | sed -e 's/^/ /' -e 's/$$/,/' >> xlat.c
|
||||
@echo " NULL" >> xlat.c
|
||||
@echo "};" >> xlat.c
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ typedef struct cal_entry {
|
||||
int duration;
|
||||
char *filename;
|
||||
int lineno;
|
||||
int lineno_start;
|
||||
Trigger trig;
|
||||
TimeTrig tt;
|
||||
int nonconst_expr;
|
||||
@@ -2327,6 +2328,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
return E_NO_MEM;
|
||||
}
|
||||
e->lineno = LineNo;
|
||||
e->lineno_start = LineNoStart;
|
||||
|
||||
if (trig.typ == PASSTHRU_TYPE || is_color) {
|
||||
StrnCpy(e->passthru, trig.passthru, PASSTHRU_LEN);
|
||||
@@ -2528,6 +2530,9 @@ static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
||||
if (DoPrefixLineNo) {
|
||||
PrintJSONKeyPairString("filename", e->filename);
|
||||
PrintJSONKeyPairInt("lineno", e->lineno);
|
||||
if (e->lineno != e->lineno_start) {
|
||||
PrintJSONKeyPairInt("lineno_start", e->lineno_start);
|
||||
}
|
||||
}
|
||||
PrintJSONKeyPairString("passthru", e->passthru);
|
||||
PrintJSONKeyPairString("tags", DBufValue(&(e->tags)));
|
||||
@@ -2944,9 +2949,6 @@ char const *SynthesizeTag(void)
|
||||
static char out[128];
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, (unsigned char *) CurLine, strlen(CurLine));
|
||||
MD5Update(&ctx, (unsigned char *) FileName, strlen(FileName));
|
||||
snprintf((char *) buf, sizeof(buf), "%d", LineNo);
|
||||
MD5Update(&ctx, buf, strlen( (char *) buf));
|
||||
MD5Final(buf, &ctx);
|
||||
snprintf(out, sizeof(out), "__syn__%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
(unsigned int) buf[0], (unsigned int) buf[1],
|
||||
|
||||
@@ -72,13 +72,13 @@ check_trigger_function(char const *fname, char const *type)
|
||||
return;
|
||||
}
|
||||
if (f->nargs != 1) {
|
||||
Wprint(tr("%s function `%s' defined at %s:%d should take 1 argument but actually takes %d"), type, fname, f->filename, f->lineno, f->nargs);
|
||||
Wprint(tr("%s function `%s' defined at %s(%s) should take 1 argument but actually takes %d"), type, fname, f->filename, line_range(f->lineno_start, f->lineno), f->nargs);
|
||||
return;
|
||||
}
|
||||
if (ensure_expr_references_first_local_arg(f->node)) {
|
||||
return;
|
||||
}
|
||||
Wprint(tr("%s function `%s' defined at %s:%d does not use its argument"), type, fname, f->filename, f->lineno);
|
||||
Wprint(tr("%s function `%s' defined at %s(%s) does not use its argument"), type, fname, f->filename, line_range(f->lineno_start, f->lineno));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1558,8 +1558,8 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
int y, m, d;
|
||||
FromDSE(LastTriggerDate, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%d): Trig(satisfied) = %s, %d %s, %d",
|
||||
FileName, LineNo,
|
||||
fprintf(ErrFp, "%s(%s): Trig(satisfied) = %s, %d %s, %d",
|
||||
FileName, line_range(LineNoStart, LineNo),
|
||||
get_day_name(LastTriggerDate % 7),
|
||||
d,
|
||||
get_month_name(m),
|
||||
|
||||
@@ -40,8 +40,8 @@ check_subst_args(UserFunc *f, int n)
|
||||
if (f->nargs == n) {
|
||||
return 1;
|
||||
}
|
||||
Wprint(tr("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);
|
||||
Wprint(tr("Function `%s' defined at %s(%s) should take %d argument%s, but actually takes %d"),
|
||||
f->name, f->filename, line_range(f->lineno_start, f->lineno), n, (n == 1 ? "" : "s"), f->nargs);
|
||||
return 0;
|
||||
}
|
||||
/***************************************************************/
|
||||
@@ -79,6 +79,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
int origLen = DBufLen(dbuf);
|
||||
int altmode;
|
||||
int r;
|
||||
int origtime;
|
||||
Value v;
|
||||
UserFunc *func;
|
||||
|
||||
@@ -87,6 +88,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
if (tt) {
|
||||
tim = tt->ttime;
|
||||
}
|
||||
origtime = tim;
|
||||
if (tim == NO_TIME) tim = curtime;
|
||||
tdiff = tim - curtime;
|
||||
adiff = ABS(tdiff);
|
||||
@@ -123,7 +125,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
pm = (h < 12) ? tr("am") : tr("pm");
|
||||
}
|
||||
|
||||
hh = (h == 12) ? 12 : h % 12;
|
||||
hh = (h == 12 || h == 0) ? 12 : h % 12;
|
||||
|
||||
ch = curtime / 60;
|
||||
cmin = curtime % 60;
|
||||
@@ -149,7 +151,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
if (r != OK) {
|
||||
cpm = (h < 12) ? tr("am") : tr("pm");
|
||||
}
|
||||
chh = (ch == 12) ? 12 : ch % 12;
|
||||
chh = (ch == 0 || ch == 12) ? 12 : ch % 12;
|
||||
|
||||
func = FindUserFunc("subst_ordinal");
|
||||
if (func && check_subst_args(func, 1)) {
|
||||
@@ -405,6 +407,12 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
Eprint("%s", GetErr(r));
|
||||
}
|
||||
}
|
||||
if (origtime == NO_TIME) {
|
||||
if ((c >= '0' && c <= '9') || (c == '!')) {
|
||||
Wprint(tr("`%%%c' substitution sequence should not be used without an AT clause"), c);
|
||||
}
|
||||
}
|
||||
|
||||
switch(UPPER(c)) {
|
||||
case 'A':
|
||||
if (altmode == '*' || !strcmp(tr("on"), "")) {
|
||||
|
||||
25
src/expr.c
25
src/expr.c
@@ -197,7 +197,7 @@ static char const *get_operator_name(expr_node *node);
|
||||
static UserFunc *CurrentUserFunc = NULL;
|
||||
|
||||
/* How many expr_node objects to allocate at a time */
|
||||
#define ALLOC_CHUNK 64
|
||||
#define ALLOC_CHUNK 256
|
||||
|
||||
static char const *
|
||||
find_end_of_expr(char const *s)
|
||||
@@ -626,6 +626,18 @@ debug_exit_userfunc(expr_node *node, Value *ans, int r, Value *locals, int nargs
|
||||
fprintf(ErrFp, "\n");
|
||||
}
|
||||
|
||||
static void
|
||||
print_placeholders(int n)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<n; i++) {
|
||||
if (i > 0) {
|
||||
fprintf(ErrFp, ", ");
|
||||
}
|
||||
fprintf(ErrFp, "?");
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* eval_userfunc - evaluate a user-defined function */
|
||||
@@ -667,12 +679,12 @@ eval_userfunc(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
|
||||
/* Make sure we have the right number of arguments */
|
||||
if (node->num_kids < f->nargs) {
|
||||
DBG(fprintf(ErrFp, "%s(...) => %s\n", fname, GetErr(E_2FEW_ARGS)));
|
||||
DBG(fprintf(ErrFp, "%s(", fname); print_placeholders(node->num_kids); fprintf(ErrFp, ") => %s\n", GetErr(E_2FEW_ARGS)));
|
||||
Eprint("%s(): %s", f->name, GetErr(E_2FEW_ARGS));
|
||||
return E_2FEW_ARGS;
|
||||
}
|
||||
if (node->num_kids > f->nargs) {
|
||||
DBG(fprintf(ErrFp, "%s(...) => %s\n", fname, GetErr(E_2MANY_ARGS)));
|
||||
DBG(fprintf(ErrFp, "%s(", fname); print_placeholders(node->num_kids); fprintf(ErrFp, ") => %s\n", GetErr(E_2MANY_ARGS)));
|
||||
Eprint("%s(): %s", f->name, GetErr(E_2MANY_ARGS));
|
||||
return E_2MANY_ARGS;
|
||||
}
|
||||
@@ -723,7 +735,7 @@ eval_userfunc(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
FuncRecursionLevel++;
|
||||
|
||||
/* Add a call to the call stack for better error messages */
|
||||
pushed = push_call(f->filename, f->name, f->lineno);
|
||||
pushed = push_call(f->filename, f->name, f->lineno, f->lineno_start);
|
||||
|
||||
DBG(debug_enter_userfunc(node, new_locals, f->nargs));
|
||||
|
||||
@@ -1130,7 +1142,7 @@ static int add(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
|
||||
/* If either is a string, coerce them both to strings and concatenate */
|
||||
if (v1.type == STR_TYPE || v2.type == STR_TYPE) {
|
||||
/* Skanky... copy the values shallowly fode debug */
|
||||
/* Skanky... copy the values shallowly for debug */
|
||||
Value o1 = v1;
|
||||
Value o2 = v2;
|
||||
if ( (r = DoCoerce(STR_TYPE, &v1)) ) {
|
||||
@@ -1164,6 +1176,8 @@ static int add(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
strcpy(ans->v.str, v1.v.str);
|
||||
strcpy(ans->v.str+l1, v2.v.str);
|
||||
DBG(debug_evaluation_binop(ans, OK, &o1, &o2, "+"));
|
||||
DestroyValue(v1);
|
||||
DestroyValue(v2);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -2188,7 +2202,6 @@ static expr_node *parse_atom(char const **e, int *r, Var *locals, int level)
|
||||
return NULL;
|
||||
}
|
||||
if (!ISID(*s) &&
|
||||
*s != '%' &&
|
||||
*s != '$' &&
|
||||
*s != '"' &&
|
||||
*s != '\'') {
|
||||
|
||||
14
src/files.c
14
src/files.c
@@ -50,6 +50,7 @@ typedef struct cache {
|
||||
struct cache *next;
|
||||
char const *text;
|
||||
int LineNo;
|
||||
int LineNoStart;
|
||||
} CachedLine;
|
||||
|
||||
typedef struct cheader {
|
||||
@@ -77,6 +78,7 @@ typedef struct {
|
||||
char const *filename;
|
||||
FilenameChain *chain;
|
||||
int LineNo;
|
||||
int LineNoStart;
|
||||
unsigned int IfFlags;
|
||||
int NumIfs;
|
||||
int IfLinenos[IF_NEST];
|
||||
@@ -189,6 +191,7 @@ int ReadLine(void)
|
||||
if (CLine) {
|
||||
CurLine = CLine->text;
|
||||
LineNo = CLine->LineNo;
|
||||
LineNoStart = CLine->LineNoStart;
|
||||
CLine = CLine->next;
|
||||
got_a_fresh_line();
|
||||
clear_callstack();
|
||||
@@ -218,6 +221,7 @@ static int ReadLineFromFile(int use_pclose)
|
||||
DBufInit(&buf);
|
||||
DBufFree(&LineBuffer);
|
||||
|
||||
LineNoStart = LineNo+1;
|
||||
while(fp) {
|
||||
if (DBufGets(&buf, fp) != OK) {
|
||||
DBufFree(&LineBuffer);
|
||||
@@ -332,6 +336,7 @@ int OpenFile(char const *fname)
|
||||
CLine = h->cache;
|
||||
STRSET(FileName, fname);
|
||||
LineNo = 0;
|
||||
LineNoStart = 0;
|
||||
if (!h->ownedByMe) {
|
||||
RunDisabled |= RUN_NOTOWNER;
|
||||
} else {
|
||||
@@ -367,6 +372,7 @@ int OpenFile(char const *fname)
|
||||
CLine = NULL;
|
||||
if (ShouldCache) {
|
||||
LineNo = 0;
|
||||
LineNoStart = 0;
|
||||
r = CacheFile(fname, 0);
|
||||
if (r == OK) {
|
||||
fp = NULL;
|
||||
@@ -385,6 +391,7 @@ int OpenFile(char const *fname)
|
||||
}
|
||||
STRSET(FileName, fname);
|
||||
LineNo = 0;
|
||||
LineNoStart = 0;
|
||||
if (FileName) return OK; else return E_NO_MEM;
|
||||
}
|
||||
|
||||
@@ -487,6 +494,7 @@ static int CacheFile(char const *fname, int use_pclose)
|
||||
}
|
||||
cl->next = NULL;
|
||||
cl->LineNo = LineNo;
|
||||
cl->LineNoStart = LineNoStart;
|
||||
cl->text = StrDup(s);
|
||||
DBufFree(&LineBuffer);
|
||||
if (!cl->text) {
|
||||
@@ -565,6 +573,7 @@ static int PopFile(void)
|
||||
IStackPtr--;
|
||||
|
||||
LineNo = i->LineNo;
|
||||
LineNoStart = i->LineNoStart;
|
||||
IfFlags = i->IfFlags;
|
||||
memcpy(IfLinenos, i->IfLinenos, IF_NEST);
|
||||
NumIfs = i->NumIfs;
|
||||
@@ -906,6 +915,7 @@ static int IncludeCmd(char const *cmd)
|
||||
}
|
||||
i->ownedByMe = 1;
|
||||
i->LineNo = LineNo;
|
||||
i->LineNoStart = LineNo;
|
||||
i->NumIfs = NumIfs;
|
||||
i->IfFlags = IfFlags;
|
||||
memcpy(i->IfLinenos, IfLinenos, IF_NEST);
|
||||
@@ -932,6 +942,7 @@ static int IncludeCmd(char const *cmd)
|
||||
STRSET(FileName, fname);
|
||||
DBufFree(&buf);
|
||||
LineNo = 0;
|
||||
LineNoStart = 0;
|
||||
if (!h->ownedByMe) {
|
||||
RunDisabled |= RUN_NOTOWNER;
|
||||
} else {
|
||||
@@ -963,6 +974,7 @@ static int IncludeCmd(char const *cmd)
|
||||
}
|
||||
fp = fp2;
|
||||
LineNo = 0;
|
||||
LineNoStart = 0;
|
||||
|
||||
/* Temporarily turn of file tracing */
|
||||
old_flag = DebugFlag;
|
||||
@@ -978,6 +990,7 @@ static int IncludeCmd(char const *cmd)
|
||||
fp = NULL;
|
||||
CLine = CachedFiles->cache;
|
||||
LineNo = 0;
|
||||
LineNoStart = 0;
|
||||
STRSET(FileName, fname);
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
@@ -1014,6 +1027,7 @@ int IncludeFile(char const *fname)
|
||||
i->filename = NULL;
|
||||
}
|
||||
i->LineNo = LineNo;
|
||||
i->LineNoStart = LineNoStart;
|
||||
i->NumIfs = NumIfs;
|
||||
i->IfFlags = IfFlags;
|
||||
memcpy(i->IfLinenos, IfLinenos, IF_NEST);
|
||||
|
||||
56
src/funcs.c
56
src/funcs.c
@@ -125,6 +125,10 @@ static int FMonnum (func_info *);
|
||||
static int FMoondate (func_info *);
|
||||
static int FMoondatetime (func_info *);
|
||||
static int FMoonphase (func_info *);
|
||||
static int FMoonrise (func_info *);
|
||||
static int FMoonrisedir (func_info *);
|
||||
static int FMoonset (func_info *);
|
||||
static int FMoonsetdir (func_info *);
|
||||
static int FMoontime (func_info *);
|
||||
static int FMultiTrig (func_info *);
|
||||
static int FNDawn (func_info *);
|
||||
@@ -286,6 +290,10 @@ BuiltinFunc Func[] = {
|
||||
{ "moondate", 1, 3, 0, FMoondate, NULL },
|
||||
{ "moondatetime", 1, 3, 0, FMoondatetime, NULL },
|
||||
{ "moonphase", 0, 2, 0, FMoonphase, NULL },
|
||||
{ "moonrise", 0, 1, 0, FMoonrise, NULL },
|
||||
{ "moonrisedir", 0, 1, 0, FMoonrisedir, NULL },
|
||||
{ "moonset", 0, 1, 0, FMoonset, NULL },
|
||||
{ "moonsetdir", 0, 1, 0, FMoonsetdir, NULL },
|
||||
{ "moontime", 1, 3, 0, FMoontime, NULL },
|
||||
{ "multitrig", 1, NO_MAX, 0, FMultiTrig, NULL },
|
||||
{ "ndawn", 0, 1, 0, FNDawn, NULL },
|
||||
@@ -3316,6 +3324,54 @@ static int FMoondatetime(func_info *info)
|
||||
return MoonStuff(DATETIME_TYPE, info);
|
||||
}
|
||||
|
||||
static int FMoonrise(func_info *info)
|
||||
{
|
||||
int start = DSEToday;
|
||||
if (Nargs >= 1) {
|
||||
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||
start = DATEPART(ARG(0));
|
||||
}
|
||||
RetVal.type = DATETIME_TYPE;
|
||||
RETVAL = GetMoonrise(start);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FMoonset(func_info *info)
|
||||
{
|
||||
int start = DSEToday;
|
||||
if (Nargs >= 1) {
|
||||
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||
start = DATEPART(ARG(0));
|
||||
}
|
||||
RetVal.type = DATETIME_TYPE;
|
||||
RETVAL = GetMoonset(start);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FMoonrisedir(func_info *info)
|
||||
{
|
||||
int start = DSEToday;
|
||||
if (Nargs >= 1) {
|
||||
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||
start = DATEPART(ARG(0));
|
||||
}
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = GetMoonrise_angle(start);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FMoonsetdir(func_info *info)
|
||||
{
|
||||
int start = DSEToday;
|
||||
if (Nargs >= 1) {
|
||||
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||
start = DATEPART(ARG(0));
|
||||
}
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = GetMoonset_angle(start);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int MoonStuff(int type_wanted, func_info *info)
|
||||
{
|
||||
int startdate, starttim;
|
||||
|
||||
@@ -47,6 +47,7 @@ EXTERN int CurDay;
|
||||
EXTERN int CurMon;
|
||||
EXTERN int CurYear;
|
||||
EXTERN int LineNo;
|
||||
EXTERN int LineNoStart;
|
||||
EXTERN int FreshLine;
|
||||
EXTERN int WarnedAboutImplicit;
|
||||
EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS];
|
||||
@@ -119,7 +120,7 @@ EXTERN INIT( int PurgeIncludeDepth, 0);
|
||||
EXTERN INIT( FILE *PurgeFP, NULL);
|
||||
EXTERN INIT( int NumIfs, 0);
|
||||
EXTERN INIT( unsigned int IfFlags, 0);
|
||||
EXTERN INIT( int IfLinenos[IF_NEST], {0});
|
||||
EXTERN INIT( int IfLinenos[IF_NEST], {0});
|
||||
EXTERN INIT( int LastTrigValid, 0);
|
||||
EXTERN Trigger LastTrigger;
|
||||
EXTERN TimeTrig LastTimeTrig;
|
||||
|
||||
36
src/main.c
36
src/main.c
@@ -897,11 +897,21 @@ void Wprint(char const *fmt, ...)
|
||||
va_list argptr;
|
||||
|
||||
|
||||
/* We can't use line_range because caller might have used it */
|
||||
if (FileName) {
|
||||
if (strcmp(FileName, "-"))
|
||||
(void) fprintf(ErrFp, "%s(%d): ", FileName, LineNo);
|
||||
else
|
||||
(void) fprintf(ErrFp, "-stdin-(%d): ", LineNo);
|
||||
if (strcmp(FileName, "-")) {
|
||||
if (LineNoStart == LineNo) {
|
||||
(void) fprintf(ErrFp, "%s(%d): ", FileName, LineNo);
|
||||
} else {
|
||||
(void) fprintf(ErrFp, "%s(%d:%d): ", FileName, LineNoStart, LineNo);
|
||||
}
|
||||
} else {
|
||||
if (LineNoStart == LineNo) {
|
||||
(void) fprintf(ErrFp, "-stdin-(%d): ", LineNo);
|
||||
} else {
|
||||
(void) fprintf(ErrFp, "-stdin-(%d:%d): ", LineNoStart, LineNo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
va_start(argptr, fmt);
|
||||
@@ -933,7 +943,12 @@ void Eprint(char const *fmt, ...)
|
||||
fname = "-stdin-";
|
||||
}
|
||||
if (FreshLine) {
|
||||
(void) fprintf(ErrFp, "%s(%d): ", fname, LineNo);
|
||||
/* We can't use line_range because caller might have used it */
|
||||
if (LineNo == LineNoStart) {
|
||||
(void) fprintf(ErrFp, "%s(%d): ", fname, LineNo);
|
||||
} else {
|
||||
(void) fprintf(ErrFp, "%s(%d:%d): ", fname, LineNoStart, LineNo);
|
||||
}
|
||||
} else {
|
||||
fprintf(ErrFp, " ");
|
||||
}
|
||||
@@ -1117,8 +1132,7 @@ int DoIf(ParsePtr p)
|
||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
Eprint("%s", GetErr(r));
|
||||
} else
|
||||
if ( (v.type != STR_TYPE && v.v.val) ||
|
||||
(v.type == STR_TYPE && strcmp(v.v.str, "")) ) {
|
||||
if (truthy(&v)) {
|
||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
} else {
|
||||
syndrome = IF_FALSE | BEFORE_ELSE;
|
||||
@@ -2022,7 +2036,6 @@ SaveLastTimeTrig(TimeTrig const *t)
|
||||
void
|
||||
System(char const *cmd, int is_queued)
|
||||
{
|
||||
int r;
|
||||
pid_t kid;
|
||||
int fd;
|
||||
int status;
|
||||
@@ -2055,15 +2068,12 @@ System(char const *cmd, int is_queued)
|
||||
}
|
||||
}
|
||||
/* This is the child process or original if we never forked */
|
||||
r = system(cmd);
|
||||
(void) system(cmd);
|
||||
if (do_exit) {
|
||||
/* In the child process, so exit! */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (r == 0) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
char const *
|
||||
|
||||
403
src/moon.c
403
src/moon.c
@@ -546,3 +546,406 @@ void HuntPhase(int startdate, int starttim, int phas, int *date, int *time)
|
||||
t1 = h*60 + min;
|
||||
UTCToLocal(d1, t1, date, time);
|
||||
}
|
||||
|
||||
/*
|
||||
Moonrise and Moonset calculations
|
||||
Derived from: https://github.com/signetica/MoonRise
|
||||
Original license from that project:
|
||||
|
||||
Copyright 2007 Stephen R. Schmitt
|
||||
Subsequent work Copyright 2020 Cyrus Rahman
|
||||
|
||||
You may use or modify this source code in any way you find useful,
|
||||
provided that you agree that the author(s) have no warranty,
|
||||
obligations or liability. You must determine the suitability of this
|
||||
source code for your use.
|
||||
|
||||
Redistributions of this source code must retain this copyright notice.
|
||||
*/
|
||||
|
||||
/* How many hours to search for moonrise / moonset on either side of
|
||||
starting point */
|
||||
#define MR_WINDOW 48
|
||||
|
||||
#define K1 15*(PI/180)*1.0027379
|
||||
|
||||
#define remainder(x, y) ((x) - (y) * rint((x)/(y)))
|
||||
|
||||
struct MoonInfo {
|
||||
time_t queryTime;
|
||||
time_t riseTime;
|
||||
time_t setTime;
|
||||
double riseAz;
|
||||
double setAz;
|
||||
int hasRise;
|
||||
int hasSet;
|
||||
int isVisible;
|
||||
};
|
||||
|
||||
static void init_moon_info(struct MoonInfo *info)
|
||||
{
|
||||
info->queryTime = (time_t) 0;
|
||||
info->riseTime = (time_t) 0;
|
||||
info->setTime = (time_t) 0;
|
||||
info->riseAz = 0.0;
|
||||
info->setAz = 0.0;
|
||||
info->hasRise = 0;
|
||||
info->hasSet = 0;
|
||||
info->isVisible = 0;
|
||||
}
|
||||
/*
|
||||
Local Sidereal Time
|
||||
Provides local sidereal time in degrees, requires longitude in degrees
|
||||
and time in fractional Julian days since Jan 1, 2000, 1200UTC (e.g. the
|
||||
Julian date - 2451545).
|
||||
cf. USNO Astronomical Almanac and
|
||||
https://astronomy.stackexchange.com/questions/24859/local-sidereal-time
|
||||
*/
|
||||
|
||||
static double local_sidereal_time(double offset_days, double longitude)
|
||||
{
|
||||
double ltime = (15.0L * (6.697374558L + 0.06570982441908L * offset_days +
|
||||
remainder(offset_days, 1) * 24 + 12 +
|
||||
0.000026 * (offset_days / 36525) * (offset_days / 36525)) + longitude) / 360.0;
|
||||
ltime -= floor(ltime);
|
||||
return ltime * 360.0;
|
||||
}
|
||||
|
||||
static double julian_from_time_t(time_t t)
|
||||
{
|
||||
return ((double) t) / 86400.0L + 2440587.5L;
|
||||
}
|
||||
|
||||
static time_t time_t_from_dse(int dse)
|
||||
{
|
||||
int y, m, d;
|
||||
struct tm local;
|
||||
FromDSE(dse, &y, &m, &d);
|
||||
|
||||
local.tm_sec = 0;
|
||||
local.tm_min = 0;
|
||||
local.tm_hour = 0;
|
||||
local.tm_mday = d;
|
||||
local.tm_mon = m;
|
||||
local.tm_year = y-1900;
|
||||
local.tm_isdst = -1;
|
||||
|
||||
return mktime(&local);
|
||||
}
|
||||
|
||||
static int datetime_from_time_t(time_t t)
|
||||
{
|
||||
struct tm *local;
|
||||
int ans;
|
||||
|
||||
/* Round to nearest minute */
|
||||
int min_offset = ((long) t) % 60;
|
||||
if (min_offset >= 30) {
|
||||
t += (60 - min_offset);
|
||||
} else {
|
||||
t -= min_offset;
|
||||
}
|
||||
|
||||
local = localtime(&t);
|
||||
|
||||
ans = DSE(local->tm_year + 1900, local->tm_mon, local->tm_mday) * 1440;
|
||||
ans += local->tm_hour * 60;
|
||||
ans += local->tm_min;
|
||||
return ans;
|
||||
}
|
||||
|
||||
/* 3-point interpolation */
|
||||
static double interpolate(double f0, double f1, double f2, double p)
|
||||
{
|
||||
double a = f1-f0;
|
||||
double b = f2-f1-a;
|
||||
return f0 + p * (2*a + b * (2*p - 1));
|
||||
}
|
||||
|
||||
/* Moon position using fundamental arguments
|
||||
Van Flandern & Pulkkinen, 1979) */
|
||||
void moon_position(double dayOffset, double *ra, double *declination, double *distance)
|
||||
{
|
||||
double l = 0.606434 + 0.03660110129 * dayOffset;
|
||||
double m = 0.374897 + 0.03629164709 * dayOffset;
|
||||
double f = 0.259091 + 0.03674819520 * dayOffset;
|
||||
double d = 0.827362 + 0.03386319198 * dayOffset;
|
||||
double n = 0.347343 - 0.00014709391 * dayOffset;
|
||||
double g = 0.993126 + 0.00273777850 * dayOffset;
|
||||
|
||||
l = 2 * PI * (l - floor(l));
|
||||
m = 2 * PI * (m - floor(m));
|
||||
f = 2 * PI * (f - floor(f));
|
||||
d = 2 * PI * (d - floor(d));
|
||||
n = 2 * PI * (n - floor(n));
|
||||
g = 2 * PI * (g - floor(g));
|
||||
|
||||
double v, u, w;
|
||||
v = 0.39558 * sin(f + n)
|
||||
+ 0.08200 * sin(f)
|
||||
+ 0.03257 * sin(m - f - n)
|
||||
+ 0.01092 * sin(m + f + n)
|
||||
+ 0.00666 * sin(m - f)
|
||||
- 0.00644 * sin(m + f - 2*d + n)
|
||||
- 0.00331 * sin(f - 2*d + n)
|
||||
- 0.00304 * sin(f - 2*d)
|
||||
- 0.00240 * sin(m - f - 2*d - n)
|
||||
+ 0.00226 * sin(m + f)
|
||||
- 0.00108 * sin(m + f - 2*d)
|
||||
- 0.00079 * sin(f - n)
|
||||
+ 0.00078 * sin(f + 2*d + n);
|
||||
u = 1
|
||||
- 0.10828 * cos(m)
|
||||
- 0.01880 * cos(m - 2*d)
|
||||
- 0.01479 * cos(2*d)
|
||||
+ 0.00181 * cos(2*m - 2*d)
|
||||
- 0.00147 * cos(2*m)
|
||||
- 0.00105 * cos(2*d - g)
|
||||
- 0.00075 * cos(m - 2*d + g);
|
||||
w = 0.10478 * sin(m)
|
||||
- 0.04105 * sin(2*f + 2*n)
|
||||
- 0.02130 * sin(m - 2*d)
|
||||
- 0.01779 * sin(2*f + n)
|
||||
+ 0.01774 * sin(n)
|
||||
+ 0.00987 * sin(2*d)
|
||||
- 0.00338 * sin(m - 2*f - 2*n)
|
||||
- 0.00309 * sin(g)
|
||||
- 0.00190 * sin(2*f)
|
||||
- 0.00144 * sin(m + n)
|
||||
- 0.00144 * sin(m - 2*f - n)
|
||||
- 0.00113 * sin(m + 2*f + 2*n)
|
||||
- 0.00094 * sin(m - 2*d + g)
|
||||
- 0.00092 * sin(2*m - 2*d);
|
||||
|
||||
double s;
|
||||
s = w / sqrt(u - v*v);
|
||||
*ra = l + atan(s / sqrt(1 - s*s)); // Right ascension
|
||||
|
||||
s = v / sqrt(u);
|
||||
*declination = atan(s / sqrt(1 - s*s)); // Declination
|
||||
*distance = 60.40974 * sqrt(u); // Distance
|
||||
}
|
||||
|
||||
/* Search for moonrise / moonset events during an hour */
|
||||
static void test_moon_event(int k, double offset_days, struct MoonInfo *moon_info,
|
||||
double latitude, double longitude,
|
||||
double ra[], double declination[], double distance[])
|
||||
{
|
||||
double ha[3], VHz[3];
|
||||
double lSideTime;
|
||||
|
||||
/* Get (local_sidereal_time - MR_WINDOW / 2) hours in radians. */
|
||||
lSideTime = local_sidereal_time(offset_days, longitude) * 2 * PI / 360.0;
|
||||
|
||||
/* Calculate hour angle */
|
||||
ha[0] = lSideTime - ra[0] + k*K1;
|
||||
ha[2] = lSideTime - ra[2] + k*K1 + K1;
|
||||
|
||||
// Hour Angle and declination at half hour.
|
||||
ha[1] = (ha[2] + ha[0])/2;
|
||||
declination[1] = (declination[2] + declination[0])/2;
|
||||
|
||||
double s = sin((PI / 180) * latitude);
|
||||
double c = cos((PI / 180) * latitude);
|
||||
|
||||
// refraction + semidiameter at horizon + distance correction
|
||||
double z = cos((PI / 180) * (90.567 - 41.685 / distance[0]));
|
||||
|
||||
VHz[0] = s * sin(declination[0]) + c * cos(declination[0]) * cos(ha[0]) - z;
|
||||
VHz[2] = s * sin(declination[2]) + c * cos(declination[2]) * cos(ha[2]) - z;
|
||||
|
||||
if (signbit(VHz[0]) == signbit(VHz[2]))
|
||||
goto noevent; // No event this hour.
|
||||
|
||||
VHz[1] = s * sin(declination[1]) + c * cos(declination[1]) * cos(ha[1]) - z;
|
||||
|
||||
double a, b, d, e, time;
|
||||
a = 2 * VHz[2] - 4 * VHz[1] + 2 * VHz[0];
|
||||
b = 4 * VHz[1] - 3 * VHz[0] - VHz[2];
|
||||
d = b * b - 4 * a * VHz[0];
|
||||
|
||||
if (d < 0)
|
||||
goto noevent; // No event this hour.
|
||||
|
||||
d = sqrt(d);
|
||||
e = (-b + d) / (2 * a);
|
||||
if ((e < 0) || (e > 1))
|
||||
e = (-b - d) / (2 * a);
|
||||
time = k + e + 1 / 120; // Time since k=0 of event (in hours).
|
||||
|
||||
// The time we started searching + the time from the start of the search to the
|
||||
// event is the time of the event. Add (time since k=0) - window/2 hours.
|
||||
time_t eventTime;
|
||||
eventTime = moon_info->queryTime + (time - MR_WINDOW / 2) *60 *60;
|
||||
|
||||
double hz, nz, dz, az;
|
||||
hz = ha[0] + e * (ha[2] - ha[0]); // Azimuth of the moon at the event.
|
||||
nz = -cos(declination[1]) * sin(hz);
|
||||
dz = c * sin(declination[1]) - s * cos(declination[1]) * cos(hz);
|
||||
az = atan2(nz, dz) * (180 / PI);
|
||||
if (az < 0) {
|
||||
az += 360;
|
||||
}
|
||||
|
||||
// If there is no previously recorded event of this type, save this event.
|
||||
//
|
||||
// If this event is previous to queryTime, and is the nearest event to queryTime
|
||||
// of events of its type previous to queryType, save this event, replacing the
|
||||
// previously recorded event of its type. Events subsequent to queryTime are
|
||||
// treated similarly, although since events are tested in chronological order
|
||||
// no replacements will occur as successive events will be further from
|
||||
// queryTime.
|
||||
//
|
||||
// If this event is subsequent to queryTime and there is an event of its type
|
||||
// previous to queryTime, then there is an event of the other type between the
|
||||
// two events of this event's type. If the event of the other type is
|
||||
// previous to queryTime, then it is the nearest event to queryTime that is
|
||||
// previous to queryTime. In this case save the current event, replacing
|
||||
// the previously recorded event of its type. Otherwise discard the current
|
||||
// event.
|
||||
//
|
||||
if ((VHz[0] < 0) && (VHz[2] > 0)) {
|
||||
if (!moon_info->hasRise ||
|
||||
((moon_info->riseTime < moon_info->queryTime) == (eventTime < moon_info->queryTime) &&
|
||||
labs(moon_info->riseTime - moon_info->queryTime) > labs(eventTime - moon_info->queryTime)) ||
|
||||
((moon_info->riseTime < moon_info->queryTime) != (eventTime < moon_info->queryTime) &&
|
||||
(moon_info->hasSet &&
|
||||
(moon_info->riseTime < moon_info->queryTime) == (moon_info->setTime < moon_info->queryTime)))) {
|
||||
moon_info->riseTime = eventTime;
|
||||
moon_info->riseAz = az;
|
||||
moon_info->hasRise = 1;
|
||||
}
|
||||
}
|
||||
if ((VHz[0] > 0) && (VHz[2] < 0)) {
|
||||
if (!moon_info->hasSet ||
|
||||
((moon_info->setTime < moon_info->queryTime) == (eventTime < moon_info->queryTime) &&
|
||||
labs(moon_info->setTime - moon_info->queryTime) > labs(eventTime - moon_info->queryTime)) ||
|
||||
((moon_info->setTime < moon_info->queryTime) != (eventTime < moon_info->queryTime) &&
|
||||
(moon_info->hasRise &&
|
||||
(moon_info->setTime < moon_info->queryTime) == (moon_info->riseTime < moon_info->queryTime)))) {
|
||||
moon_info->setTime = eventTime;
|
||||
moon_info->setAz = az;
|
||||
moon_info->hasSet = 1;
|
||||
}
|
||||
}
|
||||
|
||||
noevent:
|
||||
// There are obscure cases in the polar regions that require extra logic.
|
||||
if (!moon_info->hasRise && !moon_info->hasSet)
|
||||
moon_info->isVisible = !signbit(VHz[2]);
|
||||
else if (moon_info->hasRise && !moon_info->hasSet)
|
||||
moon_info->isVisible = (moon_info->queryTime > moon_info->riseTime);
|
||||
else if (!moon_info->hasRise && moon_info->hasSet)
|
||||
moon_info->isVisible = (moon_info->queryTime < moon_info->setTime);
|
||||
else
|
||||
moon_info->isVisible = ((moon_info->riseTime < moon_info->setTime && moon_info->riseTime < moon_info->queryTime && moon_info->setTime > moon_info->queryTime) ||
|
||||
(moon_info->riseTime > moon_info->setTime && (moon_info->riseTime < moon_info->queryTime || moon_info->setTime > moon_info->queryTime)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_moonrise_moonset(double latitude, double longitude, time_t t,
|
||||
struct MoonInfo *mi)
|
||||
{
|
||||
double ra[3], declination[3], distance[3];
|
||||
double offset_days;
|
||||
int i;
|
||||
|
||||
init_moon_info(mi);
|
||||
|
||||
mi->queryTime = t;
|
||||
|
||||
/* Days since Jan 1, 2000 12:00UTC */
|
||||
offset_days = julian_from_time_t(t) - 2451545L;
|
||||
|
||||
offset_days -= (double) MR_WINDOW / (2.0 * 24.0);
|
||||
|
||||
for (i=0; i<3; i++) {
|
||||
moon_position(offset_days + i * ((double) MR_WINDOW / (2.0 * 24.0)), &ra[i], &declination[i], &distance[i]);
|
||||
}
|
||||
|
||||
if (ra[1] <= ra[0]) {
|
||||
ra[1] += 2*PI;
|
||||
}
|
||||
if (ra[2] <= ra[1]) {
|
||||
ra[2] += 2*PI;
|
||||
}
|
||||
|
||||
double window_ra[3], window_declination[3], window_distance[3];
|
||||
|
||||
window_ra[0] = ra[0];
|
||||
window_declination[0] = declination[0];
|
||||
window_distance[0] = distance[0];
|
||||
|
||||
for (int k=0; k < MR_WINDOW; k++) {
|
||||
double ph = (double) (k+1) / (double) MR_WINDOW;
|
||||
window_ra[2] = interpolate(ra[0], ra[1], ra[2], ph);
|
||||
window_declination[2] = interpolate(declination[0], declination[1], declination[2], ph);
|
||||
window_distance[2] = interpolate(distance[0], distance[1], distance[2], ph);
|
||||
test_moon_event(k, offset_days, mi, latitude, longitude, window_ra, window_declination, window_distance);
|
||||
|
||||
/* Step to next interval */
|
||||
window_ra[0] = window_ra[2];
|
||||
window_declination[0] = window_declination[2];
|
||||
window_distance[0] = window_distance[2];
|
||||
}
|
||||
}
|
||||
|
||||
/* Get next moonrise in minutes after midnight of BASEYR
|
||||
starting from given DSE.
|
||||
Returns 0 if no moonrise could be computes */
|
||||
|
||||
#define ME_SEARCH_DAYS 180
|
||||
static int GetMoonevent(int dse, int is_rise, int want_angle)
|
||||
{
|
||||
int i;
|
||||
int angle;
|
||||
struct MoonInfo mi;
|
||||
time_t t = time_t_from_dse(dse);
|
||||
for (i=0; i<ME_SEARCH_DAYS; i++) {
|
||||
calculate_moonrise_moonset(Latitude, Longitude, t + i * 86400, &mi);
|
||||
if (is_rise) {
|
||||
if (mi.hasRise && mi.riseTime >= t) {
|
||||
if (want_angle) {
|
||||
angle = (int) (mi.riseAz + 0.5);
|
||||
return angle;
|
||||
} else {
|
||||
return datetime_from_time_t(mi.riseTime);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mi.hasSet && mi.setTime >= t) {
|
||||
if (want_angle) {
|
||||
angle = (int) (mi.setAz + 0.5);
|
||||
return angle;
|
||||
} else {
|
||||
return datetime_from_time_t(mi.setTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (want_angle) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int GetMoonrise(int dse)
|
||||
{
|
||||
return GetMoonevent(dse, 1, 0);
|
||||
}
|
||||
int GetMoonset(int dse)
|
||||
{
|
||||
return GetMoonevent(dse, 0, 0);
|
||||
}
|
||||
|
||||
int GetMoonrise_angle(int dse)
|
||||
{
|
||||
return GetMoonevent(dse, 1, 1);
|
||||
}
|
||||
int GetMoonset_angle(int dse)
|
||||
{
|
||||
return GetMoonevent(dse, 0, 1);
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ char const *get_day_name(int wkday);
|
||||
char const *get_month_name(int mon);
|
||||
|
||||
void set_cloexec(FILE *fp);
|
||||
int push_call(char const *filename, char const *func, int lineno);
|
||||
int push_call(char const *filename, char const *func, int lineno, int lineno_start);
|
||||
void clear_callstack(void);
|
||||
int print_callstack(FILE *fp);
|
||||
void pop_call(void);
|
||||
@@ -284,3 +284,8 @@ int TrigInfoHeadersAreTheSame(char const *i1, char const *i2);
|
||||
int TrigInfoIsValid(char const *info);
|
||||
char const *FindTrigInfo(Trigger *t, char const *header);
|
||||
void WriteJSONInfoChain(TrigInfo *ti);
|
||||
char const *line_range(int lineno_start, int lineno);
|
||||
int GetMoonrise(int dse);
|
||||
int GetMoonset(int dse);
|
||||
int GetMoonrise_angle(int dse);
|
||||
int GetMoonset_angle(int dse);
|
||||
|
||||
@@ -61,6 +61,7 @@ typedef struct queuedrem {
|
||||
char const *text;
|
||||
char const *fname;
|
||||
int lineno;
|
||||
int lineno_start;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
char sched[VAR_NAME_LEN+1];
|
||||
Trigger t;
|
||||
@@ -224,6 +225,7 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
||||
}
|
||||
|
||||
qelem->lineno = LineNo;
|
||||
qelem->lineno_start = LineNoStart;
|
||||
NumQueued++;
|
||||
qelem->typ = trig->typ;
|
||||
strcpy(qelem->passthru, trig->passthru);
|
||||
@@ -784,6 +786,9 @@ json_queue(QueuedRem const *q)
|
||||
PrintJSONKeyPairInt("ntrig", q->ntrig);
|
||||
PrintJSONKeyPairString("filename", q->fname);
|
||||
PrintJSONKeyPairInt("lineno", q->lineno);
|
||||
if (q->lineno_start != q->lineno) {
|
||||
PrintJSONKeyPairInt("lineno_start", q->lineno_start);
|
||||
}
|
||||
switch(q->typ) {
|
||||
case NO_TYPE: PrintJSONKeyPairString("type", "NO_TYPE"); break;
|
||||
case MSG_TYPE: PrintJSONKeyPairString("type", "MSG_TYPE"); break;
|
||||
|
||||
@@ -452,8 +452,8 @@ AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int sav
|
||||
r = today;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
FromDSE(r, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%d): Trig(adj) = %s, %d %s, %d",
|
||||
FileName, LineNo,
|
||||
fprintf(ErrFp, "%s(%s): Trig(adj) = %s, %d %s, %d",
|
||||
FileName, line_range(LineNoStart, LineNo),
|
||||
get_day_name(r % 7),
|
||||
d,
|
||||
get_month_name(m),
|
||||
@@ -580,8 +580,8 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
if (result == -1) {
|
||||
trig->expired = 1;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%d): %s\n",
|
||||
FileName, LineNo, GetErr(E_EXPIRED));
|
||||
fprintf(ErrFp, "%s(%s): %s\n",
|
||||
FileName, line_range(LineNoStart, LineNo), GetErr(E_EXPIRED));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -603,8 +603,8 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
}
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
FromDSE(result, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d",
|
||||
FileName, LineNo,
|
||||
fprintf(ErrFp, "%s(%s): Trig = %s, %d %s, %d",
|
||||
FileName, line_range(LineNoStart, LineNo),
|
||||
get_day_name(result % 7),
|
||||
d,
|
||||
get_month_name(m),
|
||||
@@ -630,8 +630,8 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
trig->rep == NO_REP) {
|
||||
trig->expired = 1;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%d): %s\n",
|
||||
FileName, LineNo, GetErr(E_EXPIRED));
|
||||
fprintf(ErrFp, "%s(%s): %s\n",
|
||||
FileName, line_range(LineNoStart, LineNo), GetErr(E_EXPIRED));
|
||||
}
|
||||
if (save_in_globals) {
|
||||
LastTriggerDate = result;
|
||||
@@ -655,8 +655,8 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
}
|
||||
trig->expired = 1;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%d): %s\n",
|
||||
FileName, LineNo, GetErr(E_EXPIRED));
|
||||
fprintf(ErrFp, "%s(%s): %s\n",
|
||||
FileName, line_range(LineNoStart, LineNo), GetErr(E_EXPIRED));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -308,5 +308,6 @@ typedef struct udf_struct {
|
||||
int nargs;
|
||||
char const *filename;
|
||||
int lineno;
|
||||
int lineno_start;
|
||||
int recurse_flag;
|
||||
} UserFunc;
|
||||
|
||||
@@ -208,8 +208,8 @@ int DoFset(ParsePtr p)
|
||||
return OK;
|
||||
}
|
||||
/* Warn about redefinition */
|
||||
Wprint(tr("Function `%s' redefined (previously defined at %s:%d)"),
|
||||
existing->name, existing->filename, existing->lineno);
|
||||
Wprint(tr("Function `%s' redefined: previously defined at %s(%s)"),
|
||||
existing->name, existing->filename, line_range(existing->lineno_start, existing->lineno));
|
||||
}
|
||||
|
||||
/* Should be followed by '(' */
|
||||
@@ -238,6 +238,7 @@ int DoFset(ParsePtr p)
|
||||
return E_NO_MEM;
|
||||
}
|
||||
func->lineno = LineNo;
|
||||
func->lineno_start = LineNoStart;
|
||||
func->recurse_flag = 0;
|
||||
StrnCpy(func->name, DBufValue(&buf), VAR_NAME_LEN);
|
||||
DBufFree(&buf);
|
||||
|
||||
18
src/utils.c
18
src/utils.c
@@ -192,6 +192,7 @@ typedef struct cs_s {
|
||||
char const *filename;
|
||||
char const *func;
|
||||
int lineno;
|
||||
int lineno_start;
|
||||
} cs;
|
||||
|
||||
static cs *callstack = NULL;
|
||||
@@ -206,7 +207,7 @@ destroy_cs(cs *entry)
|
||||
|
||||
|
||||
int
|
||||
push_call(char const *filename, char const *func, int lineno)
|
||||
push_call(char const *filename, char const *func, int lineno, int lineno_start)
|
||||
{
|
||||
cs *entry;
|
||||
if (freecs) {
|
||||
@@ -222,6 +223,7 @@ push_call(char const *filename, char const *func, int lineno)
|
||||
entry->filename = filename;
|
||||
entry->func = func;
|
||||
entry->lineno = lineno;
|
||||
entry->lineno_start = lineno_start;
|
||||
entry->next = callstack;
|
||||
callstack = entry;
|
||||
return OK;
|
||||
@@ -255,7 +257,7 @@ print_callstack_aux(FILE *fp, cs *entry)
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
fprintf(fp, " ");
|
||||
fprintf(fp, tr("%s(%d): [#%d] %s function `%s'"), entry->filename, entry->lineno, i, in, entry->func);
|
||||
fprintf(fp, tr("%s(%s): [#%d] %s function `%s'"), entry->filename, line_range(entry->lineno_start, entry->lineno), i, in, entry->func);
|
||||
}
|
||||
prev = entry;
|
||||
entry = entry->next;
|
||||
@@ -289,3 +291,15 @@ pop_call(void)
|
||||
destroy_cs(entry);
|
||||
}
|
||||
}
|
||||
|
||||
char const *
|
||||
line_range(int lineno_start, int lineno)
|
||||
{
|
||||
static char buf[128];
|
||||
if (lineno_start == lineno) {
|
||||
snprintf(buf, sizeof(buf), "%d", lineno);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "%d:%d", lineno_start, lineno);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -181,11 +181,13 @@ EOF
|
||||
../src/remind -pppq - 1 Jan 2012 9:00 <<'EOF' >> ../tests/test.out 2>&1
|
||||
REM 2 MSG Normal
|
||||
SET $DefaultColor "255 0 0"
|
||||
REM 3 MSG %"Red%" on the calendar!
|
||||
REM 3 \
|
||||
MSG %"Red%" on the calendar!
|
||||
SET $DefaultColor "-1 -1 -1"
|
||||
REM 4 MSG Normal
|
||||
# Should give an error
|
||||
SET $DefaultColor "256 0 0"
|
||||
# Should give an error - split on two lines to test line number reporting
|
||||
SET $DefaultColor \
|
||||
"256 0 0"
|
||||
EOF
|
||||
|
||||
# Test default color with weekly calendar
|
||||
@@ -690,6 +692,11 @@ set a "\x0P"
|
||||
set a "\x00P"
|
||||
EOF
|
||||
|
||||
# Test diagnostics when using a timed substitution without an AT clause
|
||||
../src/remind - 1 Feb 2024 1:00 <<EOF >> ../tests/test.out 2>&1
|
||||
REM MSG %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %! hahaha
|
||||
EOF
|
||||
|
||||
# Test translate table dumping
|
||||
../src/remind - 1 Feb 2024 <<EOF >> ../tests/test.out 2>&1
|
||||
TRANSLATE "\x03" "BREAK"
|
||||
|
||||
186
tests/test.cmp
186
tests/test.cmp
@@ -801,12 +801,12 @@ Leaving UserFN _ofunc(1991-02-28) => 0
|
||||
|
||||
# omitfunc ignores local/global omits
|
||||
fset _ofunc(x) 0
|
||||
../tests/test.rem(227): Function `_ofunc' redefined (previously defined at ../tests/test.rem:222)
|
||||
../tests/test.rem(227): Function `_ofunc' redefined: previously defined at ../tests/test.rem(222)
|
||||
OMIT 1 March
|
||||
OMIT 2 March 1991
|
||||
REM 1 March OMIT Sun OMITFUNC _ofunc AFTER MSG Should trigger 1 March
|
||||
../tests/test.rem(230): Warning: OMIT is ignored if you use OMITFUNC
|
||||
../tests/test.rem(230): OMITFUNC function `_ofunc' defined at ../tests/test.rem:227 does not use its argument
|
||||
../tests/test.rem(230): OMITFUNC function `_ofunc' defined at ../tests/test.rem(227) does not use its argument
|
||||
Entering UserFN _ofunc(1991-02-15)
|
||||
Leaving UserFN _ofunc(1991-02-15) => 0
|
||||
Entering UserFN _ofunc(1991-03-01)
|
||||
@@ -1047,7 +1047,7 @@ set a057 value("a05"+"6")
|
||||
"a05" + "6" => "a056"
|
||||
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
set a058 version()
|
||||
version() => "05.03.01"
|
||||
version() => "05.03.05"
|
||||
set a059 wkday(today())
|
||||
today() => 1991-02-16
|
||||
wkday(1991-02-16) => "Saturday"
|
||||
@@ -2611,7 +2611,7 @@ a056 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
a007 "1991-02-16"
|
||||
a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
a008 "11:44"
|
||||
a058 "05.03.01"
|
||||
a058 "05.03.05"
|
||||
a059 "Saturday"
|
||||
a010 12
|
||||
a060 6
|
||||
@@ -4004,7 +4004,7 @@ psmoon(0) => ../tests/test.rem(813): psmoon() is deprecated; use SPECIAL MOON in
|
||||
FSET _f(x) 0
|
||||
SET tmp evaltrig("Wed SKIP OMITFUNC _f",date(1992,1,8))
|
||||
date(1992, 1, 8) => 1992-01-08
|
||||
evaltrig("Wed SKIP OMITFUNC _f", 1992-01-08) => ../tests/test.rem(817): OMITFUNC function `_f' defined at ../tests/test.rem:816 does not use its argument
|
||||
evaltrig("Wed SKIP OMITFUNC _f", 1992-01-08) => ../tests/test.rem(817): OMITFUNC function `_f' defined at ../tests/test.rem(816) does not use its argument
|
||||
Entering UserFN _f(1992-01-08)
|
||||
Leaving UserFN _f(1992-01-08) => 0
|
||||
../tests/test.rem(817): Trig = Wednesday, 8 January, 1992
|
||||
@@ -4050,7 +4050,7 @@ ENDIF
|
||||
|
||||
# Trig with a good warnfunc
|
||||
FSET w(x) choose(x, 5, 3, 1, 0)
|
||||
../tests/test.rem(832): Function `w' redefined (previously defined at ../tests/test.rem:826)
|
||||
../tests/test.rem(832): Function `w' redefined: previously defined at ../tests/test.rem(826)
|
||||
|
||||
# Short-circuit operators
|
||||
IF trig("sun warn w") || trig("thu warn w")
|
||||
@@ -4998,7 +4998,7 @@ Undefined:
|
||||
FSET subst_bad() "foo"
|
||||
REM MSG %{bad}
|
||||
../tests/test.rem(933): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(933): Function `subst_bad' defined at ../tests/test.rem:932 should take 3 arguments, but actually takes 0
|
||||
../tests/test.rem(933): Function `subst_bad' defined at ../tests/test.rem(932) should take 3 arguments, but actually takes 0
|
||||
|
||||
|
||||
|
||||
@@ -5006,8 +5006,8 @@ FSET subst_ampm(a, b, c, d, e, f, g) "wookie"
|
||||
|
||||
REM AT 11:00 MSG %2
|
||||
../tests/test.rem(937): Trig = Saturday, 16 February, 1991 AT 11:00
|
||||
../tests/test.rem(937): Function `subst_ampm' defined at ../tests/test.rem:935 should take 1 argument, but actually takes 7
|
||||
../tests/test.rem(937): Function `subst_ampm' defined at ../tests/test.rem:935 should take 1 argument, but actually takes 7
|
||||
../tests/test.rem(937): Function `subst_ampm' defined at ../tests/test.rem(935) should take 1 argument, but actually takes 7
|
||||
../tests/test.rem(937): Function `subst_ampm' defined at ../tests/test.rem(935) should take 1 argument, but actually takes 7
|
||||
at 11:00am
|
||||
|
||||
FUNSET subst_ampm
|
||||
@@ -5182,7 +5182,7 @@ FSET f(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a1
|
||||
|
||||
# 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
|
||||
../tests/test.rem(1023): Function `f' redefined (previously defined at ../tests/test.rem:1020)
|
||||
../tests/test.rem(1023): Function `f' redefined: previously defined at ../tests/test.rem(1020)
|
||||
../tests/test.rem(1023): Too many arguments
|
||||
|
||||
# Check that SATISFY expressions that don't reference trigdate are diagnosed
|
||||
@@ -5632,8 +5632,8 @@ REM SATISFY ""
|
||||
REM SATISFY [version() > "01.00.00"]
|
||||
../tests/test.rem(1050): SATISFY: expression has no reference to trigdate() or $T...
|
||||
../tests/test.rem(1050): Trig = Saturday, 16 February, 1991
|
||||
version() => "05.03.01"
|
||||
"05.03.01" > "01.00.00" => 1
|
||||
version() => "05.03.05"
|
||||
"05.03.05" > "01.00.00" => 1
|
||||
../tests/test.rem(1050): Trig(satisfied) = Saturday, 16 February, 1991
|
||||
REM SATISFY [max(x, max(x, 1, 2, 3), 4, 5, 6) * 5]
|
||||
../tests/test.rem(1051): SATISFY: expression has no reference to trigdate() or $T...
|
||||
@@ -5647,63 +5647,63 @@ max(3, 3, 4, 5, 6) => 6
|
||||
|
||||
FSET gg(x) 0
|
||||
REM WARN gg MSG Wookie
|
||||
../tests/test.rem(1054): WARN function `gg' defined at ../tests/test.rem:1053 does not use its argument
|
||||
../tests/test.rem(1054): WARN function `gg' defined at ../tests/test.rem(1053) does not use its argument
|
||||
../tests/test.rem(1054): Trig = Saturday, 16 February, 1991
|
||||
Entering UserFN gg(1)
|
||||
Leaving UserFN gg(1) => 0
|
||||
Wookie
|
||||
|
||||
REM AT 11:00 SCHED gg MSG blork
|
||||
../tests/test.rem(1055): SCHED function `gg' defined at ../tests/test.rem:1053 does not use its argument
|
||||
../tests/test.rem(1055): SCHED function `gg' defined at ../tests/test.rem(1053) does not use its argument
|
||||
../tests/test.rem(1055): Trig = Saturday, 16 February, 1991 AT 11:00
|
||||
blork
|
||||
|
||||
REM OMITFUNC gg MSG hehe
|
||||
../tests/test.rem(1056): OMITFUNC function `gg' defined at ../tests/test.rem:1053 does not use its argument
|
||||
../tests/test.rem(1056): OMITFUNC function `gg' defined at ../tests/test.rem(1053) does not use its argument
|
||||
../tests/test.rem(1056): Trig = Saturday, 16 February, 1991
|
||||
hehe
|
||||
|
||||
|
||||
FSET gg(x,y,z) 0
|
||||
../tests/test.rem(1058): Function `gg' redefined (previously defined at ../tests/test.rem:1053)
|
||||
../tests/test.rem(1058): Function `gg' redefined: previously defined at ../tests/test.rem(1053)
|
||||
REM WARN gg MSG Wookie
|
||||
../tests/test.rem(1059): WARN function `gg' defined at ../tests/test.rem:1058 should take 1 argument but actually takes 3
|
||||
../tests/test.rem(1059): WARN function `gg' defined at ../tests/test.rem(1058) should take 1 argument but actually takes 3
|
||||
../tests/test.rem(1059): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(1059): Undefined WARN function: `gg'
|
||||
Wookie
|
||||
|
||||
REM AT 11:00 SCHED gg MSG blork
|
||||
../tests/test.rem(1060): SCHED function `gg' defined at ../tests/test.rem:1058 should take 1 argument but actually takes 3
|
||||
../tests/test.rem(1060): SCHED function `gg' defined at ../tests/test.rem(1058) should take 1 argument but actually takes 3
|
||||
../tests/test.rem(1060): Trig = Saturday, 16 February, 1991 AT 11:00
|
||||
blork
|
||||
|
||||
REM OMITFUNC gg MSG hehe
|
||||
../tests/test.rem(1061): OMITFUNC function `gg' defined at ../tests/test.rem:1058 should take 1 argument but actually takes 3
|
||||
../tests/test.rem(1061): OMITFUNC function `gg' defined at ../tests/test.rem(1058) should take 1 argument but actually takes 3
|
||||
../tests/test.rem(1061): Trig = Saturday, 16 February, 1991
|
||||
hehe
|
||||
|
||||
|
||||
FSET gg() 0
|
||||
../tests/test.rem(1063): Function `gg' redefined (previously defined at ../tests/test.rem:1058)
|
||||
../tests/test.rem(1063): Function `gg' redefined: previously defined at ../tests/test.rem(1058)
|
||||
REM WARN gg MSG Wookie
|
||||
../tests/test.rem(1064): WARN function `gg' defined at ../tests/test.rem:1063 should take 1 argument but actually takes 0
|
||||
../tests/test.rem(1064): WARN function `gg' defined at ../tests/test.rem(1063) should take 1 argument but actually takes 0
|
||||
../tests/test.rem(1064): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(1064): Undefined WARN function: `gg'
|
||||
Wookie
|
||||
|
||||
REM AT 11:00 SCHED gg MSG blork
|
||||
../tests/test.rem(1065): SCHED function `gg' defined at ../tests/test.rem:1063 should take 1 argument but actually takes 0
|
||||
../tests/test.rem(1065): SCHED function `gg' defined at ../tests/test.rem(1063) should take 1 argument but actually takes 0
|
||||
../tests/test.rem(1065): Trig = Saturday, 16 February, 1991 AT 11:00
|
||||
blork
|
||||
|
||||
REM OMITFUNC gg MSG hehe
|
||||
../tests/test.rem(1066): OMITFUNC function `gg' defined at ../tests/test.rem:1063 should take 1 argument but actually takes 0
|
||||
../tests/test.rem(1066): OMITFUNC function `gg' defined at ../tests/test.rem(1063) should take 1 argument but actually takes 0
|
||||
../tests/test.rem(1066): Trig = Saturday, 16 February, 1991
|
||||
hehe
|
||||
|
||||
|
||||
FSET gg(x) x-x
|
||||
../tests/test.rem(1068): Function `gg' redefined (previously defined at ../tests/test.rem:1063)
|
||||
../tests/test.rem(1068): Function `gg' redefined: previously defined at ../tests/test.rem(1063)
|
||||
REM WARN gg MSG Wookie
|
||||
../tests/test.rem(1069): Trig = Saturday, 16 February, 1991
|
||||
Entering UserFN gg(1)
|
||||
@@ -5833,10 +5833,10 @@ max()
|
||||
|
||||
fset dooby(x) 1
|
||||
set zxk dooby()
|
||||
dooby(...) => Not enough arguments
|
||||
dooby() => Not enough arguments
|
||||
../tests/test.rem(1123): dooby(): Not enough arguments
|
||||
set zxk dooby(1, 2)
|
||||
dooby(...) => Too many arguments
|
||||
dooby(?, ?) => Too many arguments
|
||||
../tests/test.rem(1124): dooby(): Too many arguments
|
||||
set zxk dooby(1)
|
||||
Entering UserFN dooby(1)
|
||||
@@ -5973,7 +5973,7 @@ Hello
|
||||
On the next line
|
||||
|
||||
FSET msgsuffix(x) char(8) + " on the same line"
|
||||
../tests/test.rem(1184): Function `msgsuffix' redefined (previously defined at ../tests/test.rem:1181)
|
||||
../tests/test.rem(1184): Function `msgsuffix' redefined: previously defined at ../tests/test.rem(1181)
|
||||
REM MSG Hello
|
||||
../tests/test.rem(1185): Trig = Saturday, 16 February, 1991
|
||||
Entering UserFN msgsuffix(5000)
|
||||
@@ -16271,7 +16271,7 @@ Translation hash table statistics:
|
||||
Entries: 1; Buckets: 7; Non-empty Buckets: 1
|
||||
Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000
|
||||
Growths: 0; Shrinks: 0
|
||||
Expression nodes allocated: 300096
|
||||
Expression nodes allocated: 300288
|
||||
Expression nodes high-water: 300073
|
||||
Expression nodes leaked: 0
|
||||
Parse level high-water: 25
|
||||
@@ -22389,44 +22389,44 @@ February 29
|
||||
{"date":"2012-01-23","filename":"-","lineno":1,"wd":["Monday"],"priority":5000,"omitfunc":"foo","nonconst_expr":1,"body":"bar"}
|
||||
{"date":"2012-01-30","filename":"-","lineno":1,"wd":["Monday"],"priority":5000,"omitfunc":"foo","nonconst_expr":1,"body":"bar"}
|
||||
# rem2ps2 end
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(7): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
-stdin-(8:9): Number too high
|
||||
[
|
||||
{
|
||||
"translations":{"LANGID":"en"},"caltype":"monthly","monthname":"January","year":2012,"daysinmonth":31,"firstwkday":0,"mondayfirst":0,"daynames":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"prevmonthname":"December","daysinprevmonth":31,"prevmonthyear":2011,"nextmonthname":"February","daysinnextmonth":29,"nextmonthyear":2012,"entries":[
|
||||
{"date":"2012-01-02","filename":"-","lineno":1,"d":2,"priority":5000,"body":"Normal"},
|
||||
{"date":"2012-01-03","filename":"-","lineno":3,"passthru":"COLOR","d":3,"priority":5000,"r":255,"g":0,"b":0,"rawbody":"%\"Red%\" on the calendar!","calendar_body":"Red","plain_body":"Red on the calendar!","body":"255 0 0 %\"Red%\" on the calendar!"},
|
||||
{"date":"2012-01-04","filename":"-","lineno":5,"d":4,"priority":5000,"body":"Normal"}
|
||||
{"date":"2012-01-03","filename":"-","lineno":4,"lineno_start":3,"passthru":"COLOR","d":3,"priority":5000,"r":255,"g":0,"b":0,"rawbody":"%\"Red%\" on the calendar!","calendar_body":"Red","plain_body":"Red on the calendar!","body":"255 0 0 %\"Red%\" on the calendar!"},
|
||||
{"date":"2012-01-04","filename":"-","lineno":6,"d":4,"priority":5000,"body":"Normal"}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -23200,7 +23200,7 @@ SECURITY: Won't read world-writable file or directory!
|
||||
Error reading include_dir/ww: Can't open file
|
||||
SECURITY: Won't read world-writable file or directory!
|
||||
Error reading include_dir/ww: No files matching *.rem
|
||||
05.03.01
|
||||
05.03.05
|
||||
Enabling test mode: This is meant for the acceptance test.
|
||||
Do not use --test in production.
|
||||
In test mode, the system time is fixed at 2025-01-06@19:00
|
||||
@@ -24123,6 +24123,10 @@ monnum
|
||||
moondate
|
||||
moondatetime
|
||||
moonphase
|
||||
moonrise
|
||||
moonrisedir
|
||||
moonset
|
||||
moonsetdir
|
||||
moontime
|
||||
multitrig
|
||||
ndawn
|
||||
@@ -24491,11 +24495,11 @@ TRANSLATE "Expression evaluation is disabled" ""
|
||||
TRANSLATE "Time limit for expression evaluation exceeded" ""
|
||||
|
||||
# Other Messages
|
||||
TRANSLATE "%s function `%s' defined at %s:%d does not use its argument" ""
|
||||
TRANSLATE "%s function `%s' defined at %s:%d should take 1 argument but actually takes %d" ""
|
||||
TRANSLATE "%s function `%s' defined at %s(%s) does not use its argument" ""
|
||||
TRANSLATE "%s function `%s' defined at %s(%s) should take 1 argument but actually takes %d" ""
|
||||
TRANSLATE "%s is deprecated; use %s instead" ""
|
||||
TRANSLATE "%s(%d): IF without ENDIF" ""
|
||||
TRANSLATE "%s(%d): ["["]#%d] %s function `%s'" ""
|
||||
TRANSLATE "%s(%s): ["["]#%d] %s function `%s'" ""
|
||||
TRANSLATE "(Security note: $RunOff variable tested.)" ""
|
||||
TRANSLATE "Accepting \"%s\" for $Latitude/$Longitude, but you should use the \"C\" locale decimal separator \".\" instead" ""
|
||||
TRANSLATE "Caching directory `%s' listing" ""
|
||||
@@ -24509,8 +24513,8 @@ TRANSLATE "Duplicate INFO headers are not permitted" ""
|
||||
TRANSLATE "Error: THROUGH date earlier than start date" ""
|
||||
TRANSLATE "Executing `%s' for INCLUDECMD and caching as `%s'" ""
|
||||
TRANSLATE "Found cached directory listing for `%s'" ""
|
||||
TRANSLATE "Function `%s' defined at %s:%d should take %d argument%s, but actually takes %d" ""
|
||||
TRANSLATE "Function `%s' redefined (previously defined at %s:%d)" ""
|
||||
TRANSLATE "Function `%s' defined at %s(%s) should take %d argument%s, but actually takes %d" ""
|
||||
TRANSLATE "Function `%s' redefined: previously defined at %s(%s)" ""
|
||||
TRANSLATE "GetValidHebDate: Bad adarbehave value %d" ""
|
||||
TRANSLATE "In" ""
|
||||
TRANSLATE "Invalid INFO string: Must be of the form \"Header: Value\"" ""
|
||||
@@ -24548,6 +24552,7 @@ TRANSLATE "Warning: Useless use of UNTIL with fully-specified date and no *rep"
|
||||
TRANSLATE "Warning: Variable name `%.*s...' truncated to `%.*s'" ""
|
||||
TRANSLATE "You have OMITted everything! The space-time continuum is at risk." ""
|
||||
TRANSLATE "\\x00 is not a valid escape sequence" ""
|
||||
TRANSLATE "`%%%c' substitution sequence should not be used without an AT clause" ""
|
||||
TRANSLATE "did you mean" ""
|
||||
TRANSLATE "here" ""
|
||||
TRANSLATE "psmoon() is deprecated; use SPECIAL MOON instead." ""
|
||||
@@ -24691,6 +24696,21 @@ a "xPOO"
|
||||
-stdin-(24): \x00 is not a valid escape sequence
|
||||
-stdin-(25): \x00 is not a valid escape sequence
|
||||
-stdin-(26): \x00 is not a valid escape sequence
|
||||
-stdin-(1): `%0' substitution sequence should not be used without an AT clause
|
||||
-stdin-(1): `%1' substitution sequence should not be used without an AT clause
|
||||
-stdin-(1): `%2' substitution sequence should not be used without an AT clause
|
||||
-stdin-(1): `%3' substitution sequence should not be used without an AT clause
|
||||
-stdin-(1): `%4' substitution sequence should not be used without an AT clause
|
||||
-stdin-(1): `%5' substitution sequence should not be used without an AT clause
|
||||
-stdin-(1): `%6' substitution sequence should not be used without an AT clause
|
||||
-stdin-(1): `%7' substitution sequence should not be used without an AT clause
|
||||
-stdin-(1): `%8' substitution sequence should not be used without an AT clause
|
||||
-stdin-(1): `%9' substitution sequence should not be used without an AT clause
|
||||
-stdin-(1): `%!' substitution sequence should not be used without an AT clause
|
||||
Reminders for Thursday, 1st February, 2024:
|
||||
|
||||
s now at 1:00am at 01:00 0 0 from now 0 0 s is hahaha
|
||||
|
||||
# Translation table
|
||||
TRANSLATE "LANGID" "en"
|
||||
TRANSLATE "\x03" "BREAK"
|
||||
@@ -25117,7 +25137,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "13 horas i 34 minuts fa" and %*1 yields: "13 horas i 34 minuts fa"
|
||||
%2 yields: "a les 0:00am" and %*2 yields: "0:00am"
|
||||
%2 yields: "a les 12:00am" and %*2 yields: "12:00am"
|
||||
%3 yields: "a les 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -26019,7 +26039,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "13 timer og 34 minutter siden" and %*1 yields: "13 timer og 34 minutter siden"
|
||||
%2 yields: "kl. 0:00 om natten" and %*2 yields: "0:00 om natten"
|
||||
%2 yields: "kl. 12:00 om natten" and %*2 yields: "12:00 om natten"
|
||||
%3 yields: "kl. 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -26921,7 +26941,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "13 Stunden und 34 Minuten vorher" and %*1 yields: "13 Stunden und 34 Minuten vorher"
|
||||
%2 yields: "um 0:00 nachts" and %*2 yields: "0:00 nachts"
|
||||
%2 yields: "um 12:00 nachts" and %*2 yields: "12:00 nachts"
|
||||
%3 yields: "um 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -27823,7 +27843,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "13 hours and 34 minutes ago" and %*1 yields: "13 hours and 34 minutes ago"
|
||||
%2 yields: "at 0:00am" and %*2 yields: "0:00am"
|
||||
%2 yields: "at 12:00am" and %*2 yields: "12:00am"
|
||||
%3 yields: "at 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -28725,7 +28745,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "13 horas y 34 minutos hace" and %*1 yields: "13 horas y 34 minutos hace"
|
||||
%2 yields: "a las 0:00am" and %*2 yields: "0:00am"
|
||||
%2 yields: "a las 12:00am" and %*2 yields: "12:00am"
|
||||
%3 yields: "a las 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -29627,7 +29647,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "13 tuntia 34 minuuttia sitten" and %*1 yields: "13 tuntia 34 minuuttia sitten"
|
||||
%2 yields: "klo 0:00 ap." and %*2 yields: "0:00 ap."
|
||||
%2 yields: "klo 12:00 ap." and %*2 yields: "12:00 ap."
|
||||
%3 yields: "klo 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -30529,7 +30549,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "il y a 13 heures et 34 minutes" and %*1 yields: "il y a 13 heures et 34 minutes"
|
||||
%2 yields: "à 0:00am" and %*2 yields: "0:00am"
|
||||
%2 yields: "à 12:00am" and %*2 yields: "12:00am"
|
||||
%3 yields: "à 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -31431,7 +31451,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "13 ώρες και 34 λεπτά πριν" and %*1 yields: "13 ώρες και 34 λεπτά πριν"
|
||||
%2 yields: "στις 0:00πμ" and %*2 yields: "0:00πμ"
|
||||
%2 yields: "στις 12:00πμ" and %*2 yields: "12:00πμ"
|
||||
%3 yields: "στις 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -32333,7 +32353,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "13 klukkustundir og 34 mínútur síðan" and %*1 yields: "13 klukkustundir og 34 mínútur síðan"
|
||||
%2 yields: "kl. 0:00fh" and %*2 yields: "0:00fh"
|
||||
%2 yields: "kl. 12:00fh" and %*2 yields: "12:00fh"
|
||||
%3 yields: "kl. 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -33235,7 +33255,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "13 ore e 34 minuti fa" and %*1 yields: "13 ore e 34 minuti fa"
|
||||
%2 yields: "alle 0:00am" and %*2 yields: "0:00am"
|
||||
%2 yields: "alle 12:00am" and %*2 yields: "12:00am"
|
||||
%3 yields: "alle 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -34137,7 +34157,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "13 uren en 34 minuten geleden" and %*1 yields: "13 uren en 34 minuten geleden"
|
||||
%2 yields: "op 0:00am" and %*2 yields: "0:00am"
|
||||
%2 yields: "op 12:00am" and %*2 yields: "12:00am"
|
||||
%3 yields: "op 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -35039,7 +35059,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "13 timer og 34 minutter siden" and %*1 yields: "13 timer og 34 minutter siden"
|
||||
%2 yields: "kl. 0:00am" and %*2 yields: "0:00am"
|
||||
%2 yields: "kl. 12:00am" and %*2 yields: "12:00am"
|
||||
%3 yields: "kl. 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -35941,7 +35961,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "13 godzin i 34 minuty temu" and %*1 yields: "13 godzin i 34 minuty temu"
|
||||
%2 yields: "o 0:00 w nocy" and %*2 yields: "0:00 w nocy"
|
||||
%2 yields: "o 12:00 w nocy" and %*2 yields: "12:00 w nocy"
|
||||
%3 yields: "o 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -36843,7 +36863,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "13 horas e 34 minutos atrás" and %*1 yields: "13 horas e 34 minutos atrás"
|
||||
%2 yields: "as 0:00am" and %*2 yields: "0:00am"
|
||||
%2 yields: "as 12:00am" and %*2 yields: "12:00am"
|
||||
%3 yields: "as 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
@@ -37745,7 +37765,7 @@ Time substitutions for 13:32 where now() = 13:34
|
||||
Time substitutions for 00:00 where now() = 13:34
|
||||
|
||||
%1 yields: "acum 13 ore şi 34 minute" and %*1 yields: "acum 13 ore şi 34 minute"
|
||||
%2 yields: "la ora 0:00 noaptea" and %*2 yields: "0:00 noaptea"
|
||||
%2 yields: "la ora 12:00 noaptea" and %*2 yields: "12:00 noaptea"
|
||||
%3 yields: "la ora 00:00" and %*3 yields: "00:00"
|
||||
%4 yields: "-814" and %*4 yields: "-814"
|
||||
%5 yields: "814" and %*5 yields: "814"
|
||||
|
||||
Reference in New Issue
Block a user