mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-18 23:38:40 +02:00
Compare commits
78 Commits
4e7cfc20ce
...
05.02.03
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d09abc363 | ||
|
|
3dcd353fb5 | ||
|
|
124c5c4e7e | ||
|
|
77024562b3 | ||
|
|
35c33ae915 | ||
|
|
901831ff75 | ||
|
|
e0c5e878a8 | ||
|
|
ffba7fcb03 | ||
|
|
b3f3cb9ce0 | ||
|
|
6f11e727f8 | ||
|
|
9f7ea96e87 | ||
|
|
d650b8564c | ||
|
|
4f2e4030eb | ||
|
|
447bda5c91 | ||
|
|
4f351c089e | ||
|
|
6b31778973 | ||
|
|
dcf8b46beb | ||
|
|
0f582ccb60 | ||
|
|
8d0743dd3e | ||
|
|
436526c27d | ||
|
|
5f3f3b410f | ||
|
|
4f79b0d42a | ||
|
|
c96f9f21ed | ||
|
|
dc192f2a69 | ||
|
|
ac3dd1ec7c | ||
|
|
b5717828f0 | ||
|
|
c0d73fb9d1 | ||
|
|
3a2ac067b0 | ||
|
|
1d467ab9ed | ||
|
|
c2ec4e9d29 | ||
|
|
96c11e89eb | ||
|
|
a35920f28e | ||
|
|
17ccf5d2b4 | ||
|
|
788a09b2cd | ||
|
|
9f0e23a307 | ||
|
|
542620c188 | ||
|
|
50419bd83a | ||
|
|
2b7c582392 | ||
|
|
812a2af64b | ||
|
|
17d7abd4a4 | ||
|
|
098e98c59e | ||
|
|
c5e0dbf2e5 | ||
|
|
18c8bc719f | ||
|
|
195ed15167 | ||
|
|
51677cd7b5 | ||
|
|
aef5b353cd | ||
|
|
8a99c29533 | ||
|
|
0bf2b0772a | ||
|
|
a033a48acd | ||
|
|
0feb81c8cc | ||
|
|
1850607542 | ||
|
|
213138a7b7 | ||
|
|
562cec3dc8 | ||
|
|
18b57d26b4 | ||
|
|
c80d72f623 | ||
|
|
2739a41651 | ||
|
|
5a56f4c61b | ||
|
|
77080ff600 | ||
|
|
c4aa21ff51 | ||
|
|
34c513ba3b | ||
|
|
35c16a060a | ||
|
|
69dedc577f | ||
|
|
a7d8f3c887 | ||
|
|
800a4b15b2 | ||
|
|
3e981fd8be | ||
|
|
7c530d3068 | ||
|
|
58f9cf641b | ||
|
|
53906035fe | ||
|
|
4804325863 | ||
|
|
5f5e7054f4 | ||
|
|
078dba1e98 | ||
|
|
8ebec9584c | ||
|
|
2504b39be2 | ||
|
|
e394f402f8 | ||
|
|
5a2914f6c7 | ||
|
|
a19b009f7c | ||
|
|
6373ae8ca5 | ||
|
|
b8c4786b33 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -23,7 +23,6 @@ rem2pdf/Makefile.old
|
|||||||
rem2pdf/Makefile.top
|
rem2pdf/Makefile.top
|
||||||
rem2pdf/bin/rem2pdf
|
rem2pdf/bin/rem2pdf
|
||||||
scripts/tkremind
|
scripts/tkremind
|
||||||
set-irc-topic
|
|
||||||
src/*.tar.gz*
|
src/*.tar.gz*
|
||||||
src/Makefile
|
src/Makefile
|
||||||
src/config.h
|
src/config.h
|
||||||
@@ -35,3 +34,4 @@ tests/test.out
|
|||||||
www/Makefile
|
www/Makefile
|
||||||
gmon.out
|
gmon.out
|
||||||
tests/once.timestamp
|
tests/once.timestamp
|
||||||
|
src/xlat.c
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ THE REMIND COPYRIGHT
|
|||||||
1. REMIND refers to the entire set of files and documentation in the
|
1. REMIND refers to the entire set of files and documentation in the
|
||||||
REMIND package.
|
REMIND package.
|
||||||
|
|
||||||
2. REMIND is Copyright 1992-2024 Dianne Skoll, except where noted in
|
2. REMIND is Copyright (C) 1992-2025 Dianne Skoll, except where noted in
|
||||||
individual files.
|
individual files.
|
||||||
|
|
||||||
3. DISTRIBUTION AND USE
|
3. DISTRIBUTION AND USE
|
||||||
|
|||||||
78
README
78
README
@@ -1,78 +0,0 @@
|
|||||||
REMIND
|
|
||||||
|
|
||||||
Remind is a full-featured calendar/alarm program. Copying policy is
|
|
||||||
in the file "COPYRIGHT" in this directory.
|
|
||||||
|
|
||||||
Installation notes for various operating systems are in "docs". See
|
|
||||||
the appropriate README file for installation on your system.
|
|
||||||
|
|
||||||
Manual pages are in "man".
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Quick UNIX installation instructions for the very impatient:
|
|
||||||
|
|
||||||
If you have Tcl/Tk (wish 4.1 or higher) installed and are running X Windows:
|
|
||||||
--------------------------------------------------------------
|
|
||||||
|
|
||||||
1) Type: wish ./build.tk from this directory. Fill in the various
|
|
||||||
options and hit "Build Remind"
|
|
||||||
|
|
||||||
2) Type: "make install" -- you may need to be root to do this.
|
|
||||||
|
|
||||||
If you do NOT have Tcl/Tk or are NOT running X Windows:
|
|
||||||
-------------------------------------------------------
|
|
||||||
|
|
||||||
1) Edit the file "src/custom.h" according to your preferences.
|
|
||||||
|
|
||||||
2) Edit the file "src/lang.h" to choose a language.
|
|
||||||
|
|
||||||
3) Type: "./configure" (You can supply options; type "./configure --help"
|
|
||||||
for details.)
|
|
||||||
|
|
||||||
4) Type: "make"
|
|
||||||
|
|
||||||
5) Type: "make install" -- you may need to be root to do this.
|
|
||||||
|
|
||||||
PREREQUISITES:
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Remind and rem2ps have no prerequisites beyond the standard C library and
|
|
||||||
the standard math library.
|
|
||||||
|
|
||||||
Rem2HTML requires the JSON::MaybeXS Perl module.
|
|
||||||
Rem2PDF requires the JSON::MaybeXS, Pango and Cairo Perl modules.
|
|
||||||
|
|
||||||
- On Debian-like systems, these prerequisites may be installed with:
|
|
||||||
|
|
||||||
apt install libjson-maybexs-perl libpango-perl libcairo-perl
|
|
||||||
|
|
||||||
- On RPM-based systems, you need perl-Pango, perl-Cairo and perl-JSON-MaybeXS
|
|
||||||
|
|
||||||
- On Gentoo, you need dev-perl/Pango, dev-perl/Cairo and dev-perl/JSON-MaybeXS.
|
|
||||||
|
|
||||||
- On Arch linux, you need pango-perl, cairo-perl and perl-json-maybexs
|
|
||||||
|
|
||||||
TkRemind requires Tcl/Tk and the tcllib library.
|
|
||||||
|
|
||||||
- On Debian-like systems, install with:
|
|
||||||
|
|
||||||
apt install tcl tk tcllib
|
|
||||||
|
|
||||||
- On RPM-based systems, you need tcl, tk and tcllib
|
|
||||||
|
|
||||||
- On Arch Linux, you need tk and tcllib. The latter is available at
|
|
||||||
https://aur.archlinux.org/packages/tcllib
|
|
||||||
|
|
||||||
If the little arrows for "Previous Month" and "Next Month" do not display
|
|
||||||
correctly in TkRemind, you may need to install the Noto Fonts. Install
|
|
||||||
all of your distribution's Nonto Font-related packages.
|
|
||||||
|
|
||||||
- On Debian-like systems, install with:
|
|
||||||
|
|
||||||
apt install fonts-noto-core fonts-noto-color-emoji \
|
|
||||||
fonts-noto-extra fonts-noto-ui-core fonts-noto-ui-extra
|
|
||||||
|
|
||||||
==========================================================================
|
|
||||||
Contact info: mailto:dianne@skoll.ca
|
|
||||||
Home page: https://dianne.skoll.ca/projects/remind/
|
|
||||||
63
README.md
Normal file
63
README.md
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# REMIND
|
||||||
|
|
||||||
|
Remind is a full-featured calendar/alarm program. Copying policy is
|
||||||
|
in the file "COPYRIGHT" included with the source; Remind is licensed under
|
||||||
|
the GNU General Public License, Vesion 2.
|
||||||
|
|
||||||
|
## Prerequisites:
|
||||||
|
|
||||||
|
remind and rem2ps have no prerequisites beyond the standard C library and
|
||||||
|
the standard math library.
|
||||||
|
|
||||||
|
rem2html requires the JSON::MaybeXS Perl module and rem2pdf
|
||||||
|
requires the JSON::MaybeXS, Pango and Cairo Perl modules.
|
||||||
|
|
||||||
|
- On Debian-like systems, these prerequisites may be installed with:
|
||||||
|
|
||||||
|
`apt install libjson-maybexs-perl libpango-perl libcairo-perl`
|
||||||
|
|
||||||
|
- On RPM-based systems, you need `perl-Pango`, `perl-Cairo` and
|
||||||
|
`perl-JSON-MaybeXS`
|
||||||
|
|
||||||
|
- On Gentoo, you need `dev-perl/Pango`, `dev-perl/Cairo` and
|
||||||
|
`dev-perl/JSON-MaybeXS`.
|
||||||
|
|
||||||
|
- On Arch linux, you need `pango-perl`, `cairo-perl` and `perl-json-maybexs`
|
||||||
|
|
||||||
|
TkRemind requires Tcl/Tk and the tcllib library.
|
||||||
|
|
||||||
|
- On Debian-like systems, install with:
|
||||||
|
|
||||||
|
`apt install tcl tk tcllib`
|
||||||
|
|
||||||
|
- On RPM-based systems, you need `tcl`, `tk` and `tcllib`
|
||||||
|
|
||||||
|
- On Arch Linux, you need `tk` and `tcllib`. The latter is available at
|
||||||
|
https://aur.archlinux.org/packages/tcllib
|
||||||
|
|
||||||
|
If the little arrows for "Previous Month" and "Next Month" do not display
|
||||||
|
correctly in TkRemind, you may need to install the Noto Fonts. Install
|
||||||
|
all of your distribution's Nonto Font-related packages.
|
||||||
|
|
||||||
|
- On Debian-like systems, install with:
|
||||||
|
|
||||||
|
`apt install fonts-noto-core fonts-noto-color-emoji fonts-noto-extra fonts-noto-ui-core fonts-noto-ui-extra`
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Remind can be installed with the usual:
|
||||||
|
|
||||||
|
`./configure && make && make test && sudo make install`
|
||||||
|
|
||||||
|
You can edit custom.h to configure some aspects of Remind. Or, if
|
||||||
|
you have Tcl/Tk installed, you can use the graphical build tool to
|
||||||
|
edit custom.h on your behalf:
|
||||||
|
|
||||||
|
`wish ./build.tk`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Contact info: dianne@skoll.ca
|
||||||
|
|
||||||
|
Home page: [https://dianne.skoll.ca/projects/remind/](https://dianne.skoll.ca/projects/remind/)
|
||||||
|
|
||||||
6
build.tk
6
build.tk
@@ -8,7 +8,7 @@
|
|||||||
# A cheesy graphical front-end for building and installing REMIND.
|
# A cheesy graphical front-end for building and installing REMIND.
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2018 Dianne Skoll
|
# Copyright (C) 1992-2025 Dianne Skoll
|
||||||
#
|
#
|
||||||
#--------------------------------------------------------------
|
#--------------------------------------------------------------
|
||||||
|
|
||||||
@@ -487,7 +487,7 @@ proc CallMake {} {
|
|||||||
# Michael McLennan, Bell Labs Innovations for Lucent Technologies
|
# Michael McLennan, Bell Labs Innovations for Lucent Technologies
|
||||||
# Addison-Wesley Professional Computing Series
|
# Addison-Wesley Professional Computing Series
|
||||||
# ======================================================================
|
# ======================================================================
|
||||||
# Copyright (c) 1996-1997 Lucent Technologies Inc. and Mark Harrison
|
# Copyright (C) 1996-1997 Lucent Technologies Inc. and Mark Harrison
|
||||||
# ======================================================================
|
# ======================================================================
|
||||||
|
|
||||||
option add *Tabnotebook.tabs.background #666666 widgetDefault
|
option add *Tabnotebook.tabs.background #666666 widgetDefault
|
||||||
@@ -601,7 +601,7 @@ proc tabnotebook_display {win name} {
|
|||||||
# Michael McLennan, Bell Labs Innovations for Lucent Technologies
|
# Michael McLennan, Bell Labs Innovations for Lucent Technologies
|
||||||
# Addison-Wesley Professional Computing Series
|
# Addison-Wesley Professional Computing Series
|
||||||
# ======================================================================
|
# ======================================================================
|
||||||
# Copyright (c) 1996-1997 Lucent Technologies Inc. and Mark Harrison
|
# Copyright (C) 1996-1997 Lucent Technologies Inc. and Mark Harrison
|
||||||
# ======================================================================
|
# ======================================================================
|
||||||
|
|
||||||
option add *Notebook.borderWidth 2 widgetDefault
|
option add *Notebook.borderWidth 2 widgetDefault
|
||||||
|
|||||||
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.02.00.
|
# Generated by GNU Autoconf 2.71 for remind 05.02.03.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# 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.02.00'
|
PACKAGE_VERSION='05.02.03'
|
||||||
PACKAGE_STRING='remind 05.02.00'
|
PACKAGE_STRING='remind 05.02.03'
|
||||||
PACKAGE_BUGREPORT=''
|
PACKAGE_BUGREPORT=''
|
||||||
PACKAGE_URL='https://dianne.skoll.ca/projects/remind/'
|
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.
|
# 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.02.00 to adapt to many kinds of systems.
|
\`configure' configures remind 05.02.03 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@@ -1327,7 +1327,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.02.00:";;
|
short | recursive ) echo "Configuration of remind 05.02.03:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@@ -1415,7 +1415,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.02.00
|
remind configure 05.02.03
|
||||||
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.
|
||||||
@@ -1865,7 +1865,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.02.00, which was
|
It was created by remind $as_me 05.02.03, 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
|
||||||
@@ -4710,7 +4710,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.02.00, which was
|
This file was extended by remind $as_me 05.02.03, 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
|
||||||
@@ -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
|
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.02.00
|
remind config.status 05.02.03
|
||||||
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.02.00, , , https://dianne.skoll.ca/projects/remind/)
|
AC_INIT(remind, 05.02.03, , , https://dianne.skoll.ca/projects/remind/)
|
||||||
AC_CONFIG_SRCDIR([src/queue.c])
|
AC_CONFIG_SRCDIR([src/queue.c])
|
||||||
|
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
|
|||||||
@@ -130,8 +130,8 @@
|
|||||||
(defconst remind-builtin-variables
|
(defconst remind-builtin-variables
|
||||||
(sort
|
(sort
|
||||||
(list " $AddBlankLines" "$Ago" "$Am" "$And" "$April" "$At" "$August"
|
(list " $AddBlankLines" "$Ago" "$Am" "$And" "$April" "$At" "$August"
|
||||||
"$CalcUTC" "$CalMode" "$Daemon" "$DateSep" "$DateTimeSep" "$December"
|
"$CalcUTC" "$CalMode" "$CalType" "$Daemon" "$DateSep" "$DateTimeSep"
|
||||||
"$DedupeReminders" "$DefaultColor" "$DefaultDelta"
|
"$December" "$DedupeReminders" "$DefaultColor" "$DefaultDelta"
|
||||||
"$DefaultPrio" "$DefaultTDelta" "$DeltaOverride"
|
"$DefaultPrio" "$DefaultTDelta" "$DeltaOverride"
|
||||||
"$DontFork" "$DontQueue" "$DontTrigAts" "$EndSent" "$EndSentIg"
|
"$DontFork" "$DontQueue" "$DontTrigAts" "$EndSent" "$EndSentIg"
|
||||||
"$ExpressionTimeLimit" "$February" "$FirstIndent" "$FoldYear"
|
"$ExpressionTimeLimit" "$February" "$FirstIndent" "$FoldYear"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
REMIND version 3.2 for UNIX
|
Remind for UNIX and Linux
|
||||||
|
|
||||||
REMIND is a sophisticated alarm/calendar program. Details are given
|
Remind is a sophisticated alarm/calendar program. Details are given
|
||||||
in the man page, "remind.1".
|
in the man page, "remind.1".
|
||||||
|
|
||||||
INSTALLING REMIND:
|
INSTALLING REMIND:
|
||||||
@@ -19,88 +19,13 @@ If you do NOT have Tcl/Tk or are NOT running X11:
|
|||||||
|
|
||||||
1) Edit the file "src/custom.h" according to your preferences.
|
1) Edit the file "src/custom.h" according to your preferences.
|
||||||
|
|
||||||
2) Edit the file "src/lang.h" to choose a language.
|
2) Type: "make"
|
||||||
|
|
||||||
3) Type: "make"
|
3) Type: "make install" -- you may need to be root to do this.
|
||||||
|
|
||||||
4) Type: "make install" -- you may need to be root to do this.
|
|
||||||
|
|
||||||
The subdirectory "www" contains scripts for making a nice calendar
|
The subdirectory "www" contains scripts for making a nice calendar
|
||||||
web server. See the files README and Makefile in that directory.
|
web server. See the files README and Makefile in that directory.
|
||||||
|
|
||||||
The file "examples/defs.rem" has some sample Remind definitions and
|
|
||||||
commands, as well as U.S. and Jewish holidays.
|
|
||||||
|
|
||||||
OTHER LANGUAGE SUPPORT
|
|
||||||
|
|
||||||
Remind has support for languages other than English. See the file
|
|
||||||
"src/lang.h" for details. The language support may vary - you can change
|
|
||||||
only the substitution filter, or you can translate all of the usage
|
|
||||||
instructions and error messages as well. See "src/langs/french.h" for an
|
|
||||||
example of the latter.
|
|
||||||
|
|
||||||
To compile Remind for a non-english language, look at the constants
|
|
||||||
defined in "src/lang.h". Then, to compile Remind for Italian (as an
|
|
||||||
example), type:
|
|
||||||
|
|
||||||
make "LANGDEF=-DLANG=ITALIAN"
|
|
||||||
|
|
||||||
If you add support for a non-English language, Remind will accept both the
|
|
||||||
English and non-English names of months and weekdays in an input script.
|
|
||||||
However, you should not rely on this feature if you want to write portable
|
|
||||||
Remind scripts.
|
|
||||||
|
|
||||||
At a minimum, you should support month and day names in the foreign
|
|
||||||
language, and should modify the substitution filter appropriately.
|
|
||||||
If you are truly diligent, you can translate usage and error messages
|
|
||||||
too.
|
|
||||||
|
|
||||||
Take a look at the files "src/langs/english.h" and
|
|
||||||
"src/langs/german.h" if you want to add support for your favourite
|
|
||||||
language. If you do add another language to Remind, please let me
|
|
||||||
know! Here are the basic guidelines:
|
|
||||||
|
|
||||||
- Your language file should be called "src/langs/lxxx.h", where lxxx
|
|
||||||
is the first 8 characters of the ENGLISH name of your language.
|
|
||||||
|
|
||||||
- Your language file should define L_LANGNAME to be the full English
|
|
||||||
name of your language, with the first letter capitalized and the rest
|
|
||||||
lower-case.
|
|
||||||
|
|
||||||
- You can test your language file with the script "tests/tstlang.rem"
|
|
||||||
|
|
||||||
- Your localized strings must be encoded using UTF-8.
|
|
||||||
|
|
||||||
RELEASE NOTES -- miscellaneous info that couldn't go anywhere else!
|
|
||||||
|
|
||||||
1. POPUP REMINDERS
|
|
||||||
|
|
||||||
If you're running under X11 and you have the Tcl tools, you can create
|
|
||||||
simple pop-up reminders by creating the following Tcl script called
|
|
||||||
'popup'. It pops a message on to the screen and waits for you to
|
|
||||||
press the 'OK' button. If you don't press the OK button within 15
|
|
||||||
seconds, it exits anyway. To use it, you can use the '-k' option for
|
|
||||||
Remind as follows:
|
|
||||||
|
|
||||||
remind "-kpopup '%s'&" .reminders
|
|
||||||
|
|
||||||
Or use the following in your Remind script:
|
|
||||||
|
|
||||||
REM AT 17:00 RUN popup 'Time to go home.' &
|
|
||||||
|
|
||||||
This Tcl script is a slightly modified version of one submitted by
|
|
||||||
Norman Walsh.
|
|
||||||
|
|
||||||
-------------- Cut Here ---------- Cut Here ---------- Cut Here -------------
|
|
||||||
#!/usr/local/bin/wish
|
|
||||||
wm withdraw .
|
|
||||||
after 15000 { destroy . ; exit }
|
|
||||||
tk_messageBox -message Message -detail $argv -icon info -type ok
|
|
||||||
destroy .
|
|
||||||
exit
|
|
||||||
-------------- Cut Here ---------- Cut Here ---------- Cut Here -------------
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
Dianne Skoll <dianne@skoll.ca>
|
Dianne Skoll <dianne@skoll.ca>
|
||||||
https://dianne.skoll.ca/projects/remind/
|
https://dianne.skoll.ca/projects/remind/
|
||||||
|
|||||||
@@ -1,10 +1,63 @@
|
|||||||
CHANGES TO REMIND
|
CHANGES TO REMIND
|
||||||
|
|
||||||
* VERSION 5.2 Patch 0 - ????-??=??
|
* VERSION 5.2 Patch 3 - 2025-01-22
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: Add "TRANSLATE GENERATE" command for generating
|
||||||
|
a skeleton set of TRANSLATE commands to make it easier to localize
|
||||||
|
Remind.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: Add "q" debug flag for tracing calls to _()
|
||||||
|
or %(...) in the substitution filter; this will help with localizing
|
||||||
|
reminder files.
|
||||||
|
|
||||||
|
- NEW FILES: remind: Add holidays/lgbtq.rem for LGBTQ holidays. Add
|
||||||
|
country-specific files in holidays/lgbtq/*.rem
|
||||||
|
|
||||||
|
- IMPROVEMENT: TkRemind: use "info patchlevel" to display full Tcl/Tk
|
||||||
|
version.
|
||||||
|
|
||||||
|
- IMPROVEMENT: remind: The DEBUG command issues a warning if given an
|
||||||
|
unknown debug flag.
|
||||||
|
|
||||||
|
- BUG FIX: remind: "make test" will now succeed even if run between
|
||||||
|
23:55 and 00:00 UTC. This is done with a new --test flag for remind.
|
||||||
|
|
||||||
|
- BUG FIX: remind: Avoid potential buffer overflow if someone supplies
|
||||||
|
ridiculously-long translations for "am" or "pm".
|
||||||
|
|
||||||
|
* VERSION 5.2 Patch 2 - 2025-01-06
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: The "-p+" option lets you produce weekly calendars;
|
||||||
|
so far, the rem2pdf and rem2html back-ends support rendering of weekly
|
||||||
|
calendars.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: The $CalType system variable indicates the type of
|
||||||
|
calendar being produced; its value is one of "monthly", "weekly",
|
||||||
|
or "none". "none" signifies agenda mode rather than calendar mode.
|
||||||
|
|
||||||
|
- IMPROVEMENT: remind: Warn if a POP-OMIT-CONTEXT matches a
|
||||||
|
PUSH-OMIT-CONTEXT that is in a different file.
|
||||||
|
|
||||||
|
- CHANGE: remind: Split the "-ds" debug option into two separate options:
|
||||||
|
"-ds" for debugging expression-parsing and "-dh" for printing hash
|
||||||
|
table statistics on exit.
|
||||||
|
|
||||||
|
* VERSION 5.2 Patch 1 - 2024-12-16
|
||||||
|
|
||||||
|
- BUG FIX: remind: Fix a logic error that only showed itself on big-endian
|
||||||
|
architectures. Found thanks to Debian testing and a notification from
|
||||||
|
Jochen Sprickerhof.
|
||||||
|
|
||||||
|
* VERSION 5.2 Patch 0 - 2024-12-16
|
||||||
|
|
||||||
- MAJOR NEW FEATURE: remind: Add the TRANSLATE command, the _()
|
- MAJOR NEW FEATURE: remind: Add the TRANSLATE command, the _()
|
||||||
built-in function and the %(...) substitution sequence. These allow
|
built-in function and the %(...) substitution sequence. These allow
|
||||||
you to localize your reminder files more easily.
|
you to localize your reminder files more easily. The translation table
|
||||||
|
is also made available to back-ends like rem2pdf and tkremind,
|
||||||
|
which they can use as they see fit.
|
||||||
|
|
||||||
|
- MINOR FEATURE: tkremind, rem2html: Localize the names of the moon
|
||||||
|
phases.
|
||||||
|
|
||||||
- MAJOR CHANGE: remind: Remind used to support compile-time localization
|
- MAJOR CHANGE: remind: Remind used to support compile-time localization
|
||||||
into different languages (French, English, etc.) That compile-time
|
into different languages (French, English, etc.) That compile-time
|
||||||
@@ -27,6 +80,10 @@ CHANGES TO REMIND
|
|||||||
|
|
||||||
INCLUDE [$SysInclude]/foo/bar.rem
|
INCLUDE [$SysInclude]/foo/bar.rem
|
||||||
|
|
||||||
|
- MINOR IMPROVEMENT: Allow INCLUDE, DO and SYSINCLUDE to include files with
|
||||||
|
spaces in their names; in this case, you have to put the filename inside
|
||||||
|
double-quotes.
|
||||||
|
|
||||||
- IMPROVEMENT: remind: Refuse to open subdirectories named "*.rem"
|
- IMPROVEMENT: remind: Refuse to open subdirectories named "*.rem"
|
||||||
under a top-level directory rather than trying and failing with a
|
under a top-level directory rather than trying and failing with a
|
||||||
confusing error.
|
confusing error.
|
||||||
@@ -43,8 +100,12 @@ CHANGES TO REMIND
|
|||||||
- MINOR FIXES: remind: Fix typos in comments; use memcpy to copy OMIT
|
- MINOR FIXES: remind: Fix typos in comments; use memcpy to copy OMIT
|
||||||
contexts internally.
|
contexts internally.
|
||||||
|
|
||||||
- BUG FIX: Actually allow the documented 9 levels of INCLUDE rather than
|
- BUG FIX: remind: Actually allow the documented 9 levels of INCLUDE
|
||||||
8.
|
rather than 8.
|
||||||
|
|
||||||
|
- BUG FIX: remind: If an INCLUDE statement failed inside an IF statement,
|
||||||
|
Remind would print spurious errors about unmatched IF/ENDIF. This has
|
||||||
|
been fixed.
|
||||||
|
|
||||||
* VERSION 5.1 Patch 1 - 2024-11-18
|
* VERSION 5.1 Patch 1 - 2024-11-18
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
# "#PSSTUFF" for nifty PostScript examples #
|
# "#PSSTUFF" for nifty PostScript examples #
|
||||||
# #
|
# #
|
||||||
# This file is part of REMIND. #
|
# This file is part of REMIND. #
|
||||||
# Copyright (C) 1992-2024 Dianne Skoll #
|
# Copyright (C) 1992-2025 Dianne Skoll #
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
# #
|
# #
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Not all sequences are supported by all terminals.
|
# Not all sequences are supported by all terminals.
|
||||||
|
|
||||||
# This file is part of REMIND
|
# This file is part of REMIND
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
if !defined("ansi_bold")
|
if !defined("ansi_bold")
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
REM 1 Feb 2022 MSG %(Chinese New Year) (%(Tiger))
|
REM 1 Feb 2022 MSG %(Chinese New Year) (%(Tiger))
|
||||||
REM 22 Jan 2023 MSG %(Chinese New Year) (%(Rabbit))
|
REM 22 Jan 2023 MSG %(Chinese New Year) (%(Rabbit))
|
||||||
REM 10 Feb 2024 MSG %(Chinese New Year) (%(Dragon))
|
REM 10 Feb 2024 MSG %(Chinese New Year) (%(Dragon))
|
||||||
|
|||||||
34
include/holidays/lgbtq.rem
Normal file
34
include/holidays/lgbtq.rem
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# List of LGBTQ awareness days
|
||||||
|
# Sourced from https://en.wikipedia.org/wiki/List_of_LGBTQ_awareness_periods
|
||||||
|
# These are the internationally-recognized days.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
REM Sun 14 Feb MSG Start of Aromantic Spectrum Awareness Week
|
||||||
|
REM 1 Mar MSG Zero Discrimination Day
|
||||||
|
REM 31 Mar MSG Trans Day of Visibility
|
||||||
|
REM 6 Apr MSG International Asexuality Day
|
||||||
|
REM Wed 8 Apr MSG International Day of Pink
|
||||||
|
REM 26 Apr MSG Lesbian Visibility Day
|
||||||
|
REM 17 May MSG International Day Against Homophobia, Biphobia and Transphobia
|
||||||
|
REM 19 May MSG Agender Pride Day
|
||||||
|
REM 24 May MSG Pansexual & Panromantic Awareness Day
|
||||||
|
REM 1 Jun MSG Start of LGBT Pride Month
|
||||||
|
REM 5 Jun MSG Aromantic Visibility Day
|
||||||
|
REM Mon 8 Jul MSG Start of Non-Binary Awareness Week
|
||||||
|
REM 14 Jul MSG Non-Binary People's Day
|
||||||
|
REM 16 Jul MSG Drag Day
|
||||||
|
REM 9 Aug MSG Start of Dyke Week
|
||||||
|
REM 16 Sep MSG Start of Bisexual Awareness Week
|
||||||
|
REM 23 Sep MSG Celebrate Bisexuality Day
|
||||||
|
REM 8 Oct MSG Lesbian Day
|
||||||
|
REM 11 Oct MSG National Coming Out Day
|
||||||
|
REM Wed 15 Oct MSG Pronouns Day
|
||||||
|
REM 17 Oct MSG Start of Genderfluid Visibility Week
|
||||||
|
REM Sun 19 Oct MSG Start of Ace Week
|
||||||
|
REM 26 Oct MSG Intersex Awareness Day
|
||||||
|
REM 8 Nov MSG Intersex Day of Remembrance
|
||||||
|
REM 1 Nov MSG Start of Trans Awareness Month
|
||||||
|
REM Sun 1 Nov MSG Trans Parent Day
|
||||||
|
REM 13 Nov MSG Start of Trans Awareness Week
|
||||||
|
REM 20 Nov MSG Transgender Day of Remembrance
|
||||||
8
include/holidays/lgbtq/au.rem
Normal file
8
include/holidays/lgbtq/au.rem
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# List of LGBTQ awareness days
|
||||||
|
# Sourced from https://en.wikipedia.org/wiki/List_of_LGBTQ_awareness_periods
|
||||||
|
# These are the holidays recognized in Australia
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
REM Sat 1 Mar MSG Mardi Gras Parade
|
||||||
|
REM Fri 1 Sep --7 MSG Wear it Purple Day
|
||||||
|
REM 1 Oct MSG Start of LGBT History Month
|
||||||
10
include/holidays/lgbtq/br.rem
Normal file
10
include/holidays/lgbtq/br.rem
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# List of LGBTQ awareness days
|
||||||
|
# Sourced from https://en.wikipedia.org/wiki/List_of_LGBTQ_awareness_periods
|
||||||
|
# These are the holidays recognized in Brazil
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
REM 29 Jan MSG National Day of Transgender Visibility
|
||||||
|
REM 20 Feb MSG Trans Men and Transmasculine Day
|
||||||
|
REM 25 Mar MSG National Gay Pride Day
|
||||||
|
REM 29 Aug MSG National Day of Lesbian Visibility
|
||||||
7
include/holidays/lgbtq/ca.rem
Normal file
7
include/holidays/lgbtq/ca.rem
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# List of LGBTQ awareness days
|
||||||
|
# Sourced from https://en.wikipedia.org/wiki/List_of_LGBTQ_awareness_periods
|
||||||
|
# These are the holidays recognized in Canada
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
REM 1 Oct MSG Start of LGBT History Month
|
||||||
7
include/holidays/lgbtq/cl.rem
Normal file
7
include/holidays/lgbtq/cl.rem
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# List of LGBTQ awareness days
|
||||||
|
# Sourced from https://en.wikipedia.org/wiki/List_of_LGBTQ_awareness_periods
|
||||||
|
# These are the holidays recognized in Chile
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
REM 9 Jul MSG Lesbian Visibility Day
|
||||||
7
include/holidays/lgbtq/ie.rem
Normal file
7
include/holidays/lgbtq/ie.rem
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# List of LGBTQ awareness days
|
||||||
|
# Sourced from https://en.wikipedia.org/wiki/List_of_LGBTQ_awareness_periods
|
||||||
|
# These are the holidays recognized in Ireland
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
REM 22 May MSG Irish Marriage Referendum Day
|
||||||
7
include/holidays/lgbtq/in.rem
Normal file
7
include/holidays/lgbtq/in.rem
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# List of LGBTQ awareness days
|
||||||
|
# Sourced from https://en.wikipedia.org/wiki/List_of_LGBTQ_awareness_periods
|
||||||
|
# These are the holidays recognized in India
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
REM 2 Jul MSG Indian Coming Out Day
|
||||||
7
include/holidays/lgbtq/nl.rem
Normal file
7
include/holidays/lgbtq/nl.rem
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# List of LGBTQ awareness days
|
||||||
|
# Sourced from https://en.wikipedia.org/wiki/List_of_LGBTQ_awareness_periods
|
||||||
|
# These are the holidays recognized in the Netherlands
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
REM Fri 8 Dec MSG Purple Friday
|
||||||
7
include/holidays/lgbtq/ua.rem
Normal file
7
include/holidays/lgbtq/ua.rem
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# List of LGBTQ awareness days
|
||||||
|
# Sourced from https://en.wikipedia.org/wiki/List_of_LGBTQ_awareness_periods
|
||||||
|
# These are the holidays recognized in Ukraine
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
REM 12 Dec MSG Day of Remembrance of Homosexuals in Ukraine (victims of the totalitarian Soviet regime)
|
||||||
8
include/holidays/lgbtq/uk.rem
Normal file
8
include/holidays/lgbtq/uk.rem
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# List of LGBTQ awareness days
|
||||||
|
# Sourced from https://en.wikipedia.org/wiki/List_of_LGBTQ_awareness_periods
|
||||||
|
# These are the holidays recognized in the United Kingdom
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
REM 1 Feb MSG Start of LGBT History Month
|
||||||
|
REM 6 May MSG Start of Trans+ History Week
|
||||||
16
include/holidays/lgbtq/us.rem
Normal file
16
include/holidays/lgbtq/us.rem
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# List of LGBTQ awareness days
|
||||||
|
# Sourced from https://en.wikipedia.org/wiki/List_of_LGBTQ_awareness_periods
|
||||||
|
# These are the holidays recognized in the United States of America
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
REM 1 Mar MSG Start of Bisexual Health Awareness Month
|
||||||
|
REM Fri 8 Apr MSG Day of Silence
|
||||||
|
REM 9 Apr MSG Sapphic Visibility Day
|
||||||
|
REM 22 May MSG Harvey Milk Day
|
||||||
|
REM 5 Jun MSG HIV Long-Term Survivors Awareness Day
|
||||||
|
REM 12 Jun MSG Pulse Night of Remembrance
|
||||||
|
REM 28 Jun MSG Stonewall Riots Anniversary
|
||||||
|
REM 1 Aug MSG Start of Transgender History Month (CA)
|
||||||
|
REM 1 Oct MSG Start of LGBT History Month
|
||||||
|
REM Thu 15 Oct MSG Spirit Day
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Catalan language.
|
# Support for the Catalan language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file was created by Eloi Torrents <eloitor@disroot.org>
|
# This file was created by Eloi Torrents <eloitor@disroot.org>
|
||||||
|
|
||||||
TRANSLATE "LANGID" "ca"
|
TRANSLATE "LANGID" "ca"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Danish language.
|
# Support for the Danish language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file is derived from a translation by Mogens Lynnerup.
|
# This file is derived from a translation by Mogens Lynnerup.
|
||||||
|
|
||||||
TRANSLATE "LANGID" "da"
|
TRANSLATE "LANGID" "da"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the German language.
|
# Support for the German language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file is derived from a translation by Wolfgang Thronicke
|
# This file is derived from a translation by Wolfgang Thronicke
|
||||||
|
|
||||||
TRANSLATE "LANGID" "de"
|
TRANSLATE "LANGID" "de"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Support for the English language.
|
# Support for the English language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# Nothing to do for English since it is the default.
|
# Nothing to do for English since it is the default.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Spanish language.
|
# Support for the Spanish language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file is derived from a translation by Rafa Couto <rafacouto@biogate.com>
|
# This file is derived from a translation by Rafa Couto <rafacouto@biogate.com>
|
||||||
|
|
||||||
TRANSLATE "LANGID" "es"
|
TRANSLATE "LANGID" "es"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Finnish language.
|
# Support for the Finnish language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file is derived from a translation by Mikko Silvonen
|
# This file is derived from a translation by Mikko Silvonen
|
||||||
|
|
||||||
TRANSLATE "LANGID" "fi"
|
TRANSLATE "LANGID" "fi"
|
||||||
@@ -170,19 +170,19 @@ TRANSLATE "Leaving UserFN" "Poistutaan funktiosta"
|
|||||||
TRANSLATE "Expired" "Vanhentunut"
|
TRANSLATE "Expired" "Vanhentunut"
|
||||||
TRANSLATE "fork() failed - can't do queued reminders" "fork() epäonnistui - jonomuistutukset eivät toimi"
|
TRANSLATE "fork() failed - can't do queued reminders" "fork() epäonnistui - jonomuistutukset eivät toimi"
|
||||||
TRANSLATE "Can't access file" "Tiedoston avaus ei onnistu"
|
TRANSLATE "Can't access file" "Tiedoston avaus ei onnistu"
|
||||||
TRANSLATE "Illegal system date: Year is less than %d\n" "Virheellinen järjestelmäpäiväys: vuosi on vähemmän kuin %d\n"
|
TRANSLATE "Illegal system date: Year is less than %d" "Virheellinen järjestelmäpäiväys: vuosi on vähemmän kuin %d"
|
||||||
TRANSLATE "Unknown debug flag '%c'\n" "Tuntematon virheenetsintätarkenne '%c'\n"
|
TRANSLATE "Unknown debug flag '%c'" "Tuntematon virheenetsintätarkenne '%c'"
|
||||||
TRANSLATE "Unknown option '%c'\n" "Tuntematon tarkenne '%c'\n"
|
TRANSLATE "Unknown option '%c'" "Tuntematon tarkenne '%c'"
|
||||||
TRANSLATE "Unknown user '%s'\n" "Tuntematon käyttäjä '%s'\n"
|
TRANSLATE "Unknown user '%s'" "Tuntematon käyttäjä '%s'"
|
||||||
TRANSLATE "Could not change gid to %d\n" "Ryhmänumeron vaihto %d:ksi ei onnistunut\n"
|
TRANSLATE "Could not change gid to %d" "Ryhmänumeron vaihto %d:ksi ei onnistunut"
|
||||||
TRANSLATE "Could not change uid to %d\n" "Käyttäjänumeron vaihto %d:ksi ei onnistunut\n"
|
TRANSLATE "Could not change uid to %d" "Käyttäjänumeron vaihto %d:ksi ei onnistunut"
|
||||||
TRANSLATE "Out of memory for environment\n" "Muisti ei riitä ympäristölle\n"
|
TRANSLATE "Out of memory for environment" "Muisti ei riitä ympäristölle"
|
||||||
TRANSLATE "Missing '=' sign" "Puuttuva '='-merkki"
|
TRANSLATE "Missing '=' sign" "Puuttuva '='-merkki"
|
||||||
TRANSLATE "Missing variable name" "Puuttuva muuttujanimi"
|
TRANSLATE "Missing variable name" "Puuttuva muuttujanimi"
|
||||||
TRANSLATE "Missing expression" "Puuttuva lauseke"
|
TRANSLATE "Missing expression" "Puuttuva lauseke"
|
||||||
TRANSLATE "Remind: '-i' option: %s\n" "Remind: tarkenne '-i': %s\n"
|
TRANSLATE "Remind: '-i' option: %s" "Remind: tarkenne '-i': %s"
|
||||||
TRANSLATE "No reminders." "Ei viestejä."
|
TRANSLATE "No reminders." "Ei viestejä."
|
||||||
TRANSLATE "%d reminder(s) queued for later today.\n" "%d viesti(ä) tämän päivän jonossa.\n"
|
TRANSLATE "%d reminder(s) queued for later today." "%d viesti(ä) tämän päivän jonossa."
|
||||||
TRANSLATE "Expecting number" "Numero puuttuu"
|
TRANSLATE "Expecting number" "Numero puuttuu"
|
||||||
TRANSLATE "Undefined WARN function" "Virheellinen funktio WARN-lausekkeessa"
|
TRANSLATE "Undefined WARN function" "Virheellinen funktio WARN-lausekkeessa"
|
||||||
TRANSLATE "Can't convert between time zones" "Aikavyöhykkeiden välillä ei voi muuntaa"
|
TRANSLATE "Can't convert between time zones" "Aikavyöhykkeiden välillä ei voi muuntaa"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the French language.
|
# Support for the French language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file is derived from a translation by Laurent Duperval
|
# This file is derived from a translation by Laurent Duperval
|
||||||
|
|
||||||
TRANSLATE "LANGID" "fr"
|
TRANSLATE "LANGID" "fr"
|
||||||
@@ -138,17 +138,17 @@ TRANSLATE "Leaving UserFN" "Sortie de UserFN"
|
|||||||
TRANSLATE "Expired" "Expiré"
|
TRANSLATE "Expired" "Expiré"
|
||||||
TRANSLATE "fork() failed - can't do queued reminders" "fork() échoué - impossible de faire les appels en queue"
|
TRANSLATE "fork() failed - can't do queued reminders" "fork() échoué - impossible de faire les appels en queue"
|
||||||
TRANSLATE "Can't access file" "Impossible d'accéder au fichier"
|
TRANSLATE "Can't access file" "Impossible d'accéder au fichier"
|
||||||
TRANSLATE "Illegal system date: Year is less than %d\n" "Date système illégale: Année est inférieure à %d\n"
|
TRANSLATE "Illegal system date: Year is less than %d" "Date système illégale: Année est inférieure à %d"
|
||||||
TRANSLATE "Unknown debug flag '%c'\n" "Option de déverminage inconnue '%c'\n"
|
TRANSLATE "Unknown debug flag '%c'" "Option de déverminage inconnue '%c'"
|
||||||
TRANSLATE "Unknown option '%c'\n" "Option inconnue '%c'\n"
|
TRANSLATE "Unknown option '%c'" "Option inconnue '%c'"
|
||||||
TRANSLATE "Unknown user '%s'\n" "Usager inconnu '%s'\n"
|
TRANSLATE "Unknown user '%s'" "Usager inconnu '%s'"
|
||||||
TRANSLATE "Could not change gid to %d\n" "Impossible de changer gid pour %d\n"
|
TRANSLATE "Could not change gid to %d" "Impossible de changer gid pour %d"
|
||||||
TRANSLATE "Could not change uid to %d\n" "Impossible de changer uid pour %d\n"
|
TRANSLATE "Could not change uid to %d" "Impossible de changer uid pour %d"
|
||||||
TRANSLATE "Out of memory for environment\n" "Manque de mémoire pour environnement\n"
|
TRANSLATE "Out of memory for environment" "Manque de mémoire pour environnement"
|
||||||
TRANSLATE "Missing '=' sign" "Signe '=' manquant"
|
TRANSLATE "Missing '=' sign" "Signe '=' manquant"
|
||||||
TRANSLATE "Missing variable name" "Nom de variable absent"
|
TRANSLATE "Missing variable name" "Nom de variable absent"
|
||||||
TRANSLATE "Missing expression" "Expression absente"
|
TRANSLATE "Missing expression" "Expression absente"
|
||||||
TRANSLATE "%d reminder(s) queued for later today.\n" "%d rappel(s) en file pour aujourd'hui.\n"
|
TRANSLATE "%d reminder(s) queued for later today." "%d rappel(s) en file pour aujourd'hui."
|
||||||
TRANSLATE "Expecting number" "Nombre attendu"
|
TRANSLATE "Expecting number" "Nombre attendu"
|
||||||
TRANSLATE "Undefined WARN function" "Fonction illégale après WARN"
|
TRANSLATE "Undefined WARN function" "Fonction illégale après WARN"
|
||||||
TRANSLATE "Can't convert between time zones" "Impossible de convertir entre les fuseaux horaires"
|
TRANSLATE "Can't convert between time zones" "Impossible de convertir entre les fuseaux horaires"
|
||||||
@@ -160,3 +160,5 @@ TRANSLATE "Expecting weekday name" "Nom du jour de la semaine attendu"
|
|||||||
TRANSLATE "Duplicate argument name" "Nom de l'argument en double"
|
TRANSLATE "Duplicate argument name" "Nom de l'argument en double"
|
||||||
TRANSLATE "Expression evaluation is disabled" "L'évaluation de l'expression est désactivée"
|
TRANSLATE "Expression evaluation is disabled" "L'évaluation de l'expression est désactivée"
|
||||||
TRANSLATE "Time limit for expression evaluation exceeded" "Délai d'évaluation de l'expression dépassé"
|
TRANSLATE "Time limit for expression evaluation exceeded" "Délai d'évaluation de l'expression dépassé"
|
||||||
|
TRANSLATE "here" "ici"
|
||||||
|
TRANSLATE "did you mean" "voulais-vous dire"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Hellenic (Greek) language.
|
# Support for the Hellenic (Greek) language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file is derived from a translation by jarlaxl lamat (jarlaxl@freemail.gr)
|
# This file is derived from a translation by jarlaxl lamat (jarlaxl@freemail.gr)
|
||||||
|
|
||||||
TRANSLATE "LANGID" "gr"
|
TRANSLATE "LANGID" "gr"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Icelanding language.
|
# Support for the Icelanding language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file is derived from a translation by Björn Davíðsson (bjossi@snerpa.is)
|
# This file is derived from a translation by Björn Davíðsson (bjossi@snerpa.is)
|
||||||
|
|
||||||
TRANSLATE "LANGID" "is"
|
TRANSLATE "LANGID" "is"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Italian language.
|
# Support for the Italian language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file is derived from a translation by Valerio Aimale
|
# This file is derived from a translation by Valerio Aimale
|
||||||
|
|
||||||
TRANSLATE "LANGID" "it"
|
TRANSLATE "LANGID" "it"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Dutch language.
|
# Support for the Dutch language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file is derived from a translation by Willem Kasdorp and Erik-Jan Vens
|
# This file is derived from a translation by Willem Kasdorp and Erik-Jan Vens
|
||||||
|
|
||||||
TRANSLATE "LANGID" "nl"
|
TRANSLATE "LANGID" "nl"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Norwegian language.
|
# Support for the Norwegian language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file is derived from a translation by Trygve Randen
|
# This file is derived from a translation by Trygve Randen
|
||||||
|
|
||||||
TRANSLATE "LANGID" "no"
|
TRANSLATE "LANGID" "no"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Polish language.
|
# Support for the Polish language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file is derived from a translation by Jerzy Sobczyk
|
# This file is derived from a translation by Jerzy Sobczyk
|
||||||
|
|
||||||
TRANSLATE "LANGID" "pl"
|
TRANSLATE "LANGID" "pl"
|
||||||
@@ -146,19 +146,19 @@ TRANSLATE "Leaving UserFN" "Koniec UserFN"
|
|||||||
TRANSLATE "Expired" "Przemineło"
|
TRANSLATE "Expired" "Przemineło"
|
||||||
TRANSLATE "fork() failed - can't do queued reminders" "Niepowodzenie w funkcji fork() - nie mogę kolejkować przypomnień"
|
TRANSLATE "fork() failed - can't do queued reminders" "Niepowodzenie w funkcji fork() - nie mogę kolejkować przypomnień"
|
||||||
TRANSLATE "Can't access file" "Nie ma dostępu do pliku"
|
TRANSLATE "Can't access file" "Nie ma dostępu do pliku"
|
||||||
TRANSLATE "Illegal system date: Year is less than %d\n" "Błędna data systemowa: Rok mniejszy niż %d\n"
|
TRANSLATE "Illegal system date: Year is less than %d" "Błędna data systemowa: Rok mniejszy niż %d"
|
||||||
TRANSLATE "Unknown debug flag '%c'\n" "Nieznana flaga odpluskwiania '%c'\n"
|
TRANSLATE "Unknown debug flag '%c'" "Nieznana flaga odpluskwiania '%c'"
|
||||||
TRANSLATE "Unknown option '%c'\n" "Nieznana opcja '%c'\n"
|
TRANSLATE "Unknown option '%c'" "Nieznana opcja '%c'"
|
||||||
TRANSLATE "Unknown user '%s'\n" "Nieznany użytkownik '%s'\n"
|
TRANSLATE "Unknown user '%s'" "Nieznany użytkownik '%s'"
|
||||||
TRANSLATE "Could not change gid to %d\n" "Nie mogę zmienić gid na %d\n"
|
TRANSLATE "Could not change gid to %d" "Nie mogę zmienić gid na %d"
|
||||||
TRANSLATE "Could not change uid to %d\n" "Nie mogę zmienić uid na %d\n"
|
TRANSLATE "Could not change uid to %d" "Nie mogę zmienić uid na %d"
|
||||||
TRANSLATE "Out of memory for environment\n" "Brak pamięci na zmienne środowiska\n"
|
TRANSLATE "Out of memory for environment" "Brak pamięci na zmienne środowiska"
|
||||||
TRANSLATE "Missing '=' sign" "Brak znaku '='"
|
TRANSLATE "Missing '=' sign" "Brak znaku '='"
|
||||||
TRANSLATE "Missing variable name" "Brak nazwy zmiennej"
|
TRANSLATE "Missing variable name" "Brak nazwy zmiennej"
|
||||||
TRANSLATE "Missing expression" "Brak wyrażenia"
|
TRANSLATE "Missing expression" "Brak wyrażenia"
|
||||||
TRANSLATE "Remind: '-i' option: %s\n" "Remind: '-i' option: %s\n"
|
TRANSLATE "Remind: '-i' option: %s" "Remind: '-i' option: %s"
|
||||||
TRANSLATE "No reminders." "Brak przypomnień."
|
TRANSLATE "No reminders." "Brak przypomnień."
|
||||||
TRANSLATE "%d reminder(s) queued for later today.\n" "%d Przypomnienia zakolejkowane na później.\n"
|
TRANSLATE "%d reminder(s) queued for later today." "%d Przypomnienia zakolejkowane na później."
|
||||||
TRANSLATE "Expecting number" "Spodziewana liczba"
|
TRANSLATE "Expecting number" "Spodziewana liczba"
|
||||||
TRANSLATE "Undefined WARN function" "Nielegalna funkcja w klauzuli WARN:"
|
TRANSLATE "Undefined WARN function" "Nielegalna funkcja w klauzuli WARN:"
|
||||||
TRANSLATE "Can't convert between time zones" "Nie można konwertować między strefami czasowymi"
|
TRANSLATE "Can't convert between time zones" "Nie można konwertować między strefami czasowymi"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the (Brazilian) Portuguese language.
|
# Support for the (Brazilian) Portuguese language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file is derived from a translation by Marco Paganini
|
# This file is derived from a translation by Marco Paganini
|
||||||
|
|
||||||
TRANSLATE "LANGID" "pt"
|
TRANSLATE "LANGID" "pt"
|
||||||
@@ -145,19 +145,19 @@ TRANSLATE "Leaving UserFN" "Saindo UserFN"
|
|||||||
TRANSLATE "Expired" "Expirou"
|
TRANSLATE "Expired" "Expirou"
|
||||||
TRANSLATE "fork() failed - can't do queued reminders" "fork() falhou - Nao posso processar compromissos na fila"
|
TRANSLATE "fork() failed - can't do queued reminders" "fork() falhou - Nao posso processar compromissos na fila"
|
||||||
TRANSLATE "Can't access file" "Nao consigo acessar o arquivo"
|
TRANSLATE "Can't access file" "Nao consigo acessar o arquivo"
|
||||||
TRANSLATE "Illegal system date: Year is less than %d\n" "Data do sistema ilegal: Ano e menor que %d\n"
|
TRANSLATE "Illegal system date: Year is less than %d" "Data do sistema ilegal: Ano e menor que %d"
|
||||||
TRANSLATE "Unknown debug flag '%c'\n" "Flag de debug desconhecido '%c'\n"
|
TRANSLATE "Unknown debug flag '%c'" "Flag de debug desconhecido '%c'"
|
||||||
TRANSLATE "Unknown option '%c'\n" "Opcao desconhecida '%c'\n"
|
TRANSLATE "Unknown option '%c'" "Opcao desconhecida '%c'"
|
||||||
TRANSLATE "Unknown user '%s'\n" "Usuario desconhecido '%s'\n"
|
TRANSLATE "Unknown user '%s'" "Usuario desconhecido '%s'"
|
||||||
TRANSLATE "Could not change gid to %d\n" "Nao consigo mudar gid para %d\n"
|
TRANSLATE "Could not change gid to %d" "Nao consigo mudar gid para %d"
|
||||||
TRANSLATE "Could not change uid to %d\n" "Nao consigo mudar uid para %d\n"
|
TRANSLATE "Could not change uid to %d" "Nao consigo mudar uid para %d"
|
||||||
TRANSLATE "Out of memory for environment\n" "Sem memoria para o environment\n"
|
TRANSLATE "Out of memory for environment" "Sem memoria para o environment"
|
||||||
TRANSLATE "Missing '=' sign" "Falta o sinal de '='"
|
TRANSLATE "Missing '=' sign" "Falta o sinal de '='"
|
||||||
TRANSLATE "Missing variable name" "Falta o nome da variavel"
|
TRANSLATE "Missing variable name" "Falta o nome da variavel"
|
||||||
TRANSLATE "Missing expression" "Falta a expressao"
|
TRANSLATE "Missing expression" "Falta a expressao"
|
||||||
TRANSLATE "Remind: '-i' option: %s\n" "Remind: '-i' opcao: %s\n"
|
TRANSLATE "Remind: '-i' option: %s" "Remind: '-i' opcao: %s"
|
||||||
TRANSLATE "No reminders." "Sem compromissos."
|
TRANSLATE "No reminders." "Sem compromissos."
|
||||||
TRANSLATE "%d reminder(s) queued for later today.\n" "%d compromisso(s) colocados na fila para mais tarde.\n"
|
TRANSLATE "%d reminder(s) queued for later today." "%d compromisso(s) colocados na fila para mais tarde."
|
||||||
TRANSLATE "Expecting number" "Esperando numero"
|
TRANSLATE "Expecting number" "Esperando numero"
|
||||||
TRANSLATE "Undefined WARN function" "Funcao ilegal na clausula WARN"
|
TRANSLATE "Undefined WARN function" "Funcao ilegal na clausula WARN"
|
||||||
TRANSLATE "Can't convert between time zones" "Não consigo converter entre fusos horários"
|
TRANSLATE "Can't convert between time zones" "Não consigo converter entre fusos horários"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Romanian language.
|
# Support for the Romanian language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
# This file is derived from a translation by Liviu Daia
|
# This file is derived from a translation by Liviu Daia
|
||||||
|
|
||||||
TRANSLATE "LANGID" "ro"
|
TRANSLATE "LANGID" "ro"
|
||||||
|
|||||||
@@ -637,70 +637,100 @@ However, back-ends should keep reading until EOF in case more data for
|
|||||||
subsequent months is forthcoming.
|
subsequent months is forthcoming.
|
||||||
.PP
|
.PP
|
||||||
|
|
||||||
.SH REM2PS PURE JSON INPUT FORMAT (-PPP OPTION)
|
.SH REM2PS PURE JSON INPUT FORMAT (-PPP OR -P+ OPTION)
|
||||||
\fBRemind \-ppp\fR emits \fIpure JSON\fR output. The format is
|
\fBRemind \-ppp\fR and \fBremind \-p+\fR emit \fIpure JSON\fR output.
|
||||||
as follows:
|
The format is as follows:
|
||||||
.PP
|
.PP
|
||||||
\fBRemind\fR outputs a JSON array. Each element of the array is a
|
\fBRemind\fR outputs a JSON array. Each element of the array is a
|
||||||
\fImonth descriptor\fR.
|
\fImonth descriptor\fR or a \fIweek descriptor\fR in the case of
|
||||||
|
\fBremind \-p+\fR.
|
||||||
.PP
|
.PP
|
||||||
Each month descriptor is a JSON object with the following elements:
|
Each descriptor is a JSON object with the following elements:
|
||||||
|
.TP
|
||||||
|
.B caltype \fItype\fR
|
||||||
|
The calendar type, either \fBmonthly\fR or \fBweekly\fR. Older versions
|
||||||
|
of \fBRemind\fR did not include a \fBcaltype\fR element, so a missing
|
||||||
|
\fBcaltype\fR should be treated as \fBmonthly\fR.
|
||||||
.TP
|
.TP
|
||||||
.B monthname \fIname\fR
|
.B monthname \fIname\fR
|
||||||
The name of the month.
|
The name of the month. Present in monthly calendar types only.
|
||||||
.TP
|
.TP
|
||||||
.B year \fIyyyy\fR
|
.B year \fIyyyy\fR
|
||||||
The year.
|
The year. Present in monthly calendar types only.
|
||||||
.TP
|
.TP
|
||||||
.B daysinmonnth \fIn\fR
|
.B daysinmonnth \fIn\fR
|
||||||
The number of days in the current month.
|
The number of days in the current month. Present in monthly calendar types only.
|
||||||
.TP
|
.TP
|
||||||
.B firstwkday \fIn\fR
|
.B firstwkday \fIn\fR
|
||||||
The weekday of the first day of the month (0 = Sunday, 1 = Monday, 6 = Saturday).
|
The weekday of the first day of the month (0 = Sunday, 1 = Monday, 6 = Saturday). Present in monthly calendar types only.
|
||||||
.TP
|
.TP
|
||||||
.B mondayfirst \fIn\fR
|
.B mondayfirst \fIn\fR
|
||||||
An indicator of whether or not the calendar week should start with
|
An indicator of whether or not the calendar week should start with
|
||||||
Sunday (n=0) or Monday (n=1).
|
Sunday (n=0) or Monday (n=1). Present in monthly calendar types only.
|
||||||
.TP
|
.TP
|
||||||
.B daynames \fR[\fIdays\fR]
|
.B daynames \fR[\fIdays\fR]
|
||||||
A seven-element array of day names; each element is a string representing
|
A seven-element array of day names; each element is a string representing
|
||||||
the names of the days from Sunday through Saturday.
|
the names of the days from Sunday through Saturday. Present in monthly calendar types only.
|
||||||
.TP
|
.TP
|
||||||
.B prevmonthname \fIname\fR
|
.B prevmonthname \fIname\fR
|
||||||
The name of the previous month.
|
The name of the previous month. Present in monthly calendar types only.
|
||||||
.TP
|
.TP
|
||||||
.B daysinprevmonth \fIn\fR
|
.B daysinprevmonth \fIn\fR
|
||||||
The number of days in the previous month.
|
The number of days in the previous month. Present in monthly calendar types only.
|
||||||
.TP
|
.TP
|
||||||
.B prevmonthyear \fIyyyy\fR
|
.B prevmonthyear \fIyyyy\fR
|
||||||
The year of the previous month. (The same as \fByear\fR unless the current
|
The year of the previous month. (The same as \fByear\fR unless the current
|
||||||
month is January.)
|
month is January.) Present in monthly calendar types only.
|
||||||
.TP
|
.TP
|
||||||
.B nextmonthname \fIname\fR
|
.B nextmonthname \fIname\fR
|
||||||
The name of the following month.
|
The name of the following month. Present in monthly calendar types only.
|
||||||
.TP
|
.TP
|
||||||
.B daysinnextmonth \fIn\fR
|
.B daysinnextmonth \fIn\fR
|
||||||
The number of days in the following month.
|
The number of days in the following month. Present in monthly calendar types only.
|
||||||
.TP
|
.TP
|
||||||
.B nextmonthyear \fIyyyy\fR
|
.B nextmonthyear \fIyyyy\fR
|
||||||
The year of the following month. (The same as \fByear\fR unless the
|
The year of the following month. (The same as \fByear\fR unless the
|
||||||
current month is December.)
|
current month is December.) Present in monthly calendar types only.
|
||||||
.TP
|
.TP
|
||||||
.B translations \fR{\fIobject\fR}
|
.B translations \fR{\fIobject\fR}
|
||||||
A complete dump of the Remind translation table. In output for multiple
|
A complete dump of the Remind translation table. In output for multiple
|
||||||
months, the translation table is included only with the first month.
|
months or weeks, the translation table is included only with the first month
|
||||||
|
or week. Present in both weekly and monthly calendar types.
|
||||||
.TP
|
.TP
|
||||||
.B entries \fR[\fIarray\fR]
|
.B entries \fR[\fIarray\fR]
|
||||||
The \fBentries\fR key consists of an array of calendar entries; each
|
The \fBentries\fR key, present in both weekly and monthly calendar
|
||||||
entry is a JSON object that has the same format as described in the
|
types, consists of an array of calendar entries; each entry is a JSON
|
||||||
\fBCALENDAR ENTRIES\fR section in the \fB\-PP FORMAT\fR section,
|
object that has the same format as described in the \fBCALENDAR
|
||||||
\fIwith the following difference\fR: In \fB\-PP\fR mode, if a reminder
|
ENTRIES\fR section in the \fB\-PP FORMAT\fR section, \fIwith the
|
||||||
has \fB%"\fR markers, only the text between the markers
|
following difference\fR: In \fB\-PP\fR mode, if a reminder has
|
||||||
is included in the \fBbody\fR element. In \fB\-PPP\fR mode, the
|
\fB%"\fR markers, only the text between the markers is included in the
|
||||||
entire text \fIincluding\fR the \fB%"\fR markers is included and it's up to
|
\fBbody\fR element. In \fB\-PPP\fR mode, the entire text
|
||||||
the back-end to extract the portion between the markers if that
|
\fIincluding\fR the \fB%"\fR markers is included and it's up to the
|
||||||
is desired.
|
back-end to extract the portion between the markers if that is
|
||||||
|
desired.
|
||||||
|
.TP
|
||||||
|
.B dates \fR[\fIarray\fR]
|
||||||
|
The \fBdates\fR key, present in weekly calendar types only,
|
||||||
|
contains seven entries; one for each column in the weekly
|
||||||
|
calendar. Each entry is a JSON object containing the following
|
||||||
|
key/value pairs:
|
||||||
|
.RS
|
||||||
|
.TP
|
||||||
|
.B date \fR\fIYYYY-MM-DD\fR
|
||||||
|
The date of the column.
|
||||||
|
.TP
|
||||||
|
.B day \fR\fIDD\fR
|
||||||
|
The day number of the column.
|
||||||
|
.TP
|
||||||
|
.B dayname \fR\fIweekday_name\fR
|
||||||
|
The name of the weekday (possibly localized).
|
||||||
|
.TP
|
||||||
|
.B month \fR\fImonth_name\fR
|
||||||
|
The name of the month (possibly localized).
|
||||||
|
.TP
|
||||||
|
.B year \fR\fIYYYY\fR
|
||||||
|
The year.
|
||||||
|
.RE
|
||||||
|
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
rem2ps was written by Dianne Skoll <dianne@skoll.ca>
|
rem2ps was written by Dianne Skoll <dianne@skoll.ca>
|
||||||
|
|||||||
110
man/remind.1.in
110
man/remind.1.in
@@ -182,12 +182,18 @@ If you immediately follow the \fBs\fR with the letter
|
|||||||
day they actually occur \fIas well as\fR on any preceding days specified
|
day they actually occur \fIas well as\fR on any preceding days specified
|
||||||
by the reminder's \fIdelta\fR.
|
by the reminder's \fIdelta\fR.
|
||||||
.TP
|
.TP
|
||||||
.B \-p\fR[\fBa\fR][\fBp\fR][\fBp\fR][\fBq\fR]\fIn\fR
|
.B \-p\fR[\fBa\fR][\fBp\fR][\fBp\fR][\fBq\fR][+]\fIn\fR
|
||||||
The \fB\-p\fR option is very similar to the \fB\-s\fR option, except
|
The \fB\-p\fR option is very similar to the \fB\-s\fR option, except
|
||||||
that the output contains additional information for use by the
|
that the output contains additional information for use by a back-end such as the
|
||||||
\fBRem2PS\fR program, which creates a PostScript calendar, and various
|
\fBRem2PS\fR program, which creates a PostScript calendar, and various
|
||||||
other back-end programs. For this
|
other back-end programs. If \fIn\fR starts with "+", then it specifies
|
||||||
option, \fIn\fR cannot start with "+"; it must specify a number of months.
|
a number of weeks rather than a number of months, and back-ends are expected
|
||||||
|
to produce weekly calendars. Note that not all back-ends support
|
||||||
|
weekly calendars; currently, only \fBrem2pdf\fR does. Specifying a weekly
|
||||||
|
calendar implicitly enables the pure JSON interchange format, similar
|
||||||
|
to \fB\-ppp\fR.
|
||||||
|
.RS
|
||||||
|
.PP
|
||||||
The format of the \fB\-p\fR output is described in the \fBrem2ps(1)\fR
|
The format of the \fB\-p\fR output is described in the \fBrem2ps(1)\fR
|
||||||
man page. If you immediately follow the \fBp\fR with the letter
|
man page. If you immediately follow the \fBp\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,7 +206,6 @@ three p's, as in \fB\-ppp\fR, then \fBRemind\fR uses a pure JSON
|
|||||||
format, again documented in \fBrem2ps(1)\fR. If you include a \fBq\fR
|
format, again documented in \fBrem2ps(1)\fR. If you include a \fBq\fR
|
||||||
letter with this option, then the normal calendar-mode substitution filter
|
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
|
|
||||||
.PP
|
.PP
|
||||||
The \fB\-p\fR, \fB\-pp\fR and \fB\-ppp\fR options implicitly enable
|
The \fB\-p\fR, \fB\-pp\fR and \fB\-ppp\fR options implicitly enable
|
||||||
the \fB\-o\fR option.
|
the \fB\-o\fR option.
|
||||||
@@ -310,6 +315,13 @@ Trace the reading of reminder files
|
|||||||
Trace expression parsing and display the internal expression node
|
Trace expression parsing and display the internal expression node
|
||||||
tree. This is unlikely to be useful unless you are working on
|
tree. This is unlikely to be useful unless you are working on
|
||||||
\fBRemind\fR's expression evaluation engine.
|
\fBRemind\fR's expression evaluation engine.
|
||||||
|
.TP
|
||||||
|
.B h
|
||||||
|
Dump hash-table statistics on exit.
|
||||||
|
.TP
|
||||||
|
.B q
|
||||||
|
Output a TRANSLATE command each time the \fB_()\fR built-in function
|
||||||
|
is called or the \fB%(...)\fR substitution sequence is encountered.
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
\fB\-g\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR]]]]
|
\fB\-g\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR]]]]
|
||||||
@@ -470,11 +482,13 @@ 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.
|
||||||
.TP
|
.TP
|
||||||
.B \-\-print-errs
|
.B \-\-print-errs
|
||||||
The \fB\-\-print-errs\fR option causes \fBRemind\fR to print all possible
|
The \fB\-\-print-errs\fR option causes \fBRemind\fR to print all
|
||||||
error messages to standard output and then exit. The messages are printed
|
possible error messages to standard output and then exit. The
|
||||||
in a format suitable for the first argument of a TRANSLATE command. If
|
messages are printed in a format suitable for the first argument of a
|
||||||
you TRANSLATE the error messages, then \fBRemind\fR will use the translated
|
TRANSLATE command. If you TRANSLATE the error messages, then
|
||||||
versions when outputting error and warning messages.
|
\fBRemind\fR will use the translated versions when outputting error
|
||||||
|
and warning messages. See also TRANSLATE GENERATE in the section
|
||||||
|
"THE TRANSLATION TABLE".
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
Note that if an untranslated message contains printf-style formatting
|
Note that if an untranslated message contains printf-style formatting
|
||||||
@@ -516,11 +530,16 @@ resources. Note that the limit \fIn\fR is approximate and
|
|||||||
\fBRemind\fR might execute for one or two more seconds before it is
|
\fBRemind\fR might execute for one or two more seconds before it is
|
||||||
killed. If \fIn\fR is specified as zero, then no limit is applied, just
|
killed. If \fIn\fR is specified as zero, then no limit is applied, just
|
||||||
as if the option had not been used at all.
|
as if the option had not been used at all.
|
||||||
|
.RS
|
||||||
.PP
|
.PP
|
||||||
If a limit is applied, it applies only to the foreground run of \fBRemind\fR.
|
If a limit is applied, it applies only to the foreground run of \fBRemind\fR.
|
||||||
If \fBRemind\fR finishes processing the script and then starts handling
|
If \fBRemind\fR finishes processing the script and then starts handling
|
||||||
queued reminders, the time limit is reset to no limit.
|
queued reminders, the time limit is reset to no limit.
|
||||||
.PP
|
.RE
|
||||||
|
.TP
|
||||||
|
.B \-\-test
|
||||||
|
The \fB\-\-test\fR long option is only for use by the acceptance tests
|
||||||
|
run by "make test". Do not use this option in production.
|
||||||
.SH REMINDER FILES
|
.SH REMINDER FILES
|
||||||
.PP
|
.PP
|
||||||
\fBRemind\fR uses scripts to control its operation. You can use any
|
\fBRemind\fR uses scripts to control its operation. You can use any
|
||||||
@@ -1927,19 +1946,18 @@ commands.
|
|||||||
.SH THE DO, INCLUDE AND SYSINCLUDE COMMANDS
|
.SH THE DO, INCLUDE AND SYSINCLUDE COMMANDS
|
||||||
.PP
|
.PP
|
||||||
\fBRemind\fR allows you to include other files in your reminder script,
|
\fBRemind\fR allows you to include other files in your reminder script,
|
||||||
similar to the C preprocessor #include directive. For example, your
|
similar to the C preprocessor #include directive. For example, you
|
||||||
system administrator may maintain a file of holidays or system-wide
|
might organize different reminders into different files like this:
|
||||||
reminders. You can include these in your reminder script as follows:
|
|
||||||
.PP
|
.PP
|
||||||
.nf
|
.nf
|
||||||
INCLUDE /usr/share/remind/holidays
|
INCLUDE holidays.rem
|
||||||
INCLUDE /usr/share/remind/reminders
|
INCLUDE birthdays.rem
|
||||||
|
INCLUDE "quote files with spaces.rem"
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
(The actual pathnames vary from system to system - ask your system
|
\fBINCLUDE\fR files can be nested up to a depth of 8. As shown above, if a
|
||||||
administrator.)
|
filename has spaces in it (not recommended!) you can use double-quotes
|
||||||
.PP
|
around the filename.
|
||||||
\fBINCLUDE\fR files can be nested up to a depth of 8.
|
|
||||||
.PP
|
.PP
|
||||||
If you specify a filename of "-" in the \fBINCLUDE\fR command, \fBRemind\fR
|
If you specify a filename of "-" in the \fBINCLUDE\fR command, \fBRemind\fR
|
||||||
will begin reading from standard input.
|
will begin reading from standard input.
|
||||||
@@ -1983,7 +2001,7 @@ symbolic links to files.
|
|||||||
.PP
|
.PP
|
||||||
The \fBSYSINCLUDE\fR command is similar to \fBDO\fR, but it looks for
|
The \fBSYSINCLUDE\fR command is similar to \fBDO\fR, but it looks for
|
||||||
relative pathnames under the system directory containing standard reminder
|
relative pathnames under the system directory containing standard reminder
|
||||||
scripts. For thie version of \fBRemind\fR, the system directory is
|
scripts. For this version of \fBRemind\fR, the system directory is
|
||||||
"@prefix@/share/remind".
|
"@prefix@/share/remind".
|
||||||
.PP
|
.PP
|
||||||
.SH THE RUN COMMAND
|
.SH THE RUN COMMAND
|
||||||
@@ -2535,12 +2553,17 @@ Universal Time Coordinated in the \fB$MinsFromUTC\fR system variable.
|
|||||||
.B $CalMode (read-only)
|
.B $CalMode (read-only)
|
||||||
If non-zero, then the \fB\-c\fR option was supplied on the command line.
|
If non-zero, then the \fB\-c\fR option was supplied on the command line.
|
||||||
.TP
|
.TP
|
||||||
|
.B $CalType (read-only, STRING type)
|
||||||
|
If the \fB\-c\fR, \fB\-s\fR or \fB\-p\fR command-line options were
|
||||||
|
used, then this variable has the value "monthly". If \fB\-c+\fR,
|
||||||
|
\fB\-s+\fR or \fB\-p+\fR were used, then "weekly". Otherwise, "none".
|
||||||
|
.TP
|
||||||
.B $Daemon (read-only)
|
.B $Daemon (read-only)
|
||||||
If "daemon mode" \fB\-z\fR was invoked, contains the number of
|
If "daemon mode" \fB\-z\fR was invoked, contains the number of
|
||||||
minutes between wakeups. If not running in daemon mode, contains
|
minutes between wakeups. If not running in daemon mode, contains
|
||||||
0. In server mode (either \fB-z0\fR or \fB-zj\fR), contains -1.
|
0. In server mode (either \fB-z0\fR or \fB-zj\fR), contains -1.
|
||||||
.TP
|
.TP
|
||||||
.B $DateSep
|
.B $DateSep (STRING type)
|
||||||
This variable can be set only to "/" or "-". It holds the character
|
This variable can be set only to "/" or "-". It holds the character
|
||||||
used to separate portions of a date when \fBRemind\fR prints a DATE or
|
used to separate portions of a date when \fBRemind\fR prints a DATE or
|
||||||
DATETIME value.
|
DATETIME value.
|
||||||
@@ -2595,7 +2618,7 @@ print "bar". The third will not trigger because it's a duplicate of the
|
|||||||
first "foo".
|
first "foo".
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
.B $DefaultColor
|
.B $DefaultColor (STRING type)
|
||||||
This variable can be set to a string that has the form of three
|
This variable can be set to a string that has the form of three
|
||||||
space-separated numbers. Each number must be an integer from 0 to
|
space-separated numbers. Each number must be an integer from 0 to
|
||||||
255, or all three numbers must be -1. The default value of
|
255, or all three numbers must be -1. The default value of
|
||||||
@@ -2972,7 +2995,7 @@ Equivalent to \fByear(trigdate())\fR.
|
|||||||
.B $Tt (read-only, TIME type)
|
.B $Tt (read-only, TIME type)
|
||||||
Equivalent to \fBtrigtime()\fR.
|
Equivalent to \fBtrigtime()\fR.
|
||||||
.TP
|
.TP
|
||||||
.B $TimeSep
|
.B $TimeSep (STRING type)
|
||||||
This variable can be set only to ":" or ".". It holds the character
|
This variable can be set only to ":" or ".". It holds the character
|
||||||
used to separate portions of a time when \fBRemind\fR prints a TIME or
|
used to separate portions of a time when \fBRemind\fR prints a TIME or
|
||||||
DATETIME value.
|
DATETIME value.
|
||||||
@@ -3535,7 +3558,7 @@ clauses are \fInot\fR taken into account by this function.
|
|||||||
Returns a \fBSTRING\fR naming the compiled-in language supported by
|
Returns a \fBSTRING\fR naming the compiled-in language supported by
|
||||||
\fBRemind\fR. Remind used to support compiled-in support for other
|
\fBRemind\fR. Remind used to support compiled-in support for other
|
||||||
languages, but now all localization is done at run-time. As such,
|
languages, but now all localization is done at run-time. As such,
|
||||||
this function always returnes "English". However, the expression
|
this function always returns "English". However, the expression
|
||||||
\fB_("LANGID")\fR returns the two-character ISO 639 language code
|
\fB_("LANGID")\fR returns the two-character ISO 639 language code
|
||||||
of any language pack in effect, assuming the language pack author has
|
of any language pack in effect, assuming the language pack author has
|
||||||
written the localization correctly!
|
written the localization correctly!
|
||||||
@@ -5742,13 +5765,48 @@ function, as follows:
|
|||||||
By using \fBTRANSLATE\fR and \fB_\fR judiciously, you can make your
|
By using \fBTRANSLATE\fR and \fB_\fR judiciously, you can make your
|
||||||
reminder files easy to translate.
|
reminder files easy to translate.
|
||||||
.PP
|
.PP
|
||||||
\fBTRANSLATE\fR has three additional forms: If it is followed
|
\fBTRANSLATE\fR has four additional forms: If it is followed
|
||||||
by \fIone\fR quoted string instead of two, then \fBRemind\fR deletes the
|
by \fIone\fR quoted string instead of two, then \fBRemind\fR deletes the
|
||||||
translation table entry for that string. If it is followed by
|
translation table entry for that string. If it is followed by
|
||||||
the keyword \fBDUMP\fR, then \fBRemind\fR dumps all translation table entries
|
the keyword \fBDUMP\fR, then \fBRemind\fR dumps all translation table entries
|
||||||
to standard output. And if it is followed by \fBCLEAR\fR, then
|
to standard output. And if it is followed by \fBCLEAR\fR, then
|
||||||
\fBRemind\fR deletes all of the translation table entries.
|
\fBRemind\fR deletes all of the translation table entries.
|
||||||
.PP
|
.PP
|
||||||
|
The fourth form, \fBTRANSLATE GENERATE\fR, dumps all of the
|
||||||
|
strings that can be localized (as a series of TRANSLATE commands) to
|
||||||
|
standard output. Strings that are already localized are output
|
||||||
|
with their localization; strings that are not localized are
|
||||||
|
output as:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
TRANSLATE "untranslated" ""
|
||||||
|
.nf
|
||||||
|
.PP
|
||||||
|
If you want to add a new language, you can obtain a skeleton translation
|
||||||
|
file by running:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
echo "TRANSLATE GENERATE" | remind -h - > /tmp/skeleton.rem
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
If you have an existing language file that is missing some translations,
|
||||||
|
you can update it by running:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
(echo INCLUDE mylang.rem; echo TRANSLATE GENERATE) | \\
|
||||||
|
remind -h - > /tmp/mylang-update.rem
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
and then editing \fBmylang-update.rem\fR to add in the missing translations.
|
||||||
|
.PP
|
||||||
|
If you have some reminder scripts that use the \fB_()\fR built-in function
|
||||||
|
or \fB%(...)\fR substitution sequence, you can generate a list of needed
|
||||||
|
TRANSLATE commands by running:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
remind -q -n -dq myscript.rem 2>&1 | grep ^TRANSLATE | sort | uniq
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
Note that if you \fBSET\fR various translation-related system
|
Note that if you \fBSET\fR various translation-related system
|
||||||
variables such as \fB$Monday\fR, \fB$December\fR, \fB$Ago\fR, etc,
|
variables such as \fB$Monday\fR, \fB$December\fR, \fB$Ago\fR, etc,
|
||||||
then \fBRemind\fR \fIalso\fR makes a corresponding translation
|
then \fBRemind\fR \fIalso\fR makes a corresponding translation
|
||||||
|
|||||||
@@ -512,7 +512,7 @@ asynchronous status messages.
|
|||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
TkRemind was written by Dianne Skoll <dianne@skoll.ca>
|
TkRemind was written by Dianne Skoll <dianne@skoll.ca>
|
||||||
|
|
||||||
\fBTkRemind\fR is Copyright 1996-2024 by Dianne Skoll.
|
\fBTkRemind\fR is Copyright (C) 1996-2025 by Dianne Skoll.
|
||||||
|
|
||||||
.SH FILES
|
.SH FILES
|
||||||
|
|
||||||
|
|||||||
@@ -20,18 +20,20 @@ my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mond
|
|||||||
my $TIDY_PROGNAME = $0;
|
my $TIDY_PROGNAME = $0;
|
||||||
$TIDY_PROGNAME =~ s|^.*/||;
|
$TIDY_PROGNAME =~ s|^.*/||;
|
||||||
|
|
||||||
# rem2html -- convert the output of "remind -pp" to HTML
|
# rem2html -- convert the output of "remind -pp" or "remind -ppp" to HTML
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
rem2html - Convert the output of "remind -pp" to HTML
|
rem2html - Convert the output of "remind -pp" or "remind -ppp" to HTML
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
remind -ppp [remind_options] file | rem2html [options]
|
||||||
|
|
||||||
remind -pp [remind_options] file | rem2html [options]
|
remind -pp [remind_options] file | rem2html [options]
|
||||||
|
|
||||||
You can also use the old interchange format as below, but the -pp
|
You can also use the old interchange format as below, but the -pp
|
||||||
version is preferred.
|
or -ppp versions are preferred.
|
||||||
|
|
||||||
remind -p [remind_options] file | rem2html [options]
|
remind -p [remind_options] file | rem2html [options]
|
||||||
|
|
||||||
@@ -155,9 +157,10 @@ sub usage
|
|||||||
$exit_status = 1;
|
$exit_status = 1;
|
||||||
}
|
}
|
||||||
print STDERR <<"EOM";
|
print STDERR <<"EOM";
|
||||||
$TIDY_PROGNAME: Produce an HTML calendar from the output of "remind -pp"
|
$TIDY_PROGNAME: Produce an HTML calendar from the output of "remind -pp[p]"
|
||||||
|
|
||||||
Usage: remind -pp [remind_options] file | rem2html [options]
|
Usage: remind -pp [remind_options] file | rem2html [options]
|
||||||
|
or: remind -ppp [remind_options] file | rem2html [options]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
@@ -303,6 +306,9 @@ sub parse_input
|
|||||||
my $found_data = 0;
|
my $found_data = 0;
|
||||||
while(<STDIN>) {
|
while(<STDIN>) {
|
||||||
chomp;
|
chomp;
|
||||||
|
if ($_ eq '[') {
|
||||||
|
return parse_input_ppp();
|
||||||
|
}
|
||||||
if (/# translations/) {
|
if (/# translations/) {
|
||||||
slurp_translations();
|
slurp_translations();
|
||||||
next;
|
next;
|
||||||
@@ -418,6 +424,159 @@ sub parse_input
|
|||||||
return $found_data;
|
return $found_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub parse_input_ppp
|
||||||
|
{
|
||||||
|
my $json = "[\n";
|
||||||
|
my $curlies = 0;
|
||||||
|
my $did_a_calendar = 0;
|
||||||
|
while(<STDIN>) {
|
||||||
|
$json .= $_;
|
||||||
|
$curlies++ if ($_ eq "{\n");
|
||||||
|
$curlies-- if ($_ eq "}\n");
|
||||||
|
$curlies-- if ($_ eq "},\n");
|
||||||
|
if ($_ eq "]\n" && !$curlies) {
|
||||||
|
my $array;
|
||||||
|
eval {
|
||||||
|
if ($Options{utf8}) {
|
||||||
|
$array = decode_json(encode('UTF-8', $json, Encode::FB_DEFAULT));
|
||||||
|
} else {
|
||||||
|
$array = decode_json($json);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (!$array) {
|
||||||
|
print STDERR "Could not decode JSON.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (!$did_a_calendar) {
|
||||||
|
start_output();
|
||||||
|
$did_a_calendar = 1;
|
||||||
|
}
|
||||||
|
if (exists($array->[0]{caltype}) &&
|
||||||
|
$array->[0]{caltype} eq 'weekly') {
|
||||||
|
emit_ppp_calendars($array, 'weekly');
|
||||||
|
} else {
|
||||||
|
emit_ppp_calendars($array, 'monthly');
|
||||||
|
}
|
||||||
|
$json = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$did_a_calendar) {
|
||||||
|
print STDERR "$TIDY_PROGNAME: Could not find any calendar data on STDIN.\n";
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
end_output();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub emit_ppp_calendars
|
||||||
|
{
|
||||||
|
my ($array, $type) = @_;
|
||||||
|
foreach my $cal (@$array) {
|
||||||
|
emit_one_ppp_calendar($cal, $type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub emit_one_ppp_calendar
|
||||||
|
{
|
||||||
|
my ($c, $type) = @_;
|
||||||
|
|
||||||
|
undef $days;
|
||||||
|
undef $shades;
|
||||||
|
undef $moons;
|
||||||
|
undef $classes;
|
||||||
|
undef $weeks;
|
||||||
|
|
||||||
|
my $dates_to_day_index;
|
||||||
|
my $cols_to_date_info;
|
||||||
|
if (exists($c->{translations})) {
|
||||||
|
$Translations = $c->{translations};
|
||||||
|
}
|
||||||
|
if ($type eq 'monthly') {
|
||||||
|
$Month = $c->{monthname};
|
||||||
|
$Year = $c->{year};
|
||||||
|
$Numdays = $c->{daysinmonth};
|
||||||
|
$Firstwkday = $c->{firstwkday};
|
||||||
|
$Mondayfirst = $c->{mondayfirst};
|
||||||
|
@Daynames = @{$c->{daynames}};
|
||||||
|
$Prevmon = $c->{prevmonthname};
|
||||||
|
$Prevlen = $c->{daysinprevmonth};
|
||||||
|
$Nextmon = $c->{nextmonthname};
|
||||||
|
$Nextlen = $c->{daysinnextmonth};
|
||||||
|
} else {
|
||||||
|
my $idx = 0;
|
||||||
|
$Numdays = 7;
|
||||||
|
foreach my $date (@{$c->{dates}}) {
|
||||||
|
$Daynames[$idx] = $date->{dayname};
|
||||||
|
$dates_to_day_index->{$date->{date}} = $idx;
|
||||||
|
$cols_to_date_info->[$idx] = $date;
|
||||||
|
$idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $class;
|
||||||
|
if ($Options{nostyle}) {
|
||||||
|
$class = '';
|
||||||
|
} else {
|
||||||
|
$class = ' class="rem-entry"';
|
||||||
|
}
|
||||||
|
foreach my $obj (@{$c->{entries}}) {
|
||||||
|
next unless ($obj->{date} =~ /^(\d+)-(\d+)-(\d+)$/);
|
||||||
|
my $y = $1;
|
||||||
|
my $m = $2;
|
||||||
|
my $d = $3;
|
||||||
|
my $col;
|
||||||
|
if ($type eq 'weekly') {
|
||||||
|
$col = $dates_to_day_index->{$obj->{date}};
|
||||||
|
} else {
|
||||||
|
$col = $d;
|
||||||
|
$col =~ s/^0+//;
|
||||||
|
}
|
||||||
|
my $special = $obj->{passthru} || '*';
|
||||||
|
my $tag = $obj->{tags} || '*';
|
||||||
|
my $duration = $obj->{duration} || '*';
|
||||||
|
my $time = $obj->{time} || '*';
|
||||||
|
my $body = $obj->{body};
|
||||||
|
$special = uc($special);
|
||||||
|
if ($special eq 'HTML') {
|
||||||
|
push(@{$days->[$col]}, $body);
|
||||||
|
} elsif ($special eq 'HTMLCLASS') {
|
||||||
|
$classes->[$col] = $body;
|
||||||
|
} elsif ($special eq 'WEEK') {
|
||||||
|
$body =~ s/^\s+//;
|
||||||
|
$body =~ s/\s+$//;
|
||||||
|
$weeks->{$col} = $body;
|
||||||
|
} elsif ($special eq 'MOON') {
|
||||||
|
if ($body =~ /(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) {
|
||||||
|
my ($phase, $moonsize, $fontsize, $msg) = ($1, $2, $3, $4);
|
||||||
|
$moons->[$col]->{'phase'} = $phase;
|
||||||
|
$moons->[$col]->{'msg'} = $msg;
|
||||||
|
} elsif ($body =~ /(\S+)/) {
|
||||||
|
$moons->[$col]->{'phase'} = $1;
|
||||||
|
$moons->[$col]->{'msg'} = '';
|
||||||
|
}
|
||||||
|
} elsif ($special eq 'SHADE') {
|
||||||
|
if ($body =~ /(\d+)\s+(\d+)\s+(\d+)/) {
|
||||||
|
$shades->[$col] = sprintf("#%02X%02X%02X",
|
||||||
|
($1 % 256), ($2 % 256), ($3 % 256));
|
||||||
|
} elsif ($body =~ /(\d+)/) {
|
||||||
|
$shades->[$col] = sprintf("#%02X%02X%02X",
|
||||||
|
($1 % 256), ($1 % 256), ($1 % 256));
|
||||||
|
}
|
||||||
|
} elsif ($special eq 'COLOR' || $special eq 'COLOUR') {
|
||||||
|
if ($body =~ /(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/s) {
|
||||||
|
my($r, $g, $b, $text) = ($1, $2, $3, $4);
|
||||||
|
my $color = sprintf("style=\"color: #%02X%02X%02X;\"",
|
||||||
|
$r % 256, $g % 256, $b % 256);
|
||||||
|
push(@{$days->[$col]}, "<p$class $color>" . fix_whitespace(escape_html($text)) . '</p>');
|
||||||
|
}
|
||||||
|
} elsif ($special eq '*') {
|
||||||
|
push(@{$days->[$col]}, "<p$class>" . fix_whitespace(escape_html($body)) . '</p>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output_calendar($type, $cols_to_date_info);
|
||||||
|
}
|
||||||
|
|
||||||
sub fix_whitespace
|
sub fix_whitespace
|
||||||
{
|
{
|
||||||
my ($text) = @_;
|
my ($text) = @_;
|
||||||
@@ -523,23 +682,33 @@ sub small_calendar
|
|||||||
sub output_calendar
|
sub output_calendar
|
||||||
{
|
{
|
||||||
# Which column is 1st of month in?
|
# Which column is 1st of month in?
|
||||||
my $first_col = $Firstwkday;
|
my ($type, $date_info) = @_;
|
||||||
if ($Mondayfirst) {
|
|
||||||
$first_col--;
|
|
||||||
if ($first_col < 0) {
|
|
||||||
$first_col = 6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Last column
|
my ($first_col, $last_col, $number_of_rows);
|
||||||
my $last_col = ($first_col + $Numdays - 1) % 7;
|
|
||||||
|
|
||||||
# Figure out how many rows
|
if ($type eq 'monthly') {
|
||||||
my $number_of_rows = int(($first_col + $Numdays ) / 7 + 0.999);
|
$first_col = $Firstwkday;
|
||||||
|
if ($Mondayfirst) {
|
||||||
|
$first_col--;
|
||||||
|
if ($first_col < 0) {
|
||||||
|
$first_col = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Add a row for small calendars if necessary
|
# Last column
|
||||||
if ($first_col == 0 && $last_col == 6) {
|
$last_col = ($first_col + $Numdays - 1) % 7;
|
||||||
|
|
||||||
|
# Figure out how many rows
|
||||||
|
$number_of_rows = int(($first_col + $Numdays ) / 7 + 0.999);
|
||||||
|
|
||||||
|
# Add a row for small calendars if necessary
|
||||||
|
if ($first_col == 0 && $last_col == 6) {
|
||||||
$number_of_rows++;
|
$number_of_rows++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$first_col = 0;
|
||||||
|
$last_col = 6;
|
||||||
|
$number_of_rows = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Start the table
|
# Start the table
|
||||||
@@ -550,22 +719,36 @@ sub output_calendar
|
|||||||
print '<tr>';
|
print '<tr>';
|
||||||
$class = ' width="14%"';
|
$class = ' width="14%"';
|
||||||
} else {
|
} else {
|
||||||
print '<table class="rem-cal"><caption class="rem-cal-caption">' .
|
if ($type eq 'monthly') {
|
||||||
$Month . ' ' . $Year . '</caption>' . "\n";
|
print '<table class="rem-cal"><caption class="rem-cal-caption">' .
|
||||||
|
$Month . ' ' . $Year . '</caption>' . "\n";
|
||||||
|
} else {
|
||||||
|
print '<table class="rem-cal">' . "\n";
|
||||||
|
}
|
||||||
print '<tr class="rem-cal-hdr-row">';
|
print '<tr class="rem-cal-hdr-row">';
|
||||||
$class = ' class="rem-cal-hdr"';
|
$class = ' class="rem-cal-hdr"';
|
||||||
}
|
}
|
||||||
if (!$Mondayfirst) {
|
if ($type eq 'monthly') {
|
||||||
print "<th$class>" . $Daynames[0] . '</th>';
|
if (!$Mondayfirst) {
|
||||||
|
print "<th$class>" . $Daynames[0] . '</th>';
|
||||||
|
}
|
||||||
|
for (my $i=1; $i<7; $i++) {
|
||||||
|
print "<th$class>" . $Daynames[$i] . '</th>';
|
||||||
|
}
|
||||||
|
if ($Mondayfirst) {
|
||||||
|
print "<th$class>" . $Daynames[0] . '</th>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (my $i=0; $i<7; $i++) {
|
||||||
|
my $inf = $date_info->[$i];
|
||||||
|
print "<th$class>" . $inf->{dayname} . "<br>" .
|
||||||
|
$inf->{day} . ' ' .
|
||||||
|
$inf->{month} . ' ' .
|
||||||
|
$inf->{year} . '</th>';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (my $i=1; $i<7; $i++) {
|
|
||||||
print "<th$class>" . $Daynames[$i] . '</th>';
|
|
||||||
}
|
|
||||||
if ($Mondayfirst) {
|
|
||||||
print "<th$class>" . $Daynames[0] . '</th>';
|
|
||||||
}
|
|
||||||
print "</tr>\n";
|
|
||||||
|
|
||||||
|
print "</tr>\n";
|
||||||
# Start the calendar rows
|
# Start the calendar rows
|
||||||
my $col = 0;
|
my $col = 0;
|
||||||
if ($Options{nostyle}) {
|
if ($Options{nostyle}) {
|
||||||
@@ -573,16 +756,18 @@ sub output_calendar
|
|||||||
} else {
|
} else {
|
||||||
print "<tr class=\"rem-cal-row rem-cal-row-$number_of_rows-rows\">\n";
|
print "<tr class=\"rem-cal-row rem-cal-row-$number_of_rows-rows\">\n";
|
||||||
}
|
}
|
||||||
if ($first_col > 0) {
|
if ($type eq 'monthly') {
|
||||||
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
if ($first_col > 0) {
|
||||||
($Firstwkday - $Prevlen + 35) % 7);
|
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
||||||
$col++;
|
($Firstwkday - $Prevlen + 35) % 7);
|
||||||
}
|
$col++;
|
||||||
|
}
|
||||||
|
|
||||||
if ($last_col == 6 && $first_col > 0) {
|
if ($last_col == 6 && $first_col > 0) {
|
||||||
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
||||||
($Firstwkday + $Numdays) % 7);
|
($Firstwkday + $Numdays) % 7);
|
||||||
$col++;
|
$col++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($Options{nostyle}) {
|
if ($Options{nostyle}) {
|
||||||
$class = ' width="14%"';
|
$class = ' width="14%"';
|
||||||
@@ -595,7 +780,7 @@ sub output_calendar
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (my $day=1; $day<=$Numdays; $day++) {
|
for (my $day=1; $day<=$Numdays; $day++) {
|
||||||
draw_day_cell($day, $number_of_rows);
|
draw_day_cell($day, $number_of_rows, $type);
|
||||||
$col++;
|
$col++;
|
||||||
if ($col == 7) {
|
if ($col == 7) {
|
||||||
$col = 0;
|
$col = 0;
|
||||||
@@ -610,32 +795,33 @@ sub output_calendar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($col) {
|
if ($type eq 'monthly') {
|
||||||
while ($col < 7) {
|
if ($col) {
|
||||||
if ($col == 5) {
|
while ($col < 7) {
|
||||||
if ($first_col == 0) {
|
if ($col == 5) {
|
||||||
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
if ($first_col == 0) {
|
||||||
($Firstwkday - $Prevlen + 35) % 7);
|
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
||||||
} else {
|
($Firstwkday - $Prevlen + 35) % 7);
|
||||||
print("<td$class> </td>\n");
|
} else {
|
||||||
}
|
print("<td$class> </td>\n");
|
||||||
} elsif ($col == 6) {
|
}
|
||||||
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
} elsif ($col == 6) {
|
||||||
($Firstwkday + $Numdays) % 7);
|
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
||||||
} else {
|
($Firstwkday + $Numdays) % 7);
|
||||||
print("<td$class> </td>\n");
|
} else {
|
||||||
}
|
print("<td$class> </td>\n");
|
||||||
$col++;
|
}
|
||||||
}
|
$col++;
|
||||||
print "</tr>\n";
|
}
|
||||||
}
|
print "</tr>\n";
|
||||||
|
}
|
||||||
|
|
||||||
# Add a row for small calendars if they were not yet done!
|
# Add a row for small calendars if they were not yet done!
|
||||||
if ($first_col == 0 && $last_col == 6) {
|
if ($first_col == 0 && $last_col == 6) {
|
||||||
if ($Options{nostyle}) {
|
if ($Options{nostyle}) {
|
||||||
print "<tr>\n";
|
print "<tr>\n";
|
||||||
} else {
|
} else {
|
||||||
print "<tr class=\"rem-cal-row rem-cal-row-$number_of_rows-rows\">\n";
|
print "<tr class=\"rem-cal-row rem-cal-row-$number_of_rows-rows\">\n";
|
||||||
}
|
}
|
||||||
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
||||||
($Firstwkday - $Prevlen + 35) % 7);
|
($Firstwkday - $Prevlen + 35) % 7);
|
||||||
@@ -645,14 +831,18 @@ sub output_calendar
|
|||||||
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
||||||
($Firstwkday + $Numdays) % 7);
|
($Firstwkday + $Numdays) % 7);
|
||||||
print("</tr>\n");
|
print("</tr>\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
# End the table
|
# End the table
|
||||||
print "</table>\n";
|
print "</table>\n";
|
||||||
|
if ($type eq 'weekly') {
|
||||||
|
print " <br />\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub draw_day_cell
|
sub draw_day_cell
|
||||||
{
|
{
|
||||||
my($day, $number_of_rows) = @_;
|
my($day, $number_of_rows, $type) = @_;
|
||||||
my $shade = $shades->[$day];
|
my $shade = $shades->[$day];
|
||||||
my $week = '';
|
my $week = '';
|
||||||
if (exists($weeks->{$day})) {
|
if (exists($weeks->{$day})) {
|
||||||
@@ -724,11 +914,20 @@ sub draw_day_cell
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Options{nostyle}) {
|
if ($type eq 'monthly') {
|
||||||
print "<div style=\"float: right\">$day$week</div>\n";
|
if ($Options{nostyle}) {
|
||||||
print "<p> </p>\n";
|
print "<div style=\"float: right\">$day$week</div>\n";
|
||||||
|
print "<p> </p>\n";
|
||||||
|
} else {
|
||||||
|
print "<div class=\"rem-daynumber\">$day$week</div>\n";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
print "<div class=\"rem-daynumber\">$day$week</div>\n";
|
if ($Options{nostyle}) {
|
||||||
|
print "<div style=\"float: right\">$week</div>\n";
|
||||||
|
print "<p> </p>\n";
|
||||||
|
} else {
|
||||||
|
print "<div class=\"rem-daynumber\">$week</div>\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($days->[$day]) {
|
if ($days->[$day]) {
|
||||||
print(join("\n", @{$days->[$day]}));
|
print(join("\n", @{$days->[$day]}));
|
||||||
@@ -768,7 +967,7 @@ while(1) {
|
|||||||
last if (!parse_input());
|
last if (!parse_input());
|
||||||
start_output() unless $found_something;
|
start_output() unless $found_something;
|
||||||
$found_something = 1;
|
$found_something = 1;
|
||||||
output_calendar();
|
output_calendar('monthly', undef);
|
||||||
}
|
}
|
||||||
if ($found_something) {
|
if ($found_something) {
|
||||||
end_output();
|
end_output();
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ my $settings = {
|
|||||||
ps => 0,
|
ps => 0,
|
||||||
eps => 0,
|
eps => 0,
|
||||||
verbose => 0,
|
verbose => 0,
|
||||||
|
|
||||||
|
weeks_per_page => 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
my $me = $0;
|
my $me = $0;
|
||||||
@@ -81,17 +83,18 @@ Usage: remind -pp [options] filename | $me [options] > out.pdf
|
|||||||
Options:
|
Options:
|
||||||
|
|
||||||
--landscape, -l Print in landscape orientation
|
--landscape, -l Print in landscape orientation
|
||||||
--small-calendars=N Choose location for small calendars
|
--small-calendars=N Location for small calendars (monthly calendars only)
|
||||||
--svg Output SVG instead of PDF
|
--svg Output SVG instead of PDF
|
||||||
--ps Output PostScript instead of PDF
|
--ps Output PostScript instead of PDF
|
||||||
--eps Output encapsulated 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 (monthly calendars only)
|
||||||
--fill-page, -e Fill the entire page
|
--fill-page, -e Fill the entire page (monthly calendars only)
|
||||||
--media=MEDIA, -mMEDIA Size for specified media
|
--media=MEDIA, -mMEDIA Size for specified media
|
||||||
--width=W, -wW Specify media width in 1/72nds of an inch
|
--width=W, -wW Specify media width in 1/72nds of an inch
|
||||||
--height=H, -hH Specify media height in 1/72nds of an inch
|
--height=H, -hH Specify media height in 1/72nds of an inch
|
||||||
--wrap, -y Make calendar fit in at most 5 rows
|
--wrap, -y Make calendar fit in 5 rows (monthly calendars only)
|
||||||
|
--weeks-per-page=N, -pN Number of weeks per page (weekly calendars only)
|
||||||
--title-font=FONT Specify font for calendar title
|
--title-font=FONT Specify font for calendar title
|
||||||
--header-font=FONT Specify font for weekday names
|
--header-font=FONT Specify font for weekday names
|
||||||
--daynum-font=FONT Specify font for day numbers
|
--daynum-font=FONT Specify font for day numbers
|
||||||
@@ -121,6 +124,7 @@ my $ret = GetOptions('landscape|l' => \$settings->{landscape},
|
|||||||
'ps' => \$settings->{ps},
|
'ps' => \$settings->{ps},
|
||||||
'eps' => \$settings->{eps},
|
'eps' => \$settings->{eps},
|
||||||
'fill-page|e' => \$settings->{fill_entire_page},
|
'fill-page|e' => \$settings->{fill_entire_page},
|
||||||
|
'weeks-per-page|p=i' => \$settings->{weeks_per_page},
|
||||||
'media|m=s' => \$settings->{media},
|
'media|m=s' => \$settings->{media},
|
||||||
'width|w=i' => \$settings->{width},
|
'width|w=i' => \$settings->{width},
|
||||||
'wrap|y' => \$settings->{wrap_calendar},
|
'wrap|y' => \$settings->{wrap_calendar},
|
||||||
@@ -153,6 +157,12 @@ if ($help) {
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($settings->{weeks_per_page} < 1) {
|
||||||
|
$settings->{weeks_per_page} = 1;}
|
||||||
|
elsif ($settings->{weeks_per_page} > 4) {
|
||||||
|
$settings->{weeks_per_page} = 4;
|
||||||
|
}
|
||||||
|
|
||||||
if ($settings->{width} <= 0 ||
|
if ($settings->{width} <= 0 ||
|
||||||
$settings->{height} <= 0) {
|
$settings->{height} <= 0) {
|
||||||
my $size = $media_to_size->{ucfirst($settings->{media})};
|
my $size = $media_to_size->{ucfirst($settings->{media})};
|
||||||
@@ -247,6 +257,7 @@ if ($settings->{ps} && $settings->{landscape}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
my $warned = 0;
|
my $warned = 0;
|
||||||
|
my $index = 0;
|
||||||
while(1) {
|
while(1) {
|
||||||
if ($settings->{ps}) {
|
if ($settings->{ps}) {
|
||||||
$surface->dsc_begin_page_setup();
|
$surface->dsc_begin_page_setup();
|
||||||
@@ -267,14 +278,8 @@ while(1) {
|
|||||||
}
|
}
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
if (($settings->{eps} || $settings->{svg}) && $done_one) {
|
$index++;
|
||||||
if (!$warned) {
|
$obj->render($cr, $settings, $index, -1);
|
||||||
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);
|
|
||||||
$done_one = 1;
|
$done_one = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,7 +397,7 @@ month. Possible values for I<n> are:
|
|||||||
|
|
||||||
=item Z<>0
|
=item Z<>0
|
||||||
|
|
||||||
Do not draw any small calendares
|
Do not draw any small calendars
|
||||||
|
|
||||||
=item Z<>1
|
=item Z<>1
|
||||||
|
|
||||||
@@ -521,6 +526,11 @@ first row of the calendar, and adjust the small calendar positions
|
|||||||
as needed. This results in a calendar that only requires 5 rows, but
|
as needed. This results in a calendar that only requires 5 rows, but
|
||||||
with the last day or two appearing in the I<first> row.
|
with the last day or two appearing in the I<first> row.
|
||||||
|
|
||||||
|
=item --weeks-per-page=I<n>, -pI<n>.
|
||||||
|
|
||||||
|
This option is only used for weekly calendars. I<n> is the number of weeks
|
||||||
|
to print per page; it is an integer that can range from 1 to 4.
|
||||||
|
|
||||||
=item --verbose, -v
|
=item --verbose, -v
|
||||||
|
|
||||||
Print (on STDERR) the name of the month and year for each month that
|
Print (on STDERR) the name of the month and year for each month that
|
||||||
@@ -563,6 +573,12 @@ it is syntactically correct. If you use invalid Pango markup, the
|
|||||||
Pango library will print a warning and B<rem2pdf> will not render any
|
Pango library will print a warning and B<rem2pdf> will not render any
|
||||||
output for the invalid reminder.
|
output for the invalid reminder.
|
||||||
|
|
||||||
|
=head1 WEEKLY CALENDARS
|
||||||
|
|
||||||
|
B<rem2pdf> will produce weekly calendars if you invoke B<remind> with the
|
||||||
|
B<-p+> option. the B<--weeks-per-page> option specifies how many
|
||||||
|
weeks' worth of reminders to print per page, and can range from 1 to 4.
|
||||||
|
|
||||||
=head1 ABSOLUTELY-POSITIONED TEXT
|
=head1 ABSOLUTELY-POSITIONED TEXT
|
||||||
|
|
||||||
If your B<PANGO> special reminder starts with C<@I<x>,I<y>> where I<x>
|
If your B<PANGO> special reminder starts with C<@I<x>,I<y>> where I<x>
|
||||||
|
|||||||
@@ -62,6 +62,9 @@ sub create_from_hash
|
|||||||
{
|
{
|
||||||
my ($class, $hash, $specials_accepted) = @_;
|
my ($class, $hash, $specials_accepted) = @_;
|
||||||
|
|
||||||
|
if (exists($hash->{caltype}) && ($hash->{caltype} eq 'weekly')) {
|
||||||
|
return Remind::PDF::Weekly->create_from_hash($hash, $specials_accepted);
|
||||||
|
}
|
||||||
bless $hash, $class;
|
bless $hash, $class;
|
||||||
|
|
||||||
my $filtered_entries = [];
|
my $filtered_entries = [];
|
||||||
@@ -463,8 +466,16 @@ C<rem2pdf> for the contents of C<$settings>
|
|||||||
=cut
|
=cut
|
||||||
sub render
|
sub render
|
||||||
{
|
{
|
||||||
my ($self, $cr, $settings) = @_;
|
my ($self, $cr, $settings, $index, $total) = @_;
|
||||||
|
|
||||||
|
if ($settings->{svg} || $settings->{eps}) {
|
||||||
|
if ($index > 1) {
|
||||||
|
if ($index == 2) {
|
||||||
|
print STDERR "WARNING: --svg/--eps can only output one page; ignoring subsequent\nmonths in a multi-month calendar.\n";
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
$self->setup_daymap($settings);
|
$self->setup_daymap($settings);
|
||||||
$self->{horiz_lines} = [];
|
$self->{horiz_lines} = [];
|
||||||
$cr->set_line_cap('square');
|
$cr->set_line_cap('square');
|
||||||
@@ -525,7 +536,7 @@ sub render
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($settings->{verbose}) {
|
if ($settings->{verbose}) {
|
||||||
print STDERR "remdp2f: Rendered " . $self->{monthname} . ' ' . $self->{year} . "\n";
|
print STDERR "rem2pdf: Rendered " . $self->{monthname} . ' ' . $self->{year} . "\n";
|
||||||
}
|
}
|
||||||
# Done this page
|
# Done this page
|
||||||
$cr->show_page();
|
$cr->show_page();
|
||||||
@@ -1008,20 +1019,260 @@ 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 $index = 0;
|
||||||
my $warned = 0;
|
my $total = scalar(@{$self->{entries}});
|
||||||
|
|
||||||
foreach my $e (@{$self->{entries}}) {
|
foreach my $e (@{$self->{entries}}) {
|
||||||
if ($settings->{svg} && $done) {
|
$index++;
|
||||||
if (!$warned) {
|
$e->render($cr, $settings, $index, $total);
|
||||||
print STDERR "WARNING: --svg can only output one page; ignoring subsequent\nmonths in a multi-month calendar.\n";
|
}
|
||||||
$warned = 1;
|
}
|
||||||
|
|
||||||
|
package Remind::PDF::Weekly;
|
||||||
|
use base qw(Remind::PDF);
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Remind::PDF::Weekly - render a weekly calendar
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub render
|
||||||
|
{
|
||||||
|
my ($self, $cr, $settings, $index, $total) = @_;
|
||||||
|
if ($settings->{svg} || $settings->{eps}) {
|
||||||
|
if ($index > $settings->{weeks_per_page}) {
|
||||||
|
if ($index == $settings->{weeks_per_page}+1) {
|
||||||
|
print STDERR "WARNING: --svg/--eps can only output one page; ignoring subsequent pages.\n";
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings->{numbers_on_left} = 1;
|
||||||
|
# Set up bounding box
|
||||||
|
if ($settings->{weeks_per_page} == 1) {
|
||||||
|
$self->{bounding_box} = [
|
||||||
|
$settings->{margin_left},
|
||||||
|
$settings->{margin_top},
|
||||||
|
$settings->{width} - $settings->{margin_right},
|
||||||
|
$settings->{height} - $settings->{margin_bottom}]
|
||||||
|
} else {
|
||||||
|
my $total_height = $settings->{height} - $settings->{margin_top} - $settings->{margin_bottom};
|
||||||
|
my $week_height = $total_height / $settings->{weeks_per_page};
|
||||||
|
my $top_offset = (($index-1) % $settings->{weeks_per_page}) * $week_height;
|
||||||
|
my $bot_offset = $top_offset + $week_height;
|
||||||
|
$self->{bounding_box} =
|
||||||
|
$self->{bounding_box} = [
|
||||||
|
$settings->{margin_left},
|
||||||
|
$settings->{margin_top} + $top_offset,
|
||||||
|
$settings->{width} - $settings->{margin_right},
|
||||||
|
$settings->{margin_top} + $bot_offset];
|
||||||
|
if ($index != 1) {
|
||||||
|
$self->{bounding_box}[1] += 0.25 * $settings->{margin_top};
|
||||||
|
}
|
||||||
|
if ($index != $settings->{weeks_per_page}) {
|
||||||
|
$self->{bounding_box}[3] -= 0.25 * $settings->{margin_top};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$self->draw_headings($cr, $settings);
|
||||||
|
for (my $i=0; $i<7; $i++) {
|
||||||
|
$self->draw_entries($cr, $settings, $i);
|
||||||
|
}
|
||||||
|
$self->draw_lines($cr, $settings);
|
||||||
|
if ($index == $total || ($index % $settings->{weeks_per_page}) == 0) {
|
||||||
|
$cr->show_page();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($settings->{verbose}) {
|
||||||
|
print STDERR "rem2pdf: Rendered " . $self->{dates}->[0]->{date} . " to " . $self->{dates}->[6]->{date} . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub draw_headings
|
||||||
|
{
|
||||||
|
my ($self, $cr, $settings) = @_;
|
||||||
|
my $ymax = 0;
|
||||||
|
my $cell = ($settings->{width} - $settings->{margin_left} - $settings->{margin_right})/7;
|
||||||
|
|
||||||
|
for (my $i=0; $i<7; $i++) {
|
||||||
|
my $date = $self->{dates}[$i];
|
||||||
|
my $month = $date->{month};
|
||||||
|
my $year = $date->{year};
|
||||||
|
my $day = $date->{day};
|
||||||
|
my $dayname = $date->{dayname};
|
||||||
|
|
||||||
|
my $layout = Pango::Cairo::create_layout($cr);
|
||||||
|
$layout->set_text(Encode::decode('UTF-8', $dayname));
|
||||||
|
|
||||||
|
my $desc = Pango::FontDescription->from_string($settings->{header_font} . ' ' . $settings->{header_size} . 'px');
|
||||||
|
$layout->set_font_description($desc);
|
||||||
|
|
||||||
|
my ($wid, $h) = $layout->get_pixel_size();
|
||||||
|
$cr->save;
|
||||||
|
$cr->move_to($settings->{margin_left} + $i * $cell + $cell/2 - $wid/2, $self->{bounding_box}[1]);
|
||||||
|
Pango::Cairo::show_layout($cr, $layout);
|
||||||
|
$cr->restore();
|
||||||
|
|
||||||
|
$layout = Pango::Cairo::create_layout($cr);
|
||||||
|
$layout->set_text(Encode::decode('UTF-8', $day . " " . $month . " " . $year));
|
||||||
|
my $es = $settings->{entry_size};
|
||||||
|
if ($es > 8) {
|
||||||
|
$es = 8;
|
||||||
|
}
|
||||||
|
$desc = Pango::FontDescription->from_string($settings->{entry_font} . ' ' . $es . 'px');
|
||||||
|
$layout->set_font_description($desc);
|
||||||
|
|
||||||
|
my ($wid2, $h2) = $layout->get_pixel_size();
|
||||||
|
$cr->save;
|
||||||
|
$cr->move_to($settings->{margin_left} + $i * $cell + $cell/2 - $wid2/2, $self->{bounding_box}[1] + $h);
|
||||||
|
Pango::Cairo::show_layout($cr, $layout);
|
||||||
|
$cr->restore();
|
||||||
|
|
||||||
|
if ($h + $h2 > $ymax) {
|
||||||
|
$ymax = $h + $h2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$self->{heading_bottom_y} = $ymax + $self->{bounding_box}[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
sub draw_entries
|
||||||
|
{
|
||||||
|
my ($self, $cr, $settings, $i) = @_;
|
||||||
|
|
||||||
|
my $cell = ($settings->{width} - $settings->{margin_left} - $settings->{margin_right})/7;
|
||||||
|
|
||||||
|
# Coordinates of box from line-to-line
|
||||||
|
my $l2l_box = [$i * $cell + $settings->{margin_left},
|
||||||
|
$self->{heading_bottom_y},
|
||||||
|
($i+1) * $cell + $settings->{margin_left},
|
||||||
|
$self->{bounding_box}[3]];
|
||||||
|
|
||||||
|
# Coordinates of drawing-space box
|
||||||
|
my $box = [$l2l_box->[0] + $settings->{border_size},
|
||||||
|
$l2l_box->[1] + $settings->{border_size},
|
||||||
|
$l2l_box->[2] - $settings->{border_size},
|
||||||
|
$l2l_box->[3] - $settings->{border_size}];
|
||||||
|
|
||||||
|
$self->{l2l_box} = $l2l_box;
|
||||||
|
$self->{box} = $box;
|
||||||
|
|
||||||
|
# Do shading, if any
|
||||||
|
my $shade = $self->find_last_special('shade', $self->{entries}->[$i]);
|
||||||
|
if ($shade) {
|
||||||
|
$cr->save;
|
||||||
|
$cr->set_source_rgb($shade->{r} / 255,
|
||||||
|
$shade->{g} / 255,
|
||||||
|
$shade->{b} / 255);
|
||||||
|
$cr->rectangle($l2l_box->[0], $l2l_box->[1],
|
||||||
|
$l2l_box->[2] - $l2l_box->[0],
|
||||||
|
$l2l_box->[3] - $l2l_box->[1]);
|
||||||
|
$cr->fill();
|
||||||
|
$cr->restore;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the "day number" size to leave room for moon and week specials
|
||||||
|
my $layout = Pango::Cairo::create_layout($cr);
|
||||||
|
$layout->set_text("31");
|
||||||
|
my $desc = Pango::FontDescription->from_string($settings->{daynum_font} . ' ' . $settings->{daynum_size} . 'px');
|
||||||
|
|
||||||
|
$layout->set_font_description($desc);
|
||||||
|
my ($wid, $h) = $layout->get_pixel_size();
|
||||||
|
|
||||||
|
my $so_far = $box->[1] + $h + $settings->{border_size};
|
||||||
|
|
||||||
|
my $box_height = $box->[3] - $box->[1];
|
||||||
|
my $done = 0;
|
||||||
|
foreach my $entry (@{$self->{entries}->[$i]}) {
|
||||||
|
# Moon and week should not adjust height
|
||||||
|
if ($entry->isa('Remind::PDF::Entry::moon') ||
|
||||||
|
$entry->isa('Remind::PDF::Entry::week')) {
|
||||||
|
$entry->render($self, $cr, $settings, $box->[1], $i, $i, $box_height);
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# An absolutely-positioned Pango markup should not adjust height
|
||||||
|
# either
|
||||||
|
if ($entry->isa('Remind::PDF::Entry::pango') &&
|
||||||
|
defined($entry->{atx}) && defined($entry->{aty})) {
|
||||||
|
$entry->render($self, $cr, $settings, $box->[1], $i, $i, $box_height);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Shade is done already
|
||||||
|
if ($entry->isa('Remind::PDF::Entry::shade')) {
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
if ($done) {
|
||||||
|
$so_far += $settings->{border_size};
|
||||||
|
}
|
||||||
$done = 1;
|
$done = 1;
|
||||||
$e->render($cr, $settings);
|
my $h2 = $entry->render($self, $cr, $settings, $so_far, $i, $i, $box_height);
|
||||||
|
$so_far += $h2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub col_box_coordinates
|
||||||
|
{
|
||||||
|
|
||||||
|
my ($self, $so_far, $col, $height, $settings) = @_;
|
||||||
|
return (@{$self->{l2l_box}});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sub draw_lines
|
||||||
|
{
|
||||||
|
my ($self, $cr, $settings) = @_;
|
||||||
|
|
||||||
|
# Top horizonal line
|
||||||
|
$cr->move_to($self->{bounding_box}[0], $self->{bounding_box}[1]);
|
||||||
|
$cr->line_to($self->{bounding_box}[2], $self->{bounding_box}[1]);
|
||||||
|
$cr->stroke();
|
||||||
|
|
||||||
|
# Horizontal line below headings
|
||||||
|
$cr->move_to($self->{bounding_box}[0], $self->{heading_bottom_y});
|
||||||
|
$cr->line_to($self->{bounding_box}[2], $self->{heading_bottom_y});
|
||||||
|
$cr->stroke();
|
||||||
|
|
||||||
|
# Bottom horizontal line
|
||||||
|
$cr->move_to($self->{bounding_box}[0], $self->{bounding_box}[3]);
|
||||||
|
$cr->line_to($self->{bounding_box}[2], $self->{bounding_box}[3]);
|
||||||
|
$cr->stroke();
|
||||||
|
|
||||||
|
# Vertical lines
|
||||||
|
my $w = ($settings->{width} - $settings->{margin_left} - $settings->{margin_right})/7;
|
||||||
|
for (my $i=0; $i<=7; $i++) {
|
||||||
|
my $x = $settings->{margin_left} + ($i * $w);
|
||||||
|
$cr->move_to($x, $self->{bounding_box}[1]);
|
||||||
|
$cr->line_to($x, $self->{bounding_box}[3]);
|
||||||
|
$cr->stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub create_from_hash
|
||||||
|
{
|
||||||
|
my ($class, $hash, $specials_accepted) = @_;
|
||||||
|
bless $hash, $class;
|
||||||
|
|
||||||
|
my $filtered_entries = [];
|
||||||
|
my $date_to_index;
|
||||||
|
for (my $i=0; $i<7; $i++) {
|
||||||
|
$date_to_index->{$hash->{dates}[$i]->{date}} = $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (my $i=0; $i<7; $i++) {
|
||||||
|
$filtered_entries->[$i] = [];
|
||||||
|
}
|
||||||
|
foreach my $e (@{$hash->{entries}}) {
|
||||||
|
if ($hash->accept_special($e, $specials_accepted)) {
|
||||||
|
my $index = $date_to_index->{$e->{date}};
|
||||||
|
push(@{$filtered_entries->[$index]}, Remind::PDF::Entry->new_from_hash($e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$hash->{entries} = $filtered_entries;
|
||||||
|
return $hash;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
# A cheesy graphical front/back end for Remind using Tcl/Tk
|
# A cheesy graphical front/back end for Remind using Tcl/Tk
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2024 Dianne Skoll
|
# Copyright (C) 1992-2025 Dianne Skoll
|
||||||
#
|
#
|
||||||
#--------------------------------------------------------------
|
#--------------------------------------------------------------
|
||||||
|
|
||||||
@@ -798,7 +798,7 @@ proc EditOptions {} {
|
|||||||
pack $w.f -side top -expand 1 -fill both
|
pack $w.f -side top -expand 1 -fill both
|
||||||
pack $w.b -side top -expand 0 -fill x
|
pack $w.b -side top -expand 0 -fill x
|
||||||
|
|
||||||
label $w.ver -text "TkRemind version @VERSION@ on Tcl/Tk version [info tclversion] with Remind version $ver"
|
label $w.ver -text "TkRemind version @VERSION@ on Tcl/Tk version [info patchlevel] with Remind version $ver"
|
||||||
pack $w.ver -in $w.f -side top -expand 0 -fill x
|
pack $w.ver -in $w.f -side top -expand 0 -fill x
|
||||||
# Start iconified
|
# Start iconified
|
||||||
checkbutton $w.startIconified -text "Start up Iconified" \
|
checkbutton $w.startIconified -text "Start up Iconified" \
|
||||||
@@ -3086,7 +3086,7 @@ proc main {} {
|
|||||||
|
|
||||||
global AppendFile HighestTagSoFar DayNames
|
global AppendFile HighestTagSoFar DayNames
|
||||||
catch {
|
catch {
|
||||||
puts "\nTkRemind Copyright (C) 1996-2024 Dianne Skoll"
|
puts "\nTkRemind Copyright (C) 1996-2025 Dianne Skoll"
|
||||||
}
|
}
|
||||||
catch { SetFonts }
|
catch { SetFonts }
|
||||||
Initialize
|
Initialize
|
||||||
|
|||||||
@@ -31,9 +31,11 @@ REMINDSRCS= calendar.c dedupe.c dynbuf.c dorem.c dosubst.c expr.c \
|
|||||||
hbcal.c init.c main.c md5.c moon.c omit.c queue.c \
|
hbcal.c init.c main.c md5.c moon.c omit.c queue.c \
|
||||||
sort.c token.c trans.c trigger.c userfns.c utils.c var.c
|
sort.c token.c trans.c trigger.c userfns.c utils.c var.c
|
||||||
|
|
||||||
|
XLATSRC= xlat.c
|
||||||
|
|
||||||
REMINDHDRS=config.h custom.h dynbuf.h err.h globals.h hashtab.h \
|
REMINDHDRS=config.h custom.h dynbuf.h err.h globals.h hashtab.h \
|
||||||
md5.h protos.h rem2ps.h types.h version.h
|
md5.h protos.h rem2ps.h types.h version.h
|
||||||
REMINDOBJS= $(REMINDSRCS:.c=.o)
|
REMINDOBJS= $(REMINDSRCS:.c=.o) $(XLATSRC:.c=.o)
|
||||||
|
|
||||||
all: remind rem2ps
|
all: remind rem2ps
|
||||||
|
|
||||||
@@ -43,6 +45,13 @@ test: all
|
|||||||
.c.o:
|
.c.o:
|
||||||
@CC@ -c @CPPFLAGS@ @CFLAGS@ @DEFS@ $(CEXTRA) -DSYSDIR=$(datarootdir)/remind -I. -I$(srcdir) $<
|
@CC@ -c @CPPFLAGS@ @CFLAGS@ @DEFS@ $(CEXTRA) -DSYSDIR=$(datarootdir)/remind -I. -I$(srcdir) $<
|
||||||
|
|
||||||
|
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
|
||||||
|
@echo " NULL" >> xlat.c
|
||||||
|
@echo "};" >> xlat.c
|
||||||
|
|
||||||
$(REMINDOBJS): $(REMINDHDRS)
|
$(REMINDOBJS): $(REMINDHDRS)
|
||||||
|
|
||||||
rem2ps: rem2ps.o dynbuf.o json.o
|
rem2ps: rem2ps.o dynbuf.o json.o
|
||||||
@@ -80,7 +89,7 @@ install-stripped: install
|
|||||||
strip $(DESTDIR)$(bindir)/rem2ps || true
|
strip $(DESTDIR)$(bindir)/rem2ps || true
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *~ core *.bak $(PROGS)
|
rm -f *.o *~ core *.bak $(PROGS) $(XLATSRC)
|
||||||
|
|
||||||
clobber:
|
clobber:
|
||||||
rm -f *.o *~ remind rem2ps test.out core *.bak
|
rm -f *.o *~ remind rem2ps test.out core *.bak
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* The code for generating a calendar. */
|
/* The code for generating a calendar. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -274,6 +274,7 @@ static int ColToDay[7];
|
|||||||
static int ColSpaces;
|
static int ColSpaces;
|
||||||
|
|
||||||
static int DidAMonth;
|
static int DidAMonth;
|
||||||
|
static int DidAWeek;
|
||||||
static int DidADay;
|
static int DidADay;
|
||||||
|
|
||||||
static void ColorizeEntry(CalEntry const *e, int clamp);
|
static void ColorizeEntry(CalEntry const *e, int clamp);
|
||||||
@@ -498,7 +499,7 @@ get_month_abbrev(char const *mon)
|
|||||||
{
|
{
|
||||||
static char buf[80];
|
static char buf[80];
|
||||||
#ifndef REM_USE_WCHAR
|
#ifndef REM_USE_WCHAR
|
||||||
sprintf(buf, "%.3s", mon);
|
snprintf(buf, sizeof(buf), "%.3s", mon);
|
||||||
return buf;
|
return buf;
|
||||||
#else
|
#else
|
||||||
char *s;
|
char *s;
|
||||||
@@ -625,9 +626,9 @@ Colorize256(int r, int g, int b, int bg, int clamp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bg) {
|
if (bg) {
|
||||||
sprintf(buf, "\x1B[48;5;%dm", best);
|
snprintf(buf, sizeof(buf), "\x1B[48;5;%dm", best);
|
||||||
} else {
|
} else {
|
||||||
sprintf(buf, "\x1B[38;5;%dm", best);
|
snprintf(buf, sizeof(buf), "\x1B[38;5;%dm", best);
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
@@ -640,9 +641,9 @@ ColorizeTrue(int r, int g, int b, int bg, int clamp)
|
|||||||
ClampColor(&r, &g, &b);
|
ClampColor(&r, &g, &b);
|
||||||
}
|
}
|
||||||
if (bg) {
|
if (bg) {
|
||||||
sprintf(buf, "\x1B[48;2;%d;%d;%dm", r, g, b);
|
snprintf(buf, sizeof(buf), "\x1B[48;2;%d;%d;%dm", r, g, b);
|
||||||
} else {
|
} else {
|
||||||
sprintf(buf, "\x1B[38;2;%d;%d;%dm", r, g, b);
|
snprintf(buf, sizeof(buf), "\x1B[38;2;%d;%d;%dm", r, g, b);
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
@@ -834,12 +835,33 @@ void ProduceCalendar(void)
|
|||||||
WriteIntermediateCalLine();
|
WriteIntermediateCalLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (CalWeeks--)
|
DidAWeek = 0;
|
||||||
|
if (PsCal == PSCAL_LEVEL3) {
|
||||||
|
printf("[\n");
|
||||||
|
}
|
||||||
|
while (CalWeeks--) {
|
||||||
DoCalendarOneWeek(CalWeeks);
|
DoCalendarOneWeek(CalWeeks);
|
||||||
|
DidAWeek = 1;
|
||||||
|
}
|
||||||
|
if (PsCal == PSCAL_LEVEL3) {
|
||||||
|
printf("\n]\n");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SendTranslationTable(int pslevel)
|
||||||
|
{
|
||||||
|
if (pslevel < PSCAL_LEVEL3) {
|
||||||
|
printf("# translations\n");
|
||||||
|
}
|
||||||
|
DumpTranslationTable(stdout, 1);
|
||||||
|
if (pslevel < PSCAL_LEVEL3) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* DoCalendarOneWeek */
|
/* DoCalendarOneWeek */
|
||||||
@@ -870,9 +892,33 @@ static void DoCalendarOneWeek(int nleft)
|
|||||||
/* Output the entries */
|
/* Output the entries */
|
||||||
/* If it's "Simple Calendar" format, do it simply... */
|
/* If it's "Simple Calendar" format, do it simply... */
|
||||||
if (DoSimpleCalendar) {
|
if (DoSimpleCalendar) {
|
||||||
|
if (PsCal == PSCAL_LEVEL3) {
|
||||||
|
if (DidAWeek) {
|
||||||
|
printf(",\n");
|
||||||
|
}
|
||||||
|
printf("{\n\"caltype\":\"weekly\",");
|
||||||
|
if (!DidAWeek) {
|
||||||
|
printf("\"translations\":");
|
||||||
|
SendTranslationTable(PsCal);
|
||||||
|
printf(",");
|
||||||
|
}
|
||||||
|
printf("\"dates\":[");
|
||||||
|
for (i=0; i<7; i++) {
|
||||||
|
if (i != 0) {
|
||||||
|
printf(",");
|
||||||
|
}
|
||||||
|
FromDSE(OrigDse+i-wd, &y, &m, &d);
|
||||||
|
printf("{\"dayname\":\"%s\",\"date\":\"%04d-%02d-%02d\",\"year\":%d,\"month\":\"%s\",\"day\":%d}", get_day_name((OrigDse+i-wd)%7),y, m+1, d, y, get_month_name(m), d);
|
||||||
|
}
|
||||||
|
printf("],\"entries\":[");
|
||||||
|
}
|
||||||
|
DidADay = 0;
|
||||||
for (i=0; i<7; i++) {
|
for (i=0; i<7; i++) {
|
||||||
WriteSimpleEntries(i, OrigDse+i-wd);
|
WriteSimpleEntries(i, OrigDse+i-wd);
|
||||||
}
|
}
|
||||||
|
if (PsCal == PSCAL_LEVEL3) {
|
||||||
|
printf("\n]\n}");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -965,18 +1011,6 @@ static void DoCalendarOneWeek(int nleft)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
SendTranslationTable(int pslevel)
|
|
||||||
{
|
|
||||||
if (pslevel < PSCAL_LEVEL3) {
|
|
||||||
printf("# translations\n");
|
|
||||||
}
|
|
||||||
DumpTranslationTable(stdout, 1);
|
|
||||||
if (pslevel < PSCAL_LEVEL3) {
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* DoSimpleCalendarOneMonth */
|
/* DoSimpleCalendarOneMonth */
|
||||||
@@ -1030,6 +1064,7 @@ static void DoSimpleCalendarOneMonth(void)
|
|||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
} else {
|
} else {
|
||||||
|
PrintJSONKeyPairString("caltype", "monthly");
|
||||||
PrintJSONKeyPairString("monthname", get_month_name(m));
|
PrintJSONKeyPairString("monthname", get_month_name(m));
|
||||||
PrintJSONKeyPairInt("year", y);
|
PrintJSONKeyPairInt("year", y);
|
||||||
PrintJSONKeyPairInt("daysinmonth", DaysInMonth(m, y));
|
PrintJSONKeyPairInt("daysinmonth", DaysInMonth(m, y));
|
||||||
@@ -1272,7 +1307,7 @@ static void PrintLeft(char const *s, int width, char pad)
|
|||||||
buf = calloc(len+1, sizeof(wchar_t));
|
buf = calloc(len+1, sizeof(wchar_t));
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
/* Uh-oh... cannot recover */
|
/* Uh-oh... cannot recover */
|
||||||
fprintf(stderr, "%s\n", GetErr(E_NO_MEM));
|
fprintf(ErrFp, "%s\n", GetErr(E_NO_MEM));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1357,7 +1392,7 @@ static void PrintCentered(char const *s, int width, char *pad)
|
|||||||
buf = calloc(len+1, sizeof(wchar_t));
|
buf = calloc(len+1, sizeof(wchar_t));
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
/* Uh-oh... cannot recover */
|
/* Uh-oh... cannot recover */
|
||||||
fprintf(stderr, "%s\n", GetErr(E_NO_MEM));
|
fprintf(ErrFp, "%s\n", GetErr(E_NO_MEM));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1777,7 +1812,7 @@ static void WriteCalHeader(void)
|
|||||||
int y, m, d;
|
int y, m, d;
|
||||||
|
|
||||||
FromDSE(DSEToday, &y, &m, &d);
|
FromDSE(DSEToday, &y, &m, &d);
|
||||||
sprintf(buf, "%s %d", get_month_name(m), y);
|
snprintf(buf, sizeof(buf), "%s %d", get_month_name(m), y);
|
||||||
|
|
||||||
WriteTopCalLine();
|
WriteTopCalLine();
|
||||||
|
|
||||||
@@ -1981,7 +2016,7 @@ static int DoCalRem(ParsePtr p, int col)
|
|||||||
trig.typ == MSF_TYPE) {
|
trig.typ == MSF_TYPE) {
|
||||||
if (PsCal && is_color) {
|
if (PsCal && is_color) {
|
||||||
char cbuf[24];
|
char cbuf[24];
|
||||||
sprintf(cbuf, "%d %d %d ", col_r, col_g, col_b);
|
snprintf(cbuf, sizeof(cbuf), "%d %d %d ", col_r, col_g, col_b);
|
||||||
DBufPuts(&pre_buf, cbuf);
|
DBufPuts(&pre_buf, cbuf);
|
||||||
strcpy(trig.passthru, "COLOR");
|
strcpy(trig.passthru, "COLOR");
|
||||||
/* Don't change trig.typ or next if() will trigger! */
|
/* Don't change trig.typ or next if() will trigger! */
|
||||||
@@ -2114,7 +2149,7 @@ static int DoCalRem(ParsePtr p, int col)
|
|||||||
if (trig.typ != PASSTHRU_TYPE &&
|
if (trig.typ != PASSTHRU_TYPE &&
|
||||||
UserFuncExists("calprefix")==1) {
|
UserFuncExists("calprefix")==1) {
|
||||||
char evalBuf[64];
|
char evalBuf[64];
|
||||||
sprintf(evalBuf, "calprefix(%d)", trig.priority);
|
snprintf(evalBuf, sizeof(evalBuf), "calprefix(%d)", trig.priority);
|
||||||
s2 = evalBuf;
|
s2 = evalBuf;
|
||||||
r = EvalExpr(&s2, &v, NULL);
|
r = EvalExpr(&s2, &v, NULL);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
@@ -2157,7 +2192,7 @@ static int DoCalRem(ParsePtr p, int col)
|
|||||||
if (trig.typ != PASSTHRU_TYPE &&
|
if (trig.typ != PASSTHRU_TYPE &&
|
||||||
UserFuncExists("calsuffix")==1) {
|
UserFuncExists("calsuffix")==1) {
|
||||||
char evalBuf[64];
|
char evalBuf[64];
|
||||||
sprintf(evalBuf, "calsuffix(%d)", trig.priority);
|
snprintf(evalBuf, sizeof(evalBuf), "calsuffix(%d)", trig.priority);
|
||||||
s2 = evalBuf;
|
s2 = evalBuf;
|
||||||
r = EvalExpr(&s2, &v, NULL);
|
r = EvalExpr(&s2, &v, NULL);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
@@ -2701,7 +2736,7 @@ CalendarTime(int tim, int duration)
|
|||||||
else hh2 = h2;
|
else hh2 = h2;
|
||||||
|
|
||||||
if (days) {
|
if (days) {
|
||||||
sprintf(daybuf, "+%d", days);
|
snprintf(daybuf, sizeof(daybuf), "+%d", days);
|
||||||
} else {
|
} else {
|
||||||
daybuf[0] = 0;
|
daybuf[0] = 0;
|
||||||
}
|
}
|
||||||
@@ -2724,12 +2759,12 @@ CalendarTime(int tim, int duration)
|
|||||||
|
|
||||||
switch(ScFormat) {
|
switch(ScFormat) {
|
||||||
case SC_AMPM:
|
case SC_AMPM:
|
||||||
sprintf(buf, "%d%c%02d%s-%d%c%02d%s%s ",
|
snprintf(buf, sizeof(buf), "%d%c%02d%s-%d%c%02d%s%s ",
|
||||||
hh, TimeSep, min, ampm1, hh2, TimeSep, min2, ampm2, daybuf);
|
hh, TimeSep, min, ampm1, hh2, TimeSep, min2, ampm2, daybuf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SC_MIL:
|
case SC_MIL:
|
||||||
sprintf(buf, "%02d%c%02d-%02d%c%02d%s ",
|
snprintf(buf, sizeof(buf), "%02d%c%02d-%02d%c%02d%s ",
|
||||||
h, TimeSep, min, h2, TimeSep, min2, daybuf);
|
h, TimeSep, min, h2, TimeSep, min2, daybuf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2747,7 +2782,7 @@ CalendarTime(int tim, int duration)
|
|||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
char const *SimpleTime(int tim)
|
char const *SimpleTime(int tim)
|
||||||
{
|
{
|
||||||
static char buf[32];
|
static char buf[128];
|
||||||
int h, min, hh;
|
int h, min, hh;
|
||||||
|
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
@@ -2761,7 +2796,7 @@ char const *SimpleTime(int tim)
|
|||||||
if (h == 0) hh=12;
|
if (h == 0) hh=12;
|
||||||
else if (h > 12) hh=h-12;
|
else if (h > 12) hh=h-12;
|
||||||
else hh=h;
|
else hh=h;
|
||||||
sprintf(buf, "%d%c%02d%s ", hh, TimeSep, min, (h>=12) ? tr("pm") : tr("am"));
|
snprintf(buf, sizeof(buf), "%d%c%02d%.64s ", hh, TimeSep, min, (h>=12) ? tr("pm") : tr("am"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2769,7 +2804,7 @@ char const *SimpleTime(int tim)
|
|||||||
if (tim != NO_TIME) {
|
if (tim != NO_TIME) {
|
||||||
h = tim / 60;
|
h = tim / 60;
|
||||||
min = tim % 60;
|
min = tim % 60;
|
||||||
sprintf(buf, "%02d%c%02d ", h, TimeSep, min);
|
snprintf(buf, sizeof(buf), "%02d%c%02d ", h, TimeSep, min);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2821,7 +2856,7 @@ char const *SynthesizeTag(void)
|
|||||||
MD5Init(&ctx);
|
MD5Init(&ctx);
|
||||||
MD5Update(&ctx, (unsigned char *) CurLine, strlen(CurLine));
|
MD5Update(&ctx, (unsigned char *) CurLine, strlen(CurLine));
|
||||||
MD5Final(buf, &ctx);
|
MD5Final(buf, &ctx);
|
||||||
sprintf(out, "__syn__%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
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],
|
(unsigned int) buf[0], (unsigned int) buf[1],
|
||||||
(unsigned int) buf[2], (unsigned int) buf[3],
|
(unsigned int) buf[2], (unsigned int) buf[3],
|
||||||
(unsigned int) buf[4], (unsigned int) buf[5],
|
(unsigned int) buf[4], (unsigned int) buf[5],
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* which you can customize. */
|
/* which you can customize. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* which you can customize. */
|
/* which you can customize. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
12
src/dedupe.c
12
src/dedupe.c
@@ -5,7 +5,7 @@
|
|||||||
/* Code to suppress duplicate reminders */
|
/* Code to suppress duplicate reminders */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -167,17 +167,13 @@ InitDedupeTable(void)
|
|||||||
if (hash_table_init(&DedupeTable,
|
if (hash_table_init(&DedupeTable,
|
||||||
offsetof(DedupeEntry, link),
|
offsetof(DedupeEntry, link),
|
||||||
DedupeHashFunc, CompareDedupes) < 0) {
|
DedupeHashFunc, CompareDedupes) < 0) {
|
||||||
fprintf(stderr, "Unable to initialize function hash table: Out of memory. Exiting.\n");
|
fprintf(ErrFp, "Unable to initialize function hash table: Out of memory. Exiting.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
get_dedupe_hash_stats(int *total, int *maxlen, double *avglen)
|
dump_dedupe_hash_stats(void)
|
||||||
{
|
{
|
||||||
struct hash_table_stats s;
|
hash_table_dump_stats(&DedupeTable, ErrFp);
|
||||||
hash_table_get_stats(&DedupeTable, &s);
|
|
||||||
*total = s.num_entries;
|
|
||||||
*maxlen = s.max_len;
|
|
||||||
*avglen = s.avg_len;
|
|
||||||
}
|
}
|
||||||
|
|||||||
44
src/dorem.c
44
src/dorem.c
@@ -7,7 +7,7 @@
|
|||||||
/* commands. */
|
/* commands. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -67,18 +67,18 @@ check_trigger_function(char const *fname, char const *type)
|
|||||||
if (!f) {
|
if (!f) {
|
||||||
if (strcmp(type, "WARN")) {
|
if (strcmp(type, "WARN")) {
|
||||||
/* Undefined WARN functions are diagnosed elsewhere... */
|
/* Undefined WARN functions are diagnosed elsewhere... */
|
||||||
Wprint("Undefined %s function: `%s'", type, fname);
|
Wprint(tr("Undefined %s function: `%s'"), type, fname);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (f->nargs != 1) {
|
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);
|
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);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ensure_expr_references_first_local_arg(f->node)) {
|
if (ensure_expr_references_first_local_arg(f->node)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Wprint("%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:%d does not use its argument"), type, fname, f->filename, f->lineno);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -154,7 +154,7 @@ static void ensure_satnode_mentions_trigdate(expr_node *node)
|
|||||||
if (node->type == N_CONSTANT) {
|
if (node->type == N_CONSTANT) {
|
||||||
if (node->u.value.type == INT_TYPE) {
|
if (node->u.value.type == INT_TYPE) {
|
||||||
if (node->u.value.v.val == 0) {
|
if (node->u.value.v.val == 0) {
|
||||||
Wprint("SATISFY: constant 0 will never be true");
|
Wprint(tr("SATISFY: constant 0 will never be true"));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -166,14 +166,14 @@ static void ensure_satnode_mentions_trigdate(expr_node *node)
|
|||||||
str = node->u.name;
|
str = node->u.name;
|
||||||
}
|
}
|
||||||
if (!*str) {
|
if (!*str) {
|
||||||
Wprint("SATISFY: constant \"\" will never be true");
|
Wprint(tr("SATISFY: constant \"\" will never be true"));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure_satnode_mentions_trigdate_aux(node, &mentioned);
|
ensure_satnode_mentions_trigdate_aux(node, &mentioned);
|
||||||
if (!mentioned) {
|
if (!mentioned) {
|
||||||
Wprint("SATISFY: expression has no reference to trigdate() or $T...");
|
Wprint(tr("SATISFY: expression has no reference to trigdate() or $T..."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,7 +615,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
|||||||
case T_Omit:
|
case T_Omit:
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
if (trig->omitfunc[0]) {
|
if (trig->omitfunc[0]) {
|
||||||
Wprint("Warning: OMIT is ignored if you use OMITFUNC");
|
Wprint(tr("Warning: OMIT is ignored if you use OMITFUNC"));
|
||||||
}
|
}
|
||||||
|
|
||||||
r = ParseLocalOmit(s, trig);
|
r = ParseLocalOmit(s, trig);
|
||||||
@@ -629,7 +629,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
|||||||
|
|
||||||
case T_OmitFunc:
|
case T_OmitFunc:
|
||||||
if (trig->localomit) {
|
if (trig->localomit) {
|
||||||
Wprint("Warning: OMIT is ignored if you use OMITFUNC");
|
Wprint(tr("Warning: OMIT is ignored if you use OMITFUNC"));
|
||||||
}
|
}
|
||||||
r=ParseToken(s, &buf);
|
r=ParseToken(s, &buf);
|
||||||
if (r) return r;
|
if (r) return r;
|
||||||
@@ -707,7 +707,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
|||||||
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 && !SuppressImplicitRemWarnings) {
|
if (!WarnedAboutImplicit && !SuppressImplicitRemWarnings) {
|
||||||
Wprint("Missing REM type; assuming MSG");
|
Wprint(tr("Missing REM type; assuming MSG"));
|
||||||
WarnedAboutImplicit = 1;
|
WarnedAboutImplicit = 1;
|
||||||
}
|
}
|
||||||
parsing = 0;
|
parsing = 0;
|
||||||
@@ -738,22 +738,22 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
|||||||
if (!s->nonconst_expr) {
|
if (!s->nonconst_expr) {
|
||||||
if (trig->y != NO_YR && trig->m != NO_MON && trig->d != NO_DAY && trig->until != NO_UNTIL) {
|
if (trig->y != NO_YR && trig->m != NO_MON && trig->d != NO_DAY && trig->until != NO_UNTIL) {
|
||||||
if (DSE(trig->y, trig->m, trig->d) > trig->until) {
|
if (DSE(trig->y, trig->m, trig->d) > trig->until) {
|
||||||
Wprint("Warning: UNTIL/THROUGH date earlier than start date");
|
Wprint(tr("Warning: UNTIL/THROUGH date earlier than start date"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (trig->from != NO_DATE) {
|
if (trig->from != NO_DATE) {
|
||||||
if (trig->until != NO_UNTIL && trig->until < trig->from) {
|
if (trig->until != NO_UNTIL && trig->until < trig->from) {
|
||||||
Wprint("Warning: UNTIL/THROUGH date earlier than FROM date");
|
Wprint(tr("Warning: UNTIL/THROUGH date earlier than FROM date"));
|
||||||
}
|
}
|
||||||
} else if (trig->scanfrom != NO_DATE) {
|
} else if (trig->scanfrom != NO_DATE) {
|
||||||
if (trig->until != NO_UNTIL && trig->until < trig->scanfrom) {
|
if (trig->until != NO_UNTIL && trig->until < trig->scanfrom) {
|
||||||
Wprint("Warning: UNTIL/THROUGH date earlier than SCANFROM date");
|
Wprint(tr("Warning: UNTIL/THROUGH date earlier than SCANFROM date"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trig->y != NO_YR && trig->m != NO_MON && trig->d != NO_DAY && trig->until != NO_UNTIL && trig->rep == NO_REP) {
|
if (trig->y != NO_YR && trig->m != NO_MON && trig->d != NO_DAY && trig->until != NO_UNTIL && trig->rep == NO_REP) {
|
||||||
Wprint("Warning: Useless use of UNTIL with fully-specified date and no *rep");
|
Wprint(tr("Warning: Useless use of UNTIL with fully-specified date and no *rep"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set scanfrom to default if not set explicitly */
|
/* Set scanfrom to default if not set explicitly */
|
||||||
@@ -1180,7 +1180,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
FromDSE(dse, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
sprintf(tmpBuf, "%04d/%02d/%02d ", y, m+1, d);
|
snprintf(tmpBuf, sizeof(tmpBuf), "%04d/%02d/%02d ", y, m+1, d);
|
||||||
if (DBufPuts(&calRow, tmpBuf) != OK) {
|
if (DBufPuts(&calRow, tmpBuf) != OK) {
|
||||||
DBufFree(&calRow);
|
DBufFree(&calRow);
|
||||||
DBufFree(&pre_buf);
|
DBufFree(&pre_buf);
|
||||||
@@ -1201,9 +1201,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
|||||||
DBufPuts(&calRow, "* ");
|
DBufPuts(&calRow, "* ");
|
||||||
}
|
}
|
||||||
if (tim->duration != NO_TIME) {
|
if (tim->duration != NO_TIME) {
|
||||||
sprintf(tmpBuf, "%d ", tim->duration);
|
snprintf(tmpBuf, sizeof(tmpBuf), "%d ", tim->duration);
|
||||||
} else {
|
} else {
|
||||||
sprintf(tmpBuf, "* ");
|
snprintf(tmpBuf, sizeof(tmpBuf), "* ");
|
||||||
}
|
}
|
||||||
if (DBufPuts(&calRow, tmpBuf) != OK) {
|
if (DBufPuts(&calRow, tmpBuf) != OK) {
|
||||||
DBufFree(&calRow);
|
DBufFree(&calRow);
|
||||||
@@ -1211,9 +1211,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
|||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
if (tim->ttime != NO_TIME) {
|
if (tim->ttime != NO_TIME) {
|
||||||
sprintf(tmpBuf, "%d ", tim->ttime);
|
snprintf(tmpBuf, sizeof(tmpBuf), "%d ", tim->ttime);
|
||||||
} else {
|
} else {
|
||||||
sprintf(tmpBuf, "* ");
|
snprintf(tmpBuf, sizeof(tmpBuf), "* ");
|
||||||
}
|
}
|
||||||
if (DBufPuts(&calRow, tmpBuf) != OK) {
|
if (DBufPuts(&calRow, tmpBuf) != OK) {
|
||||||
DBufFree(&calRow);
|
DBufFree(&calRow);
|
||||||
@@ -1263,7 +1263,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
|||||||
/* Don't use msgprefix() on RUN-type reminders */
|
/* Don't use msgprefix() on RUN-type reminders */
|
||||||
if (t->typ != RUN_TYPE) {
|
if (t->typ != RUN_TYPE) {
|
||||||
if (UserFuncExists("msgprefix") == 1) {
|
if (UserFuncExists("msgprefix") == 1) {
|
||||||
sprintf(PrioExpr, "msgprefix(%d)", t->priority);
|
snprintf(PrioExpr, sizeof(PrioExpr), "msgprefix(%d)", t->priority);
|
||||||
s = PrioExpr;
|
s = PrioExpr;
|
||||||
r = EvalExpr(&s, &v, NULL);
|
r = EvalExpr(&s, &v, NULL);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
@@ -1289,7 +1289,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
|||||||
|
|
||||||
if (t->typ != RUN_TYPE) {
|
if (t->typ != RUN_TYPE) {
|
||||||
if (UserFuncExists("msgsuffix") == 1) {
|
if (UserFuncExists("msgsuffix") == 1) {
|
||||||
sprintf(PrioExpr, "msgsuffix(%d)", t->priority);
|
snprintf(PrioExpr, sizeof(PrioExpr), "msgsuffix(%d)", t->priority);
|
||||||
s = PrioExpr;
|
s = PrioExpr;
|
||||||
r = EvalExpr(&s, &v, NULL);
|
r = EvalExpr(&s, &v, NULL);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
@@ -1694,7 +1694,7 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int dse, int *err)
|
|||||||
return (dse == DSEToday);
|
return (dse == DSEToday);
|
||||||
}
|
}
|
||||||
for (i=1; ; i++) {
|
for (i=1; ; i++) {
|
||||||
sprintf(buffer, "%s(%d)", t->warn, i);
|
snprintf(buffer, sizeof(buffer), "%s(%d)", t->warn, i);
|
||||||
s = buffer;
|
s = buffer;
|
||||||
r = EvalExpr(&s, &v, NULL);
|
r = EvalExpr(&s, &v, NULL);
|
||||||
if (r) {
|
if (r) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* reminders are triggered. */
|
/* reminders are triggered. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -40,7 +40,7 @@ check_subst_args(UserFunc *f, int n)
|
|||||||
if (f->nargs == n) {
|
if (f->nargs == n) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
Wprint("Function `%s' defined at %s:%d should take %d argument%s, but actually takes %d",
|
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);
|
f->name, f->filename, f->lineno, n, (n == 1 ? "" : "s"), f->nargs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -232,7 +232,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
DBufPutc(&orig, c);
|
DBufPutc(&orig, c);
|
||||||
}
|
}
|
||||||
if (!c) {
|
if (!c) {
|
||||||
Wprint("Warning: Unterminated %%(...) substitution sequence");
|
Wprint(tr("Warning: Unterminated %%(...) substitution sequence"));
|
||||||
}
|
}
|
||||||
err = OK;
|
err = OK;
|
||||||
if (GetTranslatedStringTryingVariants(DBufValue(&orig), &translated)) {
|
if (GetTranslatedStringTryingVariants(DBufValue(&orig), &translated)) {
|
||||||
@@ -240,6 +240,9 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
} else {
|
} else {
|
||||||
err = DBufPuts(dbuf, DBufValue(&orig));
|
err = DBufPuts(dbuf, DBufValue(&orig));
|
||||||
}
|
}
|
||||||
|
if (DebugFlag & DB_TRANSLATE) {
|
||||||
|
TranslationTemplate(DBufValue(&orig));
|
||||||
|
}
|
||||||
DBufFree(&orig);
|
DBufFree(&orig);
|
||||||
DBufFree(&translated);
|
DBufFree(&translated);
|
||||||
if (err) return err;
|
if (err) return err;
|
||||||
@@ -275,11 +278,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!c) {
|
if (!c) {
|
||||||
Wprint("Warning: Unterminated %%{...} substitution sequence");
|
Wprint(tr("Warning: Unterminated %%{...} substitution sequence"));
|
||||||
}
|
}
|
||||||
func = FindUserFunc(s);
|
func = FindUserFunc(s);
|
||||||
if (!func) {
|
if (!func) {
|
||||||
Wprint("No substition function `%s' defined", s);
|
Wprint(tr("No substition function `%s' defined"), s);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* buffers. */
|
/* buffers. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Declaration of functions for manipulating dynamic buffers */
|
/* Declaration of functions for manipulating dynamic buffers */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
20
src/err.h
20
src/err.h
@@ -5,7 +5,7 @@
|
|||||||
/* Error definitions. */
|
/* Error definitions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -230,20 +230,20 @@ EXTERN char *ErrMsg[]
|
|||||||
/* E_EXPIRED */ "Expired",
|
/* E_EXPIRED */ "Expired",
|
||||||
/* E_CANTFORK */ "fork() failed - can't do queued reminders",
|
/* E_CANTFORK */ "fork() failed - can't do queued reminders",
|
||||||
/* E_CANTACCESS */ "Can't access file",
|
/* E_CANTACCESS */ "Can't access file",
|
||||||
/* M_BAD_SYS_DATE */ "Illegal system date: Year is less than %d\n",
|
/* M_BAD_SYS_DATE */ "Illegal system date: Year is less than %d",
|
||||||
/* M_BAD_DB_FLAG */ "Unknown debug flag '%c'\n",
|
/* M_BAD_DB_FLAG */ "Unknown debug flag '%c'",
|
||||||
/* M_BAD_OPTION */ "Unknown option '%c'\n",
|
/* M_BAD_OPTION */ "Unknown option '%c'",
|
||||||
/* M_BAD_USER */ "Unknown user '%s'\n",
|
/* M_BAD_USER */ "Unknown user '%s'",
|
||||||
/* M_NO_CHG_GID */ "Could not change gid to %d\n",
|
/* M_NO_CHG_GID */ "Could not change gid to %d",
|
||||||
/* M_NO_CHG_UID */ "Could not change uid to %d\n",
|
/* M_NO_CHG_UID */ "Could not change uid to %d",
|
||||||
/* M_NOMEM_ENV */ "Out of memory for environment\n",
|
/* M_NOMEM_ENV */ "Out of memory for environment",
|
||||||
/* E_MISS_EQ */ "Missing '=' sign",
|
/* E_MISS_EQ */ "Missing '=' sign",
|
||||||
/* E_MISS_VAR */ "Missing variable name",
|
/* E_MISS_VAR */ "Missing variable name",
|
||||||
/* E_MISS_EXPR */ "Missing expression",
|
/* E_MISS_EXPR */ "Missing expression",
|
||||||
/* M_CANTSET_ACCESS */ "",
|
/* M_CANTSET_ACCESS */ "",
|
||||||
/* M_I_OPTION */ "Remind: '-i' option: %s\n",
|
/* M_I_OPTION */ "Remind: '-i' option: %s",
|
||||||
/* 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.",
|
||||||
/* E_EXPECTING_NUMBER */ "Expecting number",
|
/* E_EXPECTING_NUMBER */ "Expecting number",
|
||||||
/* M_BAD_WARN_FUNC */ "Undefined WARN function",
|
/* 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",
|
||||||
|
|||||||
84
src/expr.c
84
src/expr.c
@@ -12,7 +12,7 @@
|
|||||||
/* evaluated. */
|
/* evaluated. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -199,6 +199,46 @@ 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
|
||||||
|
|
||||||
|
static char const *
|
||||||
|
find_end_of_expr(char const *s)
|
||||||
|
{
|
||||||
|
char const *e = s;
|
||||||
|
int in_quoted_string = 0;
|
||||||
|
int escaped = 0;
|
||||||
|
|
||||||
|
while(*e) {
|
||||||
|
if (in_quoted_string) {
|
||||||
|
if (escaped) {
|
||||||
|
escaped = 0;
|
||||||
|
e++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*e == '\\') {
|
||||||
|
escaped = 1;
|
||||||
|
e++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*e == '"') {
|
||||||
|
in_quoted_string = 0;
|
||||||
|
e++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
e++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*e == '"') {
|
||||||
|
in_quoted_string = 1;
|
||||||
|
e++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*e == ']') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
e++;
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* alloc_expr_node - allocate an expr_node object */
|
/* alloc_expr_node - allocate an expr_node object */
|
||||||
@@ -1541,7 +1581,7 @@ static int parse_expr_token(DynamicBuffer *buf, char const **in)
|
|||||||
}
|
}
|
||||||
(*in)++;
|
(*in)++;
|
||||||
} else {
|
} else {
|
||||||
Eprint("%s `%c' (did you mean `%c%c'?)", GetErr(E_PARSE_ERR), c, c, c);
|
Eprint("%s `%c' (%s `%c%c'?)", GetErr(E_PARSE_ERR), c, tr("did you mean"), c, c);
|
||||||
return E_PARSE_ERR;
|
return E_PARSE_ERR;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
@@ -2137,6 +2177,7 @@ static expr_node *parse_atom(char const **e, int *r, Var *locals, int level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* It's a constant or a variable reference */
|
/* It's a constant or a variable reference */
|
||||||
|
char const *olds = *e;
|
||||||
*r = GET_TOKEN();
|
*r = GET_TOKEN();
|
||||||
if (*r != OK) return NULL;
|
if (*r != OK) return NULL;
|
||||||
node = alloc_expr_node(r);
|
node = alloc_expr_node(r);
|
||||||
@@ -2145,6 +2186,8 @@ static expr_node *parse_atom(char const **e, int *r, Var *locals, int level)
|
|||||||
}
|
}
|
||||||
*r = make_atom(node, locals);
|
*r = make_atom(node, locals);
|
||||||
if (*r != OK) {
|
if (*r != OK) {
|
||||||
|
/* Preserve location for error position when we print ^-- here */
|
||||||
|
*e = olds;
|
||||||
return free_expr_tree(node);
|
return free_expr_tree(node);
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
@@ -2498,6 +2541,7 @@ expr_node *parse_expression(char const **e, int *r, Var *locals)
|
|||||||
{
|
{
|
||||||
char const *orig = *e;
|
char const *orig = *e;
|
||||||
char const *o2 = *e;
|
char const *o2 = *e;
|
||||||
|
char const *end_of_expr;
|
||||||
if (ExpressionEvaluationDisabled) {
|
if (ExpressionEvaluationDisabled) {
|
||||||
*r = E_EXPR_DISABLED;
|
*r = E_EXPR_DISABLED;
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2529,25 +2573,29 @@ expr_node *parse_expression(char const **e, int *r, Var *locals)
|
|||||||
*r == E_2FEW_ARGS ||
|
*r == E_2FEW_ARGS ||
|
||||||
*r == E_PARSE_ERR ||
|
*r == E_PARSE_ERR ||
|
||||||
*r == E_EOLN ||
|
*r == E_EOLN ||
|
||||||
|
*r == E_BAD_NUMBER ||
|
||||||
|
*r == E_BAD_DATE ||
|
||||||
|
*r == E_BAD_TIME ||
|
||||||
*r == E_ILLEGAL_CHAR) {
|
*r == E_ILLEGAL_CHAR) {
|
||||||
orig = o2;
|
end_of_expr = find_end_of_expr(orig);
|
||||||
while (*orig) {
|
while (**e && isempty(**e)) {
|
||||||
|
(*e)++;
|
||||||
|
}
|
||||||
|
while (*orig && ((orig < end_of_expr) || (orig <= *e))) {
|
||||||
if (*orig == '\n') {
|
if (*orig == '\n') {
|
||||||
fprintf(ErrFp, " ");
|
fprintf(ErrFp, " ");
|
||||||
orig++;
|
|
||||||
} else if (*orig == ']' && ! *(orig+1)) {
|
|
||||||
break;
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(ErrFp, "%c", *orig++);
|
fprintf(ErrFp, "%c", *orig);
|
||||||
}
|
}
|
||||||
|
orig++;
|
||||||
}
|
}
|
||||||
fprintf(ErrFp, "\n");
|
fprintf(ErrFp, "\n");
|
||||||
orig = o2;
|
orig = o2;
|
||||||
while ((orig < *e) && *orig) {
|
while (*orig && (orig < *e || isspace(*orig))) {
|
||||||
orig++;
|
orig++;
|
||||||
fprintf(ErrFp, " ");
|
fprintf(ErrFp, " ");
|
||||||
}
|
}
|
||||||
fprintf(ErrFp, "^-- here\n");
|
fprintf(ErrFp, "^-- %s\n", tr("here"));
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@@ -2966,12 +3014,12 @@ int DoCoerce(char type, Value *v)
|
|||||||
}
|
}
|
||||||
case STR_TYPE:
|
case STR_TYPE:
|
||||||
switch(v->type) {
|
switch(v->type) {
|
||||||
case INT_TYPE: sprintf(coerce_buf, "%d", v->v.val); break;
|
case INT_TYPE: snprintf(coerce_buf, sizeof(coerce_buf), "%d", v->v.val); break;
|
||||||
case TIME_TYPE: sprintf(coerce_buf, "%02d%c%02d", v->v.val / 60,
|
case TIME_TYPE: snprintf(coerce_buf, sizeof(coerce_buf), "%02d%c%02d", v->v.val / 60,
|
||||||
TimeSep, v->v.val % 60);
|
TimeSep, v->v.val % 60);
|
||||||
break;
|
break;
|
||||||
case DATE_TYPE: FromDSE(v->v.val, &y, &m, &d);
|
case DATE_TYPE: FromDSE(v->v.val, &y, &m, &d);
|
||||||
sprintf(coerce_buf, "%04d%c%02d%c%02d",
|
snprintf(coerce_buf, sizeof(coerce_buf), "%04d%c%02d%c%02d",
|
||||||
y, DateSep, m+1, DateSep, d);
|
y, DateSep, m+1, DateSep, d);
|
||||||
break;
|
break;
|
||||||
case DATETIME_TYPE:
|
case DATETIME_TYPE:
|
||||||
@@ -2980,7 +3028,7 @@ int DoCoerce(char type, Value *v)
|
|||||||
k = v->v.val % MINUTES_PER_DAY;
|
k = v->v.val % MINUTES_PER_DAY;
|
||||||
h = k / 60;
|
h = k / 60;
|
||||||
i = k % 60;
|
i = k % 60;
|
||||||
sprintf(coerce_buf, "%04d%c%02d%c%02d%c%02d%c%02d",
|
snprintf(coerce_buf, sizeof(coerce_buf), "%04d%c%02d%c%02d%c%02d%c%02d",
|
||||||
y, DateSep, m+1, DateSep, d, DateTimeSep, h, TimeSep, i);
|
y, DateSep, m+1, DateSep, d, DateTimeSep, h, TimeSep, i);
|
||||||
break;
|
break;
|
||||||
default: return E_CANT_COERCE;
|
default: return E_CANT_COERCE;
|
||||||
@@ -3088,10 +3136,10 @@ int DoCoerce(char type, Value *v)
|
|||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
void print_expr_nodes_stats(void)
|
void print_expr_nodes_stats(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, " Expression nodes allocated: %d\n", ExprNodesAllocated);
|
fprintf(ErrFp, " Expression nodes allocated: %d\n", ExprNodesAllocated);
|
||||||
fprintf(stderr, "Expression nodes high-water: %d\n", ExprNodesHighWater);
|
fprintf(ErrFp, "Expression nodes high-water: %d\n", ExprNodesHighWater);
|
||||||
fprintf(stderr, " Expression nodes leaked: %d\n", ExprNodesUsed);
|
fprintf(ErrFp, " Expression nodes leaked: %d\n", ExprNodesUsed);
|
||||||
fprintf(stderr, " Parse level high-water: %d\n", parse_level_high_water);
|
fprintf(ErrFp, " Parse level high-water: %d\n", parse_level_high_water);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 if a value is "true" for its type, 0 if "false" */
|
/* Return 1 if a value is "true" for its type, 0 if "false" */
|
||||||
|
|||||||
40
src/files.c
40
src/files.c
@@ -7,7 +7,7 @@
|
|||||||
/* files. */
|
/* files. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -145,7 +145,8 @@ static void OpenPurgeFile(char const *fname, char const *mode)
|
|||||||
if (DBufPuts(&fname_buf, ".purged") != OK) return;
|
if (DBufPuts(&fname_buf, ".purged") != OK) return;
|
||||||
PurgeFP = fopen(DBufValue(&fname_buf), mode);
|
PurgeFP = fopen(DBufValue(&fname_buf), mode);
|
||||||
if (!PurgeFP) {
|
if (!PurgeFP) {
|
||||||
fprintf(ErrFp, "Cannot open `%s' for writing: %s\n", DBufValue(&fname_buf), strerror(errno));
|
fprintf(ErrFp, tr("Cannot open `%s' for writing: %s"), DBufValue(&fname_buf), strerror(errno));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
set_cloexec(PurgeFP);
|
set_cloexec(PurgeFP);
|
||||||
DBufFree(&fname_buf);
|
DBufFree(&fname_buf);
|
||||||
@@ -325,7 +326,8 @@ int OpenFile(char const *fname)
|
|||||||
while (h) {
|
while (h) {
|
||||||
if (!strcmp(fname, h->filename)) {
|
if (!strcmp(fname, h->filename)) {
|
||||||
if (DebugFlag & DB_TRACE_FILES) {
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
fprintf(ErrFp, "Reading `%s': Found in cache\n", fname);
|
fprintf(ErrFp, tr("Reading `%s': Found in cache"), fname);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
CLine = h->cache;
|
CLine = h->cache;
|
||||||
STRSET(FileName, fname);
|
STRSET(FileName, fname);
|
||||||
@@ -348,13 +350,14 @@ int OpenFile(char const *fname)
|
|||||||
PurgeFP = stdout;
|
PurgeFP = stdout;
|
||||||
}
|
}
|
||||||
if (DebugFlag & DB_TRACE_FILES) {
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
fprintf(ErrFp, "Reading `-': Reading stdin\n");
|
fprintf(ErrFp, "%s\n", tr("Reading `-': Reading stdin"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fp = fopen(fname, "r");
|
fp = fopen(fname, "r");
|
||||||
set_cloexec(fp);
|
set_cloexec(fp);
|
||||||
if (DebugFlag & DB_TRACE_FILES) {
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
fprintf(ErrFp, "Reading `%s': Opening file on disk\n", fname);
|
fprintf(ErrFp, tr("Reading `%s': Opening file on disk"), fname);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
if (PurgeMode) {
|
if (PurgeMode) {
|
||||||
OpenPurgeFile(fname, "w");
|
OpenPurgeFile(fname, "w");
|
||||||
@@ -401,7 +404,8 @@ static int CacheFile(char const *fname, int use_pclose)
|
|||||||
char const *s;
|
char const *s;
|
||||||
|
|
||||||
if (DebugFlag & DB_TRACE_FILES) {
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
fprintf(ErrFp, "Caching file `%s' in memory\n", fname);
|
fprintf(ErrFp, tr("Caching file `%s' in memory"), fname);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
cl = NULL;
|
cl = NULL;
|
||||||
/* Create a file header */
|
/* Create a file header */
|
||||||
@@ -539,7 +543,8 @@ static int PopFile(void)
|
|||||||
if (!Hush && NumIfs) {
|
if (!Hush && NumIfs) {
|
||||||
Eprint("%s", GetErr(E_MISS_ENDIF));
|
Eprint("%s", GetErr(E_MISS_ENDIF));
|
||||||
for (j=NumIfs-1; j >=0; j--) {
|
for (j=NumIfs-1; j >=0; j--) {
|
||||||
fprintf(ErrFp, "%s(%d): IF without ENDIF\n", FileName, IfLinenos[j]);
|
fprintf(ErrFp, tr("%s(%d): IF without ENDIF"), FileName, IfLinenos[j]);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!IStackPtr) return E_EOF;
|
if (!IStackPtr) return E_EOF;
|
||||||
@@ -608,7 +613,7 @@ int DoInclude(ParsePtr p, enum TokTypes tok)
|
|||||||
DBufInit(&buf);
|
DBufInit(&buf);
|
||||||
DBufInit(&fullname);
|
DBufInit(&fullname);
|
||||||
DBufInit(&path);
|
DBufInit(&path);
|
||||||
if ( (r=ParseToken(p, &buf)) ) return r;
|
if ( (r=ParseTokenOrQuotedString(p, &buf)) ) return r;
|
||||||
e = VerifyEoln(p);
|
e = VerifyEoln(p);
|
||||||
if (e) Eprint("%s", GetErr(e));
|
if (e) Eprint("%s", GetErr(e));
|
||||||
|
|
||||||
@@ -760,8 +765,9 @@ static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
|||||||
while(dc) {
|
while(dc) {
|
||||||
if (!strcmp(dc->dirname, dir)) {
|
if (!strcmp(dc->dirname, dir)) {
|
||||||
if (DebugFlag & DB_TRACE_FILES) {
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
fprintf(ErrFp, "Found cached directory listing for `%s'\n",
|
fprintf(ErrFp, tr("Found cached directory listing for `%s'"),
|
||||||
dir);
|
dir);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
free(dir);
|
free(dir);
|
||||||
i->chain = dc->chain;
|
i->chain = dc->chain;
|
||||||
@@ -771,7 +777,8 @@ static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (DebugFlag & DB_TRACE_FILES) {
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
fprintf(ErrFp, "Scanning directory `%s' for *.rem files\n", dir);
|
fprintf(ErrFp, tr("Scanning directory `%s' for *.rem files"), dir);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShouldCache) {
|
if (ShouldCache) {
|
||||||
@@ -785,7 +792,8 @@ static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
|||||||
}
|
}
|
||||||
if (dc) {
|
if (dc) {
|
||||||
if (DebugFlag & DB_TRACE_FILES) {
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
fprintf(ErrFp, "Caching directory `%s' listing\n", dir);
|
fprintf(ErrFp, tr("Caching directory `%s' listing"), dir);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
dc->chain = NULL;
|
dc->chain = NULL;
|
||||||
@@ -917,7 +925,8 @@ static int IncludeCmd(char const *cmd)
|
|||||||
while(h) {
|
while(h) {
|
||||||
if (!strcmp(fname, h->filename)) {
|
if (!strcmp(fname, h->filename)) {
|
||||||
if (DebugFlag & DB_TRACE_FILES) {
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
fprintf(ErrFp, "Reading command `%s': Found in cache\n", fname);
|
fprintf(ErrFp, tr("Reading command `%s': Found in cache"), fname);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
CLine = h->cache;
|
CLine = h->cache;
|
||||||
STRSET(FileName, fname);
|
STRSET(FileName, fname);
|
||||||
@@ -934,8 +943,9 @@ static int IncludeCmd(char const *cmd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (DebugFlag & DB_TRACE_FILES) {
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
fprintf(ErrFp, "Executing `%s' for INCLUDECMD and caching as `%s'\n",
|
fprintf(ErrFp, tr("Executing `%s' for INCLUDECMD and caching as `%s'"),
|
||||||
cmd, fname);
|
cmd, fname);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not found in cache */
|
/* Not found in cache */
|
||||||
@@ -1201,7 +1211,7 @@ static int CheckSafetyAux(struct stat *statbuf)
|
|||||||
if (!geteuid()) {
|
if (!geteuid()) {
|
||||||
/* Reject files not owned by root or group/world writable */
|
/* Reject files not owned by root or group/world writable */
|
||||||
if (statbuf->st_uid != 0) {
|
if (statbuf->st_uid != 0) {
|
||||||
fprintf(ErrFp, "SECURITY: Won't read non-root-owned file or directory when running as root!\n");
|
fprintf(ErrFp, "%s\n", tr("SECURITY: Won't read non-root-owned file or directory when running as root!"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1211,7 +1221,7 @@ static int CheckSafetyAux(struct stat *statbuf)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if ((statbuf->st_mode & S_IWOTH)) {
|
if ((statbuf->st_mode & S_IWOTH)) {
|
||||||
fprintf(ErrFp, "SECURITY: Won't read world-writable file or directory!\n");
|
fprintf(ErrFp, "%s\n", tr("SECURITY: Won't read world-writable file or directory!"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
87
src/funcs.c
87
src/funcs.c
@@ -6,7 +6,7 @@
|
|||||||
/* expressions. */
|
/* expressions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -392,6 +392,9 @@ static int F_(func_info *info)
|
|||||||
}
|
}
|
||||||
r = RetStrVal(DBufValue(&translated), info);
|
r = RetStrVal(DBufValue(&translated), info);
|
||||||
DBufFree(&translated);
|
DBufFree(&translated);
|
||||||
|
if (DebugFlag & DB_TRANSLATE) {
|
||||||
|
TranslationTemplate(ARGSTR(0));
|
||||||
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1073,7 +1076,7 @@ static int FOrd(func_info *info)
|
|||||||
if (u == 1 && t != 11) s = "st";
|
if (u == 1 && t != 11) s = "st";
|
||||||
if (u == 2 && t != 12) s = "nd";
|
if (u == 2 && t != 12) s = "nd";
|
||||||
if (u == 3 && t != 13) s = "rd";
|
if (u == 3 && t != 13) s = "rd";
|
||||||
sprintf(buf, "%d%s", v, s);
|
snprintf(buf, sizeof(buf), "%d%s", v, s);
|
||||||
return RetStrVal(buf, info);
|
return RetStrVal(buf, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1825,10 +1828,10 @@ static int FTrigger(func_info *info)
|
|||||||
|
|
||||||
FromDSE(date, &y, &m, &d);
|
FromDSE(date, &y, &m, &d);
|
||||||
if (tim != NO_TIME) {
|
if (tim != NO_TIME) {
|
||||||
sprintf(buf, "%d %s %d AT %02d:%02d", d, MonthName[m], y,
|
snprintf(buf, sizeof(buf), "%d %s %d AT %02d:%02d", d, MonthName[m], y,
|
||||||
tim/60, tim%60);
|
tim/60, tim%60);
|
||||||
} else {
|
} else {
|
||||||
sprintf(buf, "%d %s %d", d, MonthName[m], y);
|
snprintf(buf, sizeof(buf), "%d %s %d", d, MonthName[m], y);
|
||||||
}
|
}
|
||||||
return RetStrVal(buf, info);
|
return RetStrVal(buf, info);
|
||||||
}
|
}
|
||||||
@@ -3009,6 +3012,7 @@ static int FPsshade(func_info *info)
|
|||||||
char psbuff[256];
|
char psbuff[256];
|
||||||
char *s = psbuff;
|
char *s = psbuff;
|
||||||
int i;
|
int i;
|
||||||
|
size_t len = sizeof(psbuff);
|
||||||
|
|
||||||
/* 1 or 3 args */
|
/* 1 or 3 args */
|
||||||
if (Nargs != 1 && Nargs != 3) return E_2MANY_ARGS;
|
if (Nargs != 1 && Nargs != 3) return E_2MANY_ARGS;
|
||||||
@@ -3021,19 +3025,22 @@ static int FPsshade(func_info *info)
|
|||||||
|
|
||||||
if (!psshade_warned) {
|
if (!psshade_warned) {
|
||||||
psshade_warned = 1;
|
psshade_warned = 1;
|
||||||
Wprint("psshade() is deprecated; use SPECIAL SHADE instead.");
|
Wprint(tr("psshade() is deprecated; use SPECIAL SHADE instead."));
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(s, "/_A LineWidth 2 div def ");
|
snprintf(s, len, "/_A LineWidth 2 div def ");
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
sprintf(s, "_A _A moveto ");
|
snprintf(s, len, "_A _A moveto ");
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
sprintf(s, "BoxWidth _A sub _A lineto BoxWidth _A sub BoxHeight _A sub lineto ");
|
snprintf(s, len, "BoxWidth _A sub _A lineto BoxWidth _A sub BoxHeight _A sub lineto ");
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
if (Nargs == 1) {
|
if (Nargs == 1) {
|
||||||
sprintf(s, "_A BoxHeight _A sub lineto closepath %d 100 div setgray fill 0.0 setgray", ARGV(0));
|
snprintf(s, len, "_A BoxHeight _A sub lineto closepath %d 100 div setgray fill 0.0 setgray", ARGV(0));
|
||||||
} else {
|
} else {
|
||||||
sprintf(s, "_A BoxHeight _A sub lineto closepath %d 100 div %d 100 div %d 100 div setrgbcolor fill 0.0 setgray", ARGV(0), ARGV(1), ARGV(2));
|
snprintf(s, len, "_A BoxHeight _A sub lineto closepath %d 100 div %d 100 div %d 100 div setrgbcolor fill 0.0 setgray", ARGV(0), ARGV(1), ARGV(2));
|
||||||
}
|
}
|
||||||
return RetStrVal(psbuff, info);
|
return RetStrVal(psbuff, info);
|
||||||
}
|
}
|
||||||
@@ -3056,6 +3063,7 @@ static int FPsmoon(func_info *info)
|
|||||||
char const *extra = NULL;
|
char const *extra = NULL;
|
||||||
int size = -1;
|
int size = -1;
|
||||||
int fontsize = -1;
|
int fontsize = -1;
|
||||||
|
size_t len = sizeof(psbuff);
|
||||||
|
|
||||||
ASSERT_TYPE(0, INT_TYPE);
|
ASSERT_TYPE(0, INT_TYPE);
|
||||||
if (ARGV(0) < 0) return E_2LOW;
|
if (ARGV(0) < 0) return E_2LOW;
|
||||||
@@ -3076,63 +3084,74 @@ static int FPsmoon(func_info *info)
|
|||||||
}
|
}
|
||||||
if (!psmoon_warned) {
|
if (!psmoon_warned) {
|
||||||
psmoon_warned = 1;
|
psmoon_warned = 1;
|
||||||
Wprint("psmoon() is deprecated; use SPECIAL MOON instead.");
|
Wprint(tr("psmoon() is deprecated; use SPECIAL MOON instead."));
|
||||||
}
|
}
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
sprintf(sizebuf, "%d", size);
|
snprintf(sizebuf, sizeof(sizebuf), "%d", size);
|
||||||
} else {
|
} else {
|
||||||
strcpy(sizebuf, "DaySize 2 div");
|
strcpy(sizebuf, "DaySize 2 div");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fontsize > 0) {
|
if (fontsize > 0) {
|
||||||
sprintf(fontsizebuf, "%d", fontsize);
|
snprintf(fontsizebuf, sizeof(fontsizebuf), "%d", fontsize);
|
||||||
} else {
|
} else {
|
||||||
strcpy(fontsizebuf, "EntrySize");
|
strcpy(fontsizebuf, "EntrySize");
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(s, "gsave 0 setgray newpath Border %s add BoxHeight Border sub %s sub",
|
snprintf(s, len, "gsave 0 setgray newpath Border %s add BoxHeight Border sub %s sub",
|
||||||
sizebuf, sizebuf);
|
sizebuf, sizebuf);
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
sprintf(s, " %s 0 360 arc closepath", sizebuf);
|
snprintf(s, len, " %s 0 360 arc closepath", sizebuf);
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
switch(ARGV(0)) {
|
switch(ARGV(0)) {
|
||||||
case 0:
|
case 0:
|
||||||
sprintf(s, " fill");
|
snprintf(s, len, " fill");
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
sprintf(s, " stroke");
|
snprintf(s, len, " stroke");
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
sprintf(s, " stroke");
|
snprintf(s, len, " stroke");
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
sprintf(s, " newpath Border %s add BoxHeight Border sub %s sub",
|
snprintf(s, len, " newpath Border %s add BoxHeight Border sub %s sub",
|
||||||
sizebuf, sizebuf);
|
sizebuf, sizebuf);
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
sprintf(s, " %s 90 270 arc closepath fill", sizebuf);
|
snprintf(s, len, " %s 90 270 arc closepath fill", sizebuf);
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
sprintf(s, " stroke");
|
snprintf(s, len, " stroke");
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
sprintf(s, " newpath Border %s add BoxHeight Border sub %s sub",
|
snprintf(s, len, " newpath Border %s add BoxHeight Border sub %s sub",
|
||||||
sizebuf, sizebuf);
|
sizebuf, sizebuf);
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
sprintf(s, " %s 270 90 arc closepath fill", sizebuf);
|
snprintf(s, len, " %s 270 90 arc closepath fill", sizebuf);
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (extra) {
|
if (extra) {
|
||||||
sprintf(s, " Border %s add %s add Border add BoxHeight border sub %s sub %s sub moveto /EntryFont findfont %s scalefont setfont (%s) show",
|
snprintf(s, len, " Border %s add %s add Border add BoxHeight border sub %s sub %s sub moveto /EntryFont findfont %s scalefont setfont (%s) show",
|
||||||
sizebuf, sizebuf, sizebuf, sizebuf, fontsizebuf, extra);
|
sizebuf, sizebuf, sizebuf, sizebuf, fontsizebuf, extra);
|
||||||
|
len -= strlen(s);
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(s, " grestore");
|
snprintf(s, len, " grestore");
|
||||||
return RetStrVal(psbuff, info);
|
return RetStrVal(psbuff, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3263,20 +3282,20 @@ static int FDatepart(func_info *info)
|
|||||||
* used for the timezone stuff! */
|
* used for the timezone stuff! */
|
||||||
static int setenv(char const *varname, char const *val, int overwrite)
|
static int setenv(char const *varname, char const *val, int overwrite)
|
||||||
{
|
{
|
||||||
static char tzbuf[256];
|
static char tzbuf[128];
|
||||||
if (strcmp(varname, "TZ")) {
|
if (strcmp(varname, "TZ")) {
|
||||||
fprintf(stderr, "built-in setenv can only be used with TZ\n");
|
fprintf(ErrFp, "built-in setenv can only be used with TZ\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
if (!overwrite) {
|
if (!overwrite) {
|
||||||
fprintf(stderr, "built-in setenv must have overwrite=1\n");
|
fprintf(ErrFp, "built-in setenv must have overwrite=1\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(val) > 250) {
|
if (strlen(val) > 250) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sprintf(tzbuf, "%s=%s", varname, val);
|
snprintf(tzbuf, sizeof(tzbuf), "%s=%s", varname, val);
|
||||||
return(putenv(tzbuf));
|
return(putenv(tzbuf));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -3285,12 +3304,12 @@ static int setenv(char const *varname, char const *val, int overwrite)
|
|||||||
* used for the timezone stuff! */
|
* used for the timezone stuff! */
|
||||||
static void unsetenv(char const *varname)
|
static void unsetenv(char const *varname)
|
||||||
{
|
{
|
||||||
static char tzbuf[8];
|
static char tzbuf[128];
|
||||||
if (strcmp(varname, "TZ")) {
|
if (strcmp(varname, "TZ")) {
|
||||||
fprintf(stderr, "built-in unsetenv can only be used with TZ\n");
|
fprintf(ErrFp, "built-in unsetenv can only be used with TZ\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
sprintf(tzbuf, "%s", varname);
|
snprintf(tzbuf, sizeof(tzbuf), "%s", varname);
|
||||||
putenv(tzbuf);
|
putenv(tzbuf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -3622,7 +3641,7 @@ FEvalTrig(func_info *info)
|
|||||||
} else {
|
} else {
|
||||||
/* Hokey... */
|
/* Hokey... */
|
||||||
if (trig.scanfrom != DSEToday) {
|
if (trig.scanfrom != DSEToday) {
|
||||||
Wprint("Warning: SCANFROM is ignored in two-argument form of evaltrig()");
|
Wprint(tr("Warning: SCANFROM is ignored in two-argument form of evaltrig()"));
|
||||||
}
|
}
|
||||||
dse = ComputeTrigger(scanfrom, &trig, &tim, &r, 0);
|
dse = ComputeTrigger(scanfrom, &trig, &tim, &r, 0);
|
||||||
}
|
}
|
||||||
@@ -3677,7 +3696,7 @@ FMultiTrig(func_info *info)
|
|||||||
return E_PARSE_ERR;
|
return E_PARSE_ERR;
|
||||||
}
|
}
|
||||||
if (tim.ttime != NO_TIME) {
|
if (tim.ttime != NO_TIME) {
|
||||||
Eprint("Cannot use AT clause in multitrig() function");
|
Eprint(tr("Cannot use AT clause in multitrig() function"));
|
||||||
return E_PARSE_ERR;
|
return E_PARSE_ERR;
|
||||||
}
|
}
|
||||||
dse = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 0);
|
dse = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 0);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/* globals.h and err.h */
|
/* globals.h and err.h */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
/* MK_GLOBALS. Also contains useful macro definitions. */
|
/* MK_GLOBALS. Also contains useful macro definitions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -68,6 +68,7 @@ EXTERN INIT( int PsCal, 0);
|
|||||||
EXTERN INIT( int CalWidth, 80);
|
EXTERN INIT( int CalWidth, 80);
|
||||||
EXTERN INIT( int CalWeeks, 0);
|
EXTERN INIT( int CalWeeks, 0);
|
||||||
EXTERN INIT( int CalMonths, 0);
|
EXTERN INIT( int CalMonths, 0);
|
||||||
|
EXTERN INIT( char const *CalType, "none");
|
||||||
EXTERN INIT( int Hush, 0);
|
EXTERN INIT( int Hush, 0);
|
||||||
EXTERN INIT( int NextMode, 0);
|
EXTERN INIT( int NextMode, 0);
|
||||||
EXTERN INIT( int InfiniteDelta, 0);
|
EXTERN INIT( int InfiniteDelta, 0);
|
||||||
@@ -175,6 +176,9 @@ EXTERN INIT( unsigned int FuncRecursionLevel, 0);
|
|||||||
/* Suppress warnings about implicit REM and MSG */
|
/* Suppress warnings about implicit REM and MSG */
|
||||||
EXTERN INIT( int SuppressImplicitRemWarnings, 0);
|
EXTERN INIT( int SuppressImplicitRemWarnings, 0);
|
||||||
|
|
||||||
|
/* Test mode - used by the acceptance tests */
|
||||||
|
EXTERN INIT( int TestMode, 0);
|
||||||
|
|
||||||
extern int NumFullOmits, NumPartialOmits;
|
extern int NumFullOmits, NumPartialOmits;
|
||||||
|
|
||||||
/* List of months */
|
/* List of months */
|
||||||
@@ -236,3 +240,6 @@ EXTERN int SuppressLRM
|
|||||||
= 0
|
= 0
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Translatable messages */
|
||||||
|
extern char const *translatables[];
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Implementation of hash table. */
|
/* Implementation of hash table. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
* These are used as choices for the number of hash buckets in the table
|
* These are used as choices for the number of hash buckets in the table
|
||||||
*/
|
*/
|
||||||
static size_t bucket_choices[] = {
|
static size_t bucket_choices[] = {
|
||||||
17, 37, 79, 163, 331, 673, 1361, 2729, 5471, 10949, 21911, 43853, 87719,
|
7, 17, 37, 79, 163, 331, 673, 1361, 2729, 5471, 10949, 21911, 43853, 87719,
|
||||||
175447, 350899, 701819, 1403641, 2807303, 5614657, 11229331, 22458671,
|
175447, 350899, 701819, 1403641, 2807303, 5614657, 11229331, 22458671,
|
||||||
44917381, 89834777, 179669557, 359339171, 718678369, 1437356741 };
|
44917381, 89834777, 179669557, 359339171, 718678369, 1437356741 };
|
||||||
|
|
||||||
@@ -108,6 +108,8 @@ hash_table_init(hash_table *t,
|
|||||||
t->hashfunc = hashfunc;
|
t->hashfunc = hashfunc;
|
||||||
t->compare = compare;
|
t->compare = compare;
|
||||||
t->buckets = malloc(sizeof(void *) * bucket_choices[0]);
|
t->buckets = malloc(sizeof(void *) * bucket_choices[0]);
|
||||||
|
t->num_growths = 0;
|
||||||
|
t->num_shrinks = 0;
|
||||||
if (!t->buckets) {
|
if (!t->buckets) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -216,6 +218,11 @@ hash_table_resize(hash_table *t, int dir)
|
|||||||
/* Out of memory... just don't resize? */
|
/* Out of memory... just don't resize? */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (dir == 1) {
|
||||||
|
t->num_growths++;
|
||||||
|
} else {
|
||||||
|
t->num_shrinks++;
|
||||||
|
}
|
||||||
for (size_t j=0; j<num_new_buckets; j++) {
|
for (size_t j=0; j<num_new_buckets; j++) {
|
||||||
new_buckets[j] = NULL;
|
new_buckets[j] = NULL;
|
||||||
}
|
}
|
||||||
@@ -305,32 +312,6 @@ hash_table_find(hash_table *t, void *candidate)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Find the next item in a hash table
|
|
||||||
*
|
|
||||||
* \param t Pointer to a hash table object
|
|
||||||
* \param obj Pointer to an object that was perviously returned by
|
|
||||||
* hash_table_find() or hash_table_find_next().
|
|
||||||
*
|
|
||||||
* \return A pointer to the next object matching obj, or NULL if
|
|
||||||
* no more exist
|
|
||||||
*/
|
|
||||||
void *
|
|
||||||
hash_table_find_next(hash_table *t, void *obj)
|
|
||||||
{
|
|
||||||
if (!obj) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
void *ptr = LINK(t, obj)->next;
|
|
||||||
while(ptr) {
|
|
||||||
if (!t->compare(obj, ptr)) {
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
ptr = LINK(t, ptr)->next;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Delete an item from a hash table
|
* \brief Delete an item from a hash table
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Header file for hash-table related functions. */
|
/* Header file for hash-table related functions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -29,6 +29,8 @@ struct hash_link {
|
|||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int bucket_choice_index; /**< Index into array of possible bucket counts */
|
unsigned int bucket_choice_index; /**< Index into array of possible bucket counts */
|
||||||
|
size_t num_growths; /**< How many times have we grown the hash table? */
|
||||||
|
size_t num_shrinks; /**< How many times have we grown the hash table? */
|
||||||
size_t num_entries; /**< Number of entries in the hash table */
|
size_t num_entries; /**< Number of entries in the hash table */
|
||||||
size_t hash_link_offset; /**< Offset of the struct hash_link in the container */
|
size_t hash_link_offset; /**< Offset of the struct hash_link in the container */
|
||||||
void **buckets; /**< Array of buckets */
|
void **buckets; /**< Array of buckets */
|
||||||
@@ -45,6 +47,8 @@ struct hash_table_stats {
|
|||||||
size_t num_nonempty_buckets; /**< Number of non-emptry buckets */
|
size_t num_nonempty_buckets; /**< Number of non-emptry buckets */
|
||||||
size_t max_len; /**< Length of longest chain in the hash table */
|
size_t max_len; /**< Length of longest chain in the hash table */
|
||||||
size_t min_len; /**< Length of the shortest chain in the hash table */
|
size_t min_len; /**< Length of the shortest chain in the hash table */
|
||||||
|
size_t num_growths; /**< How many times have we grown the hash table? */
|
||||||
|
size_t num_shrinks; /**< How many times have we grown the hash table? */
|
||||||
double avg_len; /**< Average chain length */
|
double avg_len; /**< Average chain length */
|
||||||
double avg_nonempty_len; /**< Average chain length of non-empty bucket */
|
double avg_nonempty_len; /**< Average chain length of non-empty bucket */
|
||||||
double stddev; /**< Standard deviation of chain lengths */
|
double stddev; /**< Standard deviation of chain lengths */
|
||||||
@@ -60,7 +64,6 @@ size_t hash_table_num_buckets(hash_table *t);
|
|||||||
size_t hash_table_chain_len(hash_table *t, size_t i);
|
size_t hash_table_chain_len(hash_table *t, size_t i);
|
||||||
int hash_table_insert(hash_table *t, void *item);
|
int hash_table_insert(hash_table *t, void *item);
|
||||||
void *hash_table_find(hash_table *t, void *candidate);
|
void *hash_table_find(hash_table *t, void *candidate);
|
||||||
void *hash_table_find_next(hash_table *t, void *obj);
|
|
||||||
int hash_table_delete(hash_table *t, void *item);
|
int hash_table_delete(hash_table *t, void *item);
|
||||||
int hash_table_delete_no_resize(hash_table *t, void *item);
|
int hash_table_delete_no_resize(hash_table *t, void *item);
|
||||||
void *hash_table_next(hash_table *t, void *cur);
|
void *hash_table_next(hash_table *t, void *cur);
|
||||||
@@ -84,29 +87,3 @@ void hash_table_get_stats(hash_table *t, struct hash_table_stats *stat);
|
|||||||
(item); \
|
(item); \
|
||||||
(item) = hash_table_next((t), (item)))
|
(item) = hash_table_next((t), (item)))
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Iterate over all items in a hash table that match a candidate
|
|
||||||
*
|
|
||||||
* This macro iterates over all items in a hash table that match a
|
|
||||||
* candidate object. (In general, a hash table may contain multiple
|
|
||||||
* objects with the same key.) Here is an example assuming that the hash
|
|
||||||
* table holds objects of type struct int_object:
|
|
||||||
*
|
|
||||||
* struct int_object {
|
|
||||||
* int value;
|
|
||||||
* struct hash_link link;
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* hash_table tab;
|
|
||||||
* int_object candidate;
|
|
||||||
*
|
|
||||||
* candidate.value = 7;
|
|
||||||
* int_object *item;
|
|
||||||
* hash_table_for_each_matching(item, &candidate, &tab) {
|
|
||||||
* // Do something with item, which will match "7"
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
#define hash_table_for_each_matching(item, candidate, t) \
|
|
||||||
for ((item) = hash_table_find((t), (candidate)); \
|
|
||||||
(item); \
|
|
||||||
(item) = hash_table_find_next((t), (item)))
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Utility function to print hash table stats. */
|
/* Utility function to print hash table stats. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -33,14 +33,15 @@ hash_table_dump_stats(hash_table *t, FILE *fp)
|
|||||||
{
|
{
|
||||||
struct hash_table_stats stat;
|
struct hash_table_stats stat;
|
||||||
hash_table_get_stats(t, &stat);
|
hash_table_get_stats(t, &stat);
|
||||||
fprintf(fp, "#Entries: %lu\n#Buckets: %lu\n#Non-empty Buckets: %lu\n",
|
fprintf(fp, " Entries: %lu; Buckets: %lu; Non-empty Buckets: %lu\n",
|
||||||
(unsigned long) stat.num_entries,
|
(unsigned long) stat.num_entries,
|
||||||
(unsigned long) stat.num_buckets,
|
(unsigned long) stat.num_buckets,
|
||||||
(unsigned long) stat.num_nonempty_buckets);
|
(unsigned long) stat.num_nonempty_buckets);
|
||||||
fprintf(fp, "Max len: %lu\nMin len: %lu\nAvg len: %.4f\nStd dev: %.4f\nAvg nonempty len: %.4f\n",
|
fprintf(fp, " Maxlen: %lu; Minlen: %lu; Avglen: %.3f; Stddev: %.3f; Avg nonempty len: %.3f\n",
|
||||||
(unsigned long) stat.max_len,
|
(unsigned long) stat.max_len,
|
||||||
(unsigned long) stat.min_len,
|
(unsigned long) stat.min_len,
|
||||||
stat.avg_len, stat.stddev, stat.avg_nonempty_len);
|
stat.avg_len, stat.stddev, stat.avg_nonempty_len);
|
||||||
|
fprintf(fp, " Growths: %lu; Shrinks: %lu\n", (unsigned long) stat.num_growths, (unsigned long) stat.num_shrinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,6 +68,8 @@ hash_table_get_stats(hash_table *t, struct hash_table_stats *stat)
|
|||||||
stat->stddev = 0.0;
|
stat->stddev = 0.0;
|
||||||
stat->num_nonempty_buckets = 0;
|
stat->num_nonempty_buckets = 0;
|
||||||
stat->avg_nonempty_len = 0.0;
|
stat->avg_nonempty_len = 0.0;
|
||||||
|
stat->num_growths = t->num_growths;
|
||||||
|
stat->num_shrinks = t->num_shrinks;
|
||||||
double sum = 0.0;
|
double sum = 0.0;
|
||||||
double sumsq = 0.0;
|
double sumsq = 0.0;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Support for the Hebrew calendar */
|
/* Support for the Hebrew calendar */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/* Derived from code written by Amos Shapir in 1978; revised */
|
/* Derived from code written by Amos Shapir in 1978; revised */
|
||||||
@@ -324,7 +324,7 @@ int GetValidHebDate(int yin, int min, int din, int adarbehave,
|
|||||||
case ADAR2ADARB: *mout = min = ADARB; break;
|
case ADAR2ADARB: *mout = min = ADARB; break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Eprint("GetValidHebDate: Bad adarbehave value %d", adarbehave);
|
Eprint(tr("GetValidHebDate: Bad adarbehave value %d"), adarbehave);
|
||||||
return E_SWERR;
|
return E_SWERR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -464,7 +464,7 @@ int ComputeJahr(int y, int m, int d, int *ans)
|
|||||||
|
|
||||||
/* Check for Adar A */
|
/* Check for Adar A */
|
||||||
if (m == ADARA && monlen[m] == 0) {
|
if (m == ADARA && monlen[m] == 0) {
|
||||||
Eprint("No Adar A in %d", y);
|
Eprint(tr("No Adar A in %d"), y);
|
||||||
return E_BAD_HEBDATE;
|
return E_BAD_HEBDATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
84
src/init.c
84
src/init.c
@@ -7,7 +7,7 @@
|
|||||||
/* in normal mode. */
|
/* in normal mode. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -149,7 +149,7 @@ static char const *DefaultFilename(void)
|
|||||||
|
|
||||||
s = getenv("HOME");
|
s = getenv("HOME");
|
||||||
if (!s) {
|
if (!s) {
|
||||||
fprintf(stderr, "HOME environment variable not set. Unable to determine reminder file.\n");
|
fprintf(ErrFp, "HOME environment variable not set. Unable to determine reminder file.\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
DBufPuts(&default_filename_buf, s);
|
DBufPuts(&default_filename_buf, s);
|
||||||
@@ -217,6 +217,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
RealToday = SystemDate(&CurYear, &CurMon, &CurDay);
|
RealToday = SystemDate(&CurYear, &CurMon, &CurDay);
|
||||||
if (RealToday < 0) {
|
if (RealToday < 0) {
|
||||||
fprintf(ErrFp, GetErr(M_BAD_SYS_DATE), BASE);
|
fprintf(ErrFp, GetErr(M_BAD_SYS_DATE), BASE);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
DSEToday = RealToday;
|
DSEToday = RealToday;
|
||||||
@@ -237,7 +238,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
InvokedAsRem = 1;
|
InvokedAsRem = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Invoked with a NULL argv[0]; bailing because that's just plain bizarre.\n");
|
fprintf(ErrFp, "Invoked with a NULL argv[0]; bailing because that's just plain bizarre.\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,9 +502,11 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (weeks) {
|
if (weeks) {
|
||||||
|
CalType = "weekly";
|
||||||
PARSENUM(CalWeeks, arg);
|
PARSENUM(CalWeeks, arg);
|
||||||
if (!CalWeeks) CalWeeks = 1;
|
if (!CalWeeks) CalWeeks = 1;
|
||||||
} else {
|
} else {
|
||||||
|
CalType = "monthly";
|
||||||
PARSENUM(CalMonths, arg);
|
PARSENUM(CalMonths, arg);
|
||||||
if (!CalMonths) CalMonths = 1;
|
if (!CalMonths) CalMonths = 1;
|
||||||
}
|
}
|
||||||
@@ -528,9 +531,11 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (weeks) {
|
if (weeks) {
|
||||||
|
CalType = "weekly";
|
||||||
PARSENUM(CalWeeks, arg);
|
PARSENUM(CalWeeks, arg);
|
||||||
if (!CalWeeks) CalWeeks = 1;
|
if (!CalWeeks) CalWeeks = 1;
|
||||||
} else {
|
} else {
|
||||||
|
CalType = "monthly";
|
||||||
PARSENUM(CalMonths, arg);
|
PARSENUM(CalMonths, arg);
|
||||||
if (!CalMonths) CalMonths = 1;
|
if (!CalMonths) CalMonths = 1;
|
||||||
}
|
}
|
||||||
@@ -541,10 +546,14 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
DoSimpleCalendar = 1;
|
DoSimpleCalendar = 1;
|
||||||
IgnoreOnce = 1;
|
IgnoreOnce = 1;
|
||||||
PsCal = PSCAL_LEVEL1;
|
PsCal = PSCAL_LEVEL1;
|
||||||
|
weeks = 0;
|
||||||
while (*arg == 'a' || *arg == 'A' ||
|
while (*arg == 'a' || *arg == 'A' ||
|
||||||
*arg == 'q' || *arg == 'Q' ||
|
*arg == 'q' || *arg == 'Q' ||
|
||||||
|
*arg == '+' ||
|
||||||
*arg == 'p' || *arg == 'P') {
|
*arg == 'p' || *arg == 'P') {
|
||||||
if (*arg == 'a' || *arg == 'A') {
|
if (*arg == '+') {
|
||||||
|
weeks = 1;
|
||||||
|
} else if (*arg == 'a' || *arg == 'A') {
|
||||||
DoSimpleCalDelta = 1;
|
DoSimpleCalDelta = 1;
|
||||||
} else if (*arg == 'p' || *arg == 'P') {
|
} else if (*arg == 'p' || *arg == 'P') {
|
||||||
/* JSON interchange formats always include
|
/* JSON interchange formats always include
|
||||||
@@ -560,8 +569,16 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
}
|
}
|
||||||
arg++;
|
arg++;
|
||||||
}
|
}
|
||||||
PARSENUM(CalMonths, arg);
|
if (weeks) {
|
||||||
if (!CalMonths) CalMonths = 1;
|
CalType = "weekly";
|
||||||
|
PARSENUM(CalWeeks, arg);
|
||||||
|
if (!CalWeeks) CalWeeks = 1;
|
||||||
|
PsCal = PSCAL_LEVEL3;
|
||||||
|
} else {
|
||||||
|
CalType = "monthly";
|
||||||
|
PARSENUM(CalMonths, arg);
|
||||||
|
if (!CalMonths) CalMonths = 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
@@ -577,7 +594,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
/* -wt means get width from /dev/tty */
|
/* -wt means get width from /dev/tty */
|
||||||
ttyfd = open("/dev/tty", O_RDONLY);
|
ttyfd = open("/dev/tty", O_RDONLY);
|
||||||
if (ttyfd < 0) {
|
if (ttyfd < 0) {
|
||||||
fprintf(stderr, "%s: `-wt': Cannot open /dev/tty: %s\n",
|
fprintf(ErrFp, "%s: `-wt': Cannot open /dev/tty: %s\n",
|
||||||
argv[0], strerror(errno));
|
argv[0], strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
InitCalWidthAndFormWidth(ttyfd);
|
InitCalWidthAndFormWidth(ttyfd);
|
||||||
@@ -618,14 +635,17 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
while (*arg) {
|
while (*arg) {
|
||||||
switch(*arg++) {
|
switch(*arg++) {
|
||||||
case 's': case 'S': DebugFlag |= DB_PARSE_EXPR; break;
|
case 's': case 'S': DebugFlag |= DB_PARSE_EXPR; break;
|
||||||
|
case 'h': case 'H': DebugFlag |= DB_HASHSTATS; break;
|
||||||
case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
|
case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
|
||||||
case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break;
|
case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break;
|
||||||
case 't': case 'T': DebugFlag |= DB_PRTTRIG; break;
|
case 't': case 'T': DebugFlag |= DB_PRTTRIG; break;
|
||||||
case 'v': case 'V': DebugFlag |= DB_DUMP_VARS; break;
|
case 'v': case 'V': DebugFlag |= DB_DUMP_VARS; break;
|
||||||
case 'l': case 'L': DebugFlag |= DB_PRTLINE; break;
|
case 'l': case 'L': DebugFlag |= DB_PRTLINE; break;
|
||||||
case 'f': case 'F': DebugFlag |= DB_TRACE_FILES; break;
|
case 'f': case 'F': DebugFlag |= DB_TRACE_FILES; break;
|
||||||
|
case 'q': case 'Q': DebugFlag |= DB_TRANSLATE; break;
|
||||||
default:
|
default:
|
||||||
fprintf(ErrFp, GetErr(M_BAD_DB_FLAG), *(arg-1));
|
fprintf(ErrFp, GetErr(M_BAD_DB_FLAG), *(arg-1));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -661,6 +681,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(ErrFp, GetErr(M_BAD_OPTION), *(arg-1));
|
fprintf(ErrFp, GetErr(M_BAD_OPTION), *(arg-1));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -728,7 +749,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
if (tok.type == T_Illegal && tok.val < 0) {
|
if (tok.type == T_Illegal && tok.val < 0) {
|
||||||
fprintf(stderr, "%s: `%s'\n", GetErr(-tok.val), arg);
|
fprintf(ErrFp, "%s: `%s'\n", GetErr(-tok.val), arg);
|
||||||
Usage();
|
Usage();
|
||||||
}
|
}
|
||||||
Usage();
|
Usage();
|
||||||
@@ -774,10 +795,11 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Figure out the offset from UTC */
|
/* Figure out the offset from UTC */
|
||||||
if (CalculateUTC)
|
if (CalculateUTC) {
|
||||||
(void) CalcMinsFromUTC(DSEToday, MinutesPastMidnight(0),
|
(void) CalcMinsFromUTC(DSEToday, MinutesPastMidnight(0),
|
||||||
&MinsFromUTC, NULL);
|
&MinsFromUTC, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -790,7 +812,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
#ifndef L_USAGE_OVERRIDE
|
#ifndef L_USAGE_OVERRIDE
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s Copyright 1992-2024 Dianne Skoll\n", VERSION);
|
fprintf(ErrFp, "\nREMIND %s Copyright (C) 1992-2025 Dianne Skoll\n", VERSION);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
@@ -853,6 +875,7 @@ static void ChgUser(char const *user)
|
|||||||
|
|
||||||
if (!pwent) {
|
if (!pwent) {
|
||||||
fprintf(ErrFp, GetErr(M_BAD_USER), user);
|
fprintf(ErrFp, GetErr(M_BAD_USER), user);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -861,16 +884,19 @@ static void ChgUser(char const *user)
|
|||||||
#ifdef HAVE_INITGROUPS
|
#ifdef HAVE_INITGROUPS
|
||||||
if (initgroups(pwent->pw_name, pwent->pw_gid) < 0) {
|
if (initgroups(pwent->pw_name, pwent->pw_gid) < 0) {
|
||||||
fprintf(ErrFp, GetErr(M_NO_CHG_GID), pwent->pw_gid);
|
fprintf(ErrFp, GetErr(M_NO_CHG_GID), pwent->pw_gid);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
if (setgid(pwent->pw_gid) < 0) {
|
if (setgid(pwent->pw_gid) < 0) {
|
||||||
fprintf(ErrFp, GetErr(M_NO_CHG_GID), pwent->pw_gid);
|
fprintf(ErrFp, GetErr(M_NO_CHG_GID), pwent->pw_gid);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setuid(pwent->pw_uid) < 0) {
|
if (setuid(pwent->pw_uid) < 0) {
|
||||||
fprintf(ErrFp, GetErr(M_NO_CHG_UID), pwent->pw_uid);
|
fprintf(ErrFp, GetErr(M_NO_CHG_UID), pwent->pw_uid);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -878,6 +904,7 @@ static void ChgUser(char const *user)
|
|||||||
home = malloc(strlen(pwent->pw_dir) + 6);
|
home = malloc(strlen(pwent->pw_dir) + 6);
|
||||||
if (!home) {
|
if (!home) {
|
||||||
fprintf(ErrFp, "%s", GetErr(M_NOMEM_ENV));
|
fprintf(ErrFp, "%s", GetErr(M_NOMEM_ENV));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
sprintf(home, "HOME=%s", pwent->pw_dir);
|
sprintf(home, "HOME=%s", pwent->pw_dir);
|
||||||
@@ -886,6 +913,7 @@ static void ChgUser(char const *user)
|
|||||||
shell = malloc(strlen(pwent->pw_shell) + 7);
|
shell = malloc(strlen(pwent->pw_shell) + 7);
|
||||||
if (!shell) {
|
if (!shell) {
|
||||||
fprintf(ErrFp, "%s", GetErr(M_NOMEM_ENV));
|
fprintf(ErrFp, "%s", GetErr(M_NOMEM_ENV));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
sprintf(shell, "SHELL=%s", pwent->pw_shell);
|
sprintf(shell, "SHELL=%s", pwent->pw_shell);
|
||||||
@@ -895,6 +923,7 @@ static void ChgUser(char const *user)
|
|||||||
username = malloc(strlen(pwent->pw_name) + 6);
|
username = malloc(strlen(pwent->pw_name) + 6);
|
||||||
if (!username) {
|
if (!username) {
|
||||||
fprintf(ErrFp, "%s", GetErr(M_NOMEM_ENV));
|
fprintf(ErrFp, "%s", GetErr(M_NOMEM_ENV));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
sprintf(username, "USER=%s", pwent->pw_name);
|
sprintf(username, "USER=%s", pwent->pw_name);
|
||||||
@@ -902,6 +931,7 @@ static void ChgUser(char const *user)
|
|||||||
logname= malloc(strlen(pwent->pw_name) + 9);
|
logname= malloc(strlen(pwent->pw_name) + 9);
|
||||||
if (!logname) {
|
if (!logname) {
|
||||||
fprintf(ErrFp, "%s", GetErr(M_NOMEM_ENV));
|
fprintf(ErrFp, "%s", GetErr(M_NOMEM_ENV));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
sprintf(logname, "LOGNAME=%s", pwent->pw_name);
|
sprintf(logname, "LOGNAME=%s", pwent->pw_name);
|
||||||
@@ -947,6 +977,7 @@ static void InitializeVar(char const *str)
|
|||||||
varname[r++] = *str;
|
varname[r++] = *str;
|
||||||
} else {
|
} else {
|
||||||
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(E_ILLEGAL_CHAR));
|
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(E_ILLEGAL_CHAR));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -960,12 +991,14 @@ static void InitializeVar(char const *str)
|
|||||||
varname[r] = 0;
|
varname[r] = 0;
|
||||||
if (!*varname) {
|
if (!*varname) {
|
||||||
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(E_MISS_VAR));
|
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(E_MISS_VAR));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!*str) {
|
if (!*str) {
|
||||||
/* Setting a system var does require =expr on the commandline */
|
/* Setting a system var does require =expr on the commandline */
|
||||||
if (*varname == '$') {
|
if (*varname == '$') {
|
||||||
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(E_MISS_EQ));
|
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(E_MISS_EQ));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
val.type = INT_TYPE;
|
val.type = INT_TYPE;
|
||||||
@@ -976,40 +1009,51 @@ static void InitializeVar(char const *str)
|
|||||||
}
|
}
|
||||||
if (r) {
|
if (r) {
|
||||||
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(r));
|
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(r));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*varname) {
|
if (!*varname) {
|
||||||
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(E_MISS_VAR));
|
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(E_MISS_VAR));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
expr = str+1;
|
expr = str+1;
|
||||||
if (!*expr) {
|
if (!*expr) {
|
||||||
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(E_MISS_EXPR));
|
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(E_MISS_EXPR));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
r=EvalExpr(&expr, &val, NULL);
|
r=EvalExpr(&expr, &val, NULL);
|
||||||
if (r) {
|
if (r) {
|
||||||
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(r));
|
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(r));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*varname == '$') {
|
if (*varname == '$') {
|
||||||
r=SetSysVar(varname+1, &val);
|
r=SetSysVar(varname+1, &val);
|
||||||
DestroyValue(val);
|
DestroyValue(val);
|
||||||
if (r) fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(r));
|
if (r) {
|
||||||
|
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(r));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
r=SetVar(varname, &val);
|
r=SetVar(varname, &val);
|
||||||
if (r) {
|
if (r) {
|
||||||
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(r));
|
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(r));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
r=PreserveVar(varname);
|
r=PreserveVar(varname);
|
||||||
if (r) fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(r));
|
if (r) {
|
||||||
|
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(r));
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1018,7 +1062,7 @@ AddTrustedUser(char const *username)
|
|||||||
{
|
{
|
||||||
struct passwd *pwent;
|
struct passwd *pwent;
|
||||||
if (NumTrustedUsers >= MAX_TRUSTED_USERS) {
|
if (NumTrustedUsers >= MAX_TRUSTED_USERS) {
|
||||||
fprintf(stderr, "Too many trusted users (%d max)\n",
|
fprintf(ErrFp, "Too many trusted users (%d max)\n",
|
||||||
MAX_TRUSTED_USERS);
|
MAX_TRUSTED_USERS);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@@ -1026,6 +1070,7 @@ AddTrustedUser(char const *username)
|
|||||||
pwent = getpwnam(username);
|
pwent = getpwnam(username);
|
||||||
if (!pwent) {
|
if (!pwent) {
|
||||||
fprintf(ErrFp, GetErr(M_BAD_USER), username);
|
fprintf(ErrFp, GetErr(M_BAD_USER), username);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
TrustedUsers[NumTrustedUsers] = pwent->pw_uid;
|
TrustedUsers[NumTrustedUsers] = pwent->pw_uid;
|
||||||
@@ -1077,6 +1122,17 @@ static void
|
|||||||
ProcessLongOption(char const *arg)
|
ProcessLongOption(char const *arg)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
|
if (!strcmp(arg, "test")) {
|
||||||
|
fprintf(stderr, "Enabling test mode: This is meant for the acceptance test.\nDo not use --test in production.\nIn test mode, the system time is fixed at 2025-01-06@19:00\n");
|
||||||
|
TestMode = 1;
|
||||||
|
|
||||||
|
/* Update RealToday because of TestMode */
|
||||||
|
RealToday = SystemDate(&CurYear, &CurMon, &CurDay);
|
||||||
|
DSEToday = RealToday;
|
||||||
|
FromDSE(DSEToday, &CurYear, &CurMon, &CurDay);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!strcmp(arg, "version")) {
|
if (!strcmp(arg, "version")) {
|
||||||
printf("%s\n", VERSION);
|
printf("%s\n", VERSION);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
|
|||||||
40
src/json.c
40
src/json.c
@@ -299,7 +299,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
if (flags & flag_string)
|
if (flags & flag_string)
|
||||||
{
|
{
|
||||||
if (!b)
|
if (!b)
|
||||||
{ sprintf (error, "Unexpected EOF in string (at %u:%u)", line_and_col);
|
{ snprintf (error, sizeof(error), "Unexpected EOF in string (at %u:%u)", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,7 +325,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
|
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||||
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
|
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
|
||||||
{
|
{
|
||||||
sprintf (error, "Invalid character value `%c` (at %u:%u)", b, line_and_col);
|
snprintf (error, sizeof(error), "Invalid character value `%c` (at %u:%u)", b, line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +342,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
|
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||||
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
|
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
|
||||||
{
|
{
|
||||||
sprintf (error, "Invalid character value `%c` (at %u:%u)", b, line_and_col);
|
snprintf (error, sizeof(error), "Invalid character value `%c` (at %u:%u)", b, line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,7 +472,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
if (flags & flag_block_comment)
|
if (flags & flag_block_comment)
|
||||||
{
|
{
|
||||||
if (!b)
|
if (!b)
|
||||||
{ sprintf (error, "%u:%u: Unexpected EOF in block comment", line_and_col);
|
{ snprintf (error, sizeof(error), "%u:%u: Unexpected EOF in block comment", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,12 +488,12 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
else if (b == '/')
|
else if (b == '/')
|
||||||
{
|
{
|
||||||
if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
|
if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
|
||||||
{ sprintf (error, "%u:%u: Comment not allowed here", line_and_col);
|
{ snprintf (error, sizeof(error), "%u:%u: Comment not allowed here", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++ state.ptr == end)
|
if (++ state.ptr == end)
|
||||||
{ sprintf (error, "%u:%u: EOF unexpected", line_and_col);
|
{ snprintf (error, sizeof(error), "%u:%u: EOF unexpected", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +508,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
sprintf (error, "%u:%u: Unexpected `%c` in comment opening sequence", line_and_col, b);
|
snprintf (error, sizeof(error), "%u:%u: Unexpected `%c` in comment opening sequence", line_and_col, b);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -526,7 +526,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
sprintf (error, "%u:%u: Trailing garbage: `%c`",
|
snprintf (error, sizeof(error), "%u:%u: Trailing garbage: `%c`",
|
||||||
state.cur_line, state.cur_col, b);
|
state.cur_line, state.cur_col, b);
|
||||||
|
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
@@ -545,7 +545,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
if (top && top->type == json_array)
|
if (top && top->type == json_array)
|
||||||
flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
|
flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
|
||||||
else
|
else
|
||||||
{ sprintf (error, "%u:%u: Unexpected ]", line_and_col);
|
{ snprintf (error, sizeof(error), "%u:%u: Unexpected ]", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,7 +561,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf (error, "%u:%u: Expected , before %c",
|
snprintf (error, sizeof(error), "%u:%u: Expected , before %c",
|
||||||
state.cur_line, state.cur_col, b);
|
state.cur_line, state.cur_col, b);
|
||||||
|
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
@@ -576,7 +576,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf (error, "%u:%u: Expected : before %c",
|
snprintf (error, sizeof(error), "%u:%u: Expected : before %c",
|
||||||
state.cur_line, state.cur_col, b);
|
state.cur_line, state.cur_col, b);
|
||||||
|
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
@@ -702,7 +702,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ sprintf (error, "%u:%u: Unexpected %c when seeking value", line_and_col, b);
|
{ snprintf (error, sizeof(error), "%u:%u: Unexpected %c when seeking value", line_and_col, b);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -722,7 +722,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
case '"':
|
case '"':
|
||||||
|
|
||||||
if (flags & flag_need_comma)
|
if (flags & flag_need_comma)
|
||||||
{ sprintf (error, "%u:%u: Expected , before \"", line_and_col);
|
{ snprintf (error, sizeof(error), "%u:%u: Expected , before \"", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,7 +747,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
default:
|
default:
|
||||||
sprintf (error, "%u:%u: Unexpected `%c` in object", line_and_col, b);
|
snprintf (error, sizeof(error), "%u:%u: Unexpected `%c` in object", line_and_col, b);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -765,7 +765,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
if (! (flags & flag_num_e))
|
if (! (flags & flag_num_e))
|
||||||
{
|
{
|
||||||
if (flags & flag_num_zero)
|
if (flags & flag_num_zero)
|
||||||
{ sprintf (error, "%u:%u: Unexpected `0` before `%c`", line_and_col, b);
|
{ snprintf (error, sizeof(error), "%u:%u: Unexpected `0` before `%c`", line_and_col, b);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -814,7 +814,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
else if (b == '.' && top->type == json_integer)
|
else if (b == '.' && top->type == json_integer)
|
||||||
{
|
{
|
||||||
if (!num_digits)
|
if (!num_digits)
|
||||||
{ sprintf (error, "%u:%u: Expected digit before `.`", line_and_col);
|
{ snprintf (error, sizeof(error), "%u:%u: Expected digit before `.`", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -831,7 +831,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
if (top->type == json_double)
|
if (top->type == json_double)
|
||||||
{
|
{
|
||||||
if (!num_digits)
|
if (!num_digits)
|
||||||
{ sprintf (error, "%u:%u: Expected digit after `.`", line_and_col);
|
{ snprintf (error, sizeof(error), "%u:%u: Expected digit after `.`", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -857,7 +857,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!num_digits)
|
if (!num_digits)
|
||||||
{ sprintf (error, "%u:%u: Expected digit after `e`", line_and_col);
|
{ snprintf (error, sizeof(error), "%u:%u: Expected digit after `e`", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -942,7 +942,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
|
|
||||||
e_unknown_value:
|
e_unknown_value:
|
||||||
|
|
||||||
sprintf (error, "%u:%u: Unknown value", line_and_col);
|
snprintf (error, sizeof(error), "%u:%u: Unknown value", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
|
|
||||||
e_alloc_failure:
|
e_alloc_failure:
|
||||||
@@ -952,7 +952,7 @@ e_alloc_failure:
|
|||||||
|
|
||||||
e_overflow:
|
e_overflow:
|
||||||
|
|
||||||
sprintf (error, "%u:%u: Too long (caught overflow)", line_and_col);
|
snprintf (error, sizeof(error), "%u:%u: Too long (caught overflow)", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
|
|
||||||
e_failed:
|
e_failed:
|
||||||
|
|||||||
123
src/main.c
123
src/main.c
@@ -6,7 +6,7 @@
|
|||||||
/* routines, etc. */
|
/* routines, etc. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -60,19 +60,21 @@ exitfunc(void)
|
|||||||
/* Kill any execution-time-limiter process */
|
/* Kill any execution-time-limiter process */
|
||||||
unlimit_execution_time();
|
unlimit_execution_time();
|
||||||
|
|
||||||
int maxlen, total;
|
if (DebugFlag & DB_HASHSTATS) {
|
||||||
double avglen;
|
|
||||||
if (DebugFlag & DB_PARSE_EXPR) {
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fflush(stderr);
|
fflush(ErrFp);
|
||||||
get_var_hash_stats(&total, &maxlen, &avglen);
|
fprintf(ErrFp, "Variable hash table statistics:\n");
|
||||||
fprintf(stderr, " Var hash: total = %d; maxlen = %d; avglen = %.3f\n", total, maxlen, avglen);
|
dump_var_hash_stats();
|
||||||
get_userfunc_hash_stats(&total, &maxlen, &avglen);
|
|
||||||
fprintf(stderr, " Func hash: total = %d; maxlen = %d; avglen = %.3f\n", total, maxlen, avglen);
|
fprintf(ErrFp, "Function hash table statistics:\n");
|
||||||
get_dedupe_hash_stats(&total, &maxlen, &avglen);
|
dump_userfunc_hash_stats();
|
||||||
fprintf(stderr, "Dedup hash: total = %d; maxlen = %d; avglen = %.3f\n", total, maxlen, avglen);
|
|
||||||
get_translation_hash_stats(&total, &maxlen, &avglen);
|
fprintf(ErrFp, "Dedupe hash table statistics:\n");
|
||||||
fprintf(stderr, "Trans hash: total = %d; maxlen = %d; avglen = %.3f\n", total, maxlen, avglen);
|
dump_dedupe_hash_stats();
|
||||||
|
|
||||||
|
fprintf(ErrFp, "Translation hash table statistics:\n");
|
||||||
|
dump_translation_hash_stats();
|
||||||
|
|
||||||
UnsetAllUserFuncs();
|
UnsetAllUserFuncs();
|
||||||
print_expr_nodes_stats();
|
print_expr_nodes_stats();
|
||||||
}
|
}
|
||||||
@@ -128,7 +130,7 @@ int main(int argc, char *argv[])
|
|||||||
sigemptyset(&act.sa_mask);
|
sigemptyset(&act.sa_mask);
|
||||||
act.sa_flags = SA_RESTART;
|
act.sa_flags = SA_RESTART;
|
||||||
if (sigaction(SIGALRM, &act, NULL) < 0) {
|
if (sigaction(SIGALRM, &act, NULL) < 0) {
|
||||||
fprintf(stderr, "%s: sigaction() failed: %s\n",
|
fprintf(ErrFp, "%s: sigaction() failed: %s\n",
|
||||||
argv[0], strerror(errno));
|
argv[0], strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -137,7 +139,7 @@ int main(int argc, char *argv[])
|
|||||||
act.sa_flags = SA_RESTART;
|
act.sa_flags = SA_RESTART;
|
||||||
sigemptyset(&act.sa_mask);
|
sigemptyset(&act.sa_mask);
|
||||||
if (sigaction(SIGXCPU, &act, NULL) < 0) {
|
if (sigaction(SIGXCPU, &act, NULL) < 0) {
|
||||||
fprintf(stderr, "%s: sigaction() failed: %s\n",
|
fprintf(ErrFp, "%s: sigaction() failed: %s\n",
|
||||||
argv[0], strerror(errno));
|
argv[0], strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -177,6 +179,7 @@ int main(int argc, char *argv[])
|
|||||||
printf("%s\n", GetErr(E_NOREMINDERS));
|
printf("%s\n", GetErr(E_NOREMINDERS));
|
||||||
} else if (!Daemon && !NextMode && !NumTriggered) {
|
} else if (!Daemon && !NextMode && !NumTriggered) {
|
||||||
printf(GetErr(M_QUEUED), NumQueued);
|
printf(GetErr(M_QUEUED), NumQueued);
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,7 +374,7 @@ static void DoReminders(void)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
if (!SuppressImplicitRemWarnings) {
|
if (!SuppressImplicitRemWarnings) {
|
||||||
Wprint("Unrecognized command; interpreting as REM");
|
Wprint(tr("Unrecognized command; interpreting as REM"));
|
||||||
WarnedAboutImplicit = 1;
|
WarnedAboutImplicit = 1;
|
||||||
}
|
}
|
||||||
DestroyParser(&p);
|
DestroyParser(&p);
|
||||||
@@ -600,6 +603,24 @@ int ParseNonSpaceChar(ParsePtr p, int *err, int peek)
|
|||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* */
|
||||||
|
/* ParseTokenOrQuotedString */
|
||||||
|
/* */
|
||||||
|
/* Parse either a token or a double-quote-delimited string. */
|
||||||
|
/* */
|
||||||
|
/***************************************************************/
|
||||||
|
int ParseTokenOrQuotedString(ParsePtr p, DynamicBuffer *dbuf)
|
||||||
|
{
|
||||||
|
int c, err;
|
||||||
|
c = ParseNonSpaceChar(p, &err, 1);
|
||||||
|
if (err) return err;
|
||||||
|
if (c != '"') {
|
||||||
|
return ParseToken(p, dbuf);
|
||||||
|
}
|
||||||
|
return ParseQuotedString(p, dbuf);
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* ParseQuotedString */
|
/* ParseQuotedString */
|
||||||
@@ -989,6 +1010,11 @@ int SystemTime(int realtime)
|
|||||||
|
|
||||||
if (!realtime && (SysTime != -1)) return SysTime;
|
if (!realtime && (SysTime != -1)) return SysTime;
|
||||||
|
|
||||||
|
if (TestMode) {
|
||||||
|
/* Pretend it's 7:00PM in test mode */
|
||||||
|
return 19 * 3600;
|
||||||
|
}
|
||||||
|
|
||||||
now = time(NULL);
|
now = time(NULL);
|
||||||
t = localtime(&now);
|
t = localtime(&now);
|
||||||
return t->tm_hour * 3600L + t->tm_min * 60L +
|
return t->tm_hour * 3600L + t->tm_min * 60L +
|
||||||
@@ -1022,6 +1048,14 @@ int SystemDate(int *y, int *m, int *d)
|
|||||||
time_t now;
|
time_t now;
|
||||||
struct tm *t;
|
struct tm *t;
|
||||||
|
|
||||||
|
/* In test mode, always return 6 January 2025 */
|
||||||
|
if (TestMode) {
|
||||||
|
*y = 2025;
|
||||||
|
*m = 0;
|
||||||
|
*d = 6;
|
||||||
|
return 12789; /* 2025-01-06 */
|
||||||
|
}
|
||||||
|
|
||||||
now = time(NULL);
|
now = time(NULL);
|
||||||
t = localtime(&now);
|
t = localtime(&now);
|
||||||
|
|
||||||
@@ -1247,12 +1281,24 @@ int DoDebug(ParsePtr p)
|
|||||||
else DebugFlag &= ~DB_ECHO_LINE;
|
else DebugFlag &= ~DB_ECHO_LINE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
case 'Q':
|
||||||
|
if (val) DebugFlag |= DB_TRANSLATE;
|
||||||
|
else DebugFlag &= ~DB_TRANSLATE;
|
||||||
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
case 'S':
|
case 'S':
|
||||||
if (val) DebugFlag |= DB_PARSE_EXPR;
|
if (val) DebugFlag |= DB_PARSE_EXPR;
|
||||||
else DebugFlag &= ~DB_PARSE_EXPR;
|
else DebugFlag &= ~DB_PARSE_EXPR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
case 'H':
|
||||||
|
if (val) DebugFlag |= DB_HASHSTATS;
|
||||||
|
else DebugFlag &= ~DB_HASHSTATS;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
if (val) DebugFlag |= DB_PRTEXPR;
|
if (val) DebugFlag |= DB_PRTEXPR;
|
||||||
@@ -1282,6 +1328,9 @@ int DoDebug(ParsePtr p)
|
|||||||
if (val) DebugFlag |= DB_TRACE_FILES;
|
if (val) DebugFlag |= DB_TRACE_FILES;
|
||||||
else DebugFlag &= ~DB_TRACE_FILES;
|
else DebugFlag &= ~DB_TRACE_FILES;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
Wprint(GetErr(M_BAD_DB_FLAG), ch);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1980,7 +2029,7 @@ get_day_name(int wkday)
|
|||||||
if (wkday < 0 || wkday > 6) {
|
if (wkday < 0 || wkday > 6) {
|
||||||
return "INVALID_WKDAY";
|
return "INVALID_WKDAY";
|
||||||
}
|
}
|
||||||
return t(DayName[wkday]);
|
return tr(DayName[wkday]);
|
||||||
}
|
}
|
||||||
|
|
||||||
char const *
|
char const *
|
||||||
@@ -1989,7 +2038,7 @@ get_month_name(int mon)
|
|||||||
if (mon < 0 || mon > 11) {
|
if (mon < 0 || mon > 11) {
|
||||||
return "INVALID_MON";
|
return "INVALID_MON";
|
||||||
}
|
}
|
||||||
return t(MonthName[mon]);
|
return tr(MonthName[mon]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GetOnceDateFromFile(void)
|
static int GetOnceDateFromFile(void)
|
||||||
@@ -2008,7 +2057,7 @@ static int GetOnceDateFromFile(void)
|
|||||||
/* Save today to file */
|
/* Save today to file */
|
||||||
fp = fopen(OnceFile, "w");
|
fp = fopen(OnceFile, "w");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
Wprint("Warning: Unable to save ONCE timestamp to %s: %s",
|
Wprint(tr("Warning: Unable to save ONCE timestamp to %s: %s"),
|
||||||
OnceFile, strerror(errno));
|
OnceFile, strerror(errno));
|
||||||
return once_date;
|
return once_date;
|
||||||
}
|
}
|
||||||
@@ -2029,25 +2078,9 @@ int GetOnceDate(void)
|
|||||||
return OnceDate;
|
return OnceDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
get_printf_escapes(char const *str, DynamicBuffer *out)
|
|
||||||
{
|
|
||||||
char const *s = str;
|
|
||||||
while(*s) {
|
|
||||||
if (*s == '%' && *(s+1) != 0) {
|
|
||||||
s++;
|
|
||||||
DBufPutc(out, *s);
|
|
||||||
}
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *GetErr(int r)
|
char const *GetErr(int r)
|
||||||
{
|
{
|
||||||
char const *msg;
|
char const *msg;
|
||||||
DynamicBuffer origEscapes;
|
|
||||||
DynamicBuffer translatedEscapes;
|
|
||||||
int dangerous;
|
|
||||||
|
|
||||||
if (r < 0 || r >= NumErrs) {
|
if (r < 0 || r >= NumErrs) {
|
||||||
r = E_SWERR;
|
r = E_SWERR;
|
||||||
@@ -2058,23 +2091,5 @@ char const *GetErr(int r)
|
|||||||
return ErrMsg[r];
|
return ErrMsg[r];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to make sure both the original and translated version
|
return msg;
|
||||||
have the *SAME* printf-style escapes to avoid a malicious
|
|
||||||
translation file doing a format-string attack */
|
|
||||||
DBufInit(&origEscapes);
|
|
||||||
DBufInit(&translatedEscapes);
|
|
||||||
|
|
||||||
get_printf_escapes(ErrMsg[r], &origEscapes);
|
|
||||||
get_printf_escapes(msg, &translatedEscapes);
|
|
||||||
|
|
||||||
dangerous = strcmp(DBufValue(&origEscapes), DBufValue(&translatedEscapes));
|
|
||||||
|
|
||||||
DBufFree(&origEscapes);
|
|
||||||
DBufFree(&translatedEscapes);
|
|
||||||
|
|
||||||
if (dangerous) {
|
|
||||||
return ErrMsg[r];
|
|
||||||
} else {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Calculations for figuring out moon phases. */
|
/* Calculations for figuring out moon phases. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
15
src/omit.c
15
src/omit.c
@@ -6,7 +6,7 @@
|
|||||||
/* the data structures for OMITted dates. */
|
/* the data structures for OMITted dates. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -92,7 +92,7 @@ int DestroyOmitContexts(int print_unmatched)
|
|||||||
|
|
||||||
while (c) {
|
while (c) {
|
||||||
if (print_unmatched) {
|
if (print_unmatched) {
|
||||||
Wprint("Unmatched PUSH-OMIT-CONTEXT at %s(%d)",
|
Wprint(tr("Unmatched PUSH-OMIT-CONTEXT at %s(%d)"),
|
||||||
c->filename, c->lineno);
|
c->filename, c->lineno);
|
||||||
}
|
}
|
||||||
num++;
|
num++;
|
||||||
@@ -185,6 +185,9 @@ int PopOmitContext(ParsePtr p)
|
|||||||
/* Remove the context from the stack */
|
/* Remove the context from the stack */
|
||||||
SavedOmitContexts = c->next;
|
SavedOmitContexts = c->next;
|
||||||
|
|
||||||
|
if (c->filename && FileName && strcmp(c->filename, FileName)) {
|
||||||
|
Wprint(tr("POP-OMIT-CONTEXT at %s:%d matches PUSH-OMIT-CONTEXT in different file: %s:%d"), FileName, LineNo, c->filename, c->lineno);
|
||||||
|
}
|
||||||
/* Free memory used by the saved context */
|
/* Free memory used by the saved context */
|
||||||
if (c->partsave) free(c->partsave);
|
if (c->partsave) free(c->partsave);
|
||||||
if (c->fullsave) free(c->fullsave);
|
if (c->fullsave) free(c->fullsave);
|
||||||
@@ -215,7 +218,7 @@ int IsOmitted(int dse, int localomit, char const *omitfunc, int *omit)
|
|||||||
Value v;
|
Value v;
|
||||||
|
|
||||||
FromDSE(dse, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
sprintf(expr, "%s('%04d-%02d-%02d')",
|
snprintf(expr, sizeof(expr), "%s('%04d-%02d-%02d')",
|
||||||
omitfunc, y, m+1, d);
|
omitfunc, y, m+1, d);
|
||||||
s = expr;
|
s = expr;
|
||||||
r = EvalExpr(&s, &v, NULL);
|
r = EvalExpr(&s, &v, NULL);
|
||||||
@@ -392,7 +395,7 @@ int DoOmit(ParsePtr p)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
if (tok.type == T_Until) {
|
if (tok.type == T_Until) {
|
||||||
Eprint("OMIT: UNTIL not allowed; did you mean THROUGH?");
|
Eprint(tr("OMIT: UNTIL not allowed; did you mean THROUGH?"));
|
||||||
} else if (tok.type == T_Illegal && tok.val < 0) {
|
} else if (tok.type == T_Illegal && tok.val < 0) {
|
||||||
Eprint("%s: `%s'", GetErr(-tok.val), DBufValue(&buf));
|
Eprint("%s: `%s'", GetErr(-tok.val), DBufValue(&buf));
|
||||||
} else {
|
} else {
|
||||||
@@ -462,7 +465,7 @@ int DoOmit(ParsePtr p)
|
|||||||
InsertIntoSortedArray(PartialOmitArray, NumPartialOmits, syndrome);
|
InsertIntoSortedArray(PartialOmitArray, NumPartialOmits, syndrome);
|
||||||
NumPartialOmits++;
|
NumPartialOmits++;
|
||||||
if (NumPartialOmits == 366) {
|
if (NumPartialOmits == 366) {
|
||||||
Wprint("You have OMITted everything! The space-time continuum is at risk.");
|
Wprint(tr("You have OMITted everything! The space-time continuum is at risk."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mc == m[1] && dc == d[1]) {
|
if (mc == m[1] && dc == d[1]) {
|
||||||
@@ -484,7 +487,7 @@ int DoOmit(ParsePtr p)
|
|||||||
start = DSE(y[0], m[0], d[0]);
|
start = DSE(y[0], m[0], d[0]);
|
||||||
end = DSE(y[1], m[1], d[1]);
|
end = DSE(y[1], m[1], d[1]);
|
||||||
if (end < start) {
|
if (end < start) {
|
||||||
Eprint("Error: THROUGH date earlier than start date");
|
Eprint(tr("Error: THROUGH date earlier than start date"));
|
||||||
return E_BAD_DATE;
|
return E_BAD_DATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
16
src/protos.h
16
src/protos.h
@@ -5,7 +5,7 @@
|
|||||||
/* Function Prototypes. */
|
/* Function Prototypes. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -88,6 +88,7 @@ int JulianToGregorianOffset(int y, int m);
|
|||||||
int ParseChar (ParsePtr p, int *err, int peek);
|
int ParseChar (ParsePtr p, int *err, int peek);
|
||||||
int ParseToken (ParsePtr p, DynamicBuffer *dbuf);
|
int ParseToken (ParsePtr p, DynamicBuffer *dbuf);
|
||||||
int ParseQuotedString (ParsePtr p, DynamicBuffer *dbuf);
|
int ParseQuotedString (ParsePtr p, DynamicBuffer *dbuf);
|
||||||
|
int ParseTokenOrQuotedString (ParsePtr p, DynamicBuffer *dbuf);
|
||||||
int ParseIdentifier (ParsePtr p, DynamicBuffer *dbuf);
|
int ParseIdentifier (ParsePtr p, DynamicBuffer *dbuf);
|
||||||
expr_node * ParseExpr(ParsePtr p, int *r);
|
expr_node * ParseExpr(ParsePtr p, int *r);
|
||||||
void print_expr_nodes_stats(void);
|
void print_expr_nodes_stats(void);
|
||||||
@@ -228,7 +229,6 @@ 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);
|
||||||
void clear_callstack(void);
|
void clear_callstack(void);
|
||||||
int print_callstack(FILE *fp);
|
int print_callstack(FILE *fp);
|
||||||
int have_callstack(void);
|
|
||||||
void pop_call(void);
|
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);
|
||||||
@@ -255,10 +255,10 @@ void print_builtinfunc_tokens(void);
|
|||||||
void print_remind_tokens(void);
|
void print_remind_tokens(void);
|
||||||
|
|
||||||
/* Stats for -ds output */
|
/* Stats for -ds output */
|
||||||
void get_var_hash_stats(int *total, int *maxlen, double *avglen);
|
void dump_var_hash_stats(void);
|
||||||
void get_userfunc_hash_stats(int *total, int *maxlen, double *avglen);
|
void dump_userfunc_hash_stats(void);
|
||||||
void get_dedupe_hash_stats(int *total, int *maxlen, double *avglen);
|
void dump_dedupe_hash_stats(void);
|
||||||
void get_translation_hash_stats(int *total, int *maxlen, double *avglen);
|
void dump_translation_hash_stats(void);
|
||||||
|
|
||||||
/* Dedupe code */
|
/* Dedupe code */
|
||||||
int ShouldDedupe(int trigger_date, int trigger_time, char const *body);
|
int ShouldDedupe(int trigger_date, int trigger_time, char const *body);
|
||||||
@@ -271,6 +271,8 @@ void InitTranslationTable(void);
|
|||||||
char const *GetTranslatedString(char const *orig);
|
char const *GetTranslatedString(char const *orig);
|
||||||
int GetTranslatedStringTryingVariants(char const *orig, DynamicBuffer *out);
|
int GetTranslatedStringTryingVariants(char const *orig, DynamicBuffer *out);
|
||||||
char const *GetErr(int r);
|
char const *GetErr(int r);
|
||||||
char const *t(char const *s);
|
|
||||||
char const *tr(char const *s);
|
char const *tr(char const *s);
|
||||||
void print_escaped_string(FILE *fp, char const *s);
|
void print_escaped_string(FILE *fp, char const *s);
|
||||||
|
void print_escaped_string_helper(FILE *fp, char const *s, int esc_for_remind);
|
||||||
|
void GenerateSysvarTranslationTemplates(void);
|
||||||
|
void TranslationTemplate(char const *msg);
|
||||||
|
|||||||
19
src/queue.c
19
src/queue.c
@@ -5,7 +5,7 @@
|
|||||||
/* Queue up reminders for subsequent execution. */
|
/* Queue up reminders for subsequent execution. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -346,8 +346,9 @@ void HandleQueuedReminders(void)
|
|||||||
/* If we're a daemon, get the mod time of initial file */
|
/* If we're a daemon, get the mod time of initial file */
|
||||||
if (Daemon > 0) {
|
if (Daemon > 0) {
|
||||||
if (stat(InitialFile, &StatBuf)) {
|
if (stat(InitialFile, &StatBuf)) {
|
||||||
fprintf(ErrFp, "Cannot stat %s - not running as daemon!\n",
|
fprintf(ErrFp, tr("Cannot stat %s - not running as daemon!"),
|
||||||
InitialFile);
|
InitialFile);
|
||||||
|
fprintf(ErrFp, "\n");
|
||||||
Daemon = 0;
|
Daemon = 0;
|
||||||
} else FileModTime = StatBuf.st_mtime;
|
} else FileModTime = StatBuf.st_mtime;
|
||||||
}
|
}
|
||||||
@@ -459,7 +460,11 @@ void HandleQueuedReminders(void)
|
|||||||
if (IsServerMode() && q->typ != RUN_TYPE) {
|
if (IsServerMode() && q->typ != RUN_TYPE) {
|
||||||
if (DaemonJSON) {
|
if (DaemonJSON) {
|
||||||
printf("{\"response\":\"reminder\",");
|
printf("{\"response\":\"reminder\",");
|
||||||
snprintf(qid, sizeof(qid), "%lx", (unsigned long) q);
|
if (TestMode) {
|
||||||
|
snprintf(qid, sizeof(qid), "42424242");
|
||||||
|
} else {
|
||||||
|
snprintf(qid, sizeof(qid), "%lx", (unsigned long) q);
|
||||||
|
}
|
||||||
PrintJSONKeyPairString("qid", qid);
|
PrintJSONKeyPairString("qid", qid);
|
||||||
PrintJSONKeyPairString("ttime", SimpleTimeNoSpace(q->tt.ttime));
|
PrintJSONKeyPairString("ttime", SimpleTimeNoSpace(q->tt.ttime));
|
||||||
PrintJSONKeyPairString("now", SimpleTimeNoSpace(MinutesPastMidnight(1)));
|
PrintJSONKeyPairString("now", SimpleTimeNoSpace(MinutesPastMidnight(1)));
|
||||||
@@ -697,7 +702,7 @@ static int CalculateNextTimeUsingSched(QueuedRem *q)
|
|||||||
to be a security hole! */
|
to be a security hole! */
|
||||||
while(1) {
|
while(1) {
|
||||||
char exprBuf[VAR_NAME_LEN+32];
|
char exprBuf[VAR_NAME_LEN+32];
|
||||||
sprintf(exprBuf, "%s(%d)", q->sched, q->ntrig);
|
snprintf(exprBuf, sizeof(exprBuf), "%s(%d)", q->sched, q->ntrig);
|
||||||
s = exprBuf;
|
s = exprBuf;
|
||||||
r = EvalExpr(&s, &v, NULL);
|
r = EvalExpr(&s, &v, NULL);
|
||||||
if (r) {
|
if (r) {
|
||||||
@@ -759,7 +764,11 @@ json_queue(QueuedRem const *q)
|
|||||||
printf("{");
|
printf("{");
|
||||||
WriteJSONTrigger(&(q->t), 1, DSEToday);
|
WriteJSONTrigger(&(q->t), 1, DSEToday);
|
||||||
WriteJSONTimeTrigger(&(q->tt));
|
WriteJSONTimeTrigger(&(q->tt));
|
||||||
snprintf(idbuf, sizeof(idbuf), "%lx", (unsigned long) q);
|
if (TestMode) {
|
||||||
|
snprintf(idbuf, sizeof(idbuf), "42424242");
|
||||||
|
} else {
|
||||||
|
snprintf(idbuf, sizeof(idbuf), "%lx", (unsigned long) q);
|
||||||
|
}
|
||||||
PrintJSONKeyPairString("qid", idbuf);
|
PrintJSONKeyPairString("qid", idbuf);
|
||||||
PrintJSONKeyPairInt("rundisabled", q->RunDisabled);
|
PrintJSONKeyPairInt("rundisabled", q->RunDisabled);
|
||||||
PrintJSONKeyPairInt("ntrig", q->ntrig);
|
PrintJSONKeyPairInt("ntrig", q->ntrig);
|
||||||
|
|||||||
10
src/rem2ps.c
10
src/rem2ps.c
@@ -5,7 +5,7 @@
|
|||||||
/* Print a PostScript calendar. */
|
/* Print a PostScript calendar. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -350,7 +350,7 @@ int main(int argc, char *argv[])
|
|||||||
!strcmp(DBufValue(&buf), PSBEGIN2)) {
|
!strcmp(DBufValue(&buf), PSBEGIN2)) {
|
||||||
if (!validfile) {
|
if (!validfile) {
|
||||||
if (Verbose) {
|
if (Verbose) {
|
||||||
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2024 by Dianne Skoll\n\n", VERSION);
|
fprintf(stderr, "Rem2PS: Version %s Copyright (C) 1992-2025 by Dianne Skoll\n\n", VERSION);
|
||||||
fprintf(stderr, "Generating PostScript calendar\n");
|
fprintf(stderr, "Generating PostScript calendar\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1222,7 +1222,7 @@ int DoQueuedPs(void)
|
|||||||
if (moonsize < 0) {
|
if (moonsize < 0) {
|
||||||
size = "DaySize 2 div";
|
size = "DaySize 2 div";
|
||||||
} else {
|
} else {
|
||||||
sprintf(buffer, "%d", moonsize);
|
snprintf(buffer, sizeof(buffer), "%d", moonsize);
|
||||||
size = buffer;
|
size = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1235,7 +1235,7 @@ int DoQueuedPs(void)
|
|||||||
if (fontsize < 0) {
|
if (fontsize < 0) {
|
||||||
fsize = "EntrySize";
|
fsize = "EntrySize";
|
||||||
} else {
|
} else {
|
||||||
sprintf(fbuffer, "%d", fontsize);
|
snprintf(fbuffer, sizeof(fbuffer), "%d", fontsize);
|
||||||
fsize = fbuffer;
|
fsize = fbuffer;
|
||||||
}
|
}
|
||||||
printf("/EntryFont findfont %s scalefont setfont (",
|
printf("/EntryFont findfont %s scalefont setfont (",
|
||||||
@@ -1273,7 +1273,7 @@ int DoQueuedPs(void)
|
|||||||
if (fontsize < 0) {
|
if (fontsize < 0) {
|
||||||
fsize = "EntrySize";
|
fsize = "EntrySize";
|
||||||
} else {
|
} else {
|
||||||
sprintf(fbuffer, "%d", fontsize);
|
snprintf(fbuffer, sizeof(fbuffer), "%d", fontsize);
|
||||||
fsize = fbuffer;
|
fsize = fbuffer;
|
||||||
}
|
}
|
||||||
printf("/EntryFont findfont %s scalefont setfont (",
|
printf("/EntryFont findfont %s scalefont setfont (",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Define the PostScript prologue */
|
/* Define the PostScript prologue */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -14,7 +14,7 @@ char *PSProlog1[] =
|
|||||||
{
|
{
|
||||||
"% This file was produced by Remind and Rem2PS, written by",
|
"% This file was produced by Remind and Rem2PS, written by",
|
||||||
"% Dianne Skoll.",
|
"% Dianne Skoll.",
|
||||||
"% Remind and Rem2PS are Copyright 1992-2024 Dianne Skoll.",
|
"% Remind and Rem2PS are Copyright (C) 1992-2025 Dianne Skoll.",
|
||||||
"/ISOLatin1Encoding where { pop save true }{ false } ifelse",
|
"/ISOLatin1Encoding where { pop save true }{ false } ifelse",
|
||||||
" /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus",
|
" /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus",
|
||||||
" StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute",
|
" StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Routines for sorting reminders by trigger date */
|
/* Routines for sorting reminders by trigger date */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -183,7 +183,7 @@ static void IssueSortBanner(int dse)
|
|||||||
if (UserFuncExists("sortbanner") != 1) return;
|
if (UserFuncExists("sortbanner") != 1) return;
|
||||||
|
|
||||||
FromDSE(dse, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
sprintf(BanExpr, "sortbanner('%04d/%02d/%02d')", y, m+1, d);
|
snprintf(BanExpr, sizeof(BanExpr), "sortbanner('%04d/%02d/%02d')", y, m+1, d);
|
||||||
y = EvalExpr(&s, &v, NULL);
|
y = EvalExpr(&s, &v, NULL);
|
||||||
if (y) return;
|
if (y) return;
|
||||||
if (DoCoerce(STR_TYPE, &v)) return;
|
if (DoCoerce(STR_TYPE, &v)) return;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* classifying the tokens parsed. */
|
/* classifying the tokens parsed. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
154
src/trans.c
154
src/trans.c
@@ -6,7 +6,7 @@
|
|||||||
/* the TRANSLATE keyword. */
|
/* the TRANSLATE keyword. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -34,6 +34,71 @@ typedef struct xlat {
|
|||||||
|
|
||||||
hash_table TranslationTable;
|
hash_table TranslationTable;
|
||||||
|
|
||||||
|
static XlateItem *FindTranslation(char const *orig);
|
||||||
|
static int printf_formatters_are_safe(char const *orig, char const *translated);
|
||||||
|
|
||||||
|
void
|
||||||
|
TranslationTemplate(char const *in)
|
||||||
|
{
|
||||||
|
if (!*in) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!strcmp(in, "LANGID")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("TRANSLATE ");
|
||||||
|
print_escaped_string_helper(stdout, in, 1);
|
||||||
|
if (FindTranslation(in)) {
|
||||||
|
printf(" ");
|
||||||
|
print_escaped_string_helper(stdout, tr(in), 1);
|
||||||
|
printf("\n");
|
||||||
|
} else {
|
||||||
|
printf(" \"\"\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
GenerateTranslationTemplate(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("# Translation table template\n\n");
|
||||||
|
|
||||||
|
printf("TRANSLATE \"LANGID\" ");
|
||||||
|
print_escaped_string_helper(stdout, tr("LANGID"), 1);
|
||||||
|
printf("\n\n");
|
||||||
|
|
||||||
|
printf("BANNER %s\n", DBufValue(&Banner));
|
||||||
|
|
||||||
|
printf("\n# Weekday Names\n");
|
||||||
|
for (i=0; i<7; i++) {
|
||||||
|
printf("SET $%s ", DayName[i]);
|
||||||
|
print_escaped_string_helper(stdout, tr(DayName[i]), 1);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n# Month Names\n");
|
||||||
|
for (i=0; i<12; i++) {
|
||||||
|
printf("SET $%s ", MonthName[i]);
|
||||||
|
print_escaped_string_helper(stdout, tr(MonthName[i]), 1);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n# Other Translation-related System Variables\n");
|
||||||
|
GenerateSysvarTranslationTemplates();
|
||||||
|
|
||||||
|
printf("\n# Error Messages\n");
|
||||||
|
for (i=0; i<NumErrs; i++) {
|
||||||
|
TranslationTemplate(ErrMsg[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n# Other Messages\n");
|
||||||
|
for (i=0; translatables[i] != NULL; i++) {
|
||||||
|
TranslationTemplate(translatables[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* AllocateXlateItem - Allocate a new translation item */
|
/* AllocateXlateItem - Allocate a new translation item */
|
||||||
@@ -113,6 +178,11 @@ ClearTranslationTable(void)
|
|||||||
void
|
void
|
||||||
print_escaped_string(FILE *fp, char const *s)
|
print_escaped_string(FILE *fp, char const *s)
|
||||||
{
|
{
|
||||||
|
print_escaped_string_helper(fp, s, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_escaped_string_helper(FILE *fp, char const *s, int esc_for_remind) {
|
||||||
putc('"', fp);
|
putc('"', fp);
|
||||||
while(*s) {
|
while(*s) {
|
||||||
switch(*s) {
|
switch(*s) {
|
||||||
@@ -126,7 +196,11 @@ print_escaped_string(FILE *fp, char const *s)
|
|||||||
case '"': putc('\\', fp); putc('"', fp); break;
|
case '"': putc('\\', fp); putc('"', fp); break;
|
||||||
case '\\': putc('\\', fp); putc('\\', fp); break;
|
case '\\': putc('\\', fp); putc('\\', fp); break;
|
||||||
default:
|
default:
|
||||||
putc(*s, fp); break;
|
if (esc_for_remind && *s == '[') {
|
||||||
|
fprintf(fp, "[\"[\"]");
|
||||||
|
} else {
|
||||||
|
putc(*s, fp); break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
@@ -202,7 +276,7 @@ InitTranslationTable(void)
|
|||||||
{
|
{
|
||||||
if (hash_table_init(&TranslationTable, offsetof(XlateItem, link),
|
if (hash_table_init(&TranslationTable, offsetof(XlateItem, link),
|
||||||
HashXlateItem, CompareXlateItems) < 0) {
|
HashXlateItem, CompareXlateItems) < 0) {
|
||||||
fprintf(stderr, "Unable to initialize translation hash table: Out of memory. Exiting.\n");
|
fprintf(ErrFp, "Unable to initialize translation hash table: Out of memory. Exiting.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
InsertTranslation("LANGID", "en");
|
InsertTranslation("LANGID", "en");
|
||||||
@@ -221,7 +295,13 @@ FindTranslation(char const *orig)
|
|||||||
int
|
int
|
||||||
InsertTranslation(char const *orig, char const *translated)
|
InsertTranslation(char const *orig, char const *translated)
|
||||||
{
|
{
|
||||||
XlateItem *item = FindTranslation(orig);
|
XlateItem *item;
|
||||||
|
|
||||||
|
if (!printf_formatters_are_safe(orig, translated)) {
|
||||||
|
Eprint(tr("Invalid translation: Both original and translated must have the same printf-style formatting sequences in the same order."));
|
||||||
|
return E_PARSE_ERR;
|
||||||
|
}
|
||||||
|
item = FindTranslation(orig);
|
||||||
if (item) {
|
if (item) {
|
||||||
if (!strcmp(item->translated, translated)) {
|
if (!strcmp(item->translated, translated)) {
|
||||||
/* Translation is the same; do nothing */
|
/* Translation is the same; do nothing */
|
||||||
@@ -230,7 +310,6 @@ InsertTranslation(char const *orig, char const *translated)
|
|||||||
RemoveTranslation(item);
|
RemoveTranslation(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TRANSLATE "foo" "foo" means to remove the translation */
|
|
||||||
if (strcmp(orig, "LANGID") && (!strcmp(orig, translated))) {
|
if (strcmp(orig, "LANGID") && (!strcmp(orig, translated))) {
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -313,7 +392,7 @@ GetTranslatedStringTryingVariants(char const *orig, DynamicBuffer *out)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const *t(char const *orig)
|
char const *tr(char const *orig)
|
||||||
{
|
{
|
||||||
char const *n = GetTranslatedString(orig);
|
char const *n = GetTranslatedString(orig);
|
||||||
if (n) {
|
if (n) {
|
||||||
@@ -322,12 +401,6 @@ char const *t(char const *orig)
|
|||||||
return orig;
|
return orig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If another "t" is in scope... */
|
|
||||||
char const *tr(char const *orig)
|
|
||||||
{
|
|
||||||
return t(orig);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
DoTranslate(ParsePtr p)
|
DoTranslate(ParsePtr p)
|
||||||
{
|
{
|
||||||
@@ -359,6 +432,12 @@ DoTranslate(ParsePtr p)
|
|||||||
ClearTranslationTable();
|
ClearTranslationTable();
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
if (!StrCmpi(DBufValue(&orig), "generate")) {
|
||||||
|
DBufFree(&orig);
|
||||||
|
if (r) return r;
|
||||||
|
GenerateTranslationTemplate();
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
return E_PARSE_ERR;
|
return E_PARSE_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,12 +471,51 @@ DoTranslate(ParsePtr p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
get_translation_hash_stats(int *total, int *maxlen, double *avglen)
|
dump_translation_hash_stats(void)
|
||||||
{
|
{
|
||||||
struct hash_table_stats s;
|
hash_table_dump_stats(&TranslationTable, ErrFp);
|
||||||
hash_table_get_stats(&TranslationTable, &s);
|
|
||||||
*total = s.num_entries;
|
|
||||||
*maxlen = s.max_len;
|
|
||||||
*avglen = s.avg_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_printf_escapes(char const *str, DynamicBuffer *out)
|
||||||
|
{
|
||||||
|
char const *s = str;
|
||||||
|
while(*s) {
|
||||||
|
if (*s == '%' && *(s+1) != 0) {
|
||||||
|
|
||||||
|
/* %% is safe and does not need to be replicated in translation */
|
||||||
|
if (*(s+1) == '%') {
|
||||||
|
s += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
DBufPutc(out, *s);
|
||||||
|
while (*s && *(s+1) && strchr("#0- +'I%123456789.hlqLjzZt", *s)) {
|
||||||
|
s++;
|
||||||
|
DBufPutc(out, *s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
printf_formatters_are_safe(char const *orig, char const *translated)
|
||||||
|
{
|
||||||
|
DynamicBuffer origEscapes;
|
||||||
|
DynamicBuffer translatedEscapes;
|
||||||
|
int dangerous;
|
||||||
|
|
||||||
|
DBufInit(&origEscapes);
|
||||||
|
DBufInit(&translatedEscapes);
|
||||||
|
|
||||||
|
get_printf_escapes(orig, &origEscapes);
|
||||||
|
get_printf_escapes(translated, &translatedEscapes);
|
||||||
|
|
||||||
|
dangerous = strcmp(DBufValue(&origEscapes), DBufValue(&translatedEscapes));
|
||||||
|
|
||||||
|
if (dangerous) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Routines for figuring out the trigger date of a reminder */
|
/* Routines for figuring out the trigger date of a reminder */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
42
src/types.h
42
src/types.h
@@ -5,7 +5,7 @@
|
|||||||
/* Type definitions all dumped here. */
|
/* Type definitions all dumped here. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -58,7 +58,7 @@ enum expr_node_type
|
|||||||
N_SHORT_USER_FUNC,
|
N_SHORT_USER_FUNC,
|
||||||
N_USER_FUNC,
|
N_USER_FUNC,
|
||||||
N_OPERATOR,
|
N_OPERATOR,
|
||||||
N_ERROR = 32767,
|
N_ERROR = 0x7FFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Structure for passing in Nargs and out RetVal from functions */
|
/* Structure for passing in Nargs and out RetVal from functions */
|
||||||
@@ -200,13 +200,15 @@ typedef Parser *ParsePtr; /* Pointer to parser structure */
|
|||||||
#define NO_MAX 127
|
#define NO_MAX 127
|
||||||
|
|
||||||
/* DEFINES for debugging flags */
|
/* DEFINES for debugging flags */
|
||||||
#define DB_PRTLINE 1
|
#define DB_PRTLINE 0x001
|
||||||
#define DB_PRTEXPR 2
|
#define DB_PRTEXPR 0x002
|
||||||
#define DB_PRTTRIG 4
|
#define DB_PRTTRIG 0x004
|
||||||
#define DB_DUMP_VARS 8
|
#define DB_DUMP_VARS 0x008
|
||||||
#define DB_ECHO_LINE 16
|
#define DB_ECHO_LINE 0x010
|
||||||
#define DB_TRACE_FILES 32
|
#define DB_TRACE_FILES 0x020
|
||||||
#define DB_PARSE_EXPR 64
|
#define DB_PARSE_EXPR 0x040
|
||||||
|
#define DB_HASHSTATS 0x080
|
||||||
|
#define DB_TRANSLATE 0x100
|
||||||
|
|
||||||
/* Enumeration of the tokens */
|
/* Enumeration of the tokens */
|
||||||
enum TokTypes
|
enum TokTypes
|
||||||
@@ -231,13 +233,13 @@ typedef struct {
|
|||||||
} Token;
|
} Token;
|
||||||
|
|
||||||
/* Flags for the state of the "if" stack */
|
/* Flags for the state of the "if" stack */
|
||||||
#define IF_TRUE 0
|
#define IF_TRUE 0x00
|
||||||
#define IF_FALSE 1
|
#define IF_FALSE 0x01
|
||||||
#define BEFORE_ELSE 0
|
#define BEFORE_ELSE 0x00
|
||||||
#define AFTER_ELSE 2
|
#define AFTER_ELSE 0x02
|
||||||
#define IF_MASK 3
|
#define IF_MASK 0x03
|
||||||
#define IF_TRUE_MASK 1
|
#define IF_TRUE_MASK 0x01
|
||||||
#define IF_ELSE_MASK 2
|
#define IF_ELSE_MASK 0x02
|
||||||
|
|
||||||
/* Flags for the DoSubst function */
|
/* Flags for the DoSubst function */
|
||||||
#define NORMAL_MODE 0
|
#define NORMAL_MODE 0
|
||||||
@@ -247,9 +249,9 @@ typedef struct {
|
|||||||
#define QUOTE_MARKER 1 /* Unlikely character to appear in reminder */
|
#define QUOTE_MARKER 1 /* Unlikely character to appear in reminder */
|
||||||
|
|
||||||
/* Flags for disabling run */
|
/* Flags for disabling run */
|
||||||
#define RUN_CMDLINE 1
|
#define RUN_CMDLINE 0x01
|
||||||
#define RUN_SCRIPT 2
|
#define RUN_SCRIPT 0x02
|
||||||
#define RUN_NOTOWNER 4
|
#define RUN_NOTOWNER 0x04
|
||||||
|
|
||||||
/* Flags for the SimpleCalendar format */
|
/* Flags for the SimpleCalendar format */
|
||||||
#define SC_AMPM 0 /* Time shown as 3:00am, etc. */
|
#define SC_AMPM 0 /* Time shown as 3:00am, etc. */
|
||||||
@@ -286,7 +288,7 @@ typedef struct {
|
|||||||
char const *name;
|
char const *name;
|
||||||
char modifiable;
|
char modifiable;
|
||||||
int type;
|
int type;
|
||||||
void const *value;
|
void *value;
|
||||||
int min; /* Or const-value */
|
int min; /* Or const-value */
|
||||||
int max;
|
int max;
|
||||||
} SysVar;
|
} SysVar;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* functions. */
|
/* functions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -56,7 +56,7 @@ InitUserFunctions(void)
|
|||||||
offsetof(UserFunc, link),
|
offsetof(UserFunc, link),
|
||||||
HashUserFunc,
|
HashUserFunc,
|
||||||
CompareUserFuncs) < 0) {
|
CompareUserFuncs) < 0) {
|
||||||
fprintf(stderr, "Unable to initialize function hash table: Out of memory. Exiting.\n");
|
fprintf(ErrFp, "Unable to initialize function hash table: Out of memory. Exiting.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,7 +208,7 @@ int DoFset(ParsePtr p)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
/* Warn about redefinition */
|
/* Warn about redefinition */
|
||||||
Wprint("Function %s redefined (previously defined at %s:%d)",
|
Wprint(tr("Function `%s' redefined (previously defined at %s:%d)"),
|
||||||
existing->name, existing->filename, existing->lineno);
|
existing->name, existing->filename, existing->lineno);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,7 +352,7 @@ int DoFset(ParsePtr p)
|
|||||||
/* Add the function definition */
|
/* Add the function definition */
|
||||||
FSet(func);
|
FSet(func);
|
||||||
if (orig_namelen > VAR_NAME_LEN) {
|
if (orig_namelen > VAR_NAME_LEN) {
|
||||||
Wprint("Warning: Function name `%s...' truncated to `%s'",
|
Wprint(tr("Warning: Function name `%s...' truncated to `%s'"),
|
||||||
func->name, func->name);
|
func->name, func->name);
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
@@ -506,12 +506,8 @@ RenameUserFunc(char const *oldname, char const *newname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
get_userfunc_hash_stats(int *total, int *maxlen, double *avglen)
|
dump_userfunc_hash_stats(void)
|
||||||
{
|
{
|
||||||
struct hash_table_stats s;
|
hash_table_dump_stats(&FuncHash, ErrFp);
|
||||||
hash_table_get_stats(&FuncHash, &s);
|
|
||||||
*total = s.num_entries;
|
|
||||||
*maxlen = s.max_len;
|
|
||||||
*avglen = s.avg_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
20
src/utils.c
20
src/utils.c
@@ -5,7 +5,7 @@
|
|||||||
/* Useful utility functions. */
|
/* Useful utility functions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -244,17 +244,18 @@ static void
|
|||||||
print_callstack_aux(FILE *fp, cs *entry)
|
print_callstack_aux(FILE *fp, cs *entry)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
char const *in = "In";
|
char const *in = tr("In");
|
||||||
cs *prev = NULL;
|
cs *prev = NULL;
|
||||||
while(entry) {
|
while(entry) {
|
||||||
if (prev) {
|
if (prev) {
|
||||||
in = "Called from";
|
in = tr("Called from");
|
||||||
}
|
}
|
||||||
if (!prev || strcmp(prev->func, entry->func) || strcmp(prev->filename, entry->filename) || prev->lineno != entry->lineno) {
|
if (!prev || strcmp(prev->func, entry->func) || strcmp(prev->filename, entry->filename) || prev->lineno != entry->lineno) {
|
||||||
if (prev) {
|
if (prev) {
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
(void) fprintf(fp, " %s(%d): [#%d] %s function `%s'", entry->filename, entry->lineno, i, in, entry->func);
|
fprintf(fp, " ");
|
||||||
|
fprintf(fp, tr("%s(%d): [#%d] %s function `%s'"), entry->filename, entry->lineno, i, in, entry->func);
|
||||||
}
|
}
|
||||||
prev = entry;
|
prev = entry;
|
||||||
entry = entry->next;
|
entry = entry->next;
|
||||||
@@ -264,14 +265,11 @@ print_callstack_aux(FILE *fp, cs *entry)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (entry) {
|
if (entry) {
|
||||||
(void) fprintf(fp, "\n [remaining call frames omitted]");
|
(void) fprintf(fp, "\n [");
|
||||||
}
|
(void) fprintf(fp, "%s", tr("remaining call frames omitted"));
|
||||||
}
|
(void) fprintf(fp, "]");
|
||||||
|
|
||||||
int
|
}
|
||||||
have_callstack(void)
|
|
||||||
{
|
|
||||||
return (callstack != NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
71
src/var.c
71
src/var.c
@@ -6,7 +6,7 @@
|
|||||||
/* user- and system-defined variables. */
|
/* user- and system-defined variables. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -56,7 +56,7 @@ InitVars(void)
|
|||||||
{
|
{
|
||||||
if (hash_table_init(&VHashTbl, offsetof(Var, link),
|
if (hash_table_init(&VHashTbl, offsetof(Var, link),
|
||||||
VarHashFunc, VarCompareFunc) < 0) {
|
VarHashFunc, VarCompareFunc) < 0) {
|
||||||
fprintf(stderr, "Unable to initialize variable hash table: Out of memory. Exiting.\n");
|
fprintf(ErrFp, "Unable to initialize variable hash table: Out of memory. Exiting.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,7 +85,7 @@ strtod_in_c_locale(char const *str, char **endptr)
|
|||||||
if (**endptr) {
|
if (**endptr) {
|
||||||
x = strtod(str, endptr);
|
x = strtod(str, endptr);
|
||||||
if (!**endptr) {
|
if (!**endptr) {
|
||||||
Wprint("Accepting \"%s\" for $Latitude/$Longitude, but you should use the \"C\" locale decimal separator \".\" instead", str);
|
Wprint(tr("Accepting \"%s\" for $Latitude/$Longitude, but you should use the \"C\" locale decimal separator \".\" instead"), str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
@@ -94,7 +94,7 @@ strtod_in_c_locale(char const *str, char **endptr)
|
|||||||
static void deprecated_var(char const *var, char const *instead)
|
static void deprecated_var(char const *var, char const *instead)
|
||||||
{
|
{
|
||||||
if (DebugFlag & DB_PRTLINE) {
|
if (DebugFlag & DB_PRTLINE) {
|
||||||
Wprint("%s is deprecated; use %s instead", var, instead);
|
Wprint(tr("%s is deprecated; use %s instead"), var, instead);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +201,7 @@ static int oncefile_func(int do_set, Value *val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ProcessedOnce) {
|
if (ProcessedOnce) {
|
||||||
Wprint("Not setting $OnceFile: Already processed a reminder with a ONCE clause");
|
Wprint(tr("Not setting $OnceFile: Already processed a reminder with a ONCE clause"));
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
if (OnceFile) {
|
if (OnceFile) {
|
||||||
@@ -608,7 +608,7 @@ int DoSet (Parser *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p->isnested) {
|
if (p->isnested) {
|
||||||
Eprint("%s", "Do not use [] around expression in SET command");
|
Eprint("%s", tr("Do not use [] around expression in SET command"));
|
||||||
return E_CANTNEST_FDEF;
|
return E_CANTNEST_FDEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -628,7 +628,7 @@ int DoSet (Parser *p)
|
|||||||
if (*DBufValue(&buf) == '$') r = SetSysVar(DBufValue(&buf)+1, &v);
|
if (*DBufValue(&buf) == '$') r = SetSysVar(DBufValue(&buf)+1, &v);
|
||||||
else r = SetVar(DBufValue(&buf), &v);
|
else r = SetVar(DBufValue(&buf), &v);
|
||||||
if (buf.len > VAR_NAME_LEN) {
|
if (buf.len > VAR_NAME_LEN) {
|
||||||
Wprint("Warning: Variable name `%.*s...' truncated to `%.*s'",
|
Wprint(tr("Warning: Variable name `%.*s...' truncated to `%.*s'"),
|
||||||
VAR_NAME_LEN, DBufValue(&buf), VAR_NAME_LEN, DBufValue(&buf));
|
VAR_NAME_LEN, DBufValue(&buf), VAR_NAME_LEN, DBufValue(&buf));
|
||||||
}
|
}
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
@@ -723,7 +723,7 @@ int DoDump(ParsePtr p)
|
|||||||
/* */
|
/* */
|
||||||
/* DumpVarTable */
|
/* DumpVarTable */
|
||||||
/* */
|
/* */
|
||||||
/* Dump the variable table to stderr. */
|
/* Dump the variable table to ErrFp. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
void DumpVarTable(void)
|
void DumpVarTable(void)
|
||||||
@@ -853,6 +853,7 @@ static SysVar SysVarArr[] = {
|
|||||||
{"August", 1, TRANS_TYPE, "August", 0, 0 },
|
{"August", 1, TRANS_TYPE, "August", 0, 0 },
|
||||||
{"CalcUTC", 1, INT_TYPE, &CalculateUTC, 0, 1 },
|
{"CalcUTC", 1, INT_TYPE, &CalculateUTC, 0, 1 },
|
||||||
{"CalMode", 0, INT_TYPE, &DoCalendar, 0, 0 },
|
{"CalMode", 0, INT_TYPE, &DoCalendar, 0, 0 },
|
||||||
|
{"CalType", 0, STR_TYPE, &CalType, 0, 0 },
|
||||||
{"Daemon", 0, INT_TYPE, &Daemon, 0, 0 },
|
{"Daemon", 0, INT_TYPE, &Daemon, 0, 0 },
|
||||||
{"DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0 },
|
{"DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0 },
|
||||||
{"DateTimeSep", 1, SPECIAL_TYPE, datetime_sep_func, 0, 0 },
|
{"DateTimeSep", 1, SPECIAL_TYPE, datetime_sep_func, 0, 0 },
|
||||||
@@ -968,7 +969,7 @@ static int SetTranslatableVariable(SysVar *v, Value *value)
|
|||||||
|
|
||||||
static int GetTranslatableVariable(SysVar *v, Value *value)
|
static int GetTranslatableVariable(SysVar *v, Value *value)
|
||||||
{
|
{
|
||||||
char const *translated = t((char const *) v->value);
|
char const *translated = tr((char const *) v->value);
|
||||||
if (translated) {
|
if (translated) {
|
||||||
value->v.str = StrDup(translated);
|
value->v.str = StrDup(translated);
|
||||||
} else {
|
} else {
|
||||||
@@ -1005,7 +1006,7 @@ static int SetSysVarHelper(SysVar *v, Value *value)
|
|||||||
|
|
||||||
if (v->type == STR_TYPE) {
|
if (v->type == STR_TYPE) {
|
||||||
/* If it's already the same, don't bother doing anything */
|
/* If it's already the same, don't bother doing anything */
|
||||||
if (!strcmp(value->v.str, (char const *) v->value)) {
|
if (!strcmp(value->v.str, * (char const **) v->value)) {
|
||||||
DestroyValue(*value);
|
DestroyValue(*value);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -1077,7 +1078,7 @@ int GetSysVar(char const *name, Value *val)
|
|||||||
/* In "verbose" mode, print attempts to test $RunOff */
|
/* In "verbose" mode, print attempts to test $RunOff */
|
||||||
if (DebugFlag & DB_PRTLINE) {
|
if (DebugFlag & DB_PRTLINE) {
|
||||||
if (v->value == (void *) &RunDisabled) {
|
if (v->value == (void *) &RunDisabled) {
|
||||||
Wprint("(Security note: $RunOff variable tested.)");
|
Wprint(tr("(Security note: $RunOff variable tested.)"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
@@ -1238,6 +1239,46 @@ set_components_from_lat_and_long(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GenerateSysvarTranslationTemplates(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
char const *msg;
|
||||||
|
for (i=0; i< (int) NUMSYSVARS; i++) {
|
||||||
|
if (SysVarArr[i].type == TRANS_TYPE) {
|
||||||
|
int done=0;
|
||||||
|
msg = (char const *) SysVarArr[i].value;
|
||||||
|
/* We've already done month and day names */
|
||||||
|
for (j=0; j<7; j++) {
|
||||||
|
if (!strcmp(msg, DayName[j])) {
|
||||||
|
done=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (done) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (j=0; j<12; j++) {
|
||||||
|
if (!strcmp(msg, MonthName[j])) {
|
||||||
|
done=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (done) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("SET $%s ", SysVarArr[i].name);
|
||||||
|
print_escaped_string_helper(stdout, tr(msg), 1);
|
||||||
|
printf("\n");
|
||||||
|
} else if (!strcmp(SysVarArr[i].name, "Hplu") ||
|
||||||
|
!strcmp(SysVarArr[i].name, "Mplu")) {
|
||||||
|
msg = * (char const **) SysVarArr[i].value;
|
||||||
|
printf("SET $%s ", SysVarArr[i].name);
|
||||||
|
print_escaped_string_helper(stdout, tr(msg), 1);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
void
|
void
|
||||||
print_sysvar_tokens(void)
|
print_sysvar_tokens(void)
|
||||||
{
|
{
|
||||||
@@ -1249,11 +1290,7 @@ print_sysvar_tokens(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
get_var_hash_stats(int *total, int *maxlen, double *avglen)
|
dump_var_hash_stats(void)
|
||||||
{
|
{
|
||||||
struct hash_table_stats s;
|
hash_table_dump_stats(&VHashTbl, ErrFp);
|
||||||
hash_table_get_stats(&VHashTbl, &s);
|
|
||||||
*total = s.num_entries;
|
|
||||||
*maxlen = s.max_len;
|
|
||||||
*avglen = s.avg_len;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
debug +sx
|
debug +hsx
|
||||||
|
|
||||||
set a 1
|
set a 1
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
# in the build directory.
|
# in the build directory.
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2024 Dianne Skoll
|
# Copyright (C) 1992-2025 Dianne Skoll
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -32,20 +32,10 @@ fi
|
|||||||
# ../src/remind. This trick was suggested by Jochen Sprickerhof
|
# ../src/remind. This trick was suggested by Jochen Sprickerhof
|
||||||
alias remind="echo You should be using ../src/remind explicitly in test-rem >&2; exit 1"
|
alias remind="echo You should be using ../src/remind explicitly in test-rem >&2; exit 1"
|
||||||
|
|
||||||
|
|
||||||
# Set a known timezone so moon phases show up in predictable places
|
# Set a known timezone so moon phases show up in predictable places
|
||||||
TZ=UTC
|
TZ=UTC
|
||||||
export TZ
|
export TZ
|
||||||
|
|
||||||
RESULT=`(echo 'BANNER %'; echo 'IF now() > 23:55'; echo 'MSG late%'; echo 'ENDIF') | ../src/remind -h -`
|
|
||||||
|
|
||||||
if test "$RESULT" = "late" ; then
|
|
||||||
echo ""
|
|
||||||
echo "*** Please do not run the test suite between 23:55 and 00:00 UTC; it will fail."
|
|
||||||
echo ""
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If we're already in a utf-8 locale, do
|
# If we're already in a utf-8 locale, do
|
||||||
# nothing; otherwise, set LC_ALL
|
# nothing; otherwise, set LC_ALL
|
||||||
OK=0
|
OK=0
|
||||||
@@ -198,6 +188,17 @@ REM 4 MSG Normal
|
|||||||
SET $DefaultColor "256 0 0"
|
SET $DefaultColor "256 0 0"
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Test default color with weekly calendar
|
||||||
|
../src/remind -pq+ - 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!
|
||||||
|
SET $DefaultColor "-1 -1 -1"
|
||||||
|
REM 4 MSG Normal
|
||||||
|
# Should give an error
|
||||||
|
SET $DefaultColor "256 0 0"
|
||||||
|
EOF
|
||||||
|
|
||||||
# Test stdout
|
# Test stdout
|
||||||
../src/remind - 1 jan 2012 <<'EOF' >> ../tests/test.out 2>&1
|
../src/remind - 1 jan 2012 <<'EOF' >> ../tests/test.out 2>&1
|
||||||
BANNER %
|
BANNER %
|
||||||
@@ -465,10 +466,9 @@ rm -rf include_dir/ww
|
|||||||
../src/remind --version >> ../tests/test.out 2>&1
|
../src/remind --version >> ../tests/test.out 2>&1
|
||||||
|
|
||||||
# Test queueing. Because eventstart depends on the actual system
|
# Test queueing. Because eventstart depends on the actual system
|
||||||
# date, we have to convert it to some constant (in this case,
|
# date, we use the --test flag to fake the date and time.
|
||||||
# VOLATILE) so that tests are not dependent on the system date.
|
echo JSONQUEUE | ../src/remind --test -z0 ../tests/queue1.rem >> ../tests/test.out 2>&1
|
||||||
echo JSONQUEUE | ../src/remind -z0 ../tests/queue1.rem 2>&1 | sed -e 's/"eventstart":"................"/"eventstart":"VOLATILE"/g' | sed -e 's/"qid":"[0-9a-f]*",//g' >> ../tests/test.out 2>&1
|
echo QUEUE | ../src/remind --test -zj ../tests/queue1.rem >> ../tests/test.out 2>&1
|
||||||
echo QUEUE | ../src/remind -zj ../tests/queue1.rem 2>&1 | sed -e 's/"eventstart":"................"/"eventstart":"VOLATILE"/g' | sed -e 's/"qid":"[0-9a-f]*",//g' >> ../tests/test.out 2>&1
|
|
||||||
|
|
||||||
# Test for leap year bug that was fixed
|
# Test for leap year bug that was fixed
|
||||||
../src/remind -dte - 28 Feb 2024 <<'EOF' >> ../tests/test.out 2>&1
|
../src/remind -dte - 28 Feb 2024 <<'EOF' >> ../tests/test.out 2>&1
|
||||||
@@ -622,6 +622,29 @@ fi
|
|||||||
# Torture test #2
|
# Torture test #2
|
||||||
../src/remind ../tests/torture2.rem >> ../tests/test.out 2>&1
|
../src/remind ../tests/torture2.rem >> ../tests/test.out 2>&1
|
||||||
|
|
||||||
|
# Expression error-reporting
|
||||||
|
../src/remind -de - 1 Feb 2024 <<'EOF' >> ../tests/test.out 2>&1
|
||||||
|
set a 8 * "]]]" & 6
|
||||||
|
msg [8 * "]]]" & 6] is weird
|
||||||
|
set a 9 *
|
||||||
|
set a 9 * ]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Translation template generateion
|
||||||
|
../src/remind -h - 1 Feb 2024 <<'EOF' >> ../tests/test.out 2>&1
|
||||||
|
TRANSLATE GENERATE
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Make sure stupidly-long translations of "am" and "pm" can't cause a
|
||||||
|
# segmentation fault
|
||||||
|
../src/remind -c - 1 Feb 2024 <<'EOF' >> ../tests/test.out 2>&1
|
||||||
|
TRANS "am" "alsdkjalksdj alksjd alksdj alksjd laksjd laksjd laksjd laksjd laksjd laksjd laksjd laksjd lkasjd laksjd laksjd lkajs dlkajs dlkasj dlkasjd lkajsd lkajs dlkasjd lkasj dlkajsd lkasjd lkasjd laksjd laksjd laksjd alskdj alskdj alksdj alksdj alskdj alksdj aslkdj"
|
||||||
|
TRANS "pm" "oiwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwjwwwwwwwwwwwwwwwjwpqoejkpqwojepqowjepqojwepqowjepqowjepqowjepqowjepqowjepqowjepqojwepqowjepqowjepqowjepqowjepqowjeqpweoj"
|
||||||
|
|
||||||
|
REM WED AT 11:00 MSG wookie
|
||||||
|
REM WED AT 13:00 MSG blah
|
||||||
|
EOF
|
||||||
|
|
||||||
# Languages
|
# Languages
|
||||||
for i in ../include/lang/??.rem ; do
|
for i in ../include/lang/??.rem ; do
|
||||||
../src/remind -r -q "-ii=\"$i\"" ../tests/tstlang.rem 1 Feb 2024 13:34 >> ../tests/test.out 2>&1
|
../src/remind -r -q "-ii=\"$i\"" ../tests/tstlang.rem 1 Feb 2024 13:34 >> ../tests/test.out 2>&1
|
||||||
|
|||||||
476
tests/test.cmp
476
tests/test.cmp
@@ -801,7 +801,7 @@ Leaving UserFN _ofunc(1991-02-28) => 0
|
|||||||
|
|
||||||
# omitfunc ignores local/global omits
|
# omitfunc ignores local/global omits
|
||||||
fset _ofunc(x) 0
|
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 1 March
|
||||||
OMIT 2 March 1991
|
OMIT 2 March 1991
|
||||||
REM 1 March OMIT Sun OMITFUNC _ofunc AFTER MSG Should trigger 1 March
|
REM 1 March OMIT Sun OMITFUNC _ofunc AFTER MSG Should trigger 1 March
|
||||||
@@ -1047,7 +1047,7 @@ set a057 value("a05"+"6")
|
|||||||
"a05" + "6" => "a056"
|
"a05" + "6" => "a056"
|
||||||
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||||
set a058 version()
|
set a058 version()
|
||||||
version() => "05.02.00"
|
version() => "05.02.03"
|
||||||
set a059 wkday(today())
|
set a059 wkday(today())
|
||||||
today() => 1991-02-16
|
today() => 1991-02-16
|
||||||
wkday(1991-02-16) => "Saturday"
|
wkday(1991-02-16) => "Saturday"
|
||||||
@@ -2611,7 +2611,7 @@ a056 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
|||||||
a007 "1991-02-16"
|
a007 "1991-02-16"
|
||||||
a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||||
a008 "11:44"
|
a008 "11:44"
|
||||||
a058 "05.02.00"
|
a058 "05.02.03"
|
||||||
a059 "Saturday"
|
a059 "Saturday"
|
||||||
a010 12
|
a010 12
|
||||||
a060 6
|
a060 6
|
||||||
@@ -2743,6 +2743,7 @@ Variable Value
|
|||||||
$August "August"
|
$August "August"
|
||||||
$CalcUTC 0 [0, 1]
|
$CalcUTC 0 [0, 1]
|
||||||
$CalMode 0
|
$CalMode 0
|
||||||
|
$CalType "none"
|
||||||
$Daemon 0
|
$Daemon 0
|
||||||
$DateSep "-"
|
$DateSep "-"
|
||||||
$DateTimeSep "@"
|
$DateTimeSep "@"
|
||||||
@@ -3508,6 +3509,8 @@ REM AT 13:00PM MSG foo 13p
|
|||||||
DEBUG +x
|
DEBUG +x
|
||||||
SET x 0:00am + 0
|
SET x 0:00am + 0
|
||||||
../tests/test.rem(629): Ill-formed time: `0:00am'
|
../tests/test.rem(629): Ill-formed time: `0:00am'
|
||||||
|
0:00am + 0
|
||||||
|
^-- here
|
||||||
SET x 1:00AM + 0
|
SET x 1:00AM + 0
|
||||||
01:00 + 0 => 01:00
|
01:00 + 0 => 01:00
|
||||||
SET x 2:00am + 0
|
SET x 2:00am + 0
|
||||||
@@ -3534,9 +3537,13 @@ SET x 12:00am + 0
|
|||||||
00:00 + 0 => 00:00
|
00:00 + 0 => 00:00
|
||||||
SET x 13:00AM + 0
|
SET x 13:00AM + 0
|
||||||
../tests/test.rem(642): Ill-formed time: `13:00AM'
|
../tests/test.rem(642): Ill-formed time: `13:00AM'
|
||||||
|
13:00AM + 0
|
||||||
|
^-- here
|
||||||
|
|
||||||
SET x 0:00pm + 0
|
SET x 0:00pm + 0
|
||||||
../tests/test.rem(644): Ill-formed time: `0:00pm'
|
../tests/test.rem(644): Ill-formed time: `0:00pm'
|
||||||
|
0:00pm + 0
|
||||||
|
^-- here
|
||||||
SET x 1:00PM + 0
|
SET x 1:00PM + 0
|
||||||
13:00 + 0 => 13:00
|
13:00 + 0 => 13:00
|
||||||
SET x 2:00pm + 0
|
SET x 2:00pm + 0
|
||||||
@@ -3563,9 +3570,13 @@ SET x 12:00pm + 0
|
|||||||
12:00 + 0 => 12:00
|
12:00 + 0 => 12:00
|
||||||
SET x 13:00PM + 0
|
SET x 13:00PM + 0
|
||||||
../tests/test.rem(657): Ill-formed time: `13:00PM'
|
../tests/test.rem(657): Ill-formed time: `13:00PM'
|
||||||
|
13:00PM + 0
|
||||||
|
^-- here
|
||||||
|
|
||||||
SET x '2015-02-03@0:00am' + 0
|
SET x '2015-02-03@0:00am' + 0
|
||||||
../tests/test.rem(659): Ill-formed time: '2015-02-03@0:00am'
|
../tests/test.rem(659): Ill-formed time: '2015-02-03@0:00am'
|
||||||
|
'2015-02-03@0:00am' + 0
|
||||||
|
^-- here
|
||||||
SET x '2015-02-03@1:00AM' + 0
|
SET x '2015-02-03@1:00AM' + 0
|
||||||
2015-02-03@01:00 + 0 => 2015-02-03@01:00
|
2015-02-03@01:00 + 0 => 2015-02-03@01:00
|
||||||
SET x '2015-02-03@2:00am' + 0
|
SET x '2015-02-03@2:00am' + 0
|
||||||
@@ -3592,9 +3603,13 @@ SET x '2015-02-03@12:00am' + 0
|
|||||||
2015-02-03@00:00 + 0 => 2015-02-03@00:00
|
2015-02-03@00:00 + 0 => 2015-02-03@00:00
|
||||||
SET x '2015-02-03@13:00AM' + 0
|
SET x '2015-02-03@13:00AM' + 0
|
||||||
../tests/test.rem(672): Ill-formed time: '2015-02-03@13:00AM'
|
../tests/test.rem(672): Ill-formed time: '2015-02-03@13:00AM'
|
||||||
|
'2015-02-03@13:00AM' + 0
|
||||||
|
^-- here
|
||||||
|
|
||||||
SET x '2015-02-03@0:00pm' + 0
|
SET x '2015-02-03@0:00pm' + 0
|
||||||
../tests/test.rem(674): Ill-formed time: '2015-02-03@0:00pm'
|
../tests/test.rem(674): Ill-formed time: '2015-02-03@0:00pm'
|
||||||
|
'2015-02-03@0:00pm' + 0
|
||||||
|
^-- here
|
||||||
SET x '2015-02-03@1:00PM' + 0
|
SET x '2015-02-03@1:00PM' + 0
|
||||||
2015-02-03@13:00 + 0 => 2015-02-03@13:00
|
2015-02-03@13:00 + 0 => 2015-02-03@13:00
|
||||||
SET x '2015-02-03@2:00pm' + 0
|
SET x '2015-02-03@2:00pm' + 0
|
||||||
@@ -3621,6 +3636,8 @@ SET x '2015-02-03@12:00pm' + 0
|
|||||||
2015-02-03@12:00 + 0 => 2015-02-03@12:00
|
2015-02-03@12:00 + 0 => 2015-02-03@12:00
|
||||||
SET x '2015-02-03@13:00PM' + 0
|
SET x '2015-02-03@13:00PM' + 0
|
||||||
../tests/test.rem(687): Ill-formed time: '2015-02-03@13:00PM'
|
../tests/test.rem(687): Ill-formed time: '2015-02-03@13:00PM'
|
||||||
|
'2015-02-03@13:00PM' + 0
|
||||||
|
^-- here
|
||||||
|
|
||||||
# Test the ampm function
|
# Test the ampm function
|
||||||
set x ampm(0:12) + ""
|
set x ampm(0:12) + ""
|
||||||
@@ -4033,7 +4050,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)
|
||||||
../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
|
# Short-circuit operators
|
||||||
IF trig("sun warn w") || trig("thu warn w")
|
IF trig("sun warn w") || trig("thu warn w")
|
||||||
@@ -5165,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
|
# 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
|
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
|
../tests/test.rem(1023): Too many arguments
|
||||||
|
|
||||||
# Check that SATISFY expressions that don't reference trigdate are diagnosed
|
# Check that SATISFY expressions that don't reference trigdate are diagnosed
|
||||||
@@ -5615,8 +5632,8 @@ REM SATISFY ""
|
|||||||
REM SATISFY [version() > "01.00.00"]
|
REM SATISFY [version() > "01.00.00"]
|
||||||
../tests/test.rem(1050): SATISFY: expression has no reference to trigdate() or $T...
|
../tests/test.rem(1050): SATISFY: expression has no reference to trigdate() or $T...
|
||||||
../tests/test.rem(1050): Trig = Saturday, 16 February, 1991
|
../tests/test.rem(1050): Trig = Saturday, 16 February, 1991
|
||||||
version() => "05.02.00"
|
version() => "05.02.03"
|
||||||
"05.02.00" > "01.00.00" => 1
|
"05.02.03" > "01.00.00" => 1
|
||||||
../tests/test.rem(1050): Trig(satisfied) = Saturday, 16 February, 1991
|
../tests/test.rem(1050): Trig(satisfied) = Saturday, 16 February, 1991
|
||||||
REM SATISFY [max(x, max(x, 1, 2, 3), 4, 5, 6) * 5]
|
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...
|
../tests/test.rem(1051): SATISFY: expression has no reference to trigdate() or $T...
|
||||||
@@ -5648,7 +5665,7 @@ hehe
|
|||||||
|
|
||||||
|
|
||||||
FSET gg(x,y,z) 0
|
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
|
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): Trig = Saturday, 16 February, 1991
|
||||||
@@ -5667,7 +5684,7 @@ hehe
|
|||||||
|
|
||||||
|
|
||||||
FSET gg() 0
|
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
|
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): Trig = Saturday, 16 February, 1991
|
||||||
@@ -5686,7 +5703,7 @@ hehe
|
|||||||
|
|
||||||
|
|
||||||
FSET gg(x) x-x
|
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
|
REM WARN gg MSG Wookie
|
||||||
../tests/test.rem(1069): Trig = Saturday, 16 February, 1991
|
../tests/test.rem(1069): Trig = Saturday, 16 February, 1991
|
||||||
Entering UserFN gg(1)
|
Entering UserFN gg(1)
|
||||||
@@ -5956,7 +5973,7 @@ Hello
|
|||||||
On the next line
|
On the next line
|
||||||
|
|
||||||
FSET msgsuffix(x) char(8) + " on the same 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
|
REM MSG Hello
|
||||||
../tests/test.rem(1185): Trig = Saturday, 16 February, 1991
|
../tests/test.rem(1185): Trig = Saturday, 16 February, 1991
|
||||||
Entering UserFN msgsuffix(5000)
|
Entering UserFN msgsuffix(5000)
|
||||||
@@ -16127,8 +16144,8 @@ TRANSLATE "January" "translated-January"
|
|||||||
TRANSLATE "Tuesday" "translated-Tuesday"
|
TRANSLATE "Tuesday" "translated-Tuesday"
|
||||||
TRANSLATE "November" "translated-November"
|
TRANSLATE "November" "translated-November"
|
||||||
TRANSLATE "tomorrow" "translated-Tomorrow"
|
TRANSLATE "tomorrow" "translated-Tomorrow"
|
||||||
TRANSLATE "today" "translated-Today"
|
|
||||||
TRANSLATE "is" "translated-Is"
|
TRANSLATE "is" "translated-Is"
|
||||||
|
TRANSLATE "today" "translated-Today"
|
||||||
TRANSLATE "from now" "translated-Fromnow"
|
TRANSLATE "from now" "translated-Fromnow"
|
||||||
TRANSLATE "Friday" "translated-Friday"
|
TRANSLATE "Friday" "translated-Friday"
|
||||||
TRANSLATE "am" "translated-Am"
|
TRANSLATE "am" "translated-Am"
|
||||||
@@ -16139,8 +16156,8 @@ TRANSLATE "pm" "translated-Pm"
|
|||||||
TRANSLATE "August" "translated-August"
|
TRANSLATE "August" "translated-August"
|
||||||
TRANSLATE "May" "translated-May"
|
TRANSLATE "May" "translated-May"
|
||||||
TRANSLATE "February" "translated-February"
|
TRANSLATE "February" "translated-February"
|
||||||
TRANSLATE "on" "translated-On"
|
|
||||||
TRANSLATE "now" "translated-Now"
|
TRANSLATE "now" "translated-Now"
|
||||||
|
TRANSLATE "on" "translated-On"
|
||||||
$Ago is otherway-Ago
|
$Ago is otherway-Ago
|
||||||
$Am is otherway-Am
|
$Am is otherway-Am
|
||||||
$And is otherway-And
|
$And is otherway-And
|
||||||
@@ -16232,11 +16249,28 @@ IF 1
|
|||||||
../tests/test.rem(1435): Can't open file: /non/existent/file/should/not/work/wookie
|
../tests/test.rem(1435): Can't open file: /non/existent/file/should/not/work/wookie
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
|
do "with space.rem"
|
||||||
|
REM MSG D'oh, a file whose name has spaces! [filename()]
|
||||||
|
D'oh, a file whose name has spaces! ../tests/with space.rem
|
||||||
|
|
||||||
|
|
||||||
DEBUG -e
|
DEBUG -e
|
||||||
Var hash: total = 100141; maxlen = 5; avglen = 1.142
|
Variable hash table statistics:
|
||||||
Func hash: total = 100016; maxlen = 5; avglen = 1.140
|
Entries: 100141; Buckets: 87719; Non-empty Buckets: 66299
|
||||||
Dedup hash: total = 10000; maxlen = 7; avglen = 1.828
|
Maxlen: 5; Minlen: 0; Avglen: 1.142; Stddev: 0.878; Avg nonempty len: 1.510
|
||||||
Trans hash: total = 1; maxlen = 1; avglen = 0.059
|
Growths: 13; Shrinks: 0
|
||||||
|
Function hash table statistics:
|
||||||
|
Entries: 100016; Buckets: 87719; Non-empty Buckets: 63572
|
||||||
|
Maxlen: 5; Minlen: 0; Avglen: 1.140; Stddev: 0.934; Avg nonempty len: 1.573
|
||||||
|
Growths: 13; Shrinks: 0
|
||||||
|
Dedupe hash table statistics:
|
||||||
|
Entries: 10000; Buckets: 5471; Non-empty Buckets: 4752
|
||||||
|
Maxlen: 7; Minlen: 0; Avglen: 1.828; Stddev: 1.302; Avg nonempty len: 2.104
|
||||||
|
Growths: 9; Shrinks: 0
|
||||||
|
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: 300096
|
||||||
Expression nodes high-water: 300073
|
Expression nodes high-water: 300073
|
||||||
Expression nodes leaked: 0
|
Expression nodes leaked: 0
|
||||||
@@ -20099,7 +20133,7 @@ No reminders.
|
|||||||
<< /PageSize [612 792] >> setpagedevice
|
<< /PageSize [612 792] >> setpagedevice
|
||||||
% This file was produced by Remind and Rem2PS, written by
|
% This file was produced by Remind and Rem2PS, written by
|
||||||
% Dianne Skoll.
|
% Dianne Skoll.
|
||||||
% Remind and Rem2PS are Copyright 1992-2024 Dianne Skoll.
|
% Remind and Rem2PS are Copyright (C) 1992-2025 Dianne Skoll.
|
||||||
/ISOLatin1Encoding where { pop save true }{ false } ifelse
|
/ISOLatin1Encoding where { pop save true }{ false } ifelse
|
||||||
/ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus
|
/ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus
|
||||||
StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute
|
StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute
|
||||||
@@ -21203,7 +21237,7 @@ showpage
|
|||||||
<< /PageSize [612 792] >> setpagedevice
|
<< /PageSize [612 792] >> setpagedevice
|
||||||
% This file was produced by Remind and Rem2PS, written by
|
% This file was produced by Remind and Rem2PS, written by
|
||||||
% Dianne Skoll.
|
% Dianne Skoll.
|
||||||
% Remind and Rem2PS are Copyright 1992-2024 Dianne Skoll.
|
% Remind and Rem2PS are Copyright (C) 1992-2025 Dianne Skoll.
|
||||||
/ISOLatin1Encoding where { pop save true }{ false } ifelse
|
/ISOLatin1Encoding where { pop save true }{ false } ifelse
|
||||||
/ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus
|
/ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus
|
||||||
StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute
|
StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute
|
||||||
@@ -22389,13 +22423,29 @@ February 29
|
|||||||
-stdin-(7): Number too high
|
-stdin-(7): Number too high
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"translations":{"LANGID":"en"},"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":[
|
"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-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-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-04","filename":"-","lineno":5,"d":4,"priority":5000,"body":"Normal"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
-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
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"caltype":"weekly","translations":{"LANGID":"en"},"dates":[{"dayname":"Sunday","date":"2012-01-01","year":2012,"month":"January","day":1},{"dayname":"Monday","date":"2012-01-02","year":2012,"month":"January","day":2},{"dayname":"Tuesday","date":"2012-01-03","year":2012,"month":"January","day":3},{"dayname":"Wednesday","date":"2012-01-04","year":2012,"month":"January","day":4},{"dayname":"Thursday","date":"2012-01-05","year":2012,"month":"January","day":5},{"dayname":"Friday","date":"2012-01-06","year":2012,"month":"January","day":6},{"dayname":"Saturday","date":"2012-01-07","year":2012,"month":"January","day":7}],"entries":[{"date":"2012-01-02","d":2,"priority":5000,"body":"Normal"},
|
||||||
|
{"date":"2012-01-03","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","d":4,"priority":5000,"body":"Normal"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
STDOUT is a: FILE
|
STDOUT is a: FILE
|
||||||
STDOUT is a: PIPE
|
STDOUT is a: PIPE
|
||||||
+----------------------------------------------------------------------------+
|
+----------------------------------------------------------------------------+
|
||||||
@@ -23150,11 +23200,17 @@ SECURITY: Won't read world-writable file or directory!
|
|||||||
Error reading include_dir/ww: Can't open file
|
Error reading include_dir/ww: Can't open file
|
||||||
SECURITY: Won't read world-writable file or directory!
|
SECURITY: Won't read world-writable file or directory!
|
||||||
Error reading include_dir/ww: No files matching *.rem
|
Error reading include_dir/ww: No files matching *.rem
|
||||||
05.02.00
|
05.02.03
|
||||||
|
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
|
||||||
NOTE JSONQUEUE
|
NOTE JSONQUEUE
|
||||||
[{"priority":2,"eventstart":"VOLATILE","time":"23:59","nexttime":"23:59","tdelta":0,"trep":0,"rundisabled":0,"ntrig":1,"filename":"../tests/queue2.rem","lineno":1,"type":"MSG_TYPE","body":"XXXX"},{"priority":999,"eventstart":"VOLATILE","time":"23:58","nexttime":"23:58","tdelta":0,"trep":0,"rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":5,"type":"MSG_TYPE","body":"quux"},{"priority":42,"eventstart":"VOLATILE","time":"23:57","nexttime":"23:57","tdelta":0,"trep":0,"rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":4,"type":"MSG_TYPE","body":"bar"},{"priority":5000,"eventstart":"VOLATILE","time":"23:56","nexttime":"23:56","tdelta":0,"trep":0,"rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":3,"type":"MSG_TYPE","body":"foo"}]
|
[{"priority":2,"eventstart":"2025-01-06T23:59","time":"23:59","nexttime":"23:59","tdelta":0,"trep":0,"qid":"42424242","rundisabled":0,"ntrig":1,"filename":"../tests/queue2.rem","lineno":1,"type":"MSG_TYPE","body":"XXXX"},{"priority":999,"eventstart":"2025-01-06T23:58","time":"23:58","nexttime":"23:58","tdelta":0,"trep":0,"qid":"42424242","rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":5,"type":"MSG_TYPE","body":"quux"},{"priority":42,"eventstart":"2025-01-06T23:57","time":"23:57","nexttime":"23:57","tdelta":0,"trep":0,"qid":"42424242","rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":4,"type":"MSG_TYPE","body":"bar"},{"priority":5000,"eventstart":"2025-01-06T23:56","time":"23:56","nexttime":"23:56","tdelta":0,"trep":0,"qid":"42424242","rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":3,"type":"MSG_TYPE","body":"foo"}]
|
||||||
NOTE ENDJSONQUEUE
|
NOTE ENDJSONQUEUE
|
||||||
{"response":"queue","queue":[{"priority":2,"eventstart":"VOLATILE","time":"23:59","nexttime":"23:59","tdelta":0,"trep":0,"rundisabled":0,"ntrig":1,"filename":"../tests/queue2.rem","lineno":1,"type":"MSG_TYPE","body":"XXXX"},{"priority":999,"eventstart":"VOLATILE","time":"23:58","nexttime":"23:58","tdelta":0,"trep":0,"rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":5,"type":"MSG_TYPE","body":"quux"},{"priority":42,"eventstart":"VOLATILE","time":"23:57","nexttime":"23:57","tdelta":0,"trep":0,"rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":4,"type":"MSG_TYPE","body":"bar"},{"priority":5000,"eventstart":"VOLATILE","time":"23:56","nexttime":"23:56","tdelta":0,"trep":0,"rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":3,"type":"MSG_TYPE","body":"foo"}],"command":"QUEUE"}
|
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
|
||||||
|
{"response":"queue","queue":[{"priority":2,"eventstart":"2025-01-06T23:59","time":"23:59","nexttime":"23:59","tdelta":0,"trep":0,"qid":"42424242","rundisabled":0,"ntrig":1,"filename":"../tests/queue2.rem","lineno":1,"type":"MSG_TYPE","body":"XXXX"},{"priority":999,"eventstart":"2025-01-06T23:58","time":"23:58","nexttime":"23:58","tdelta":0,"trep":0,"qid":"42424242","rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":5,"type":"MSG_TYPE","body":"quux"},{"priority":42,"eventstart":"2025-01-06T23:57","time":"23:57","nexttime":"23:57","tdelta":0,"trep":0,"qid":"42424242","rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":4,"type":"MSG_TYPE","body":"bar"},{"priority":5000,"eventstart":"2025-01-06T23:56","time":"23:56","nexttime":"23:56","tdelta":0,"trep":0,"qid":"42424242","rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":3,"type":"MSG_TYPE","body":"foo"}],"command":"QUEUE"}
|
||||||
BANNER %
|
BANNER %
|
||||||
REM 29 MSG One
|
REM 29 MSG One
|
||||||
-(2): Trig = Thursday, 29 February, 2024
|
-(2): Trig = Thursday, 29 February, 2024
|
||||||
@@ -23360,7 +23416,7 @@ max(6, 9, 50) => 50
|
|||||||
Parsed expression: max(1,
|
Parsed expression: max(1,
|
||||||
=> Error: Illegal character
|
=> Error: Illegal character
|
||||||
Unparsed: ,1)
|
Unparsed: ,1)
|
||||||
max(1,,1)
|
,1)
|
||||||
^-- here
|
^-- here
|
||||||
Parsed expression: 5%0
|
Parsed expression: 5%0
|
||||||
=> (% 5 0)
|
=> (% 5 0)
|
||||||
@@ -23702,10 +23758,22 @@ Parsed expression: isany("foo", 1 + 1, 2:00 + 1, '2021-01-01' + 1, '2021-01-01@1
|
|||||||
"f" + "oo" => "foo"
|
"f" + "oo" => "foo"
|
||||||
isany("foo", 2, 02:01, 2021-01-02, 2021-01-01@14:01, "foo", ?) => 1
|
isany("foo", 2, 02:01, 2021-01-02, 2021-01-01@14:01, "foo", ?) => 1
|
||||||
No reminders.
|
No reminders.
|
||||||
Var hash: total = 1; maxlen = 1; avglen = 0.059
|
Variable hash table statistics:
|
||||||
Func hash: total = 0; maxlen = 0; avglen = 0.000
|
Entries: 1; Buckets: 7; Non-empty Buckets: 1
|
||||||
Dedup hash: total = 0; maxlen = 0; avglen = 0.000
|
Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000
|
||||||
Trans hash: total = 1; maxlen = 1; avglen = 0.059
|
Growths: 0; Shrinks: 0
|
||||||
|
Function hash table statistics:
|
||||||
|
Entries: 0; Buckets: 7; Non-empty Buckets: 0
|
||||||
|
Maxlen: 0; Minlen: 0; Avglen: 0.000; Stddev: 0.000; Avg nonempty len: 0.000
|
||||||
|
Growths: 0; Shrinks: 0
|
||||||
|
Dedupe hash table statistics:
|
||||||
|
Entries: 0; Buckets: 7; Non-empty Buckets: 0
|
||||||
|
Maxlen: 0; Minlen: 0; Avglen: 0.000; Stddev: 0.000; Avg nonempty len: 0.000
|
||||||
|
Growths: 0; Shrinks: 0
|
||||||
|
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: 512
|
Expression nodes allocated: 512
|
||||||
Expression nodes high-water: 499
|
Expression nodes high-water: 499
|
||||||
Expression nodes leaked: 0
|
Expression nodes leaked: 0
|
||||||
@@ -24125,6 +24193,7 @@ $At
|
|||||||
$August
|
$August
|
||||||
$CalcUTC
|
$CalcUTC
|
||||||
$CalMode
|
$CalMode
|
||||||
|
$CalType
|
||||||
$Daemon
|
$Daemon
|
||||||
$DateSep
|
$DateSep
|
||||||
$DateTimeSep
|
$DateTimeSep
|
||||||
@@ -24229,15 +24298,356 @@ $Uy
|
|||||||
$Was
|
$Was
|
||||||
$Wednesday
|
$Wednesday
|
||||||
No reminders.
|
No reminders.
|
||||||
Var hash: total = 1; maxlen = 1; avglen = 0.059
|
Variable hash table statistics:
|
||||||
Func hash: total = 1; maxlen = 1; avglen = 0.059
|
Entries: 1; Buckets: 7; Non-empty Buckets: 1
|
||||||
Dedup hash: total = 0; maxlen = 0; avglen = 0.000
|
Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000
|
||||||
Trans hash: total = 2; maxlen = 1; avglen = 0.118
|
Growths: 13; Shrinks: 13
|
||||||
|
Function 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: 13; Shrinks: 13
|
||||||
|
Dedupe hash table statistics:
|
||||||
|
Entries: 0; Buckets: 7; Non-empty Buckets: 0
|
||||||
|
Maxlen: 0; Minlen: 0; Avglen: 0.000; Stddev: 0.000; Avg nonempty len: 0.000
|
||||||
|
Growths: 0; Shrinks: 0
|
||||||
|
Translation hash table statistics:
|
||||||
|
Entries: 2; Buckets: 7; Non-empty Buckets: 1
|
||||||
|
Maxlen: 2; Minlen: 0; Avglen: 0.286; Stddev: 0.700; Avg nonempty len: 2.000
|
||||||
|
Growths: 13; Shrinks: 13
|
||||||
Expression nodes allocated: 300032
|
Expression nodes allocated: 300032
|
||||||
Expression nodes high-water: 300000
|
Expression nodes high-water: 300000
|
||||||
Expression nodes leaked: 0
|
Expression nodes leaked: 0
|
||||||
Parse level high-water: 7
|
Parse level high-water: 7
|
||||||
Agenda pel dijous, 1 de febrer de 2024:
|
set a 8 * "]]]" & 6
|
||||||
|
-stdin-(1): Parse error `&' (did you mean `&&'?)
|
||||||
|
8 * "]]]" & 6
|
||||||
|
^-- here
|
||||||
|
msg [8 * "]]]" & 6] is weird
|
||||||
|
-stdin-(2): Parse error `&' (did you mean `&&'?)
|
||||||
|
8 * "]]]" & 6
|
||||||
|
^-- here
|
||||||
|
set a 9 *
|
||||||
|
-stdin-(3): Unexpected end of line
|
||||||
|
9 *
|
||||||
|
^-- here
|
||||||
|
set a 9 * ]
|
||||||
|
-stdin-(4): Illegal character `]'
|
||||||
|
9 * ]
|
||||||
|
^-- here
|
||||||
|
|
||||||
|
Reminders for Thursday, 1st February, 2024:
|
||||||
|
|
||||||
|
No reminders.
|
||||||
|
# Translation table template
|
||||||
|
|
||||||
|
TRANSLATE "LANGID" "en"
|
||||||
|
|
||||||
|
BANNER Reminders for %w, %d%s %m, %y%o:
|
||||||
|
|
||||||
|
# Weekday Names
|
||||||
|
SET $Monday "Monday"
|
||||||
|
SET $Tuesday "Tuesday"
|
||||||
|
SET $Wednesday "Wednesday"
|
||||||
|
SET $Thursday "Thursday"
|
||||||
|
SET $Friday "Friday"
|
||||||
|
SET $Saturday "Saturday"
|
||||||
|
SET $Sunday "Sunday"
|
||||||
|
|
||||||
|
# Month Names
|
||||||
|
SET $January "January"
|
||||||
|
SET $February "February"
|
||||||
|
SET $March "March"
|
||||||
|
SET $April "April"
|
||||||
|
SET $May "May"
|
||||||
|
SET $June "June"
|
||||||
|
SET $July "July"
|
||||||
|
SET $August "August"
|
||||||
|
SET $September "September"
|
||||||
|
SET $October "October"
|
||||||
|
SET $November "November"
|
||||||
|
SET $December "December"
|
||||||
|
|
||||||
|
# Other Translation-related System Variables
|
||||||
|
SET $Ago "ago"
|
||||||
|
SET $Am "am"
|
||||||
|
SET $And "and"
|
||||||
|
SET $At "at"
|
||||||
|
SET $Fromnow "from now"
|
||||||
|
SET $Hour "hour"
|
||||||
|
SET $Hplu "s"
|
||||||
|
SET $Is "is"
|
||||||
|
SET $Minute "minute"
|
||||||
|
SET $Mplu "s"
|
||||||
|
SET $Now "now"
|
||||||
|
SET $On "on"
|
||||||
|
SET $Pm "pm"
|
||||||
|
SET $Today "today"
|
||||||
|
SET $Tomorrow "tomorrow"
|
||||||
|
SET $Was "was"
|
||||||
|
|
||||||
|
# Error Messages
|
||||||
|
TRANSLATE "Ok" ""
|
||||||
|
TRANSLATE "Missing ']'" ""
|
||||||
|
TRANSLATE "Missing quote" ""
|
||||||
|
TRANSLATE "Expression too complex" ""
|
||||||
|
TRANSLATE "Missing ')'" ""
|
||||||
|
TRANSLATE "Undefined function" ""
|
||||||
|
TRANSLATE "Illegal character" ""
|
||||||
|
TRANSLATE "Expecting binary operator" ""
|
||||||
|
TRANSLATE "Out of memory" ""
|
||||||
|
TRANSLATE "Ill-formed number" ""
|
||||||
|
TRANSLATE "Can't coerce" ""
|
||||||
|
TRANSLATE "Type mismatch" ""
|
||||||
|
TRANSLATE "Date overflow" ""
|
||||||
|
TRANSLATE "Division by zero" ""
|
||||||
|
TRANSLATE "Undefined variable" ""
|
||||||
|
TRANSLATE "Unexpected end of line" ""
|
||||||
|
TRANSLATE "Unexpected end of file" ""
|
||||||
|
TRANSLATE "I/O error" ""
|
||||||
|
TRANSLATE "Internal error" ""
|
||||||
|
TRANSLATE "Bad date specification" ""
|
||||||
|
TRANSLATE "Not enough arguments" ""
|
||||||
|
TRANSLATE "Too many arguments" ""
|
||||||
|
TRANSLATE "Ill-formed time" ""
|
||||||
|
TRANSLATE "Number too high" ""
|
||||||
|
TRANSLATE "Number too low" ""
|
||||||
|
TRANSLATE "Can't open file" ""
|
||||||
|
TRANSLATE "INCLUDE nested too deeply (max. 9)" ""
|
||||||
|
TRANSLATE "Parse error" ""
|
||||||
|
TRANSLATE "Can't compute trigger" ""
|
||||||
|
TRANSLATE "Too many nested IFs" ""
|
||||||
|
TRANSLATE "ELSE with no matching IF" ""
|
||||||
|
TRANSLATE "ENDIF with no matching IF" ""
|
||||||
|
TRANSLATE "Can't OMIT every weekday" ""
|
||||||
|
TRANSLATE "Extraneous token(s) on line" ""
|
||||||
|
TRANSLATE "POP-OMIT-CONTEXT without matching PUSH-OMIT-CONTEXT" ""
|
||||||
|
TRANSLATE "RUN disabled" ""
|
||||||
|
TRANSLATE "Domain error" ""
|
||||||
|
TRANSLATE "Invalid identifier" ""
|
||||||
|
TRANSLATE "Too many recursive function calls" ""
|
||||||
|
TRANSLATE "Cannot modify system variable" ""
|
||||||
|
TRANSLATE "C library function can't represent date/time" ""
|
||||||
|
TRANSLATE "Attempt to redefine built-in function" ""
|
||||||
|
TRANSLATE "Can't nest function definition in expression" ""
|
||||||
|
TRANSLATE "Must fully specify date to use repeat factor" ""
|
||||||
|
TRANSLATE "Year specified twice" ""
|
||||||
|
TRANSLATE "Month specified twice" ""
|
||||||
|
TRANSLATE "Day specified twice" ""
|
||||||
|
TRANSLATE "Unknown token" ""
|
||||||
|
TRANSLATE "Must specify month in OMIT command" ""
|
||||||
|
TRANSLATE "Too many full OMITs (max. 1000)" ""
|
||||||
|
TRANSLATE "Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT" ""
|
||||||
|
TRANSLATE "Error reading" ""
|
||||||
|
TRANSLATE "Expecting end-of-line" ""
|
||||||
|
TRANSLATE "Invalid Hebrew date" ""
|
||||||
|
TRANSLATE "iif(): odd number of arguments required" ""
|
||||||
|
TRANSLATE "Warning: Missing ENDIF" ""
|
||||||
|
TRANSLATE "Expecting comma" ""
|
||||||
|
TRANSLATE "Weekday specified twice" ""
|
||||||
|
TRANSLATE "Only use one of BEFORE, AFTER or SKIP" ""
|
||||||
|
TRANSLATE "Can't nest MSG, MSF, RUN, etc. in expression" ""
|
||||||
|
TRANSLATE "Repeat value specified twice" ""
|
||||||
|
TRANSLATE "Delta value specified twice" ""
|
||||||
|
TRANSLATE "Back value specified twice" ""
|
||||||
|
TRANSLATE "ONCE keyword used twice. (Hah.)" ""
|
||||||
|
TRANSLATE "Expecting time after AT" ""
|
||||||
|
TRANSLATE "THROUGH/UNTIL keyword used twice" ""
|
||||||
|
TRANSLATE "Incomplete date specification" ""
|
||||||
|
TRANSLATE "FROM/SCANFROM keyword used twice" ""
|
||||||
|
TRANSLATE "Variable" ""
|
||||||
|
TRANSLATE "Value" ""
|
||||||
|
TRANSLATE "*UNDEFINED*" ""
|
||||||
|
TRANSLATE "Entering UserFN" ""
|
||||||
|
TRANSLATE "Leaving UserFN" ""
|
||||||
|
TRANSLATE "Expired" ""
|
||||||
|
TRANSLATE "fork() failed - can't do queued reminders" ""
|
||||||
|
TRANSLATE "Can't access file" ""
|
||||||
|
TRANSLATE "Illegal system date: Year is less than %d" ""
|
||||||
|
TRANSLATE "Unknown debug flag '%c'" ""
|
||||||
|
TRANSLATE "Unknown option '%c'" ""
|
||||||
|
TRANSLATE "Unknown user '%s'" ""
|
||||||
|
TRANSLATE "Could not change gid to %d" ""
|
||||||
|
TRANSLATE "Could not change uid to %d" ""
|
||||||
|
TRANSLATE "Out of memory for environment" ""
|
||||||
|
TRANSLATE "Missing '=' sign" ""
|
||||||
|
TRANSLATE "Missing variable name" ""
|
||||||
|
TRANSLATE "Missing expression" ""
|
||||||
|
TRANSLATE "Remind: '-i' option: %s" ""
|
||||||
|
TRANSLATE "No reminders." ""
|
||||||
|
TRANSLATE "%d reminder(s) queued for later today." ""
|
||||||
|
TRANSLATE "Expecting number" ""
|
||||||
|
TRANSLATE "Undefined WARN function" ""
|
||||||
|
TRANSLATE "Can't convert between time zones" ""
|
||||||
|
TRANSLATE "No files matching *.rem" ""
|
||||||
|
TRANSLATE "String too long" ""
|
||||||
|
TRANSLATE "Time specified twice" ""
|
||||||
|
TRANSLATE "Cannot specify DURATION without specifying AT" ""
|
||||||
|
TRANSLATE "Expecting weekday name" ""
|
||||||
|
TRANSLATE "Duplicate argument name" ""
|
||||||
|
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 is deprecated; use %s instead" ""
|
||||||
|
TRANSLATE "%s(%d): IF without ENDIF" ""
|
||||||
|
TRANSLATE "%s(%d): ["["]#%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" ""
|
||||||
|
TRANSLATE "Caching file `%s' in memory" ""
|
||||||
|
TRANSLATE "Called from" ""
|
||||||
|
TRANSLATE "Cannot open `%s' for writing: %s" ""
|
||||||
|
TRANSLATE "Cannot stat %s - not running as daemon!" ""
|
||||||
|
TRANSLATE "Cannot use AT clause in multitrig() function" ""
|
||||||
|
TRANSLATE "Do not use ["["]] around expression in SET command" ""
|
||||||
|
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 "GetValidHebDate: Bad adarbehave value %d" ""
|
||||||
|
TRANSLATE "In" ""
|
||||||
|
TRANSLATE "Invalid translation: Both original and translated must have the same printf-style formatting sequences in the same order." ""
|
||||||
|
TRANSLATE "Missing REM type; assuming MSG" ""
|
||||||
|
TRANSLATE "No Adar A in %d" ""
|
||||||
|
TRANSLATE "No substition function `%s' defined" ""
|
||||||
|
TRANSLATE "Not setting $OnceFile: Already processed a reminder with a ONCE clause" ""
|
||||||
|
TRANSLATE "OMIT: UNTIL not allowed; did you mean THROUGH?" ""
|
||||||
|
TRANSLATE "POP-OMIT-CONTEXT at %s:%d matches PUSH-OMIT-CONTEXT in different file: %s:%d" ""
|
||||||
|
TRANSLATE "Reading `%s': Found in cache" ""
|
||||||
|
TRANSLATE "Reading `%s': Opening file on disk" ""
|
||||||
|
TRANSLATE "Reading `-': Reading stdin" ""
|
||||||
|
TRANSLATE "Reading command `%s': Found in cache" ""
|
||||||
|
TRANSLATE "SATISFY: constant 0 will never be true" ""
|
||||||
|
TRANSLATE "SATISFY: constant \"\" will never be true" ""
|
||||||
|
TRANSLATE "SATISFY: expression has no reference to trigdate() or $T..." ""
|
||||||
|
TRANSLATE "SECURITY: Won't read non-root-owned file or directory when running as root!" ""
|
||||||
|
TRANSLATE "SECURITY: Won't read world-writable file or directory!" ""
|
||||||
|
TRANSLATE "Scanning directory `%s' for *.rem files" ""
|
||||||
|
TRANSLATE "Undefined %s function: `%s'" ""
|
||||||
|
TRANSLATE "Unmatched PUSH-OMIT-CONTEXT at %s(%d)" ""
|
||||||
|
TRANSLATE "Unrecognized command; interpreting as REM" ""
|
||||||
|
TRANSLATE "Warning: Function name `%s...' truncated to `%s'" ""
|
||||||
|
TRANSLATE "Warning: OMIT is ignored if you use OMITFUNC" ""
|
||||||
|
TRANSLATE "Warning: SCANFROM is ignored in two-argument form of evaltrig()" ""
|
||||||
|
TRANSLATE "Warning: UNTIL/THROUGH date earlier than FROM date" ""
|
||||||
|
TRANSLATE "Warning: UNTIL/THROUGH date earlier than SCANFROM date" ""
|
||||||
|
TRANSLATE "Warning: UNTIL/THROUGH date earlier than start date" ""
|
||||||
|
TRANSLATE "Warning: Unable to save ONCE timestamp to %s: %s" ""
|
||||||
|
TRANSLATE "Warning: Unterminated %%(...) substitution sequence" ""
|
||||||
|
TRANSLATE "Warning: Unterminated %%{...} substitution sequence" ""
|
||||||
|
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 "did you mean" ""
|
||||||
|
TRANSLATE "here" ""
|
||||||
|
TRANSLATE "psmoon() is deprecated; use SPECIAL MOON instead." ""
|
||||||
|
TRANSLATE "psshade() is deprecated; use SPECIAL SHADE instead." ""
|
||||||
|
TRANSLATE "remaining call frames omitted" ""
|
||||||
|
+----------------------------------------------------------------------------+
|
||||||
|
| February 2024 |
|
||||||
|
+----------+----------+----------+----------+----------+----------+----------+
|
||||||
|
| Sunday | Monday | Tuesday |Wednesday | Thursday | Friday | Saturday |
|
||||||
|
+----------+----------+----------+----------+----------+----------+----------+
|
||||||
|
| | | | |1 |2 |3 |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | | | | | |
|
||||||
|
+----------+----------+----------+----------+----------+----------+----------+
|
||||||
|
|4 |5 |6 |7 |8 |9 |10 |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | |11:00alsdk| | | |
|
||||||
|
| | | |jalksdj | | | |
|
||||||
|
| | | |alksjd | | | |
|
||||||
|
| | | |alksdj | | | |
|
||||||
|
| | | |alksjd | | | |
|
||||||
|
| | | |laksjd | | | |
|
||||||
|
| | | |laksjd | | | |
|
||||||
|
| | | |laksjd | | | |
|
||||||
|
| | | |laksjd la | | | |
|
||||||
|
| | | |wookie | | | |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | |1:00oiwwww| | | |
|
||||||
|
| | | |wwwwwwwwww| | | |
|
||||||
|
| | | |wwwwwwwwww| | | |
|
||||||
|
| | | |wwwwwwwwww| | | |
|
||||||
|
| | | |wjwwwwwwww| | | |
|
||||||
|
| | | |wwwwwwwjwp| | | |
|
||||||
|
| | | |qoejkpqw | | | |
|
||||||
|
| | | |blah | | | |
|
||||||
|
+----------+----------+----------+----------+----------+----------+----------+
|
||||||
|
|11 |12 |13 |14 |15 |16 |17 |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | |11:00alsdk| | | |
|
||||||
|
| | | |jalksdj | | | |
|
||||||
|
| | | |alksjd | | | |
|
||||||
|
| | | |alksdj | | | |
|
||||||
|
| | | |alksjd | | | |
|
||||||
|
| | | |laksjd | | | |
|
||||||
|
| | | |laksjd | | | |
|
||||||
|
| | | |laksjd | | | |
|
||||||
|
| | | |laksjd la | | | |
|
||||||
|
| | | |wookie | | | |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | |1:00oiwwww| | | |
|
||||||
|
| | | |wwwwwwwwww| | | |
|
||||||
|
| | | |wwwwwwwwww| | | |
|
||||||
|
| | | |wwwwwwwwww| | | |
|
||||||
|
| | | |wjwwwwwwww| | | |
|
||||||
|
| | | |wwwwwwwjwp| | | |
|
||||||
|
| | | |qoejkpqw | | | |
|
||||||
|
| | | |blah | | | |
|
||||||
|
+----------+----------+----------+----------+----------+----------+----------+
|
||||||
|
|18 |19 |20 |21 |22 |23 |24 |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | |11:00alsdk| | | |
|
||||||
|
| | | |jalksdj | | | |
|
||||||
|
| | | |alksjd | | | |
|
||||||
|
| | | |alksdj | | | |
|
||||||
|
| | | |alksjd | | | |
|
||||||
|
| | | |laksjd | | | |
|
||||||
|
| | | |laksjd | | | |
|
||||||
|
| | | |laksjd | | | |
|
||||||
|
| | | |laksjd la | | | |
|
||||||
|
| | | |wookie | | | |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | |1:00oiwwww| | | |
|
||||||
|
| | | |wwwwwwwwww| | | |
|
||||||
|
| | | |wwwwwwwwww| | | |
|
||||||
|
| | | |wwwwwwwwww| | | |
|
||||||
|
| | | |wjwwwwwwww| | | |
|
||||||
|
| | | |wwwwwwwjwp| | | |
|
||||||
|
| | | |qoejkpqw | | | |
|
||||||
|
| | | |blah | | | |
|
||||||
|
+----------+----------+----------+----------+----------+----------+----------+
|
||||||
|
|25 |26 |27 |28 |29 | | |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | |11:00alsdk| | | |
|
||||||
|
| | | |jalksdj | | | |
|
||||||
|
| | | |alksjd | | | |
|
||||||
|
| | | |alksdj | | | |
|
||||||
|
| | | |alksjd | | | |
|
||||||
|
| | | |laksjd | | | |
|
||||||
|
| | | |laksjd | | | |
|
||||||
|
| | | |laksjd | | | |
|
||||||
|
| | | |laksjd la | | | |
|
||||||
|
| | | |wookie | | | |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | |1:00oiwwww| | | |
|
||||||
|
| | | |wwwwwwwwww| | | |
|
||||||
|
| | | |wwwwwwwwww| | | |
|
||||||
|
| | | |wwwwwwwwww| | | |
|
||||||
|
| | | |wjwwwwwwww| | | |
|
||||||
|
| | | |wwwwwwwjwp| | | |
|
||||||
|
| | | |qoejkpqw | | | |
|
||||||
|
| | | |blah | | | |
|
||||||
|
+----------+----------+----------+----------+----------+----------+----------+
|
||||||
|
Agenda pel dijous, 1 de febrer de 2024:
|
||||||
|
|
||||||
Language: ca
|
Language: ca
|
||||||
|
|
||||||
|
|||||||
@@ -1435,10 +1435,12 @@ IF 1
|
|||||||
INCLUDE /non/existent/file/should/not/work/wookie
|
INCLUDE /non/existent/file/should/not/work/wookie
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
|
do "with space.rem"
|
||||||
|
|
||||||
DEBUG -e
|
DEBUG -e
|
||||||
|
|
||||||
# Output expression-node stats
|
# Output expression-node stats
|
||||||
DEBUG +s
|
DEBUG +h
|
||||||
|
|
||||||
# Don't want Remind to queue reminders
|
# Don't want Remind to queue reminders
|
||||||
EXIT
|
EXIT
|
||||||
|
|||||||
@@ -600001,4 +600001,4 @@ TRANSLATE "99999"
|
|||||||
SET BOOGIE 1
|
SET BOOGIE 1
|
||||||
FSET QUUX(x) x*2
|
FSET QUUX(x) x*2
|
||||||
TRANSLATE "A" "B"
|
TRANSLATE "A" "B"
|
||||||
DEBUG +s
|
DEBUG +h
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
# Use the output to verify your translations.
|
# Use the output to verify your translations.
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2024 Dianne Skoll
|
# Copyright (C) 1992-2025 Dianne Skoll
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
#
|
#
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
1
tests/with space.rem
Normal file
1
tests/with space.rem
Normal file
@@ -0,0 +1 @@
|
|||||||
|
REM MSG D'oh, a file whose name has spaces! [filename()]
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Makefile.in for installing WWW server calendar scripts
|
# Makefile.in for installing WWW server calendar scripts
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
# Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
|
|
||||||
# The complete path to where the scripts actually live, as seen by
|
# The complete path to where the scripts actually live, as seen by
|
||||||
# the UNIX operating system.
|
# the UNIX operating system.
|
||||||
|
|||||||
18
www/README
18
www/README
@@ -1,15 +1,15 @@
|
|||||||
README
|
README
|
||||||
|
|
||||||
HTML Hebrew Calendar Server
|
HTML Calendar Server
|
||||||
|
|
||||||
This is a rudimentary Hebrew calendar server for the WWW. It
|
This is a rudimentary calendar server for the WWW. It supplies local
|
||||||
supplies local sunrise and sunset times, moon phases, upcoming Jewish
|
sunrise and sunset times, moon phases, upcoming Jewish holidays, and
|
||||||
holidays, and PostScript calendars. It only works under UNIX. I've
|
PostScript calendars. It only works under UNIX/Linux. I've only tested it
|
||||||
only tested it with Linux running NCSA's httpd and Apache's httpd, but
|
with Linux running Apache's httpd, but it should work on any UNIX/Linx web
|
||||||
it should work on any UNIX web server.
|
server that supports CGI scripts.
|
||||||
|
|
||||||
To install it, you need the Remind package, available via ftp from
|
To install it, you need the Remind package, available from
|
||||||
https://dianne.skoll.ca/projects/remind/ You should install Remind,
|
https://dianne.skoll.ca/projects/remind/ You should install Remind,
|
||||||
setting the latitude, longitude, location and time zone as appropriate
|
setting the latitude, longitude, location and time zone as appropriate
|
||||||
for your machine.
|
for your machine.
|
||||||
|
|
||||||
@@ -40,4 +40,4 @@ where "what" is one of:
|
|||||||
called "calendar.html" and installed in the HTMLDIR you specified
|
called "calendar.html" and installed in the HTMLDIR you specified
|
||||||
in the Makefile.
|
in the Makefile.
|
||||||
|
|
||||||
4) Enjoy!
|
5) Enjoy!
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
# Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
|
|
||||||
# CAL_DISPATCH -- Shell script for CGI directory to dispatch calendar
|
# CAL_DISPATCH -- Shell script for CGI directory to dispatch calendar
|
||||||
# commands.
|
# commands.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# PostScript calendar shell script
|
# PostScript calendar shell script
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
# Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
|
|
||||||
echo "Content-type: application/pdf"
|
echo "Content-type: application/pdf"
|
||||||
echo
|
echo
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# PostScript calendar shell script
|
# PostScript calendar shell script
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
# Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
|
|
||||||
echo "Content-type: application/postscript"
|
echo "Content-type: application/postscript"
|
||||||
echo
|
echo
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Hebrew date shell script
|
# Hebrew date shell script
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
# Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
|
|
||||||
echo Content-type: text/html
|
echo Content-type: text/html
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Hebrew date reminder file
|
# Hebrew date reminder file
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
# Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
|
|
||||||
BANNER %
|
BANNER %
|
||||||
IF !$PSCAL
|
IF !$PSCAL
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# HTML calendar shell script
|
# HTML calendar shell script
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
# Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
|
|
||||||
echo "Content-Type: text/html"
|
echo "Content-Type: text/html"
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Hebrew PostScript calendar shell script
|
# Hebrew PostScript calendar shell script
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
# Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
|
|
||||||
# Figure out the month: If day <= 20, use this month; otherwise, use
|
# Figure out the month: If day <= 20, use this month; otherwise, use
|
||||||
# next month.
|
# next month.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Hebrew PostScript calendar shell script
|
# Hebrew PostScript calendar shell script
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
# Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
|
|
||||||
# Figure out the month: If day <= 20, use this month; otherwise, use
|
# Figure out the month: If day <= 20, use this month; otherwise, use
|
||||||
# next month.
|
# next month.
|
||||||
|
|||||||
2
www/moon
2
www/moon
@@ -2,7 +2,7 @@
|
|||||||
# Moon shell script
|
# Moon shell script
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
# Copyright (C) 1992-2025 by Dianne Skoll
|
||||||
|
|
||||||
echo Content-type: text/html
|
echo Content-type: text/html
|
||||||
echo
|
echo
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user