mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-17 14:59:20 +02:00
Compare commits
84 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3297fe751 | ||
|
|
58ca741a1c | ||
|
|
14dbbc7bb4 | ||
|
|
df55c4032b | ||
|
|
3768155a20 | ||
|
|
2f3b9cadf4 | ||
|
|
2c79a6531a | ||
|
|
be5c856f4b | ||
|
|
712a333f08 | ||
|
|
b753e84c8c | ||
|
|
4b4acaadbb | ||
|
|
8a52f9b67d | ||
|
|
e372606281 | ||
|
|
c443d0a9da | ||
|
|
42c9ae9ea8 | ||
|
|
dac9bb4187 | ||
|
|
812d926f66 | ||
|
|
45831ea69f | ||
|
|
354e1d236b | ||
|
|
ac478039cf | ||
|
|
96f5799e6f | ||
|
|
e21479f696 | ||
|
|
25dc883e15 | ||
|
|
bfb1374ee3 | ||
|
|
cacd8f9792 | ||
|
|
3e9053a3c6 | ||
|
|
5fa357fec2 | ||
|
|
f109c3d696 | ||
|
|
b097ce7279 | ||
|
|
1297854935 | ||
|
|
0a1d0011f6 | ||
|
|
20db1be0a0 | ||
|
|
143f1d6144 | ||
|
|
358f6c9497 | ||
|
|
ca26544be8 | ||
|
|
5ceffddd5b | ||
|
|
8e3ddb96b3 | ||
|
|
377de36b35 | ||
|
|
4395e2f7ed | ||
|
|
1d0cc31b10 | ||
|
|
4b4b2ddcd4 | ||
|
|
3c9b5b786e | ||
|
|
08f1bea6ce | ||
|
|
a2cc5943e0 | ||
|
|
895ac6f0f7 | ||
|
|
759ca0253e | ||
|
|
0ca368c8d9 | ||
|
|
a467cc1b84 | ||
|
|
c65fd826a5 | ||
|
|
bd6f4e1b43 | ||
|
|
169520914f | ||
|
|
a163a0c446 | ||
|
|
295aeb0ed8 | ||
|
|
9b2fdad56c | ||
|
|
7a1184d3c5 | ||
|
|
b036244316 | ||
|
|
5ad5366e8a | ||
|
|
244677e524 | ||
|
|
f5a094a973 | ||
|
|
5681ebdb12 | ||
|
|
664fa5f08f | ||
|
|
14edec5eae | ||
|
|
6adfd2e739 | ||
|
|
34409f7a7d | ||
|
|
7e13d1052c | ||
|
|
eb1998c888 | ||
|
|
543252cbaf | ||
|
|
6df7c59876 | ||
|
|
f780e0afc3 | ||
|
|
310e8d3287 | ||
|
|
ba51bdf258 | ||
|
|
ef88b844fb | ||
|
|
67b96b0a26 | ||
|
|
562da30fb5 | ||
|
|
21175e8cf6 | ||
|
|
80d01f7158 | ||
|
|
90cac447e4 | ||
|
|
04bf5b0a8b | ||
|
|
d667c15b25 | ||
|
|
2123bf4b18 | ||
|
|
429a64f29e | ||
|
|
f39381dd6c | ||
|
|
0a9eb07f6f | ||
|
|
9c287e3fd7 |
19
.gitignore
vendored
19
.gitignore
vendored
@@ -1,16 +1,17 @@
|
|||||||
*.bak
|
*.bak
|
||||||
|
*.o
|
||||||
|
*~
|
||||||
|
.gitignore
|
||||||
|
TAGS
|
||||||
autom4te.cache
|
autom4te.cache
|
||||||
config.log
|
config.log
|
||||||
config.status
|
config.status
|
||||||
src/Makefile
|
rem2html/Makefile
|
||||||
www/Makefile
|
|
||||||
*.o
|
|
||||||
src/config.h
|
|
||||||
src/remind
|
|
||||||
src/*.tar.gz*
|
src/*.tar.gz*
|
||||||
tests/test.out
|
src/Makefile
|
||||||
.gitignore
|
src/config.h
|
||||||
*~
|
|
||||||
src/rem2ps
|
src/rem2ps
|
||||||
|
src/remind
|
||||||
src/version.h
|
src/version.h
|
||||||
TAGS
|
tests/test.out
|
||||||
|
www/Makefile
|
||||||
|
|||||||
@@ -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-2020 Dianne Skoll, except where noted in
|
2. REMIND is Copyright 1992-2021 Dianne Skoll, except where noted in
|
||||||
individual files.
|
individual files.
|
||||||
|
|
||||||
3. DISTRIBUTION AND USE
|
3. DISTRIBUTION AND USE
|
||||||
|
|||||||
3
Makefile
3
Makefile
@@ -18,7 +18,8 @@ install:
|
|||||||
@echo "* *"
|
@echo "* *"
|
||||||
@echo "*********************"
|
@echo "*********************"
|
||||||
@echo ""
|
@echo ""
|
||||||
@cd src && $(MAKE) install
|
@$(MAKE) -C src install
|
||||||
|
@$(MAKE) -C rem2html install
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
find . -name '*~' -exec rm {} \;
|
find . -name '*~' -exec rm {} \;
|
||||||
|
|||||||
49
configure
vendored
49
configure
vendored
@@ -626,6 +626,7 @@ VERSION
|
|||||||
EGREP
|
EGREP
|
||||||
GREP
|
GREP
|
||||||
CPP
|
CPP
|
||||||
|
PERL
|
||||||
SET_MAKE
|
SET_MAKE
|
||||||
LN_S
|
LN_S
|
||||||
INSTALL_DATA
|
INSTALL_DATA
|
||||||
@@ -3274,6 +3275,46 @@ $as_echo "no" >&6; }
|
|||||||
SET_MAKE="MAKE=${MAKE-make}"
|
SET_MAKE="MAKE=${MAKE-make}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Extract the first word of "perl", so it can be a program name with args.
|
||||||
|
set dummy perl; ac_word=$2
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||||
|
$as_echo_n "checking for $ac_word... " >&6; }
|
||||||
|
if ${ac_cv_path_PERL+:} false; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
case $PERL in
|
||||||
|
[\\/]* | ?:[\\/]*)
|
||||||
|
ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||||
|
for as_dir in $PATH
|
||||||
|
do
|
||||||
|
IFS=$as_save_IFS
|
||||||
|
test -z "$as_dir" && as_dir=.
|
||||||
|
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||||
|
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||||
|
ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
|
||||||
|
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
IFS=$as_save_IFS
|
||||||
|
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
PERL=$ac_cv_path_PERL
|
||||||
|
if test -n "$PERL"; then
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
|
||||||
|
$as_echo "$PERL" >&6; }
|
||||||
|
else
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
$as_echo "no" >&6; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -3820,7 +3861,7 @@ _ACEOF
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
for ac_header in sys/file.h glob.h wctype.h locale.h
|
for ac_header in sys/types.h sys/file.h glob.h wctype.h locale.h
|
||||||
do :
|
do :
|
||||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||||
@@ -3991,9 +4032,10 @@ _ACEOF
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
VERSION=03.03.05
|
VERSION=03.03.09
|
||||||
|
|
||||||
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h"
|
|
||||||
|
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h rem2html/Makefile"
|
||||||
|
|
||||||
cat >confcache <<\_ACEOF
|
cat >confcache <<\_ACEOF
|
||||||
# This file is a shell script that caches the results of configure
|
# This file is a shell script that caches the results of configure
|
||||||
@@ -4689,6 +4731,7 @@ do
|
|||||||
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
|
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
|
||||||
"www/Makefile") CONFIG_FILES="$CONFIG_FILES www/Makefile" ;;
|
"www/Makefile") CONFIG_FILES="$CONFIG_FILES www/Makefile" ;;
|
||||||
"src/version.h") CONFIG_FILES="$CONFIG_FILES src/version.h" ;;
|
"src/version.h") CONFIG_FILES="$CONFIG_FILES src/version.h" ;;
|
||||||
|
"rem2html/Makefile") CONFIG_FILES="$CONFIG_FILES rem2html/Makefile" ;;
|
||||||
|
|
||||||
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
|
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ AC_PROG_CC
|
|||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
AC_PROG_LN_S
|
AC_PROG_LN_S
|
||||||
AC_PROG_MAKE_SET
|
AC_PROG_MAKE_SET
|
||||||
|
AC_PATH_PROG([PERL], [perl])
|
||||||
|
|
||||||
dnl Checks for libraries.
|
dnl Checks for libraries.
|
||||||
dnl Replace `main' with a function in -lm:
|
dnl Replace `main' with a function in -lm:
|
||||||
@@ -61,7 +62,7 @@ AC_CHECK_SIZEOF(unsigned int)
|
|||||||
AC_CHECK_SIZEOF(unsigned long)
|
AC_CHECK_SIZEOF(unsigned long)
|
||||||
|
|
||||||
dnl Checks for header files.
|
dnl Checks for header files.
|
||||||
AC_CHECK_HEADERS(sys/file.h glob.h wctype.h locale.h)
|
AC_CHECK_HEADERS(sys/types.h sys/file.h glob.h wctype.h locale.h)
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
AC_STRUCT_TM
|
AC_STRUCT_TM
|
||||||
@@ -75,6 +76,7 @@ if test "$GCC" = yes; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale)
|
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale)
|
||||||
VERSION=03.03.05
|
VERSION=03.03.09
|
||||||
AC_SUBST(VERSION)
|
AC_SUBST(VERSION)
|
||||||
AC_OUTPUT(src/Makefile www/Makefile src/version.h)
|
AC_SUBST(PERL)
|
||||||
|
AC_OUTPUT(src/Makefile www/Makefile src/version.h rem2html/Makefile)
|
||||||
|
|||||||
@@ -1,5 +1,77 @@
|
|||||||
CHANGES TO REMIND
|
CHANGES TO REMIND
|
||||||
|
|
||||||
|
* VERSION 3.3 Patch 9 - 2021-10-14
|
||||||
|
|
||||||
|
- NEW FEATURE: Add "-+username" option to tell Remind to trust files owned by
|
||||||
|
"username" and allow RUN directives in them. Idea courtesy of Ian! D. Allen
|
||||||
|
|
||||||
|
- NEW FEATURE: Add "-u+username" variant to tell Remind to switch users to
|
||||||
|
"username" without disabling RUN directices. Idea courtesy of Ian! D. Allen
|
||||||
|
|
||||||
|
- CHANGE: rem2html: rem2html has been moved out of the www/ directory into
|
||||||
|
its own rem2html/ directory. If your system has the prerequisites
|
||||||
|
(namely Perl, Getopt::Long and JSON::Any) then rem2html will be installed
|
||||||
|
by "make install".
|
||||||
|
|
||||||
|
- CHANGE: Remove "cm2rem". It was about 20 years obsolete.
|
||||||
|
|
||||||
|
- CHANGE: rem2html: Use inline data: URL images for moon images by default,
|
||||||
|
thus producing a completely stand-alone HTML file.
|
||||||
|
|
||||||
|
- CHANGE: Remove unnecessary spaces from "remind -pp" JSON output.
|
||||||
|
|
||||||
|
- DOCUMENTATION FIX: Various man page fixes and tweaks.
|
||||||
|
|
||||||
|
- BUG FIX: rem2html: Tweak the default CSS stylesheet; more rational
|
||||||
|
handling of rem2html command-line options.
|
||||||
|
|
||||||
|
- BUG FIX: remind: "remind -c" would sometimes highlight *two* days as
|
||||||
|
"today"; this has been fixed.
|
||||||
|
|
||||||
|
- BUG FIX: Add a missing #ifdef...#endif and remove a C99-ism. This once again
|
||||||
|
allows Remind to be compiled with some very old C compilers.
|
||||||
|
|
||||||
|
* VERSION 3.3 Patch 8 - 2021-09-13
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: Add INCLUDECMD command
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: Add shellescape() built-in function
|
||||||
|
|
||||||
|
- BUG FIX: tkremind: TkRemind would sometimes fill in incorrect initial
|
||||||
|
values for the reminder-editing form if you clicked on a TkRemind-created
|
||||||
|
reminder to edit it. This has been fixed.
|
||||||
|
|
||||||
|
- BUG FIX: tkremind: Get back better error messages from Remind if you
|
||||||
|
try to create a reminder with an invalid date specification.
|
||||||
|
|
||||||
|
- BUG FIX: remind: Catch integer overflow if we try to evaluate $IntMin * -1
|
||||||
|
|
||||||
|
- DOC UPDATES: remind: Minor man page fixes
|
||||||
|
|
||||||
|
* VERSION 3.3 Patch 7 - 2021-05-10
|
||||||
|
|
||||||
|
- MINOR FIX: Refuse to run "make test" as root --- it would fail
|
||||||
|
anyway with an obscure message.
|
||||||
|
|
||||||
|
- BUG FIX: Remind would sometimes compute incorrect trigger date for:
|
||||||
|
REM Tue 29 Feb MSG ...
|
||||||
|
|
||||||
|
- BUG FIX: Remind would sometimes compute incorrect trigger date for
|
||||||
|
a date spec like: Tue 31 2021 MSG ...
|
||||||
|
|
||||||
|
* VERSION 3.3 Patch 6 - 2021-03-30
|
||||||
|
|
||||||
|
- test/test.rem: Change local to en_US.utf-8 only if current locale
|
||||||
|
is not a UTF-8 locale.
|
||||||
|
|
||||||
|
- MINOR CHANGE: Remind's arithemtic operators (+, -, *, /) give errors
|
||||||
|
on overflow rather than silently giving the wrong answer.
|
||||||
|
|
||||||
|
- MINOR CHANGE: Add $IntMin and $IntMax system variables.
|
||||||
|
|
||||||
|
- DOCUMENTATION FIX: Document that TkRemind now requires Tcl/Tk version
|
||||||
|
8.5 or newer.
|
||||||
|
|
||||||
* VERSION 3.3 Patch 5 - 2021-01-21
|
* VERSION 3.3 Patch 5 - 2021-01-21
|
||||||
|
|
||||||
- NEW FEATURE: tkremind: Add ability to change fonts and colors from
|
- NEW FEATURE: tkremind: Add ability to change fonts and colors from
|
||||||
|
|||||||
25
man/cm2rem.1
25
man/cm2rem.1
@@ -1,25 +0,0 @@
|
|||||||
.TH CM2REM 1 "18 October 1999"
|
|
||||||
.UC 4
|
|
||||||
.SH NAME
|
|
||||||
cm2rem.tcl \- Convert Sun's "cm" input file to Remind format
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B cm2rem.tcl < cm_file > remind_file
|
|
||||||
.SH DESCRIPTION
|
|
||||||
\fBcm2rem.tcl\fR reads the Sun calendar manager data file and converts
|
|
||||||
it into a \fBRemind\fR script. Note that \fBcm2rem.tcl\fR can convert
|
|
||||||
\fIonly\fR version 3 calendar manager files. If you are using version 4
|
|
||||||
files, there should be a system utility to convert them to version 3 files.
|
|
||||||
.SH AUTHOR
|
|
||||||
\fBcm2rem.tcl\fR was written by Dianne Skoll <dianne@skoll.ca>.
|
|
||||||
.SH BUGS
|
|
||||||
Not all of the Sun calendar manager options are respected. In particular,
|
|
||||||
nothing is done for e-mail actions. Also, the resulting Remind script
|
|
||||||
is not editable with \fBTkRemind\fR; you can only edit it with a text
|
|
||||||
editor.
|
|
||||||
.PP
|
|
||||||
\fBcm2rem.tcl\fR requires Tcl/Tk version 8.0 or higher. The
|
|
||||||
\fBtclsh\fR interpreter must be on your \fBpath\fR.
|
|
||||||
|
|
||||||
.SH SEE ALSO
|
|
||||||
\fBremind(1)\fR, \fBtkremind(1)\fR
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
.TH REM 1 "1 January 2020"
|
.TH REM 1 "1 January 2021"
|
||||||
.UC 4
|
.UC 4
|
||||||
.SH NAME
|
.SH NAME
|
||||||
rem \- Invoke Remind with a default filename
|
rem \- Invoke Remind with a default filename
|
||||||
|
|||||||
@@ -475,7 +475,7 @@ present and the value will be the type of SPECIAL (such as SHADE, COLOR,
|
|||||||
MOON, etc.)
|
MOON, etc.)
|
||||||
.TP
|
.TP
|
||||||
.B tags \fIdata\fR
|
.B tags \fIdata\fR
|
||||||
If any TAG clauses are present, the \fBtag\fR key will be present and consist
|
If any TAG clauses are present, the \fBtags\fR key will be present and consist
|
||||||
of a comma-separated list of tags.
|
of a comma-separated list of tags.
|
||||||
.TP
|
.TP
|
||||||
.B time \fIt\fR
|
.B time \fIt\fR
|
||||||
|
|||||||
102
man/remind.1
102
man/remind.1
@@ -1,4 +1,4 @@
|
|||||||
.TH REMIND 1 "1 January 2020"
|
.TH REMIND 1 "1 January 2021"
|
||||||
.UC 4
|
.UC 4
|
||||||
.SH NAME
|
.SH NAME
|
||||||
remind \- a sophisticated reminder service
|
remind \- a sophisticated reminder service
|
||||||
@@ -31,7 +31,8 @@ ignore them for now and skip to the section "REMINDER FILES".
|
|||||||
.B \-n
|
.B \-n
|
||||||
The \fB\-n\fR option causes \fBRemind\fR to print the \fBnext\fR occurrence
|
The \fB\-n\fR option causes \fBRemind\fR to print the \fBnext\fR occurrence
|
||||||
of each reminder in a simple calendar format. You can sort this by
|
of each reminder in a simple calendar format. You can sort this by
|
||||||
date by piping the output through \fBsort(1)\fR.
|
date by piping the output through \fBsort(1)\fR. Note that the \fB\-n\fR
|
||||||
|
option causes any \fB\-g\fR option to be \fIignored\fR.
|
||||||
.TP
|
.TP
|
||||||
.B \-j\fR[\fIn\fR]
|
.B \-j\fR[\fIn\fR]
|
||||||
Runs \fBRemind\fR in "purge" mode to get rid of expired reminders.
|
Runs \fBRemind\fR in "purge" mode to get rid of expired reminders.
|
||||||
@@ -39,7 +40,7 @@ See the section PURGE MODE for details.
|
|||||||
.TP
|
.TP
|
||||||
.B \-r
|
.B \-r
|
||||||
The \fB\-r\fR option disables \fBRUN\fR directives and the \fBshell()\fR
|
The \fB\-r\fR option disables \fBRUN\fR directives and the \fBshell()\fR
|
||||||
function. As of Remind 3.00.17, using \fB\-u\fR implies \fB\-r\fR.
|
function.
|
||||||
.TP
|
.TP
|
||||||
.B \-c\fI[flags]\fIn\fR
|
.B \-c\fI[flags]\fIn\fR
|
||||||
The \fB\-c\fR option causes \fBRemind\fR to produce a calendar that is
|
The \fB\-c\fR option causes \fBRemind\fR to produce a calendar that is
|
||||||
@@ -250,6 +251,7 @@ The optional \fBa\fR and \fBd\fR characters specify the sort order
|
|||||||
(ascending or descending) for the date, time and priority fields. See
|
(ascending or descending) for the date, time and priority fields. See
|
||||||
the section "SORTING REMINDERS" for more information.
|
the section "SORTING REMINDERS" for more information.
|
||||||
|
|
||||||
|
Note that \fB\-g\fR is \fIignored\fR if you use the \fB\-n\fR option.
|
||||||
.TP
|
.TP
|
||||||
\fB\-b\fR[\fIn\fR]
|
\fB\-b\fR[\fIn\fR]
|
||||||
Set the time format for the calendar and simple-calendar outputs. \fIN\fR
|
Set the time format for the calendar and simple-calendar outputs. \fIN\fR
|
||||||
@@ -308,7 +310,11 @@ and user name, respectively, of the specified user. LOGNAME is also
|
|||||||
set to the specified user name. This option is meant for
|
set to the specified user name. This option is meant for
|
||||||
use in shell scripts that mail reminders to all users. Note that
|
use in shell scripts that mail reminders to all users. Note that
|
||||||
as of Remind 3.00.17, using \fB\-u\fR implies \fB\-r\fR -- the RUN
|
as of Remind 3.00.17, using \fB\-u\fR implies \fB\-r\fR -- the RUN
|
||||||
directive and shell() functions are disabled.
|
directive and shell() functions are disabled. However, if you prefix
|
||||||
|
\fIname\fR with a \fB+\fR-sign, then RUN and shell() are \fInot\fR
|
||||||
|
disabled. That is, \fB\-uwhatever\fR switches the user to \fBwhatever\fR
|
||||||
|
and disables RUN, whereas \fB\-u+whatever\fR switches the user to
|
||||||
|
\fBwhatever\fR but leaves RUN enabled.
|
||||||
.PP
|
.PP
|
||||||
.RS
|
.RS
|
||||||
Non-root users can also use the \fB\-u\fR option. However, in this
|
Non-root users can also use the \fB\-u\fR option. However, in this
|
||||||
@@ -316,6 +322,13 @@ case, it only changes the environment variables as described above.
|
|||||||
It does not change the effective uid or gid.
|
It does not change the effective uid or gid.
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-+\fIusername\fR
|
||||||
|
Causes \fBRemind\fR to trust files owned by the user \fIusername\fR.
|
||||||
|
Normally, if \fBRemind\fR reads a file that you do not own, it disables
|
||||||
|
RUN and the shell() function. This option causes it to also trust files
|
||||||
|
owned by \fIusername\fR. You can supply multiple \fB\-+\fR options
|
||||||
|
to trust multiple users, up to a limit of 20 trusted users.
|
||||||
|
.TP
|
||||||
\fB-y\fR
|
\fB-y\fR
|
||||||
Causes \fBRemind\fR to synthesize a tag for any reminder that lacks a
|
Causes \fBRemind\fR to synthesize a tag for any reminder that lacks a
|
||||||
TAG clause.
|
TAG clause.
|
||||||
@@ -349,7 +362,7 @@ it as YYYY-MM-DD or YYYY/MM/DD. You can even supply a date and
|
|||||||
time on the command line as one argument: YYYY-MM-DD@HH:MM.
|
time on the command line as one argument: YYYY-MM-DD@HH:MM.
|
||||||
.PP
|
.PP
|
||||||
In addition, you can supply a \fIrepeat\fR parameter, which has the
|
In addition, you can supply a \fIrepeat\fR parameter, which has the
|
||||||
form *\fInum\fR. This causes \fBRemind\fR to be run \fInum\fR times,
|
form *\fIrep\fR. This causes \fBRemind\fR to be run \fIrep\fR times,
|
||||||
with the date incrementing on each iteration. You may have to enclose
|
with the date incrementing on each iteration. You may have to enclose
|
||||||
the parameter in quotes to avoid shell expansion. See the subsection
|
the parameter in quotes to avoid shell expansion. See the subsection
|
||||||
"Repeated Execution" in the section "CALENDAR MODE" for more
|
"Repeated Execution" in the section "CALENDAR MODE" for more
|
||||||
@@ -618,7 +631,7 @@ present. Examples:
|
|||||||
.nf
|
.nf
|
||||||
REM Sat 1 MSG First Saturday of every month
|
REM Sat 1 MSG First Saturday of every month
|
||||||
REM Mon Tue Wed Thu Fri 15 \\
|
REM Mon Tue Wed Thu Fri 15 \\
|
||||||
MSG 1st working day after 15th of every month
|
MSG 1st working day on or after 15th of every month
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
11.
|
11.
|
||||||
@@ -1579,6 +1592,53 @@ It will not run set-uid. If it reads a file you don't own, it will
|
|||||||
disable RUN and the shell() function. And if it is run as \fIroot\fR,
|
disable RUN and the shell() function. And if it is run as \fIroot\fR,
|
||||||
it will only read files owned by \fIroot\fR.
|
it will only read files owned by \fIroot\fR.
|
||||||
.PP
|
.PP
|
||||||
|
Note that if \fBRemind\fR reads standard input, it does \fInot\fR
|
||||||
|
attempt to check the ownership of standard input, even if it is
|
||||||
|
coming from a file, and hence does \fInot\fR disable RUN and shell()
|
||||||
|
in this situation.
|
||||||
|
|
||||||
|
.SH THE INCLUDECMD COMMAND
|
||||||
|
.PP
|
||||||
|
\fBRemind\fR allows you to execute a shell command and evaluate the
|
||||||
|
output of that command as if it were an included file. For example,
|
||||||
|
you could have scripts that extract reminders out of a database and print
|
||||||
|
them on stdout as REM commands. Here is an example:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
INCLUDECMD extract_reminders_for dfs
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
We assume that the command "extract_reminders_for" extracts reminders out
|
||||||
|
of a central database for the named user. Another use-case of INCLUDECMD
|
||||||
|
is if you have your reminders stored in a file in some non-Remind format;
|
||||||
|
you can write a command that transforms them to Remind format and then
|
||||||
|
Remind can "include" the file with an appropriate INCLUDECMD command.
|
||||||
|
.PP
|
||||||
|
Note that if RUN is disabled, then INCLUDECMD will fail with the error
|
||||||
|
message "RUN disabled"
|
||||||
|
.PP
|
||||||
|
INCLUDECMD passes the rest of the line to \fBpopen\fR(3), meaning that
|
||||||
|
the command is executed by the shell. As such, shell metacharacters
|
||||||
|
may need escaping or arguments quoting, depending on what you're trying
|
||||||
|
to do. Remind itself does not perform any modification of the command
|
||||||
|
line (apart from the normal [expr] expression-pasting mechanism).
|
||||||
|
.PP
|
||||||
|
If the command passed to INCLUDECMD begins with an exclamation mark "!",
|
||||||
|
then Remind disables \fBRUN\fR for the output of the command. If you are
|
||||||
|
running a command whose output you don't quite trust, you should
|
||||||
|
prefix it with "!" so that any RUN commands it emits fail.
|
||||||
|
.PP
|
||||||
|
An \fBINCLUDECMD\fR command counts towards the INCLUDE nesting depth.
|
||||||
|
For any given Remind run, a given INCLUDECMD command is only executed
|
||||||
|
once and the results are cached. For example, if you generate a
|
||||||
|
calendar, each unique INCLUDECMD command is run just once, not once
|
||||||
|
for each day of the produced calendar. "Uniqueness" is determined by
|
||||||
|
looking at the command that will be passed to the shell, so if (for example)
|
||||||
|
your INCLUDECMD uses expression-pasting that results in differences depending
|
||||||
|
on the value of \fBtoday()\fR, then each \fIunique\fR version of the
|
||||||
|
command will be executed once.
|
||||||
|
.PP
|
||||||
|
|
||||||
.SH THE BANNER COMMAND
|
.SH THE BANNER COMMAND
|
||||||
.PP
|
.PP
|
||||||
When \fBRemind\fR first issues a reminder, it prints a message like this:
|
When \fBRemind\fR first issues a reminder, it prints a message like this:
|
||||||
@@ -1868,6 +1928,11 @@ otherwise.
|
|||||||
.PP
|
.PP
|
||||||
.B NOTES
|
.B NOTES
|
||||||
.PP
|
.PP
|
||||||
|
If the result of an addition, subtraction or multiplication operation
|
||||||
|
would not fit in a C "int" type, \fBRemind\fR issues a "Number too
|
||||||
|
high" error. Unlike C, integer operations will not simply give the
|
||||||
|
wrong answer in case of overflow.
|
||||||
|
.PP
|
||||||
Operators of equal precedence are \fIalways\fR evaluated from left
|
Operators of equal precedence are \fIalways\fR evaluated from left
|
||||||
to right, except where parentheses dictate otherwise. This is important,
|
to right, except where parentheses dictate otherwise. This is important,
|
||||||
because the enhanced "+" operator is not necessarily associative.
|
because the enhanced "+" operator is not necessarily associative.
|
||||||
@@ -2060,6 +2125,14 @@ then \fBONCE\fR directives will be ignored.
|
|||||||
.B $InfDelta (read-only)
|
.B $InfDelta (read-only)
|
||||||
If non-zero, then the \fB\-t\fR option was supplied on the command line.
|
If non-zero, then the \fB\-t\fR option was supplied on the command line.
|
||||||
.TP
|
.TP
|
||||||
|
.B $IntMax (read-only)
|
||||||
|
The largest representable \fBINT\fR. On a machine with 32-bit signed integers
|
||||||
|
using twos-complement representation, this will be 2147483647.
|
||||||
|
.TP
|
||||||
|
.B $IntMin (read-only)
|
||||||
|
The smallest representable \fBINT\fR. On a machine with 32-bit signed integers
|
||||||
|
using twos-complement representation, this will be -2147483648.
|
||||||
|
.TP
|
||||||
.B $LatDeg, $LatMin, $LatSec
|
.B $LatDeg, $LatMin, $LatSec
|
||||||
These specify the latitude of your location. \fB$LatDeg\fR can
|
These specify the latitude of your location. \fB$LatDeg\fR can
|
||||||
range from \-90 to 90, and the others from \-59 to 59. Northern latitudes
|
range from \-90 to 90, and the others from \-59 to 59. Northern latitudes
|
||||||
@@ -2838,6 +2911,23 @@ If \fImaxlen\fR is specified, then \fBshell()\fR returns the first
|
|||||||
\fImaxlen\fR is specified as a negative number, then \fIall\fR the
|
\fImaxlen\fR is specified as a negative number, then \fIall\fR the
|
||||||
output from \fIcmd\fR is returned.
|
output from \fIcmd\fR is returned.
|
||||||
.RE
|
.RE
|
||||||
|
.TP
|
||||||
|
.B shellescape(s_str)
|
||||||
|
Returns \fIstr\fR with all shell metacharacters such as " ", "*", etc
|
||||||
|
escaped with a backslash. For example:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
SET a shellescape("a b*? c&d$e")
|
||||||
|
.fi
|
||||||
|
.RS
|
||||||
|
.PP
|
||||||
|
will set \fBa\fR to:
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
"a\\ b\\*\\?\\ c\\&d\\$e"
|
||||||
|
.fi
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B slide(d_start, i_amt [,s_wkday...])
|
.B slide(d_start, i_amt [,s_wkday...])
|
||||||
This function is the inverse of \fBnonomitted\fR. It adds \fIamt\fR
|
This function is the inverse of \fBnonomitted\fR. It adds \fIamt\fR
|
||||||
|
|||||||
@@ -13,8 +13,10 @@ Although not all of \fBRemind\fR's features are available with \fBTkRemind\fR,
|
|||||||
it creates. This allows you to learn \fBRemind\fR's syntax and then add
|
it creates. This allows you to learn \fBRemind\fR's syntax and then add
|
||||||
extra features as you become a more sophisticated \fBRemind\fR programmer.
|
extra features as you become a more sophisticated \fBRemind\fR programmer.
|
||||||
|
|
||||||
\fBTkRemind\fR is written in Tcl, and requires version 8.0
|
\fBTkRemind\fR is written in Tcl, and requires version 8.5 (or higher)
|
||||||
(or higher). It also requires a \fBwish\fR binary.
|
as well as the tcllib extension. It also requires a \fBwish\fR
|
||||||
|
binary. If you are using Tcl/Tk 8.5, you may also need either the Img
|
||||||
|
or the tkpng extension to handle PNG images.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
\fBTkRemind\fR itself has no options. However, it passes certain options
|
\fBTkRemind\fR itself has no options. However, it passes certain options
|
||||||
|
|||||||
29
rem2html/Makefile.in
Normal file
29
rem2html/Makefile.in
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Set by configure - don't touch.
|
||||||
|
srcdir=@srcdir@
|
||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
mandir=@mandir@
|
||||||
|
bindir=@bindir@
|
||||||
|
datadir=@datadir@
|
||||||
|
datarootdir=@datarootdir@
|
||||||
|
PERL=@PERL@
|
||||||
|
PERLMODS_NEEDED=JSON::Any Getopt::Long
|
||||||
|
all:
|
||||||
|
true
|
||||||
|
|
||||||
|
install:
|
||||||
|
@if test "$(PERL)" = "" ; then \
|
||||||
|
echo "Not installing rem2html; Perl is required"; exit 0; fi; \
|
||||||
|
for m in $(PERLMODS_NEEDED) ; \
|
||||||
|
do \
|
||||||
|
perl -M$$m -e 1 > /dev/null 2>&1; \
|
||||||
|
if test $$? != 0 ; then echo "Not installing rem2html; missing $$m"; exit 0; fi; \
|
||||||
|
done; \
|
||||||
|
echo "Installing rem2html in $(DESTDIR)$(bindir)"; \
|
||||||
|
mkdir -p $(DESTDIR)$(bindir) && sed -e 's|^#!perl|#!$(PERL)|' < rem2html > $(DESTDIR)$(bindir)/rem2html && chmod 755 $(DESTDIR)$(bindir)/rem2html && exit 0; \
|
||||||
|
exit 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
12
rem2html/README.rem2html
Normal file
12
rem2html/README.rem2html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
REM2HTML
|
||||||
|
--------
|
||||||
|
|
||||||
|
rem2html is a Perl script that transforms the output of `remind -pp
|
||||||
|
...' to HTML. Type `perl rem2html --help' for usage information.
|
||||||
|
|
||||||
|
rem2html requires the Perl modules `JSON::Any' and `Getopt::Long'. It
|
||||||
|
will not be installed unless you have those modules as well as Perl
|
||||||
|
itself.
|
||||||
|
|
||||||
|
--
|
||||||
|
Dianne Skoll
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/perl
|
#!perl
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
@@ -16,15 +16,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 -p" to HTML
|
# rem2html -- convert the output of "remind -pp" to HTML
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
rem2html - Convert the output of "remind -p" to HTML
|
rem2html - Convert the output of "remind -pp" to HTML
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
remind -p ... | rem2html [options]
|
remind -pp ... | rem2html [options]
|
||||||
|
|
||||||
|
You can also use the old interchange format as below, but the -pp
|
||||||
|
version is preferred.
|
||||||
|
|
||||||
|
remind -p ... | rem2html [options]
|
||||||
|
|
||||||
=head1 OPTIONS
|
=head1 OPTIONS
|
||||||
|
|
||||||
@@ -50,13 +55,21 @@ month name a link to I<url>.
|
|||||||
|
|
||||||
=item --imgbase I<url>
|
=item --imgbase I<url>
|
||||||
|
|
||||||
When creating URLs for images and the stylesheet, use
|
When creating URLs for the stylesheet or external images, use I<url>
|
||||||
I<url> as the base URL.
|
as the base URL.
|
||||||
|
|
||||||
|
=item --pngs
|
||||||
|
|
||||||
|
Normally, rem2html uses inline "data:" URLs for the moon phase images,
|
||||||
|
yielding a standalone HTML file. The C<--pngs> option makes it use
|
||||||
|
external images named firstquarter.png, fullmoon.png, lastquarter.png
|
||||||
|
and newmoon.png, which are expected to live in C<--imgbase>.
|
||||||
|
|
||||||
=item --stylesheet I<url.css>
|
=item --stylesheet I<url.css>
|
||||||
|
|
||||||
Use I<url.css> as the stylesheet. If this option is used,
|
Use I<url.css> as the stylesheet. If this option is used,
|
||||||
I<url.css> is I<not> interpreted relative to B<imgbase>.
|
I<url.css> is interpreted relative to B<imgbase> I<unless> it start
|
||||||
|
with a "/".
|
||||||
|
|
||||||
=item --nostyle
|
=item --nostyle
|
||||||
|
|
||||||
@@ -97,9 +110,9 @@ 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 -p"
|
$TIDY_PROGNAME: Produce an HTML calendar from the output of "remind -pp"
|
||||||
|
|
||||||
Usage: remind -p ... | rem2html [options]
|
Usage: remind -pp ... | rem2html [options]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
@@ -110,6 +123,8 @@ Options:
|
|||||||
entry a link to <url>
|
entry a link to <url>
|
||||||
--forwurl url Same as --backurl, but for the next month's small calendar
|
--forwurl url Same as --backurl, but for the next month's small calendar
|
||||||
--imgbase url Base URL of images and default stylesheet file
|
--imgbase url Base URL of images and default stylesheet file
|
||||||
|
--pngs Use external .PNG images for moon phases rater than
|
||||||
|
inline data: URLs
|
||||||
--stylesheet url.css URL of CSS stylesheet. If specified, imgbase is NOT
|
--stylesheet url.css URL of CSS stylesheet. If specified, imgbase is NOT
|
||||||
prepended to url.css
|
prepended to url.css
|
||||||
--nostyle Produce basic HTML that does not use a CSS stylesheet
|
--nostyle Produce basic HTML that does not use a CSS stylesheet
|
||||||
@@ -121,11 +136,31 @@ EOM
|
|||||||
exit($exit_status);
|
exit($exit_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub smoosh
|
||||||
|
{
|
||||||
|
my ($first, $second) = @_;
|
||||||
|
return $second unless defined ($first);
|
||||||
|
return $second if $first eq '';
|
||||||
|
return $second if ($second =~ m|^/|); # Absolute path given for second
|
||||||
|
|
||||||
|
# Squash multiple slashes
|
||||||
|
$first =~ s|/+|/|g;
|
||||||
|
|
||||||
|
# Special case
|
||||||
|
return "/$second" if ($first eq '/');
|
||||||
|
|
||||||
|
# Delete trailing slash
|
||||||
|
$first =~ s|/$||;
|
||||||
|
|
||||||
|
return "$first/$second";
|
||||||
|
}
|
||||||
|
|
||||||
sub parse_options
|
sub parse_options
|
||||||
{
|
{
|
||||||
local $SIG{__WARN__} = sub { print STDERR "$TIDY_PROGNAME: $_[0]\n"; };
|
local $SIG{__WARN__} = sub { print STDERR "$TIDY_PROGNAME: $_[0]\n"; };
|
||||||
if (!GetOptions(\%Options, "help|h",
|
if (!GetOptions(\%Options, "help|h",
|
||||||
"man",
|
"man",
|
||||||
|
"pngs",
|
||||||
"version",
|
"version",
|
||||||
"stylesheet=s",
|
"stylesheet=s",
|
||||||
"nostyle",
|
"nostyle",
|
||||||
@@ -138,45 +173,40 @@ sub parse_options
|
|||||||
"tableonly")) {
|
"tableonly")) {
|
||||||
usage(1);
|
usage(1);
|
||||||
}
|
}
|
||||||
$Options{'title'} ||= 'HTML Calendar';
|
$Options{title} ||= 'HTML Calendar';
|
||||||
|
|
||||||
# Fix up imgbase
|
my $stylesheet = $Options{stylesheet};
|
||||||
my $imgbase = '%IMAGEBASE%';
|
if ($stylesheet) {
|
||||||
if ($imgbase ne '%' . 'IMAGEBASE' . '%') {
|
$Options{stylesheet} = smoosh($Options{imgbase}, $stylesheet);
|
||||||
$Options{'imgbase'} ||= $imgbase;
|
|
||||||
} else {
|
|
||||||
$Options{'imgbase'} ||= '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$Options{'imgbase'} =~ s|/+$||;
|
|
||||||
my $stylesheet = $Options{'imgbase'};
|
|
||||||
$stylesheet .= '/' if ($stylesheet ne '');
|
|
||||||
$stylesheet .= 'rem-default.css';
|
|
||||||
$Options{'stylesheet'} ||= $stylesheet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub start_output
|
sub start_output
|
||||||
{
|
{
|
||||||
return if ($Options{'tableonly'});
|
return if ($Options{tableonly});
|
||||||
|
|
||||||
print("<html>\n<head>\n<title>" . $Options{'title'} . "</title>\n");
|
print("<html>\n<head>\n<title>" . $Options{title} . "</title>\n");
|
||||||
if (!$Options{'nostyle'}) {
|
if (!$Options{nostyle}) {
|
||||||
if ($Options{'stylesheet'}) {
|
if ($Options{stylesheet}) {
|
||||||
print('<link rel="stylesheet" type="text/css" href="' .
|
print('<link rel="stylesheet" type="text/css" href="' .
|
||||||
$Options{'stylesheet'} . '">' . "\n");
|
$Options{stylesheet} . '">' . "\n");
|
||||||
}
|
} else {
|
||||||
|
print("<style>\n");
|
||||||
|
print default_stylesheet();
|
||||||
|
print("</style>\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
print("</head>\n<body>\n");
|
print("</head>\n<body>\n");
|
||||||
if ($Options{'prologue'}) {
|
if ($Options{prologue}) {
|
||||||
print $Options{'prologue'} . "\n";
|
print $Options{prologue} . "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub end_output
|
sub end_output
|
||||||
{
|
{
|
||||||
return if ($Options{'tableonly'});
|
return if ($Options{tableonly});
|
||||||
if ($Options{'epilogue'}) {
|
if ($Options{epilogue}) {
|
||||||
print $Options{'epilogue'} . "\n";
|
print $Options{epilogue} . "\n";
|
||||||
}
|
}
|
||||||
print("</body>\n</html>\n");
|
print("</body>\n</html>\n");
|
||||||
}
|
}
|
||||||
@@ -222,7 +252,7 @@ sub parse_input
|
|||||||
|
|
||||||
$found_data = 1;
|
$found_data = 1;
|
||||||
my $class;
|
my $class;
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
$class = '';
|
$class = '';
|
||||||
} else {
|
} else {
|
||||||
$class = ' class="rem-entry"';
|
$class = ' class="rem-entry"';
|
||||||
@@ -301,7 +331,7 @@ sub small_calendar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print "<td width=\"14%\">\n";
|
print "<td width=\"14%\">\n";
|
||||||
print "<table border=\"0\">\n";
|
print "<table border=\"0\">\n";
|
||||||
print "<caption>";
|
print "<caption>";
|
||||||
@@ -316,7 +346,7 @@ sub small_calendar
|
|||||||
print "</caption>\n";
|
print "</caption>\n";
|
||||||
|
|
||||||
my $class;
|
my $class;
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print '<tr>';
|
print '<tr>';
|
||||||
$class = ' align="right"';
|
$class = ' align="right"';
|
||||||
} else {
|
} else {
|
||||||
@@ -338,7 +368,7 @@ sub small_calendar
|
|||||||
if ($col == 0) {
|
if ($col == 0) {
|
||||||
print("<tr>\n");
|
print("<tr>\n");
|
||||||
}
|
}
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print("<td align=\"right\" width=\"14%\"> </td>");
|
print("<td align=\"right\" width=\"14%\"> </td>");
|
||||||
} else {
|
} else {
|
||||||
print("<td class=\"rem-sc-empty-cell\"> </td>");
|
print("<td class=\"rem-sc-empty-cell\"> </td>");
|
||||||
@@ -350,7 +380,7 @@ sub small_calendar
|
|||||||
print("<tr>\n");
|
print("<tr>\n");
|
||||||
}
|
}
|
||||||
$col++;
|
$col++;
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print("<td align=\"right\" width=\"14%\">$day</td>");
|
print("<td align=\"right\" width=\"14%\">$day</td>");
|
||||||
} else {
|
} else {
|
||||||
print("<td class=\"rem-sc-cell\">$day</td>");
|
print("<td class=\"rem-sc-cell\">$day</td>");
|
||||||
@@ -362,7 +392,7 @@ sub small_calendar
|
|||||||
}
|
}
|
||||||
if ($col) {
|
if ($col) {
|
||||||
while ($col < 7) {
|
while ($col < 7) {
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print("<td align=\"right\" width=\"14%\"> </td>");
|
print("<td align=\"right\" width=\"14%\"> </td>");
|
||||||
} else {
|
} else {
|
||||||
print("<td class=\"rem-sc-empty-cell\"> </td>");
|
print("<td class=\"rem-sc-empty-cell\"> </td>");
|
||||||
@@ -391,7 +421,7 @@ sub output_calendar
|
|||||||
|
|
||||||
# Start the table
|
# Start the table
|
||||||
my $class;
|
my $class;
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print '<table width="100%" border="1" cellspacing=\"0\"><caption>' .
|
print '<table width="100%" border="1" cellspacing=\"0\"><caption>' .
|
||||||
$Month . ' ' . $Year . '</caption>' . "\n";
|
$Month . ' ' . $Year . '</caption>' . "\n";
|
||||||
print '<tr>';
|
print '<tr>';
|
||||||
@@ -415,23 +445,23 @@ sub output_calendar
|
|||||||
|
|
||||||
# Start the calendar rows
|
# Start the calendar rows
|
||||||
my $col = 0;
|
my $col = 0;
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print "<tr>\n";
|
print "<tr>\n";
|
||||||
} else {
|
} else {
|
||||||
print "<tr class=\"rem-cal-row\">\n";
|
print "<tr class=\"rem-cal-row\">\n";
|
||||||
}
|
}
|
||||||
if ($first_col > 0) {
|
if ($first_col > 0) {
|
||||||
small_calendar($Prevmon, $Prevlen, $Options{'backurl'},
|
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
||||||
($Firstwkday - $Prevlen + 35) % 7);
|
($Firstwkday - $Prevlen + 35) % 7);
|
||||||
$col++;
|
$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%"';
|
||||||
} else {
|
} else {
|
||||||
$class = ' class="rem-empty"';
|
$class = ' class="rem-empty"';
|
||||||
@@ -448,7 +478,7 @@ sub output_calendar
|
|||||||
$col = 0;
|
$col = 0;
|
||||||
print "</tr>\n";
|
print "</tr>\n";
|
||||||
if ($day < $Numdays) {
|
if ($day < $Numdays) {
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print "<tr>\n";
|
print "<tr>\n";
|
||||||
} else {
|
} else {
|
||||||
print "<tr class=\"rem-cal-row\">\n";
|
print "<tr class=\"rem-cal-row\">\n";
|
||||||
@@ -461,13 +491,13 @@ sub output_calendar
|
|||||||
while ($col < 7) {
|
while ($col < 7) {
|
||||||
if ($col == 5) {
|
if ($col == 5) {
|
||||||
if ($first_col == 0) {
|
if ($first_col == 0) {
|
||||||
small_calendar($Prevmon, $Prevlen, $Options{'backurl'},
|
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
||||||
($Firstwkday - $Prevlen + 35) % 7);
|
($Firstwkday - $Prevlen + 35) % 7);
|
||||||
} else {
|
} else {
|
||||||
print("<td$class> </td>\n");
|
print("<td$class> </td>\n");
|
||||||
}
|
}
|
||||||
} elsif ($col == 6) {
|
} elsif ($col == 6) {
|
||||||
small_calendar($Nextmon, $Nextlen, $Options{'forwurl'},
|
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
||||||
($Firstwkday + $Numdays) % 7);
|
($Firstwkday + $Numdays) % 7);
|
||||||
} else {
|
} else {
|
||||||
print("<td$class> </td>\n");
|
print("<td$class> </td>\n");
|
||||||
@@ -479,17 +509,17 @@ sub output_calendar
|
|||||||
|
|
||||||
# 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\">\n";
|
print "<tr class=\"rem-cal-row\">\n";
|
||||||
}
|
}
|
||||||
small_calendar($Prevmon, $Prevlen, $Options{'backurl'},
|
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
||||||
($Firstwkday - $Prevlen + 35) % 7);
|
($Firstwkday - $Prevlen + 35) % 7);
|
||||||
for (my $i=0; $i<5; $i++) {
|
for (my $i=0; $i<5; $i++) {
|
||||||
print("<td$class> </td>\n");
|
print("<td$class> </td>\n");
|
||||||
}
|
}
|
||||||
small_calendar($Nextmon, $Nextlen, $Options{'forwurl'},
|
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
||||||
($Firstwkday + $Numdays) % 7);
|
($Firstwkday + $Numdays) % 7);
|
||||||
print("</tr>\n");
|
print("</tr>\n");
|
||||||
}
|
}
|
||||||
@@ -506,7 +536,7 @@ sub draw_day_cell
|
|||||||
$week = ' ' . $weeks->{$day};
|
$week = ' ' . $weeks->{$day};
|
||||||
}
|
}
|
||||||
my $class;
|
my $class;
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
$class = $classes->[$day] || '';
|
$class = $classes->[$day] || '';
|
||||||
} else {
|
} else {
|
||||||
$class = $classes->[$day] || "rem-cell";
|
$class = $classes->[$day] || "rem-cell";
|
||||||
@@ -532,33 +562,46 @@ sub draw_day_cell
|
|||||||
my $alt;
|
my $alt;
|
||||||
my $title;
|
my $title;
|
||||||
if ($phase == 0) {
|
if ($phase == 0) {
|
||||||
$img = 'newmoon.png';
|
if ($Options{pngs}) {
|
||||||
|
$img = smoosh($Options{imgbase}, 'newmoon.png');
|
||||||
|
} else {
|
||||||
|
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAC6SURBVDiNpdNNbsIwFATgL0HKolchHKBX6yFaBOEyoPYUabvOIVKJRaCL2JX5TRNGGvnJ8ozGz89cYoElPvET+BX2yivn/1Bggw5HHMKa1h2qcPZC/JEIhvh+brIZIY6sorhMYo9hh3KGFzzfa84NZNjDt9OG/ZcH1BlaPE1IAG0+URhxzNGESKPFaHJs9Q0Ziww7HnvGeXSrJhis0jiFfjwnj3I0WRv+TKtr4hQl3lDrZ6QN9Wt654hfWfGDmBpUwDkAAAAASUVORK5CYII=';
|
||||||
|
}
|
||||||
$title = 'New Moon';
|
$title = 'New Moon';
|
||||||
$alt = 'new';
|
$alt = 'new';
|
||||||
} elsif ($phase == 1) {
|
} elsif ($phase == 1) {
|
||||||
$img = 'firstquarter.png';
|
if ($Options{pngs}) {
|
||||||
|
$img = smoosh($Options{imgbase}, 'firstquarter.png');
|
||||||
|
} else {
|
||||||
|
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADfSURBVDiNndM9TsNAFATgzy5yjZSAE85JBygETgENUPF3iBCitHAFQkcIhZ/Ryn9gRlrZmp2Z3ef3TBOHOMULPrDBMrhpi/4HI5xjix2+4nmJRbx/Yh7ahvkpRPVV4QDXwT3UQy46zGkAZDgK/iytefvHgCrkJsqZUH6cLnNbABSxd5Jhhf1IbkMXv8Qux7hH1Ic1xvk/jBWy6gavumvtwx7ectwZXkKh7MA95XgObeOtpI2U4zl0kGbpxgiPvwQUcXLrKFchc82f6Ur0PK49azOnmOI4TBu84zm4SV38DeIVYkrYJyNbAAAAAElFTkSuQmCC';
|
||||||
|
}
|
||||||
$title = 'First Quarter';
|
$title = 'First Quarter';
|
||||||
$alt = '1st';
|
$alt = '1st';
|
||||||
} elsif ($phase == 2) {
|
} elsif ($phase == 2) {
|
||||||
$img = 'fullmoon.png';
|
if ($Options{pngs}) {
|
||||||
|
$img = smoosh($Options{imgbase}, 'fullmoon.png');
|
||||||
|
} else {
|
||||||
|
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADlSURBVDiNrdNBUsJAEAXQlyw4hq4hwWPqTixET6ELkZ16CcAq7oFLqXExjaYgQVNlV/Viev7/6XT/4TjGuME7PiLXUatb8N8xwB12SFjiIXIZtU/MAntEfgvQE4YtHxhiHpjXQ5H7uLhEcaLLAleBvd0Xx9Ha/BdyU+Q5OBV5OKmj7a4YBWdSyNPe4aKHAHkzqcQZNj3JgnNexqE8heyIAulffuFF3kTfIVbBVeu/xoXGGsn2TLJJ/mqkafNiINszySYZdbS90GHlvcgsWktY4TFy7ecxTdvIzahxHQLbyFXUqkPwF2ASRNYgB/PXAAAAAElFTkSuQmCC';
|
||||||
|
}
|
||||||
$alt = 'full';
|
$alt = 'full';
|
||||||
$title = 'Full Moon';
|
$title = 'Full Moon';
|
||||||
} else {
|
} else {
|
||||||
$img = 'lastquarter.png';
|
if ($Options{pngs}) {
|
||||||
|
$img = smoosh($Options{imgbase}, 'lastquarter.png');
|
||||||
|
} else {
|
||||||
|
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADmSURBVDiNndMxTsNAEIXhzy5yCyQ6FAgcE7oQheQWUAAl5BIkREoZrgB0GFNkHBl7bURGsryaee/3jHeXdpxjghU+8InXyI0S+n0MMEeBEi+4jfV3vAvMQtsyL0J0j2GtViaeRRMyj8IlsgY8BSijE2Kur/hy09wHKMJrEolhwtwHKDHOsI4OLnoAXfl1jiNsOkR9keE4P8D4q4scbzg5xIxtjie709f1E7siC+9+Gx/8fxvPKtEsklcJSBdgWhcN8ByFR5z+AWgd5QpyE+OUWOJO+zJNU+Z6jHAdgHe7K73CuD5zFT9nCmRDIssCaAAAAABJRU5ErkJggg==';
|
||||||
|
}
|
||||||
$alt = 'last';
|
$alt = 'last';
|
||||||
$title = 'Last Quarter';
|
$title = 'Last Quarter';
|
||||||
}
|
}
|
||||||
if ($Options{'imgbase'}) {
|
if ($Options{nostyle}) {
|
||||||
$img = $Options{'imgbase'} . '/' . $img;
|
|
||||||
}
|
|
||||||
if ($Options{'nostyle'}) {
|
|
||||||
print("<div style=\"float: left\"><img border=\"0\" width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
|
print("<div style=\"float: left\"><img border=\"0\" width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
|
||||||
} else {
|
} else {
|
||||||
print("<div class=\"rem-moon\"><img width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
|
print("<div class=\"rem-moon\"><img width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print "<div style=\"float: right\">$day$week</div>\n";
|
print "<div style=\"float: right\">$day$week</div>\n";
|
||||||
print "<p> </p>\n";
|
print "<p> </p>\n";
|
||||||
} else {
|
} else {
|
||||||
@@ -581,13 +624,13 @@ sub escape_html
|
|||||||
}
|
}
|
||||||
|
|
||||||
parse_options();
|
parse_options();
|
||||||
if ($Options{'help'}) {
|
if ($Options{help}) {
|
||||||
usage(0);
|
usage(0);
|
||||||
exit(0);
|
exit(0);
|
||||||
} elsif ($Options{'man'}) {
|
} elsif ($Options{man}) {
|
||||||
system("perldoc $0");
|
system("perldoc $0");
|
||||||
exit(0);
|
exit(0);
|
||||||
} elsif ($Options{'version'}) {
|
} elsif ($Options{version}) {
|
||||||
print "rem2html version $rem2html_version.\n";
|
print "rem2html version $rem2html_version.\n";
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
@@ -612,3 +655,81 @@ if ($found_something) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub default_stylesheet
|
||||||
|
{
|
||||||
|
return <<'EOF';
|
||||||
|
table.rem-cal {
|
||||||
|
font-family: helvetica, arial, sans-serif;
|
||||||
|
font-size: 12pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.rem-sc-table {
|
||||||
|
font-family: helvetica, arial, sans-serif;
|
||||||
|
font-size: 10pt;
|
||||||
|
width: 95%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
caption.rem-cal-caption {
|
||||||
|
font-size: 14pt;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.rem-cal-hdr {
|
||||||
|
width: 14%;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
td.rem-empty, td.rem-cell, td.rem-small-calendar {
|
||||||
|
width: 14%;
|
||||||
|
height: 7em;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
td.rem-today {
|
||||||
|
width: 14%;
|
||||||
|
height: 7em;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 2px;
|
||||||
|
border-color: #EE3333;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.rem-cal {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.rem-daynumber {
|
||||||
|
float: right;
|
||||||
|
text-align: right;
|
||||||
|
vertical-align: top;
|
||||||
|
font-size: 14pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.rem-entry {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.rem-moon {
|
||||||
|
float: left;
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.rem-sc-hdr {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.rem-sc-empty-cell, td.rem-sc-cell {
|
||||||
|
text-align: right;
|
||||||
|
width: 14%;
|
||||||
|
}
|
||||||
|
|
||||||
|
caption.rem-sc-caption {
|
||||||
|
font-size: 12pt;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
Files in this directory:
|
Files in this directory:
|
||||||
|
|
||||||
tkremind -- Tcl/Tk graphical calendar using Remind as engine
|
tkremind -- Tcl/Tk graphical calendar using Remind as engine
|
||||||
cm2rem.tcl -- Convert Sun's "cm" calendar manager files to Remind.
|
|
||||||
|
|||||||
@@ -1,358 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# -*-Mode: TCL;-*-
|
|
||||||
|
|
||||||
#--------------------------------------------------------------
|
|
||||||
# cm2rem.tcl
|
|
||||||
#
|
|
||||||
# A cheesy Tcl script to convert Sun's "cm" calendar manager
|
|
||||||
# files (version 3 only) to Remind format.
|
|
||||||
#
|
|
||||||
# This file is part of REMIND.
|
|
||||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
|
||||||
#
|
|
||||||
#--------------------------------------------------------------
|
|
||||||
|
|
||||||
# the next line restarts using tclsh \
|
|
||||||
exec tclsh "$0" "$@"
|
|
||||||
|
|
||||||
set i 0
|
|
||||||
foreach month {January February March April May June
|
|
||||||
July August September October November December} {
|
|
||||||
incr i
|
|
||||||
set MonthNum($month) $i
|
|
||||||
set FullMonth([string range $month 0 2]) $month
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertParens
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# line -- a line read from a cm file
|
|
||||||
# %RETURNS:
|
|
||||||
# A new line with all ( and ) outside quotes converted to { and }.
|
|
||||||
# This cheap trick allows us to use Tcl's built-in list manipulation
|
|
||||||
# functions to munge the line.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertParens { line } {
|
|
||||||
# Convert all ( and ) to { and } unless they are inside a quoted
|
|
||||||
# string
|
|
||||||
set out ""
|
|
||||||
set len [string length $line]
|
|
||||||
set inQuotes 0
|
|
||||||
for {set i 0} {$i < $len} {incr i} {
|
|
||||||
set char [string range $line $i $i]
|
|
||||||
if {$char == "\\" && $inQuotes} {
|
|
||||||
append out $char
|
|
||||||
incr i
|
|
||||||
set char [string range $line $i $i]
|
|
||||||
append out $char
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$char == "(" && !$inQuotes} {
|
|
||||||
set char \{
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$char == ")" && !$inQuotes} {
|
|
||||||
set char \}
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$char == "\""} {
|
|
||||||
set inQuotes [expr !$inQuotes]
|
|
||||||
}
|
|
||||||
|
|
||||||
append out $char
|
|
||||||
}
|
|
||||||
return $out
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: processLine
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# line -- a line read from a cm file
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Processes a single line from the file, possibly writing a reminder
|
|
||||||
# in Remind format to stdout
|
|
||||||
#***********************************************************************
|
|
||||||
proc processLine { line } {
|
|
||||||
global Attributes
|
|
||||||
global FullMonth
|
|
||||||
|
|
||||||
catch {unset Attributes}
|
|
||||||
|
|
||||||
# Only convert lines which start with "(add"
|
|
||||||
if {[string range $line 0 3] != "(add"} {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set line [convertParens $line]
|
|
||||||
# Convert it to a list. CAREFUL: Potential security problem if
|
|
||||||
# $line contains something nasty.
|
|
||||||
|
|
||||||
eval set line $line
|
|
||||||
|
|
||||||
set Attributes(body) ""
|
|
||||||
foreach {key val} $line {
|
|
||||||
switch -exact -- $key {
|
|
||||||
"add" {
|
|
||||||
set Attributes(date) $val
|
|
||||||
}
|
|
||||||
"what:" {
|
|
||||||
append Attributes(body) $val
|
|
||||||
}
|
|
||||||
"details:" {
|
|
||||||
append Attributes(body) $val
|
|
||||||
}
|
|
||||||
"duration:" {
|
|
||||||
set Attributes(duration) $val
|
|
||||||
}
|
|
||||||
"period:" {
|
|
||||||
set Attributes(period) $val
|
|
||||||
}
|
|
||||||
"ntimes:" {
|
|
||||||
set Attributes(ntimes) $val
|
|
||||||
}
|
|
||||||
"attributes:" {
|
|
||||||
set Attributes(action) $val
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if {[info exists Attributes(action)]} {
|
|
||||||
# Nuke quotes and commas in action
|
|
||||||
regsub -all {[,\"]} $Attributes(action) { } Attributes(action)
|
|
||||||
|
|
||||||
# Add spaces to pairs
|
|
||||||
regsub -all \}\{ $Attributes(action) \}\ \{ Attributes(action)
|
|
||||||
|
|
||||||
# Add another pair of brackets to make a proper list
|
|
||||||
set Attributes(action) "{$Attributes(action)}"
|
|
||||||
|
|
||||||
# Convert to a real Tcl list
|
|
||||||
eval set Attributes(action) $Attributes(action)
|
|
||||||
}
|
|
||||||
# Split out date into month, day, year, time parts
|
|
||||||
scan $Attributes(date) "%s%s%s%s%s" wkday month day time year
|
|
||||||
set time [string range $time 0 4]
|
|
||||||
set Attributes(wkday) $wkday
|
|
||||||
set Attributes(month) $FullMonth($month)
|
|
||||||
set Attributes(day) $day
|
|
||||||
set Attributes(time) $time
|
|
||||||
set Attributes(year) $year
|
|
||||||
|
|
||||||
# Convert newlines in body to spaces
|
|
||||||
set body $Attributes(body)
|
|
||||||
regsub -all "\n" $body " " body
|
|
||||||
|
|
||||||
# TODO: Escape BODY to get rid of [] chars.
|
|
||||||
set Attributes(body) $body
|
|
||||||
|
|
||||||
# Convert to Reminder format
|
|
||||||
convertReminder
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertReminder
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses global Attributes variable which must be filled in
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Converts a reminder to Remind format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertReminder {} {
|
|
||||||
global Attributes
|
|
||||||
switch -exact $Attributes(period) {
|
|
||||||
single { convertSingleReminder }
|
|
||||||
daily { convertDailyReminder }
|
|
||||||
weekly { convertWeeklyReminder }
|
|
||||||
monthly { convertMonthlyReminder }
|
|
||||||
yearly { convertYearlyReminder }
|
|
||||||
default {
|
|
||||||
puts "\# Unable to convert reminder with period $Attributes(period)"
|
|
||||||
puts "\# Body is: $Attributes(body)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertSingleReminder
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses global Attributes variable which must be filled in
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Converts a reminder with "single" period to Remind format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertSingleReminder {} {
|
|
||||||
global Attributes
|
|
||||||
puts "REM $Attributes(day) $Attributes(month) $Attributes(year) [at][duration]MSG $Attributes(body)"
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertDailyReminder
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses global Attributes variable which must be filled in
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Converts a reminder with "daily" period to Remind format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertDailyReminder {} {
|
|
||||||
global Attributes
|
|
||||||
set ntimes [expr $Attributes(ntimes) - 1]
|
|
||||||
if {$ntimes <= 1} {
|
|
||||||
convertSingleReminder
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set until [getUntilDate $Attributes(day) $Attributes(month) $Attributes(year) $ntimes]
|
|
||||||
|
|
||||||
puts "REM $Attributes(day) $Attributes(month) $Attributes(year) *1 [at][duration]UNTIL $until MSG $Attributes(body)"
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertWeeklyReminder
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses global Attributes variable which must be filled in
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Converts a reminder with "daily" period to Remind format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertWeeklyReminder {} {
|
|
||||||
global Attributes
|
|
||||||
set ntimes [expr $Attributes(ntimes) - 1]
|
|
||||||
if {$ntimes <= 1} {
|
|
||||||
convertSingleReminder
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set until [getUntilDate $Attributes(day) $Attributes(month) $Attributes(year) [expr $ntimes * 7]]
|
|
||||||
|
|
||||||
puts "REM $Attributes(day) $Attributes(month) $Attributes(year) *7 [at][duration]UNTIL $until MSG $Attributes(body)"
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertMonthlyReminder
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses global Attributes variable which must be filled in
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Converts a reminder with "monthly" period to Remind format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertMonthlyReminder {} {
|
|
||||||
global Attributes
|
|
||||||
set ntimes [expr $Attributes(ntimes) - 1]
|
|
||||||
if {$ntimes <= 1} {
|
|
||||||
convertSingleReminder
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
# If repetition > 1000, it's infinite
|
|
||||||
if {$ntimes > 1000} {
|
|
||||||
puts "REM $Attributes(day) [at][duration]MSG $Attributes(body)"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
### UNTIL date is fudged!
|
|
||||||
set until [getUntilDate $Attributes(day) $Attributes(month) $Attributes(year) [expr $ntimes * 30]]
|
|
||||||
|
|
||||||
puts "REM $Attributes(day) [at][duration]UNTIL $until MSG $Attributes(body)"
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertYearlyReminder
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses global Attributes variable which must be filled in
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Converts a reminder with "yearly" period to Remind format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertYearlyReminder {} {
|
|
||||||
global Attributes
|
|
||||||
|
|
||||||
# No special handling of ntimes et al.
|
|
||||||
puts "REM $Attributes(day) $Attributes(month) [at][duration]MSG $Attributes(body)"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: at
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses Attributes global variable
|
|
||||||
# %RETURNS:
|
|
||||||
# A string providing the correct AT clause for a timed reminder.
|
|
||||||
#***********************************************************************
|
|
||||||
proc at {} {
|
|
||||||
global Attributes
|
|
||||||
if {![info exists Attributes(time)]} {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if {"$Attributes(time)" == ""} {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return "AT $Attributes(time) "
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: duration
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses Attributes global variable
|
|
||||||
# %RETURNS:
|
|
||||||
# A string providing the correct DURATION clause for a timed reminder.
|
|
||||||
#***********************************************************************
|
|
||||||
proc duration {} {
|
|
||||||
global Attributes
|
|
||||||
if {![info exists Attributes(duration)]} {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if {"$Attributes(duration)" == ""} {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
set h [expr $Attributes(duration) / 3600]
|
|
||||||
set remainder [expr $Attributes(duration) - $h*3600]
|
|
||||||
set m [expr $remainder / 60]
|
|
||||||
return "DURATION [format "%d:%02d " $h $m]"
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: getUntilDate
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# day, month, year -- a date
|
|
||||||
# days -- number of days to add to date
|
|
||||||
# %RETURNS:
|
|
||||||
# The date which is "days" later than supplied date in a correct UNTIL
|
|
||||||
# format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc getUntilDate { day month year days } {
|
|
||||||
global RemindPipe
|
|
||||||
global MonthNum
|
|
||||||
set date "'$year/$MonthNum($month)/$day'"
|
|
||||||
puts $RemindPipe "MSG \[trigger($date + $days)\]%"
|
|
||||||
puts $RemindPipe "flush"
|
|
||||||
flush $RemindPipe
|
|
||||||
gets $RemindPipe line
|
|
||||||
return $line
|
|
||||||
}
|
|
||||||
|
|
||||||
catch {wm withdraw .}
|
|
||||||
# Start a Remind process to issue reminders
|
|
||||||
if {[catch {set RemindPipe [open "|remind -" "r+"]} err]} {
|
|
||||||
puts stderr "Error: Cannot run Remind: $err"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
puts $RemindPipe "banner %"
|
|
||||||
flush $RemindPipe
|
|
||||||
|
|
||||||
# Write some blurb
|
|
||||||
puts "\# Reminder file converted from \"cm\" data by cm2rem.tcl"
|
|
||||||
puts ""
|
|
||||||
|
|
||||||
while {[gets stdin line] >= 0} {
|
|
||||||
processLine $line
|
|
||||||
}
|
|
||||||
exit 0
|
|
||||||
@@ -16,11 +16,22 @@ exec wish "$0" "$@"
|
|||||||
|
|
||||||
# We need at least version 8.5 because of {*} list expansion operator
|
# We need at least version 8.5 because of {*} list expansion operator
|
||||||
if {[catch {package require Tcl 8.5}]} {
|
if {[catch {package require Tcl 8.5}]} {
|
||||||
puts "This program requires Tcl 8.5 or higher."
|
puts stderr "This program requires Tcl 8.5 or higher."
|
||||||
puts "You have version [info tclversion]"
|
puts stderr "You have version [info tclversion]"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# If it's 8.5, try using the Img or the TkPNG package to
|
||||||
|
# get PNG support
|
||||||
|
if {[info tclversion] == 8.5} {
|
||||||
|
if {[catch {package require Img}]} {
|
||||||
|
if {[catch {package require tkpng}]} {
|
||||||
|
puts stderr "Tcl/Tk version 8.5 might require either the Img or tkpng"
|
||||||
|
puts stderr "package to handle PNG images correctly. TkRemind may"
|
||||||
|
puts stderr "crash because neither of these packages was found."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
wm withdraw .
|
wm withdraw .
|
||||||
|
|
||||||
set Hostname [exec hostname]
|
set Hostname [exec hostname]
|
||||||
@@ -113,13 +124,6 @@ if {[catch {package require json}]} {
|
|||||||
missing_tcllib json
|
missing_tcllib json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Check that we have the right version of wish
|
|
||||||
if {$tcl_version < 8.0} {
|
|
||||||
tk_dialog .error Error "You need wish version 8.0 or higher to run TkRemind; you have $tcl_version" error 0 OK
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$tcl_platform(platform) == "windows"} {
|
if {$tcl_platform(platform) == "windows"} {
|
||||||
tk_dialog .error Error "Please do not port Remind to Windows" error 0 OK
|
tk_dialog .error Error "Please do not port Remind to Windows" error 0 OK
|
||||||
exit 1
|
exit 1
|
||||||
@@ -927,7 +931,7 @@ proc LoadOptions {} {
|
|||||||
}
|
}
|
||||||
foreach {key val} $line {}
|
foreach {key val} $line {}
|
||||||
if {![info exists Option($key)]} {
|
if {![info exists Option($key)]} {
|
||||||
puts "Unknown option in $ConfigFile: $key"
|
puts stderr "Unknown option in $ConfigFile: $key"
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
set Option($key) $val
|
set Option($key) $val
|
||||||
@@ -1001,8 +1005,8 @@ proc FillCalWindow {} {
|
|||||||
ConfigureCalWindow $monthName $year $firstWkday $daysInMonth
|
ConfigureCalWindow $monthName $year $firstWkday $daysInMonth
|
||||||
set offset [CalEntryOffset $firstWkday]
|
set offset [CalEntryOffset $firstWkday]
|
||||||
|
|
||||||
set fntag "x"
|
|
||||||
while { [gets $file line] >= 0 } {
|
while { [gets $file line] >= 0 } {
|
||||||
|
set fntag "x"
|
||||||
# Ignore unless begins with left brace
|
# Ignore unless begins with left brace
|
||||||
if { ! [string match "\{*" $line]} {
|
if { ! [string match "\{*" $line]} {
|
||||||
continue
|
continue
|
||||||
@@ -1013,7 +1017,11 @@ proc FillCalWindow {} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if {[dict exists $obj filename]} {
|
if {[dict exists $obj filename]} {
|
||||||
set fntag [string cat "FILE_" [dict get $obj lineno] "_" [dict get $obj filename]]
|
set fname [dict get $obj filename]
|
||||||
|
# Don't make INCLUDECMD output editable
|
||||||
|
if {![string match "*|" $fname]} {
|
||||||
|
set fntag [string cat "FILE_" [dict get $obj lineno] "_" $fname]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set date [dict get $obj date]
|
set date [dict get $obj date]
|
||||||
@@ -1083,13 +1091,17 @@ proc FillCalWindow {} {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
.cal.t$n configure -state normal
|
.cal.t$n configure -state normal
|
||||||
if {[regexp {TKTAG([0-9]+)} $tag all tagno]} {
|
if {[regexp {TKTAG([0-9]+)} $tag all tagno] && "$fntag" != "x"} {
|
||||||
.cal.t$n insert end [string trim $stuff] [list REM TAGGED "TKTAG$tagno" "date_$date" $extratags $fntag]
|
.cal.t$n insert end [string trim $stuff] [list REM TAGGED "TKTAG$tagno" "date_$date" $extratags $fntag]
|
||||||
.cal.t$n tag bind "TKTAG$tagno" <Enter> "TaggedEnter .cal.t$n"
|
.cal.t$n tag bind "TKTAG$tagno" <Enter> "TaggedEnter .cal.t$n"
|
||||||
.cal.t$n tag bind "TKTAG$tagno" <Leave> "TaggedLeave .cal.t$n"
|
.cal.t$n tag bind "TKTAG$tagno" <Leave> "TaggedLeave .cal.t$n"
|
||||||
set TagToObj(TKTAG$tagno) $obj
|
set TagToObj(TKTAG$tagno) $obj
|
||||||
} else {
|
} else {
|
||||||
.cal.t$n insert end [string trim $stuff] [list REM $extratags $fntag]
|
if {"$fntag" == "x" } {
|
||||||
|
.cal.t$n insert end [string trim $stuff] [list REM $extratags]
|
||||||
|
} else {
|
||||||
|
.cal.t$n insert end [string trim $stuff] [list REM $extratags $fntag]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.cal.t$n insert end "\n"
|
.cal.t$n insert end "\n"
|
||||||
.cal.t$n configure -state disabled
|
.cal.t$n configure -state disabled
|
||||||
@@ -1833,6 +1845,7 @@ proc ModifyDay {d firstDay} {
|
|||||||
set oldFocus [focus]
|
set oldFocus [focus]
|
||||||
while {1} {
|
while {1} {
|
||||||
grab .mod
|
grab .mod
|
||||||
|
raise .mod
|
||||||
focus .mod.entry
|
focus .mod.entry
|
||||||
set ModifyDialogResult -1
|
set ModifyDialogResult -1
|
||||||
tkwait variable ModifyDialogResult
|
tkwait variable ModifyDialogResult
|
||||||
@@ -1979,7 +1992,7 @@ proc CreateReminder {w} {
|
|||||||
|
|
||||||
# Check it out!
|
# Check it out!
|
||||||
global Remind
|
global Remind
|
||||||
set f [open "|$Remind -arq -e -" r+]
|
set f [open "|$Remind -arq -e - 2>&1" r+]
|
||||||
puts $f "BANNER %"
|
puts $f "BANNER %"
|
||||||
puts $f "$rem MSG %"
|
puts $f "$rem MSG %"
|
||||||
puts $f "MSG %_%_%_%_"
|
puts $f "MSG %_%_%_%_"
|
||||||
@@ -1997,13 +2010,17 @@ proc CreateReminder {w} {
|
|||||||
return $rem
|
return $rem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# We used to return YYYY-MM-DD, but reverted to
|
||||||
|
# day monthname year because this lets Remind produce
|
||||||
|
# much better error messages.
|
||||||
proc consolidate {y m d} {
|
proc consolidate {y m d} {
|
||||||
global MonthNames
|
global MonthNames
|
||||||
if {![regexp {^[0-9]+$} $m]} {
|
if {![regexp {^[0-9]+$} $m]} {
|
||||||
set m [lsearch -exact $MonthNames $m]
|
set m [lsearch -exact $MonthNames $m]
|
||||||
incr m
|
incr m
|
||||||
}
|
}
|
||||||
return [format "%04d-%02d-%02d" $y $m $d]
|
set mname [lindex $MonthNames [expr $m-1]]
|
||||||
|
return "$d $mname $y"
|
||||||
}
|
}
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@@ -2569,7 +2586,7 @@ proc DaemonReadable { file } {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
default {
|
default {
|
||||||
puts "Unknown message from daemon: $line\n"
|
puts stderr "Unknown message from daemon: $line\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2800,7 +2817,7 @@ proc ReadTaggedOptions { tag date } {
|
|||||||
lappend ans -text-day2 $d
|
lappend ans -text-day2 $d
|
||||||
}
|
}
|
||||||
if {[dict exists $obj m]} {
|
if {[dict exists $obj m]} {
|
||||||
set mm [dict get $obj m]
|
set m [dict get $obj m]
|
||||||
set mm [string trimleft $m 0]
|
set mm [string trimleft $m 0]
|
||||||
lappend ans -text-mon1 [lindex $MonthNames [expr $mm -1]]
|
lappend ans -text-mon1 [lindex $MonthNames [expr $mm -1]]
|
||||||
lappend ans -text-mon2 [lindex $MonthNames [expr $mm -1]]
|
lappend ans -text-mon2 [lindex $MonthNames [expr $mm -1]]
|
||||||
@@ -3190,6 +3207,7 @@ proc EditTaggedReminder { w } {
|
|||||||
tkwait visibility .mod
|
tkwait visibility .mod
|
||||||
set oldFocus [focus]
|
set oldFocus [focus]
|
||||||
while {1} {
|
while {1} {
|
||||||
|
raise .mod
|
||||||
grab .mod
|
grab .mod
|
||||||
focus .mod.entry
|
focus .mod.entry
|
||||||
set ModifyDialogResult -1
|
set ModifyDialogResult -1
|
||||||
|
|||||||
@@ -18,11 +18,10 @@ INSTALL_PROGRAM=@INSTALL_PROGRAM@
|
|||||||
INSTALL_DATA=@INSTALL_DATA@
|
INSTALL_DATA=@INSTALL_DATA@
|
||||||
|
|
||||||
PROGS= remind rem2ps
|
PROGS= remind rem2ps
|
||||||
SCRIPTS= $(srcdir)/../scripts/tkremind $(srcdir)/../scripts/cm2rem.tcl
|
SCRIPTS= $(srcdir)/../scripts/tkremind
|
||||||
|
|
||||||
MANS= $(srcdir)/../man/rem2ps.1 $(srcdir)/../man/remind.1 \
|
MANS= $(srcdir)/../man/rem2ps.1 $(srcdir)/../man/remind.1 \
|
||||||
$(srcdir)/../man/tkremind.1 $(srcdir)/../man/cm2rem.1 \
|
$(srcdir)/../man/tkremind.1 $(srcdir)/../man/rem.1
|
||||||
$(srcdir)/../man/rem.1
|
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.SUFFIXES: .c .o
|
.SUFFIXES: .c .o
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ void PrintJSONKeyPairInt(char const *name, int val)
|
|||||||
{
|
{
|
||||||
printf("\"");
|
printf("\"");
|
||||||
PrintJSONString(name);
|
PrintJSONString(name);
|
||||||
printf("\":%d, ", val);
|
printf("\":%d,", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintJSONKeyPairString(char const *name, char const *val)
|
void PrintJSONKeyPairString(char const *name, char const *val)
|
||||||
@@ -282,7 +282,7 @@ void PrintJSONKeyPairString(char const *name, char const *val)
|
|||||||
PrintJSONString(name);
|
PrintJSONString(name);
|
||||||
printf("\":\"");
|
printf("\":\"");
|
||||||
PrintJSONString(val);
|
PrintJSONString(val);
|
||||||
printf("\", ");
|
printf("\",");
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintJSONKeyPairDate(char const *name, int jul)
|
void PrintJSONKeyPairDate(char const *name, int jul)
|
||||||
@@ -295,7 +295,7 @@ void PrintJSONKeyPairDate(char const *name, int jul)
|
|||||||
FromJulian(jul, &y, &m, &d);
|
FromJulian(jul, &y, &m, &d);
|
||||||
printf("\"");
|
printf("\"");
|
||||||
PrintJSONString(name);
|
PrintJSONString(name);
|
||||||
printf("\":\"%04d-%02d-%02d\", ", y, m+1, d);
|
printf("\":\"%04d-%02d-%02d\",", y, m+1, d);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,7 +313,7 @@ void PrintJSONKeyPairDateTime(char const *name, int dt)
|
|||||||
i = k % 60;
|
i = k % 60;
|
||||||
printf("\"");
|
printf("\"");
|
||||||
PrintJSONString(name);
|
PrintJSONString(name);
|
||||||
printf("\":\"%04d-%02d-%02dT%02d:%02d\", ", y, m+1, d, h, i);
|
printf("\":\"%04d-%02d-%02dT%02d:%02d\",", y, m+1, d, h, i);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,7 +328,7 @@ void PrintJSONKeyPairTime(char const *name, int t)
|
|||||||
i = t % 60;
|
i = t % 60;
|
||||||
printf("\"");
|
printf("\"");
|
||||||
PrintJSONString(name);
|
PrintJSONString(name);
|
||||||
printf("\":\"%02d:%02d\", ", h, i);
|
printf("\":\"%02d:%02d\",", h, i);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -797,7 +797,7 @@ static int WriteCalendarRow(void)
|
|||||||
PrintLeft("", ColSpaces, ' ');
|
PrintLeft("", ColSpaces, ' ');
|
||||||
else {
|
else {
|
||||||
sprintf(buf, "%d ", d+i-wd);
|
sprintf(buf, "%d ", d+i-wd);
|
||||||
if (OrigJul+i == RealToday) {
|
if (Julian(y, m, d+i-wd) == RealToday) {
|
||||||
PrintLeft(buf, ColSpaces-1, '*');
|
PrintLeft(buf, ColSpaces-1, '*');
|
||||||
PutChar(' ');
|
PutChar(' ');
|
||||||
} else {
|
} else {
|
||||||
@@ -1239,6 +1239,7 @@ static void GenerateCalEntries(int col)
|
|||||||
case T_Else: r=DoElse(&p); break;
|
case T_Else: r=DoElse(&p); break;
|
||||||
case T_EndIf: r=DoEndif(&p); break;
|
case T_EndIf: r=DoEndif(&p); break;
|
||||||
case T_Include: r=DoInclude(&p); break;
|
case T_Include: r=DoInclude(&p); break;
|
||||||
|
case T_IncludeCmd: r=DoIncludeCmd(&p); break;
|
||||||
case T_Exit: DoExit(&p); break;
|
case T_Exit: DoExit(&p); break;
|
||||||
case T_Set: r=DoSet(&p); break;
|
case T_Set: r=DoSet(&p); break;
|
||||||
case T_Fset: r=DoFset(&p); break;
|
case T_Fset: r=DoFset(&p); break;
|
||||||
@@ -1664,7 +1665,9 @@ static int DoCalRem(ParsePtr p, int col)
|
|||||||
if(!e->filename) {
|
if(!e->filename) {
|
||||||
if (e->text) free(e->text);
|
if (e->text) free(e->text);
|
||||||
if (e->raw_text) free(e->raw_text);
|
if (e->raw_text) free(e->raw_text);
|
||||||
|
#ifdef REM_USE_WCHAR
|
||||||
if (e->wc_text) free(e->wc_text);
|
if (e->wc_text) free(e->wc_text);
|
||||||
|
#endif
|
||||||
free(e);
|
free(e);
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
@@ -1753,7 +1756,7 @@ static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
|||||||
printf("\"%s\"", EnglishDayName[i]);
|
printf("\"%s\"", EnglishDayName[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("], ");
|
printf("],");
|
||||||
}
|
}
|
||||||
if (e->trig.d != NO_DAY) {
|
if (e->trig.d != NO_DAY) {
|
||||||
PrintJSONKeyPairInt("d", e->trig.d);
|
PrintJSONKeyPairInt("d", e->trig.d);
|
||||||
@@ -1806,7 +1809,7 @@ static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
|||||||
printf("\"%s\"", EnglishDayName[i]);
|
printf("\"%s\"", EnglishDayName[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("], ");
|
printf("],");
|
||||||
}
|
}
|
||||||
PrintJSONKeyPairDate("until", e->trig.until);
|
PrintJSONKeyPairDate("until", e->trig.until);
|
||||||
if (e->trig.once != NO_ONCE) {
|
if (e->trig.once != NO_ONCE) {
|
||||||
@@ -1875,7 +1878,7 @@ static void WriteSimpleEntries(int col, int jul)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DidADay = 1;
|
DidADay = 1;
|
||||||
printf("{\"date\":\"%04d-%02d-%02d\", ", y, m+1, d);
|
printf("{\"date\":\"%04d-%02d-%02d\",", y, m+1, d);
|
||||||
WriteSimpleEntryProtocol2(e, jul);
|
WriteSimpleEntryProtocol2(e, jul);
|
||||||
printf("}");
|
printf("}");
|
||||||
if (PsCal != PSCAL_LEVEL3) {
|
if (PsCal != PSCAL_LEVEL3) {
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
/* Define if you have the <sys/file.h> header file. */
|
/* Define if you have the <sys/file.h> header file. */
|
||||||
#undef HAVE_SYS_FILE_H
|
#undef HAVE_SYS_FILE_H
|
||||||
|
|
||||||
|
/* Define if you have the <sys/types.h> header file. */
|
||||||
|
#undef HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
/* Define if you have the <glob.h> header file */
|
/* Define if you have the <glob.h> header file */
|
||||||
#undef HAVE_GLOB_H
|
#undef HAVE_GLOB_H
|
||||||
|
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
24
src/dorem.c
24
src/dorem.c
@@ -7,7 +7,7 @@
|
|||||||
/* commands. */
|
/* commands. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -24,10 +24,6 @@
|
|||||||
#include "protos.h"
|
#include "protos.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
|
||||||
/* Define the shell characters not to escape */
|
|
||||||
static char const DontEscapeMe[] =
|
|
||||||
"1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,";
|
|
||||||
|
|
||||||
static int ParseTimeTrig (ParsePtr s, TimeTrig *tim, int save_in_globals);
|
static int ParseTimeTrig (ParsePtr s, TimeTrig *tim, int save_in_globals);
|
||||||
static int ParseLocalOmit (ParsePtr s, Trigger *t);
|
static int ParseLocalOmit (ParsePtr s, Trigger *t);
|
||||||
static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
|
static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
|
||||||
@@ -1230,24 +1226,16 @@ int DoMsgCommand(char const *cmd, char const *msg)
|
|||||||
DynamicBuffer execBuffer;
|
DynamicBuffer execBuffer;
|
||||||
|
|
||||||
DynamicBuffer buf;
|
DynamicBuffer buf;
|
||||||
char const *s;
|
|
||||||
|
|
||||||
DBufInit(&buf);
|
DBufInit(&buf);
|
||||||
DBufInit(&execBuffer);
|
DBufInit(&execBuffer);
|
||||||
|
|
||||||
/* Escape shell characters in msg INCLUDING WHITESPACE! */
|
/* Escape shell characters in msg */
|
||||||
for (s=msg; *s; s++) {
|
if (ShellEscape(msg, &buf) != OK) {
|
||||||
if (isspace(*s) || !strchr(DontEscapeMe, *s)) {
|
r = E_NO_MEM;
|
||||||
if (DBufPutc(&buf, '\\') != OK) {
|
goto finished;
|
||||||
r = E_NO_MEM;
|
|
||||||
goto finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (DBufPutc(&buf, *s) != OK) {
|
|
||||||
r = E_NO_MEM;
|
|
||||||
goto finished;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = DBufValue(&buf);
|
msg = DBufValue(&buf);
|
||||||
|
|
||||||
/* Do "%s" substitution */
|
/* Do "%s" substitution */
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* buffers. */
|
/* buffers. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Error definitions. */
|
/* Error definitions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
51
src/expr.c
51
src/expr.c
@@ -5,7 +5,7 @@
|
|||||||
/* This file contains routines to parse and evaluate */
|
/* This file contains routines to parse and evaluate */
|
||||||
/* expressions. */
|
/* expressions. */
|
||||||
/* */
|
/* */
|
||||||
/* Copyright 1992-2020 by Dianne Skoll */
|
/* Copyright 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -493,6 +494,7 @@ static int MakeValue(char const *s, Value *v, Var *locals, ParsePtr p)
|
|||||||
int len;
|
int len;
|
||||||
int h, m, r;
|
int h, m, r;
|
||||||
int ampm = 0;
|
int ampm = 0;
|
||||||
|
int prev_val;
|
||||||
|
|
||||||
if (*s == '\"') { /* It's a literal string "*/
|
if (*s == '\"') { /* It's a literal string "*/
|
||||||
len = strlen(s)-1;
|
len = strlen(s)-1;
|
||||||
@@ -519,9 +521,15 @@ static int MakeValue(char const *s, Value *v, Var *locals, ParsePtr p)
|
|||||||
return OK;
|
return OK;
|
||||||
} else if (isdigit(*s)) { /* It's a number - use len to hold it.*/
|
} else if (isdigit(*s)) { /* It's a number - use len to hold it.*/
|
||||||
len = 0;
|
len = 0;
|
||||||
|
prev_val = 0;
|
||||||
while (*s && isdigit(*s)) {
|
while (*s && isdigit(*s)) {
|
||||||
len *= 10;
|
len *= 10;
|
||||||
len += (*s++ - '0');
|
len += (*s++ - '0');
|
||||||
|
if (len < prev_val) {
|
||||||
|
/* We overflowed */
|
||||||
|
return E_2HIGH;
|
||||||
|
}
|
||||||
|
prev_val = len;
|
||||||
}
|
}
|
||||||
if (*s == ':' || *s == '.' || *s == TimeSep) { /* Must be a literal time */
|
if (*s == ':' || *s == '.' || *s == TimeSep) { /* Must be a literal time */
|
||||||
s++;
|
s++;
|
||||||
@@ -758,15 +766,22 @@ static int Add(void)
|
|||||||
|
|
||||||
/* If both are ints, just add 'em */
|
/* If both are ints, just add 'em */
|
||||||
if (v2.type == INT_TYPE && v1.type == INT_TYPE) {
|
if (v2.type == INT_TYPE && v1.type == INT_TYPE) {
|
||||||
v2.v.val += v1.v.val;
|
int old = v1.v.val;
|
||||||
PushValStack(v2);
|
v1.v.val += v2.v.val;
|
||||||
|
/* Check for overflow */
|
||||||
|
if (_private_add_overflow(v1.v.val, v2.v.val, old)) {
|
||||||
|
return E_2HIGH;
|
||||||
|
}
|
||||||
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If it's a date plus an int, add 'em */
|
/* If it's a date plus an int, add 'em */
|
||||||
if ((v1.type == DATE_TYPE && v2.type == INT_TYPE) ||
|
if ((v1.type == DATE_TYPE && v2.type == INT_TYPE) ||
|
||||||
(v1.type == INT_TYPE && v2.type == DATE_TYPE)) {
|
(v1.type == INT_TYPE && v2.type == DATE_TYPE)) {
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val += v2.v.val;
|
v1.v.val += v2.v.val;
|
||||||
|
if (_private_add_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
|
||||||
if (v1.v.val < 0) return E_DATE_OVER;
|
if (v1.v.val < 0) return E_DATE_OVER;
|
||||||
v1.type = DATE_TYPE;
|
v1.type = DATE_TYPE;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
@@ -776,7 +791,9 @@ static int Add(void)
|
|||||||
/* If it's a datetime plus an int or a time, add 'em */
|
/* If it's a datetime plus an int or a time, add 'em */
|
||||||
if ((v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) ||
|
if ((v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) ||
|
||||||
((v1.type == INT_TYPE || v1.type == TIME_TYPE) && v2.type == DATETIME_TYPE)) {
|
((v1.type == INT_TYPE || v1.type == TIME_TYPE) && v2.type == DATETIME_TYPE)) {
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val += v2.v.val;
|
v1.v.val += v2.v.val;
|
||||||
|
if (_private_add_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
|
||||||
if (v1.v.val < 0) return E_DATE_OVER;
|
if (v1.v.val < 0) return E_DATE_OVER;
|
||||||
v1.type = DATETIME_TYPE;
|
v1.type = DATETIME_TYPE;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
@@ -788,7 +805,10 @@ static int Add(void)
|
|||||||
if ((v1.type == TIME_TYPE && v2.type == INT_TYPE) ||
|
if ((v1.type == TIME_TYPE && v2.type == INT_TYPE) ||
|
||||||
(v1.type == INT_TYPE && v2.type == TIME_TYPE) ||
|
(v1.type == INT_TYPE && v2.type == TIME_TYPE) ||
|
||||||
(v1.type == TIME_TYPE && v2.type == TIME_TYPE)) {
|
(v1.type == TIME_TYPE && v2.type == TIME_TYPE)) {
|
||||||
v1.v.val = (v1.v.val + v2.v.val) % MINUTES_PER_DAY;
|
int old = v1.v.val;
|
||||||
|
v1.v.val += v2.v.val;
|
||||||
|
if (_private_add_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
|
||||||
|
v1.v.val = v1.v.val % MINUTES_PER_DAY;
|
||||||
if (v1.v.val < 0) v1.v.val += MINUTES_PER_DAY;
|
if (v1.v.val < 0) v1.v.val += MINUTES_PER_DAY;
|
||||||
v1.type = TIME_TYPE;
|
v1.type = TIME_TYPE;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
@@ -848,14 +868,18 @@ static int Subtract(void)
|
|||||||
|
|
||||||
/* If they're both INTs, do subtraction */
|
/* If they're both INTs, do subtraction */
|
||||||
if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
|
if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val -= v2.v.val;
|
v1.v.val -= v2.v.val;
|
||||||
|
if (_private_sub_overflow(v1.v.val, v2.v.val, old)) return E_2HIGH;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If it's a date minus an int, do subtraction, checking for underflow */
|
/* If it's a date minus an int, do subtraction, checking for underflow */
|
||||||
if (v1.type == DATE_TYPE && v2.type == INT_TYPE) {
|
if (v1.type == DATE_TYPE && v2.type == INT_TYPE) {
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val -= v2.v.val;
|
v1.v.val -= v2.v.val;
|
||||||
|
if (_private_sub_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
|
||||||
if (v1.v.val < 0) return E_DATE_OVER;
|
if (v1.v.val < 0) return E_DATE_OVER;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -864,7 +888,9 @@ static int Subtract(void)
|
|||||||
/* If it's a datetime minus an int or a time, do subtraction,
|
/* If it's a datetime minus an int or a time, do subtraction,
|
||||||
* checking for underflow */
|
* checking for underflow */
|
||||||
if (v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) {
|
if (v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) {
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val -= v2.v.val;
|
v1.v.val -= v2.v.val;
|
||||||
|
if (_private_sub_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
|
||||||
if (v1.v.val < 0) return E_DATE_OVER;
|
if (v1.v.val < 0) return E_DATE_OVER;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -882,7 +908,9 @@ static int Subtract(void)
|
|||||||
if ((v1.type == TIME_TYPE && v2.type == TIME_TYPE) ||
|
if ((v1.type == TIME_TYPE && v2.type == TIME_TYPE) ||
|
||||||
(v1.type == DATETIME_TYPE && v2.type == DATETIME_TYPE) ||
|
(v1.type == DATETIME_TYPE && v2.type == DATETIME_TYPE) ||
|
||||||
(v1.type == DATE_TYPE && v2.type == DATE_TYPE)) {
|
(v1.type == DATE_TYPE && v2.type == DATE_TYPE)) {
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val -= v2.v.val;
|
v1.v.val -= v2.v.val;
|
||||||
|
if (_private_sub_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
|
||||||
v1.type = INT_TYPE;
|
v1.type = INT_TYPE;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -912,7 +940,16 @@ static int Multiply(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
|
if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
|
||||||
|
/* Prevent floating-point exception */
|
||||||
|
if ((v2.v.val == -1 && v1.v.val == INT_MIN) ||
|
||||||
|
(v1.v.val == -1 && v2.v.val == INT_MIN)) {
|
||||||
|
return E_2HIGH;
|
||||||
|
}
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val *= v2.v.val;
|
v1.v.val *= v2.v.val;
|
||||||
|
if (v2.v.val != 0) {
|
||||||
|
if (_private_div(v1.v.val, v2.v.val) != old) return E_2HIGH;
|
||||||
|
}
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -940,6 +977,10 @@ static int Divide(void)
|
|||||||
|
|
||||||
if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
|
if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
|
||||||
if (v2.v.val == 0) return E_DIV_ZERO;
|
if (v2.v.val == 0) return E_DIV_ZERO;
|
||||||
|
/* This is the only way it can overflow */
|
||||||
|
if (v2.v.val == -1 && v1.v.val == INT_MIN) {
|
||||||
|
return E_2HIGH;
|
||||||
|
}
|
||||||
v1.v.val /= v2.v.val;
|
v1.v.val /= v2.v.val;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -1114,7 +1155,9 @@ static int UnMinus(void)
|
|||||||
{
|
{
|
||||||
Value *v = &ValStack[ValStackPtr-1];
|
Value *v = &ValStack[ValStackPtr-1];
|
||||||
if (v->type != INT_TYPE) return E_BAD_TYPE;
|
if (v->type != INT_TYPE) return E_BAD_TYPE;
|
||||||
|
int old = v->v.val;
|
||||||
v->v.val = -v->v.val;
|
v->v.val = -v->v.val;
|
||||||
|
if (_private_unminus_overflow(old, v->v.val)) return E_2HIGH;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
11
src/expr.h
11
src/expr.h
@@ -5,7 +5,7 @@
|
|||||||
/* Contains a few definitions used by expression evaluator. */
|
/* Contains a few definitions used by expression evaluator. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -53,3 +53,12 @@ if (ValStackPtr <= 0) \
|
|||||||
return E_VA_STK_UNDER; \
|
return E_VA_STK_UNDER; \
|
||||||
else \
|
else \
|
||||||
(val) = ValStack[--ValStackPtr]
|
(val) = ValStack[--ValStackPtr]
|
||||||
|
|
||||||
|
/* These functions are in utils.c and are used to detect overflow
|
||||||
|
in various arithmetic operators. They have to be in separate
|
||||||
|
functions with extern linkage to defeat compiler optimizations
|
||||||
|
that would otherwise break the overflow checks. */
|
||||||
|
extern int _private_div(int a, int b);
|
||||||
|
extern int _private_add_overflow(int result, int b, int old);
|
||||||
|
extern int _private_sub_overflow(int result, int b, int old);
|
||||||
|
extern int _private_unminus_overflow(int a, int b);
|
||||||
|
|||||||
285
src/files.c
285
src/files.c
@@ -7,7 +7,7 @@
|
|||||||
/* files. */
|
/* files. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -40,8 +40,9 @@
|
|||||||
#include "err.h"
|
#include "err.h"
|
||||||
|
|
||||||
|
|
||||||
/* Convenient macro for closing files */
|
/* Convenient macros for closing files */
|
||||||
#define FCLOSE(fp) (((fp)&&((fp)!=stdin)) ? (fclose(fp),(fp)=NULL) : ((fp)=NULL))
|
#define FCLOSE(fp) (((fp)&&((fp)!=stdin)) ? (fclose(fp),(fp)=NULL) : ((fp)=NULL))
|
||||||
|
#define PCLOSE(fp) (((fp)&&((fp)!=stdin)) ? (pclose(fp),(fp)=NULL) : ((fp)=NULL))
|
||||||
|
|
||||||
/* Define the structures needed by the file caching system */
|
/* Define the structures needed by the file caching system */
|
||||||
typedef struct cache {
|
typedef struct cache {
|
||||||
@@ -91,12 +92,12 @@ static FILE *fp;
|
|||||||
static IncludeStruct IStack[INCLUDE_NEST];
|
static IncludeStruct IStack[INCLUDE_NEST];
|
||||||
static int IStackPtr = 0;
|
static int IStackPtr = 0;
|
||||||
|
|
||||||
static int ReadLineFromFile (void);
|
static int ReadLineFromFile (int use_pclose);
|
||||||
static int CacheFile (char const *fname);
|
static int CacheFile (char const *fname, int use_pclose);
|
||||||
static void DestroyCache (CachedFile *cf);
|
static void DestroyCache (CachedFile *cf);
|
||||||
static int CheckSafety (void);
|
static int CheckSafety (void);
|
||||||
static int PopFile (void);
|
static int PopFile (void);
|
||||||
|
static int IncludeCmd(char const *);
|
||||||
static void OpenPurgeFile(char const *fname, char const *mode)
|
static void OpenPurgeFile(char const *fname, char const *mode)
|
||||||
{
|
{
|
||||||
DynamicBuffer fname_buf;
|
DynamicBuffer fname_buf;
|
||||||
@@ -167,7 +168,7 @@ int ReadLine(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Not cached. Read from the file. */
|
/* Not cached. Read from the file. */
|
||||||
return ReadLineFromFile();
|
return ReadLineFromFile(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -177,7 +178,7 @@ int ReadLine(void)
|
|||||||
/* Read a line from the file pointed to by fp. */
|
/* Read a line from the file pointed to by fp. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int ReadLineFromFile(void)
|
static int ReadLineFromFile(int use_pclose)
|
||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
char copy_buffer[4096];
|
char copy_buffer[4096];
|
||||||
@@ -200,7 +201,11 @@ static int ReadLineFromFile(void)
|
|||||||
return E_IO_ERR;
|
return E_IO_ERR;
|
||||||
}
|
}
|
||||||
if (feof(fp)) {
|
if (feof(fp)) {
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
if ((DBufLen(&buf) == 0) &&
|
if ((DBufLen(&buf) == 0) &&
|
||||||
(DBufLen(&LineBuffer) == 0) && PurgeMode) {
|
(DBufLen(&LineBuffer) == 0) && PurgeMode) {
|
||||||
if (PurgeFP != NULL && PurgeFP != stdout) fclose(PurgeFP);
|
if (PurgeFP != NULL && PurgeFP != stdout) fclose(PurgeFP);
|
||||||
@@ -248,7 +253,11 @@ static int ReadLineFromFile(void)
|
|||||||
if (PurgeFP != stdout) fclose(PurgeFP);
|
if (PurgeFP != stdout) fclose(PurgeFP);
|
||||||
PurgeFP = NULL;
|
PurgeFP = NULL;
|
||||||
}
|
}
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
DBufFree(&LineBuffer);
|
DBufFree(&LineBuffer);
|
||||||
CurLine = DBufValue(&LineBuffer);
|
CurLine = DBufValue(&LineBuffer);
|
||||||
}
|
}
|
||||||
@@ -282,9 +291,6 @@ int OpenFile(char const *fname)
|
|||||||
PurgeFP = NULL;
|
PurgeFP = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assume we own the file for now */
|
|
||||||
RunDisabled &= ~RUN_NOTOWNER;
|
|
||||||
|
|
||||||
/* If it's in the cache, get it from there. */
|
/* If it's in the cache, get it from there. */
|
||||||
|
|
||||||
while (h) {
|
while (h) {
|
||||||
@@ -297,7 +303,9 @@ int OpenFile(char const *fname)
|
|||||||
LineNo = 0;
|
LineNo = 0;
|
||||||
if (!h->ownedByMe) {
|
if (!h->ownedByMe) {
|
||||||
RunDisabled |= RUN_NOTOWNER;
|
RunDisabled |= RUN_NOTOWNER;
|
||||||
}
|
} else {
|
||||||
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
|
}
|
||||||
if (FileName) return OK; else return E_NO_MEM;
|
if (FileName) return OK; else return E_NO_MEM;
|
||||||
}
|
}
|
||||||
h = h->next;
|
h = h->next;
|
||||||
@@ -306,6 +314,7 @@ int OpenFile(char const *fname)
|
|||||||
/* If it's a dash, then it's stdin */
|
/* If it's a dash, then it's stdin */
|
||||||
if (!strcmp(fname, "-")) {
|
if (!strcmp(fname, "-")) {
|
||||||
fp = stdin;
|
fp = stdin;
|
||||||
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
if (PurgeMode) {
|
if (PurgeMode) {
|
||||||
PurgeFP = stdout;
|
PurgeFP = stdout;
|
||||||
}
|
}
|
||||||
@@ -325,7 +334,7 @@ int OpenFile(char const *fname)
|
|||||||
CLine = NULL;
|
CLine = NULL;
|
||||||
if (ShouldCache) {
|
if (ShouldCache) {
|
||||||
LineNo = 0;
|
LineNo = 0;
|
||||||
r = CacheFile(fname);
|
r = CacheFile(fname, 0);
|
||||||
if (r == OK) {
|
if (r == OK) {
|
||||||
fp = NULL;
|
fp = NULL;
|
||||||
CLine = CachedFiles->cache;
|
CLine = CachedFiles->cache;
|
||||||
@@ -353,7 +362,7 @@ int OpenFile(char const *fname)
|
|||||||
/* Returns an indication of success or failure. */
|
/* Returns an indication of success or failure. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int CacheFile(char const *fname)
|
static int CacheFile(char const *fname, int use_pclose)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
CachedFile *cf;
|
CachedFile *cf;
|
||||||
@@ -368,14 +377,22 @@ static int CacheFile(char const *fname)
|
|||||||
cf = NEW(CachedFile);
|
cf = NEW(CachedFile);
|
||||||
if (!cf) {
|
if (!cf) {
|
||||||
ShouldCache = 0;
|
ShouldCache = 0;
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
cf->cache = NULL;
|
cf->cache = NULL;
|
||||||
cf->filename = StrDup(fname);
|
cf->filename = StrDup(fname);
|
||||||
if (!cf->filename) {
|
if (!cf->filename) {
|
||||||
ShouldCache = 0;
|
ShouldCache = 0;
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
free(cf);
|
free(cf);
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
@@ -388,11 +405,15 @@ static int CacheFile(char const *fname)
|
|||||||
|
|
||||||
/* Read the file */
|
/* Read the file */
|
||||||
while(fp) {
|
while(fp) {
|
||||||
r = ReadLineFromFile();
|
r = ReadLineFromFile(use_pclose);
|
||||||
if (r) {
|
if (r) {
|
||||||
DestroyCache(cf);
|
DestroyCache(cf);
|
||||||
ShouldCache = 0;
|
ShouldCache = 0;
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
/* Skip blank chars */
|
/* Skip blank chars */
|
||||||
@@ -406,7 +427,11 @@ static int CacheFile(char const *fname)
|
|||||||
DBufFree(&LineBuffer);
|
DBufFree(&LineBuffer);
|
||||||
DestroyCache(cf);
|
DestroyCache(cf);
|
||||||
ShouldCache = 0;
|
ShouldCache = 0;
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
cl = cf->cache;
|
cl = cf->cache;
|
||||||
@@ -416,7 +441,11 @@ static int CacheFile(char const *fname)
|
|||||||
DBufFree(&LineBuffer);
|
DBufFree(&LineBuffer);
|
||||||
DestroyCache(cf);
|
DestroyCache(cf);
|
||||||
ShouldCache = 0;
|
ShouldCache = 0;
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
cl = cl->next;
|
cl = cl->next;
|
||||||
@@ -428,7 +457,11 @@ static int CacheFile(char const *fname)
|
|||||||
if (!cl->text) {
|
if (!cl->text) {
|
||||||
DestroyCache(cf);
|
DestroyCache(cf);
|
||||||
ShouldCache = 0;
|
ShouldCache = 0;
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -471,9 +504,6 @@ static int PopFile(void)
|
|||||||
{
|
{
|
||||||
IncludeStruct *i;
|
IncludeStruct *i;
|
||||||
|
|
||||||
/* Assume we own the file for now */
|
|
||||||
RunDisabled &= ~RUN_NOTOWNER;
|
|
||||||
|
|
||||||
if (!Hush && NumIfs) Eprint("%s", ErrMsg[E_MISS_ENDIF]);
|
if (!Hush && NumIfs) Eprint("%s", ErrMsg[E_MISS_ENDIF]);
|
||||||
if (!IStackPtr) return E_EOF;
|
if (!IStackPtr) return E_EOF;
|
||||||
i = &IStack[IStackPtr-1];
|
i = &IStack[IStackPtr-1];
|
||||||
@@ -500,8 +530,10 @@ static int PopFile(void)
|
|||||||
STRSET(FileName, i->filename);
|
STRSET(FileName, i->filename);
|
||||||
if (!i->ownedByMe) {
|
if (!i->ownedByMe) {
|
||||||
RunDisabled |= RUN_NOTOWNER;
|
RunDisabled |= RUN_NOTOWNER;
|
||||||
|
} else {
|
||||||
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
}
|
}
|
||||||
if (!CLine && (i->offset != -1L)) {
|
if (!CLine && (i->offset != -1L || !strcmp(i->filename, "-"))) {
|
||||||
/* We must open the file, then seek to specified position */
|
/* We must open the file, then seek to specified position */
|
||||||
if (strcmp(i->filename, "-")) {
|
if (strcmp(i->filename, "-")) {
|
||||||
fp = fopen(i->filename, "r");
|
fp = fopen(i->filename, "r");
|
||||||
@@ -544,6 +576,64 @@ int DoInclude(ParsePtr p)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* */
|
||||||
|
/* DoIncludeCmd */
|
||||||
|
/* */
|
||||||
|
/* The INCLUDECMD command. */
|
||||||
|
/* */
|
||||||
|
/***************************************************************/
|
||||||
|
int DoIncludeCmd(ParsePtr p)
|
||||||
|
{
|
||||||
|
DynamicBuffer buf;
|
||||||
|
int r;
|
||||||
|
int ch;
|
||||||
|
char append_buf[2];
|
||||||
|
int seen_nonspace = 0;
|
||||||
|
|
||||||
|
append_buf[1] = 0;
|
||||||
|
|
||||||
|
DBufInit(&buf);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
ch = ParseChar(p, &r, 0);
|
||||||
|
if (r) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if (!ch) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (isspace(ch) && !seen_nonspace) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
seen_nonspace = 1;
|
||||||
|
/* Convert \n to ' ' to better handle line continuation */
|
||||||
|
if (ch == '\n') {
|
||||||
|
ch = ' ';
|
||||||
|
}
|
||||||
|
append_buf[0] = (char) ch;
|
||||||
|
if (DBufPuts(&buf, append_buf) != OK) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RunDisabled) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_RUN_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (r=IncludeCmd(DBufValue(&buf))) ) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
DBufFree(&buf);
|
||||||
|
NumIfs = 0;
|
||||||
|
IfFlags = 0;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_GLOB
|
#ifdef HAVE_GLOB
|
||||||
static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
||||||
{
|
{
|
||||||
@@ -664,6 +754,127 @@ static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* */
|
||||||
|
/* IncludeCmd */
|
||||||
|
/* */
|
||||||
|
/* Process the INCLUDECMD command - actually do the command */
|
||||||
|
/* inclusion. */
|
||||||
|
/* */
|
||||||
|
/***************************************************************/
|
||||||
|
static int IncludeCmd(char const *cmd)
|
||||||
|
{
|
||||||
|
IncludeStruct *i;
|
||||||
|
DynamicBuffer buf;
|
||||||
|
FILE *fp2;
|
||||||
|
int r;
|
||||||
|
CachedFile *h;
|
||||||
|
char const *fname;
|
||||||
|
int old_flag;
|
||||||
|
|
||||||
|
FreshLine = 1;
|
||||||
|
if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE;
|
||||||
|
i = &IStack[IStackPtr];
|
||||||
|
|
||||||
|
/* Use "cmd|" as the filename */
|
||||||
|
DBufInit(&buf);
|
||||||
|
if (DBufPuts(&buf, cmd) != OK) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
if (DBufPuts(&buf, "|") != OK) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
fname = DBufValue(&buf);
|
||||||
|
|
||||||
|
if (FileName) {
|
||||||
|
i->filename = StrDup(FileName);
|
||||||
|
if (!i->filename) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
i->filename = NULL;
|
||||||
|
}
|
||||||
|
i->ownedByMe = 1;
|
||||||
|
i->LineNo = LineNo;
|
||||||
|
i->NumIfs = NumIfs;
|
||||||
|
i->IfFlags = IfFlags;
|
||||||
|
i->CLine = CLine;
|
||||||
|
i->offset = -1L;
|
||||||
|
i->chain = NULL;
|
||||||
|
if (fp) {
|
||||||
|
i->offset = ftell(fp);
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
|
IStackPtr++;
|
||||||
|
|
||||||
|
/* If the file is cached, use it */
|
||||||
|
h = CachedFiles;
|
||||||
|
while(h) {
|
||||||
|
if (!strcmp(fname, h->filename)) {
|
||||||
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
|
fprintf(ErrFp, "Reading command `%s': Found in cache\n", fname);
|
||||||
|
}
|
||||||
|
CLine = h->cache;
|
||||||
|
STRSET(FileName, fname);
|
||||||
|
DBufFree(&buf);
|
||||||
|
LineNo = 0;
|
||||||
|
if (!h->ownedByMe) {
|
||||||
|
RunDisabled |= RUN_NOTOWNER;
|
||||||
|
} else {
|
||||||
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
|
}
|
||||||
|
if (FileName) return OK; else return E_NO_MEM;
|
||||||
|
}
|
||||||
|
h = h->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
|
fprintf(ErrFp, "Executing `%s' for INCLUDECMD and caching as `%s'\n",
|
||||||
|
cmd, fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not found in cache */
|
||||||
|
|
||||||
|
/* If cmd starts with !, then disable RUN within the cmd output */
|
||||||
|
if (cmd[0] == '!') {
|
||||||
|
fp2 = popen(cmd+1, "r");
|
||||||
|
} else {
|
||||||
|
fp2 = popen(cmd, "r");
|
||||||
|
}
|
||||||
|
if (!fp2) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_CANT_OPEN;
|
||||||
|
}
|
||||||
|
fp = fp2;
|
||||||
|
LineNo = 0;
|
||||||
|
|
||||||
|
/* Temporarily turn of file tracing */
|
||||||
|
old_flag = DebugFlag;
|
||||||
|
DebugFlag &= (~DB_TRACE_FILES);
|
||||||
|
|
||||||
|
if (cmd[0] == '!') {
|
||||||
|
RunDisabled |= RUN_NOTOWNER;
|
||||||
|
}
|
||||||
|
r = CacheFile(fname, 1);
|
||||||
|
|
||||||
|
DebugFlag = old_flag;
|
||||||
|
if (r == OK) {
|
||||||
|
fp = NULL;
|
||||||
|
CLine = CachedFiles->cache;
|
||||||
|
LineNo = 0;
|
||||||
|
STRSET(FileName, fname);
|
||||||
|
DBufFree(&buf);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
DBufFree(&buf);
|
||||||
|
/* We failed */
|
||||||
|
PopFile();
|
||||||
|
return E_CANT_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* IncludeFile */
|
/* IncludeFile */
|
||||||
@@ -828,7 +1039,8 @@ int TopLevel(void)
|
|||||||
/* root, we refuse to open files not owned by root. */
|
/* root, we refuse to open files not owned by root. */
|
||||||
/* We also reject world-writable files, no matter */
|
/* We also reject world-writable files, no matter */
|
||||||
/* who we're running as. */
|
/* who we're running as. */
|
||||||
/* As a side effect, if we don't own the file, we disable RUN */
|
/* As a side effect, if we don't own the file, or it's not */
|
||||||
|
/* owned by a trusted user, we disable RUN */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int CheckSafety(void)
|
static int CheckSafety(void)
|
||||||
{
|
{
|
||||||
@@ -866,9 +1078,22 @@ static int CheckSafety(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If file is not owned by me, disable RUN command */
|
/* If file is not owned by me or a trusted user, disable RUN command */
|
||||||
if (statbuf.st_uid != geteuid()) {
|
|
||||||
RunDisabled |= RUN_NOTOWNER;
|
/* Assume unsafe */
|
||||||
|
RunDisabled |= RUN_NOTOWNER;
|
||||||
|
if (statbuf.st_uid == geteuid()) {
|
||||||
|
/* Owned by me... safe */
|
||||||
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
|
} else {
|
||||||
|
int i;
|
||||||
|
for (i=0; i<NumTrustedUsers; i++) {
|
||||||
|
if (statbuf.st_uid == TrustedUsers[i]) {
|
||||||
|
/* Owned by a trusted user... safe */
|
||||||
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
30
src/funcs.c
30
src/funcs.c
@@ -6,7 +6,7 @@
|
|||||||
/* expressions. */
|
/* expressions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -151,6 +151,7 @@ static int FWeekno (func_info *);
|
|||||||
static int FWkday (func_info *);
|
static int FWkday (func_info *);
|
||||||
static int FWkdaynum (func_info *);
|
static int FWkdaynum (func_info *);
|
||||||
static int FYear (func_info *);
|
static int FYear (func_info *);
|
||||||
|
static int FShellescape (func_info *);
|
||||||
|
|
||||||
static int CleanUpAfterFunc (func_info *);
|
static int CleanUpAfterFunc (func_info *);
|
||||||
static int CheckArgs (BuiltinFunc *f, int nargs);
|
static int CheckArgs (BuiltinFunc *f, int nargs);
|
||||||
@@ -267,6 +268,7 @@ BuiltinFunc Func[] = {
|
|||||||
{ "realtoday", 0, 0, 0, FRealtoday },
|
{ "realtoday", 0, 0, 0, FRealtoday },
|
||||||
{ "sgn", 1, 1, 1, FSgn },
|
{ "sgn", 1, 1, 1, FSgn },
|
||||||
{ "shell", 1, 2, 0, FShell },
|
{ "shell", 1, 2, 0, FShell },
|
||||||
|
{ "shellescape", 1, 1, 1, FShellescape },
|
||||||
{ "slide", 2, NO_MAX, 0, FSlide },
|
{ "slide", 2, NO_MAX, 0, FSlide },
|
||||||
{ "strlen", 1, 1, 1, FStrlen },
|
{ "strlen", 1, 1, 1, FStrlen },
|
||||||
{ "substr", 2, 3, 1, FSubstr },
|
{ "substr", 2, 3, 1, FSubstr },
|
||||||
@@ -866,12 +868,14 @@ static int FTime(func_info *info)
|
|||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int FAbs(func_info *info)
|
static int FAbs(func_info *info)
|
||||||
{
|
{
|
||||||
int v;
|
volatile int v;
|
||||||
|
|
||||||
ASSERT_TYPE(0, INT_TYPE);
|
ASSERT_TYPE(0, INT_TYPE);
|
||||||
v = ARGV(0);
|
v = ARGV(0);
|
||||||
RetVal.type = INT_TYPE;
|
RetVal.type = INT_TYPE;
|
||||||
RETVAL = (v < 0) ? (-v) : v;
|
RETVAL = (v < 0) ? (-v) : v;
|
||||||
|
v = RETVAL;
|
||||||
|
if (v < 0) return E_2HIGH;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1070,6 +1074,28 @@ static int FOstype(func_info *info)
|
|||||||
return RetStrVal("UNIX", info);
|
return RetStrVal("UNIX", info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* */
|
||||||
|
/* FShellescape - escape shell meta-characters */
|
||||||
|
/* */
|
||||||
|
/***************************************************************/
|
||||||
|
static int FShellescape(func_info *info)
|
||||||
|
{
|
||||||
|
DynamicBuffer buf;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
ASSERT_TYPE(0, STR_TYPE);
|
||||||
|
DBufInit (&buf);
|
||||||
|
if (ShellEscape(ARG(0).v.str, &buf) != OK) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = RetStrVal(DBufValue(&buf), info);
|
||||||
|
DBufFree(&buf);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* FUpper - convert string to upper-case */
|
/* FUpper - convert string to upper-case */
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -21,6 +21,12 @@
|
|||||||
#define INIT(var, val) var
|
#define INIT(var, val) var
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_TRUSTED_USERS 20
|
||||||
|
|
||||||
#define MINUTES_PER_DAY 1440
|
#define MINUTES_PER_DAY 1440
|
||||||
|
|
||||||
#define DaysInYear(y) (((y) % 4) ? 365 : ((!((y) % 100) && ((y) % 400)) ? 365 : 366 ))
|
#define DaysInYear(y) (((y) % 4) ? 365 : ((!((y) % 100) && ((y) % 400)) ? 365 : 366 ))
|
||||||
@@ -36,6 +42,9 @@ EXTERN int CurMon;
|
|||||||
EXTERN int CurYear;
|
EXTERN int CurYear;
|
||||||
EXTERN int LineNo;
|
EXTERN int LineNo;
|
||||||
EXTERN int FreshLine;
|
EXTERN int FreshLine;
|
||||||
|
EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS];
|
||||||
|
|
||||||
|
EXTERN INIT( int NumTrustedUsers, 0);
|
||||||
EXTERN INIT( char const *MsgCommand, NULL);
|
EXTERN INIT( char const *MsgCommand, NULL);
|
||||||
EXTERN INIT( int ShowAllErrors, 0);
|
EXTERN INIT( int ShowAllErrors, 0);
|
||||||
EXTERN INIT( int DebugFlag, 0);
|
EXTERN INIT( int DebugFlag, 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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/* Derived from code written by Amos Shapir in 1978; revised */
|
/* Derived from code written by Amos Shapir in 1978; revised */
|
||||||
/* 1985. */
|
/* 1985. */
|
||||||
|
|||||||
60
src/init.c
60
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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -89,6 +89,7 @@ static void ChgUser(char const *u);
|
|||||||
static void InitializeVar(char const *str);
|
static void InitializeVar(char const *str);
|
||||||
|
|
||||||
static char const *BadDate = "Illegal date on command line\n";
|
static char const *BadDate = "Illegal date on command line\n";
|
||||||
|
static void AddTrustedUser(char const *username);
|
||||||
|
|
||||||
static DynamicBuffer default_filename_buf;
|
static DynamicBuffer default_filename_buf;
|
||||||
|
|
||||||
@@ -114,7 +115,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(stderr, "HOME environment variable not set. Unable to determine reminder file.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
DBufPuts(&default_filename_buf, s);
|
DBufPuts(&default_filename_buf, s);
|
||||||
DBufPuts(&default_filename_buf, "/.reminders");
|
DBufPuts(&default_filename_buf, "/.reminders");
|
||||||
@@ -172,7 +173,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
if (getgid() != getegid() ||
|
if (getgid() != getegid() ||
|
||||||
getuid() != geteuid()) {
|
getuid() != geteuid()) {
|
||||||
fprintf(ErrFp, "\nRemind should not be installed set-uid or set-gid.\nCHECK YOUR SYSTEM SECURITY.\n");
|
fprintf(ErrFp, "\nRemind should not be installed set-uid or set-gid.\nCHECK YOUR SYSTEM SECURITY.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
y = NO_YR;
|
y = NO_YR;
|
||||||
@@ -183,7 +184,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, ErrMsg[M_BAD_SYS_DATE], BASE);
|
fprintf(ErrFp, ErrMsg[M_BAD_SYS_DATE], BASE);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
JulianToday = RealToday;
|
JulianToday = RealToday;
|
||||||
FromJulian(JulianToday, &CurYear, &CurMon, &CurDay);
|
FromJulian(JulianToday, &CurYear, &CurMon, &CurDay);
|
||||||
@@ -217,6 +218,10 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
}
|
}
|
||||||
while (*arg) {
|
while (*arg) {
|
||||||
switch(*arg++) {
|
switch(*arg++) {
|
||||||
|
case '+':
|
||||||
|
AddTrustedUser(arg);
|
||||||
|
while(*arg) arg++;
|
||||||
|
break;
|
||||||
|
|
||||||
case '@':
|
case '@':
|
||||||
UseVTColors = 1;
|
UseVTColors = 1;
|
||||||
@@ -330,8 +335,12 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
|
|
||||||
case 'u':
|
case 'u':
|
||||||
case 'U':
|
case 'U':
|
||||||
ChgUser(arg);
|
if (*arg == '+') {
|
||||||
RunDisabled = RUN_CMDLINE;
|
ChgUser(arg+1);
|
||||||
|
} else {
|
||||||
|
RunDisabled = RUN_CMDLINE;
|
||||||
|
ChgUser(arg);
|
||||||
|
}
|
||||||
while (*arg) arg++;
|
while (*arg) arg++;
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
@@ -535,7 +544,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
if (!InvokedAsRem) {
|
if (!InvokedAsRem) {
|
||||||
if (i >= argc) {
|
if (i >= argc) {
|
||||||
Usage();
|
Usage();
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
InitialFile = argv[i++];
|
InitialFile = argv[i++];
|
||||||
} else {
|
} else {
|
||||||
@@ -649,7 +658,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 (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
@@ -682,7 +691,7 @@ void Usage(void)
|
|||||||
fprintf(ErrFp, " -m Start calendar with Monday rather than Sunday\n");
|
fprintf(ErrFp, " -m Start calendar with Monday rather than Sunday\n");
|
||||||
fprintf(ErrFp, " -y Synthesize tags for tagless reminders\n");
|
fprintf(ErrFp, " -y Synthesize tags for tagless reminders\n");
|
||||||
fprintf(ErrFp, " -j[n] Run in 'purge' mode. [n = INCLUDE depth]\n");
|
fprintf(ErrFp, " -j[n] Run in 'purge' mode. [n = INCLUDE depth]\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
#endif /* L_USAGE_OVERRIDE */
|
#endif /* L_USAGE_OVERRIDE */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -711,23 +720,23 @@ static void ChgUser(char const *user)
|
|||||||
|
|
||||||
if (!pwent) {
|
if (!pwent) {
|
||||||
fprintf(ErrFp, ErrMsg[M_BAD_USER], user);
|
fprintf(ErrFp, ErrMsg[M_BAD_USER], user);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!myuid && setgid(pwent->pw_gid)) {
|
if (!myuid && setgid(pwent->pw_gid)) {
|
||||||
fprintf(ErrFp, ErrMsg[M_NO_CHG_GID], pwent->pw_gid);
|
fprintf(ErrFp, ErrMsg[M_NO_CHG_GID], pwent->pw_gid);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!myuid && setuid(pwent->pw_uid)) {
|
if (!myuid && setuid(pwent->pw_uid)) {
|
||||||
fprintf(ErrFp, ErrMsg[M_NO_CHG_UID], pwent->pw_uid);
|
fprintf(ErrFp, ErrMsg[M_NO_CHG_UID], pwent->pw_uid);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
home = malloc(strlen(pwent->pw_dir) + 6);
|
home = malloc(strlen(pwent->pw_dir) + 6);
|
||||||
if (!home) {
|
if (!home) {
|
||||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
sprintf(home, "HOME=%s", pwent->pw_dir);
|
sprintf(home, "HOME=%s", pwent->pw_dir);
|
||||||
putenv(home);
|
putenv(home);
|
||||||
@@ -735,7 +744,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", ErrMsg[M_NOMEM_ENV]);
|
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
sprintf(shell, "SHELL=%s", pwent->pw_shell);
|
sprintf(shell, "SHELL=%s", pwent->pw_shell);
|
||||||
putenv(shell);
|
putenv(shell);
|
||||||
@@ -744,14 +753,14 @@ 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", ErrMsg[M_NOMEM_ENV]);
|
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
sprintf(username, "USER=%s", pwent->pw_name);
|
sprintf(username, "USER=%s", pwent->pw_name);
|
||||||
putenv(username);
|
putenv(username);
|
||||||
logname= malloc(strlen(pwent->pw_name) + 9);
|
logname= malloc(strlen(pwent->pw_name) + 9);
|
||||||
if (!logname) {
|
if (!logname) {
|
||||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
sprintf(logname, "LOGNAME=%s", pwent->pw_name);
|
sprintf(logname, "LOGNAME=%s", pwent->pw_name);
|
||||||
putenv(logname);
|
putenv(logname);
|
||||||
@@ -838,6 +847,25 @@ static void InitializeVar(char const *str)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
AddTrustedUser(char const *username)
|
||||||
|
{
|
||||||
|
struct passwd *pwent;
|
||||||
|
if (NumTrustedUsers >= MAX_TRUSTED_USERS) {
|
||||||
|
fprintf(stderr, "Too many trusted users (%d max)\n",
|
||||||
|
MAX_TRUSTED_USERS);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
pwent = getpwnam(username);
|
||||||
|
if (!pwent) {
|
||||||
|
fprintf(ErrFp, ErrMsg[M_BAD_USER], username);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
TrustedUsers[NumTrustedUsers] = pwent->pw_uid;
|
||||||
|
NumTrustedUsers++;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__CYGWIN__)
|
#if defined(__APPLE__) || defined(__CYGWIN__)
|
||||||
static char const pmsg1[] = {
|
static char const pmsg1[] = {
|
||||||
0x4c, 0x62, 0x68, 0x20, 0x6e, 0x63, 0x63, 0x72, 0x6e, 0x65, 0x20,
|
0x4c, 0x62, 0x68, 0x20, 0x6e, 0x63, 0x63, 0x72, 0x6e, 0x65, 0x20,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Header file for language support for various languages. */
|
/* Header file for language support for various languages. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
|
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
/* Further corrections by Erik-Jan Vens */
|
/* Further corrections by Erik-Jan Vens */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Support for the English language. */
|
/* Support for the English language. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* This file is Copyright (C) 1993-1998 by Mikko Silvonen. */
|
/* This file is Copyright (C) 1993-1998 by Mikko Silvonen. */
|
||||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -527,7 +527,7 @@ EXTERN char *ErrMsg[] =
|
|||||||
#define L_USAGE_OVERRIDE 1
|
#define L_USAGE_OVERRIDE 1
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
|
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1993 by Laurent Duperval and */
|
/* This file is Copyright (C) 1993 by Laurent Duperval and */
|
||||||
/* Dianne Skoll. */
|
/* Dianne Skoll. */
|
||||||
/* */
|
/* */
|
||||||
@@ -359,7 +359,7 @@ EXTERN char *ErrMsg[] =
|
|||||||
#define L_USAGE_OVERRIDE 1
|
#define L_USAGE_OVERRIDE 1
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
/* I don't speak German. */
|
/* I don't speak German. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Support for the Icelandic language. */
|
/* Support for the Icelandic language. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
|
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* It is Copyright (C) 1996 by Valerio Aimale */
|
/* It is Copyright (C) 1996 by Valerio Aimale */
|
||||||
/* */
|
/* */
|
||||||
/* Remind is copyright (C) 1992-2020 by Dianne Skoll */
|
/* Remind is copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* This file is Copyright (C) 1993 by Trygve Randen. */
|
/* This file is Copyright (C) 1993 by Trygve Randen. */
|
||||||
/* Remind is Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Remind is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
/* Polish. */
|
/* Polish. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -397,7 +397,7 @@ EXTERN char *ErrMsg[] =
|
|||||||
#define L_USAGE_OVERRIDE 1
|
#define L_USAGE_OVERRIDE 1
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1996 by Marco Paganini and */
|
/* This file is Copyright (C) 1996 by Marco Paganini and */
|
||||||
/* Dianne Skoll. */
|
/* Dianne Skoll. */
|
||||||
/* */
|
/* */
|
||||||
@@ -257,7 +257,7 @@ EXTERN char *ErrMsg[] =
|
|||||||
#define L_USAGE_OVERRIDE 1
|
#define L_USAGE_OVERRIDE 1
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> VERSAO BETA <<<<\n");
|
fprintf(ErrFp, ">>>> VERSAO BETA <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
|
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
/* Author: Rafa Couto <rafacouto@biogate.com> */
|
/* Author: Rafa Couto <rafacouto@biogate.com> */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
11
src/main.c
11
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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -243,6 +243,15 @@ static void DoReminders(void)
|
|||||||
r=DoInclude(&p);
|
r=DoInclude(&p);
|
||||||
purge_handled = 1;
|
purge_handled = 1;
|
||||||
break;
|
break;
|
||||||
|
case T_IncludeCmd:
|
||||||
|
/* In purge mode, include closes file, so we
|
||||||
|
need to echo it here! */
|
||||||
|
if (PurgeMode) {
|
||||||
|
PurgeEchoLine("%s\n", CurLine);
|
||||||
|
}
|
||||||
|
r=DoIncludeCmd(&p);
|
||||||
|
purge_handled = 1;
|
||||||
|
break;
|
||||||
case T_Exit: DoExit(&p); break;
|
case T_Exit: DoExit(&p); break;
|
||||||
case T_Flush: r=DoFlush(&p); break;
|
case T_Flush: r=DoFlush(&p); break;
|
||||||
case T_Set: r=DoSet(&p); break;
|
case T_Set: r=DoSet(&p); break;
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Function Prototypes. */
|
/* Function Prototypes. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -45,6 +45,7 @@ int CopyValue (Value *dest, const Value *src);
|
|||||||
int ReadLine (void);
|
int ReadLine (void);
|
||||||
int OpenFile (char const *fname);
|
int OpenFile (char const *fname);
|
||||||
int DoInclude (ParsePtr p);
|
int DoInclude (ParsePtr p);
|
||||||
|
int DoIncludeCmd (ParsePtr p);
|
||||||
int IncludeFile (char const *fname);
|
int IncludeFile (char const *fname);
|
||||||
int GetAccessDate (char const *file);
|
int GetAccessDate (char const *file);
|
||||||
int SetAccessDate (char const *fname, int jul);
|
int SetAccessDate (char const *fname, int jul);
|
||||||
@@ -161,3 +162,4 @@ void PrintJSONKeyPairDate(char const *name, int jul);
|
|||||||
void PrintJSONKeyPairDateTime(char const *name, int dt);
|
void PrintJSONKeyPairDateTime(char const *name, int dt);
|
||||||
void PrintJSONKeyPairTime(char const *name, int t);
|
void PrintJSONKeyPairTime(char const *name, int t);
|
||||||
void System(char const *cmd);
|
void System(char const *cmd);
|
||||||
|
int ShellEscape(char const *in, DynamicBuffer *out);
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
17
src/token.c
17
src/token.c
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -62,6 +62,7 @@ Token TokArray[] = {
|
|||||||
{ "if", 2, T_If, 0 },
|
{ "if", 2, T_If, 0 },
|
||||||
{ "iftrig", 6, T_IfTrig, 0 },
|
{ "iftrig", 6, T_IfTrig, 0 },
|
||||||
{ "include", 3, T_Include, 0 },
|
{ "include", 3, T_Include, 0 },
|
||||||
|
{ "includecmd", 10, T_IncludeCmd, 0 },
|
||||||
{ "january", 3, T_Month, 0 },
|
{ "january", 3, T_Month, 0 },
|
||||||
{ "july", 3, T_Month, 6 },
|
{ "july", 3, T_Month, 6 },
|
||||||
{ "june", 3, T_Month, 5 },
|
{ "june", 3, T_Month, 5 },
|
||||||
@@ -172,6 +173,10 @@ void FindToken(char const *s, Token *tok)
|
|||||||
int top, bot, mid, r, max;
|
int top, bot, mid, r, max;
|
||||||
int l;
|
int l;
|
||||||
|
|
||||||
|
#if LANG != ENGLISH
|
||||||
|
size_t i;
|
||||||
|
#endif
|
||||||
|
|
||||||
tok->type = T_Illegal;
|
tok->type = T_Illegal;
|
||||||
if (! *s) {
|
if (! *s) {
|
||||||
tok->type = T_Empty;
|
tok->type = T_Empty;
|
||||||
@@ -229,11 +234,11 @@ void FindToken(char const *s, Token *tok)
|
|||||||
/* If language is other than English, search the DayNames[] and MonthNames[]
|
/* If language is other than English, search the DayNames[] and MonthNames[]
|
||||||
array. */
|
array. */
|
||||||
#if LANG != ENGLISH
|
#if LANG != ENGLISH
|
||||||
for (size_t x=0; x<(sizeof(NonEnglishToks) / sizeof(Token)); x++) {
|
for (i=0; i<(sizeof(NonEnglishToks) / sizeof(Token)); i++) {
|
||||||
if (l >= NonEnglishToks[x].MinLen &&
|
if (l >= NonEnglishToks[i].MinLen &&
|
||||||
!TokStrCmp(&NonEnglishToks[x], s)) {
|
!TokStrCmp(&NonEnglishToks[i], s)) {
|
||||||
tok->type = NonEnglishToks[x].type;
|
tok->type = NonEnglishToks[i].type;
|
||||||
tok->val = NonEnglishToks[x].val;
|
tok->val = NonEnglishToks[i].val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
#define GOT_YR 4
|
#define GOT_YR 4
|
||||||
#define GOT_WD 8
|
#define GOT_WD 8
|
||||||
|
|
||||||
|
#define ADVANCE_TO_WD(x, wd) while (! ((wd) & (1 << ((x)%7)))) (x)++
|
||||||
|
|
||||||
static int JYear(int jul);
|
static int JYear(int jul);
|
||||||
static int JMonth(int jul);
|
static int JMonth(int jul);
|
||||||
static int NextSimpleTrig(int startdate, Trigger *trig, int *err);
|
static int NextSimpleTrig(int startdate, Trigger *trig, int *err);
|
||||||
@@ -58,9 +60,10 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
if (trig->wd != NO_WD) typ |= GOT_WD;
|
if (trig->wd != NO_WD) typ |= GOT_WD;
|
||||||
switch(typ) {
|
switch(typ) {
|
||||||
case 0:
|
case 0:
|
||||||
|
return startdate;
|
||||||
|
|
||||||
case GOT_WD:
|
case GOT_WD:
|
||||||
if (trig->wd != NO_WD)
|
ADVANCE_TO_WD(startdate, trig->wd);
|
||||||
while(! (trig->wd & (1 << (startdate%7)))) startdate++;
|
|
||||||
return startdate;
|
return startdate;
|
||||||
|
|
||||||
case GOT_DAY:
|
case GOT_DAY:
|
||||||
@@ -83,12 +86,12 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
else return -1;
|
else return -1;
|
||||||
|
|
||||||
case GOT_DAY+GOT_MON:
|
case GOT_DAY+GOT_MON:
|
||||||
if (m > trig->m || (m == trig->m && d > trig->d)) y++;
|
|
||||||
if (trig->d > MonthDays[trig->m]) {
|
if (trig->d > MonthDays[trig->m]) {
|
||||||
*err = E_BAD_DATE;
|
*err = E_BAD_DATE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m > trig->m || (m == trig->m && d > trig->d)) y++;
|
||||||
/* Take care of Feb. 29 */
|
/* Take care of Feb. 29 */
|
||||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||||
return Julian(y, trig->m, trig->d);
|
return Julian(y, trig->m, trig->d);
|
||||||
@@ -121,19 +124,19 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
if (y > trig->y) return -1;
|
if (y > trig->y) return -1;
|
||||||
if (y < trig->y) j = Julian(trig->y, 0, 1);
|
if (y < trig->y) j = Julian(trig->y, 0, 1);
|
||||||
else j = startdate;
|
else j = startdate;
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (JYear(j) > trig->y) return -1;
|
if (JYear(j) > trig->y) return -1;
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
case GOT_MON+GOT_WD:
|
case GOT_MON+GOT_WD:
|
||||||
if (m == trig->m) {
|
if (m == trig->m) {
|
||||||
j = startdate;
|
j = startdate;
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (JMonth(j) == trig->m) return j;
|
if (JMonth(j) == trig->m) return j;
|
||||||
}
|
}
|
||||||
if (m >= trig->m) j = Julian(y+1, trig->m, 1);
|
if (m >= trig->m) j = Julian(y+1, trig->m, 1);
|
||||||
else j = Julian(y, trig->m, 1);
|
else j = Julian(y, trig->m, 1);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j; /* Guaranteed to be within the month */
|
return j; /* Guaranteed to be within the month */
|
||||||
|
|
||||||
case GOT_DAY+GOT_WD:
|
case GOT_DAY+GOT_WD:
|
||||||
@@ -144,7 +147,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
/* If there are fewer days in previous month, no match */
|
/* If there are fewer days in previous month, no match */
|
||||||
if (trig->d <= DaysInMonth(m2, y2)) {
|
if (trig->d <= DaysInMonth(m2, y2)) {
|
||||||
j = Julian(y2, m2, trig->d);
|
j = Julian(y2, m2, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -153,7 +156,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
/* Try this month */
|
/* Try this month */
|
||||||
if (trig->d <= DaysInMonth(m, y)) {
|
if (trig->d <= DaysInMonth(m, y)) {
|
||||||
j = Julian(y, m, trig->d);
|
j = Julian(y, m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,18 +165,18 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
if (m2 > 11) { m2 = 0; y++; }
|
if (m2 > 11) { m2 = 0; y++; }
|
||||||
while (trig->d > DaysInMonth(m2, y)) m2++;
|
while (trig->d > DaysInMonth(m2, y)) m2++;
|
||||||
j = Julian(y, m2, trig->d);
|
j = Julian(y, m2, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
case GOT_WD+GOT_YR+GOT_DAY:
|
case GOT_WD+GOT_YR+GOT_DAY:
|
||||||
if (y > trig->y+1 || (y > trig->y && m>0)) return -1;
|
if (y > trig->y+1 || (y > trig->y && m>0)) return -1;
|
||||||
if (y > trig->y) {
|
if (y > trig->y) {
|
||||||
j = Julian(trig->y, 11, trig->d);
|
j = Julian(trig->y, 11, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
} else if (y < trig->y) {
|
} else if (y < trig->y) {
|
||||||
j = Julian(trig->y, 0, trig->d);
|
j = Julian(trig->y, 0, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
} else {
|
} else {
|
||||||
/* Try last month */
|
/* Try last month */
|
||||||
@@ -181,14 +184,16 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
m2 = m-1;
|
m2 = m-1;
|
||||||
while (trig->d > DaysInMonth(m2, trig->y)) m2--;
|
while (trig->d > DaysInMonth(m2, trig->y)) m2--;
|
||||||
j = Julian(trig->y, m2, trig->d);
|
j = Julian(trig->y, m2, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
|
if (JYear(j) > trig->y) return -1;
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Try this month */
|
/* Try this month */
|
||||||
if (trig->d <= DaysInMonth(m, trig->y)) {
|
if (trig->d <= DaysInMonth(m, trig->y)) {
|
||||||
j = Julian(trig->y, m, trig->d);
|
j = Julian(trig->y, m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
|
if (JYear(j) > trig->y) return -1;
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +202,8 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
m++;
|
m++;
|
||||||
while (trig->d > DaysInMonth(m, trig->d)) m++;
|
while (trig->d > DaysInMonth(m, trig->d)) m++;
|
||||||
j = Julian(trig->y, m, trig->d);
|
j = Julian(trig->y, m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
|
if (JYear(j) > trig->y) return -1;
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
case GOT_DAY+GOT_MON+GOT_WD:
|
case GOT_DAY+GOT_MON+GOT_WD:
|
||||||
@@ -215,31 +221,32 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
|
|
||||||
/* Try last year */
|
/* Try last year */
|
||||||
j = Julian(y, trig->m, trig->d);
|
j = Julian(y, trig->m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
|
|
||||||
/* Try this year */
|
/* Try this year */
|
||||||
y++;
|
y++;
|
||||||
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||||
j = Julian(y, trig->m, trig->d);
|
j = Julian(y, trig->m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
|
|
||||||
/* Must be next year */
|
/* Must be next year */
|
||||||
y++;
|
y++;
|
||||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||||
j = Julian(y, trig->m, trig->d);
|
j = Julian(y, trig->m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
case GOT_WD+GOT_MON+GOT_YR:
|
case GOT_WD+GOT_MON+GOT_YR:
|
||||||
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
|
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
|
||||||
if (trig->y > y || (trig->y == y && trig->m > m)) {
|
if (trig->y > y || (trig->y == y && trig->m > m)) {
|
||||||
j = Julian(trig->y, trig->m, 1);
|
j = Julian(trig->y, trig->m, 1);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
} else {
|
} else {
|
||||||
j = startdate;
|
j = startdate;
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
FromJulian(j, &y2, &m2, &d2);
|
FromJulian(j, &y2, &m2, &d2);
|
||||||
if (m2 == trig->m) return j; else return -1;
|
if (m2 == trig->m) return j; else return -1;
|
||||||
}
|
}
|
||||||
@@ -250,7 +257,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
j = Julian(trig->y, trig->m, trig->d);
|
j = Julian(trig->y, trig->m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ typedef Parser *ParsePtr; /* Pointer to parser structure */
|
|||||||
enum TokTypes
|
enum TokTypes
|
||||||
{ T_Illegal,
|
{ T_Illegal,
|
||||||
/* Commands first */
|
/* Commands first */
|
||||||
T_Rem, T_Push, T_Pop, T_Preserve, T_Include, T_If, T_Else, T_EndIf,
|
T_Rem, T_Push, T_Pop, T_Preserve, T_Include, T_IncludeCmd, T_If, T_Else, T_EndIf,
|
||||||
T_IfTrig, T_ErrMsg,
|
T_IfTrig, T_ErrMsg,
|
||||||
T_Set, T_UnSet, T_Fset, T_Omit, T_Banner, T_Exit,
|
T_Set, T_UnSet, T_Fset, T_Omit, T_Banner, T_Exit,
|
||||||
T_WkDay,
|
T_WkDay,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* functions. */
|
/* functions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
41
src/utils.c
41
src/utils.c
@@ -5,11 +5,15 @@
|
|||||||
/* Useful utility functions. */
|
/* Useful utility functions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
static char const DontEscapeMe[] =
|
||||||
|
"1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,/";
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "err.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -123,3 +127,38 @@ int DateOK(int y, int m, int d)
|
|||||||
d > DaysInMonth(m, y) ) return 0;
|
d > DaysInMonth(m, y) ) return 0;
|
||||||
else return 1;
|
else return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Functions designed to defeat gcc optimizer */
|
||||||
|
|
||||||
|
int _private_div(int a, int b) { return a/b; }
|
||||||
|
int _private_add_overflow(int result, int b, int old)
|
||||||
|
{
|
||||||
|
if (b > 0 && result < old) return 1;
|
||||||
|
if (b < 0 && result > old) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int _private_sub_overflow(int result, int b, int old)
|
||||||
|
{
|
||||||
|
if (b < 0 && result < old) return 1;
|
||||||
|
if (b > 0 && result > old) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _private_unminus_overflow(int a, int b)
|
||||||
|
{
|
||||||
|
if (a > 0 && b > 0) return 1;
|
||||||
|
if (a < 0 && b < 0) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ShellEscape(char const *in, DynamicBuffer *out)
|
||||||
|
{
|
||||||
|
while(*in) {
|
||||||
|
if (!strchr(DontEscapeMe, *in)) {
|
||||||
|
if (DBufPutc(out, '\\') != OK) return E_NO_MEM;
|
||||||
|
}
|
||||||
|
if (DBufPutc(out, *in++) != OK) return E_NO_MEM;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
@@ -31,6 +32,9 @@
|
|||||||
#define VALUE ErrMsg[E_VAL]
|
#define VALUE ErrMsg[E_VAL]
|
||||||
#define UNDEF ErrMsg[E_UNDEF]
|
#define UNDEF ErrMsg[E_UNDEF]
|
||||||
|
|
||||||
|
static int IntMin = INT_MIN;
|
||||||
|
static int IntMax = INT_MAX;
|
||||||
|
|
||||||
static Var *VHashTbl[VAR_HASH_SIZE];
|
static Var *VHashTbl[VAR_HASH_SIZE];
|
||||||
|
|
||||||
typedef int (*SysVarFunc)(int, Value *);
|
typedef int (*SysVarFunc)(int, Value *);
|
||||||
@@ -661,6 +665,8 @@ static SysVar SysVarArr[] = {
|
|||||||
{"HushMode", 0, INT_TYPE, &Hush, 0, 0 },
|
{"HushMode", 0, INT_TYPE, &Hush, 0, 0 },
|
||||||
{"IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0 },
|
{"IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0 },
|
||||||
{"InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0 },
|
{"InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0 },
|
||||||
|
{"IntMax", 0, INT_TYPE, &IntMax, 0, 0 },
|
||||||
|
{"IntMin", 0, INT_TYPE, &IntMin, 0, 0 },
|
||||||
{"LatDeg", 1, INT_TYPE, &LatDeg, -90, 90 },
|
{"LatDeg", 1, INT_TYPE, &LatDeg, -90, 90 },
|
||||||
{"LatMin", 1, INT_TYPE, &LatMin, -59, 59 },
|
{"LatMin", 1, INT_TYPE, &LatMin, -59, 59 },
|
||||||
{"LatSec", 1, INT_TYPE, &LatSec, -59, 59 },
|
{"LatSec", 1, INT_TYPE, &LatSec, -59, 59 },
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
cd /home/dfs/Software/Remind.git || exit 1
|
|
||||||
|
|
||||||
rm -f .git/COMMIT_EDITMSG .git/*~
|
|
||||||
|
|
||||||
git update-server-info && cd .git && rsync --archive --verbose --progress --delete ./ dianne.skoll.ca:web/projects/remind/git/Remind.git/
|
|
||||||
exit $?
|
|
||||||
|
|
||||||
27
tests/test-for-backends.rem
Normal file
27
tests/test-for-backends.rem
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# This file is designed for testing how back-ends
|
||||||
|
# handle SPECIALs, including SPECIALS they don't understand
|
||||||
|
# If you're writing a back-end, test it by feeding it the output
|
||||||
|
# of: remind -pp test-for-backends.rem
|
||||||
|
|
||||||
|
# Color and shade
|
||||||
|
REM 1 SPECIAL COLOR 128 0 0 Red
|
||||||
|
REM 2 SPECIAL COLOUR 0 128 0 British Green
|
||||||
|
REM 3 SPECIAL SHADE 192 192 255
|
||||||
|
|
||||||
|
# Moon
|
||||||
|
REM [moondate(0)] SPECIAL MOON 0 -1 -1 [moontime(0)]
|
||||||
|
REM [moondate(1)] SPECIAL MOON 1 -1 -1 [moontime(1)]
|
||||||
|
REM [moondate(2)] SPECIAL MOON 2 -1 -1 [moontime(2)]
|
||||||
|
REM [moondate(3)] SPECIAL MOON 3 -1 -1 [moontime(3)]
|
||||||
|
|
||||||
|
# Week
|
||||||
|
REM Monday SPECIAL WEEK (W[weekno()])
|
||||||
|
|
||||||
|
# PostScript
|
||||||
|
REM Wed PS Border Border 2 div moveto /Helvetica-Oblique findfont 6 scalefont setfont (oof!) show
|
||||||
|
|
||||||
|
# A SPECIAL that should be ignored
|
||||||
|
REM 15 SPECIAL RANDOM-STUFF ignore me and be happy
|
||||||
|
|
||||||
|
# A normal reminder
|
||||||
|
REM 16 MSG A normal reminder
|
||||||
@@ -7,13 +7,22 @@
|
|||||||
# in the build directory.
|
# in the build directory.
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2018 Dianne Skoll
|
# Copyright (C) 1992-2021 Dianne Skoll
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
DIR=`dirname $0`
|
DIR=`dirname $0`
|
||||||
cd $DIR
|
cd $DIR
|
||||||
if test $? != 0 ; then
|
if test $? != 0 ; then
|
||||||
|
echo ""
|
||||||
echo "Unable to cd $DIR" >&2
|
echo "Unable to cd $DIR" >&2
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test `id -u` = 0 ; then
|
||||||
|
echo ""
|
||||||
|
echo "*** Please do not run the test suite as root; it will fail."
|
||||||
|
echo ""
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -56,6 +65,14 @@ echo "" >> ../tests/test.out
|
|||||||
|
|
||||||
chmod 644 include_dir/04cantread.rem
|
chmod 644 include_dir/04cantread.rem
|
||||||
|
|
||||||
|
# Feb 29 bug
|
||||||
|
echo "Feb 29 Bug Test" >> ../tests/test.out
|
||||||
|
echo 'REM Sun 29 Feb MSG [$T]' | ../src/remind -dt - 1 feb 2021 >> ../tests/test.out 2>&1
|
||||||
|
|
||||||
|
# Day Weekday Year out-of-year bug
|
||||||
|
echo "Mon 31 Dec Bug Test" >> ../tests/test.out
|
||||||
|
echo 'REM Mon 31 2021 MSG [$T]' | ../src/remind -dt - 31 dec 2021 >> ../tests/test.out 2>&1
|
||||||
|
|
||||||
echo "Color Test" >> ../tests/test.out
|
echo "Color Test" >> ../tests/test.out
|
||||||
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||||
|
|
||||||
@@ -289,8 +306,24 @@ rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
|
|||||||
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
export LC_ALL=en_US.utf-8
|
# If we're already in a utf-8 locale, do
|
||||||
export LANG=en_US.utf-8
|
# nothing; otherwise, set LC_ALL
|
||||||
|
OK=0
|
||||||
|
if echo $LC_ALL | grep -i utf-8 > /dev/null 2>&1 ; then
|
||||||
|
OK=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$LC_ALL" ; then
|
||||||
|
if echo $LANG | grep -i utf-8 > /dev/null 2>&1 ; then
|
||||||
|
export LC_ALL="$LANG"
|
||||||
|
OK=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$OK" = 0 ; then
|
||||||
|
export LC_ALL=en_US.utf-8
|
||||||
|
fi
|
||||||
|
|
||||||
../src/remind -w128 -c ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out
|
../src/remind -w128 -c ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out
|
||||||
cmp -s ../tests/test.out ../tests/test.cmp
|
cmp -s ../tests/test.out ../tests/test.cmp
|
||||||
if [ "$?" = "0" ]; then
|
if [ "$?" = "0" ]; then
|
||||||
|
|||||||
1302
tests/test.cmp
1302
tests/test.cmp
File diff suppressed because it is too large
Load Diff
@@ -15,9 +15,40 @@ REM Wed UNTIL 15 Feb 1991 SATISFY [trigdate() > '1990-01-01'] MSG wookie
|
|||||||
# bad AT
|
# bad AT
|
||||||
REM AT 0:00 0:01 0:02 MSG foo
|
REM AT 0:00 0:01 0:02 MSG foo
|
||||||
|
|
||||||
|
# Includecmd
|
||||||
|
INCLUDECMD echo REM 16 Feb 1991 MSG Blork
|
||||||
|
INCLUDECMD echo REM 18 Feb 1991 MSG Blork
|
||||||
|
|
||||||
|
# Includecmd with continuation line
|
||||||
|
INCLUDECMD echo REM 18 Feb 1991 MSG This line is \
|
||||||
|
continued so there
|
||||||
|
|
||||||
|
# This should work
|
||||||
|
INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo MSG Yippee
|
||||||
|
|
||||||
|
# This should fail
|
||||||
|
INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo MSG Yippee
|
||||||
REM MSG Today is [hebday(today())] [hebmon(today())] [hebyear(today())]
|
REM MSG Today is [hebday(today())] [hebmon(today())] [hebyear(today())]
|
||||||
fset _h(x, y) trigger(hebdate(x,y))
|
fset _h(x, y) trigger(hebdate(x,y))
|
||||||
|
|
||||||
|
# Test case from Remind mailing list
|
||||||
|
set mltest "a b"
|
||||||
|
INCLUDECMD printf 'REM %s\n' [mltest]
|
||||||
|
|
||||||
|
# Disabling RUN in an !includecmd
|
||||||
|
INCLUDECMD !echo MSG foo
|
||||||
|
INCLUDECMD !echo MSG foo
|
||||||
|
INCLUDECMD !echo INCLUDECMD echo MSG foo
|
||||||
|
INCLUDECMD !echo INCLUDECMD echo MSG foo
|
||||||
|
INCLUDECMD !echo MSG foo
|
||||||
|
INCLUDECMD !echo MSG foo
|
||||||
|
|
||||||
|
# INCLUDECMD with RUN disabled
|
||||||
|
RUN OFF
|
||||||
|
INCLUDECMD echo MSG foo
|
||||||
|
RUN ON
|
||||||
|
INCLUDECMD echo MSG foo
|
||||||
|
|
||||||
[_h(1, "Tishrey")] MSG Rosh Hashana 1
|
[_h(1, "Tishrey")] MSG Rosh Hashana 1
|
||||||
[_h(2, "Tishrey")] MSG Rosh Hashana 2
|
[_h(2, "Tishrey")] MSG Rosh Hashana 2
|
||||||
[_h(3, "Tishrey")] MSG Tzom Gedalia
|
[_h(3, "Tishrey")] MSG Tzom Gedalia
|
||||||
@@ -533,6 +564,33 @@ set x coerce("DATETIME", "2020-05-05@12:45am")
|
|||||||
set x coerce("DATETIME", "2020-05-05@12:45")
|
set x coerce("DATETIME", "2020-05-05@12:45")
|
||||||
set x coerce("DATETIME", "2020-05-05@1:45pm")
|
set x coerce("DATETIME", "2020-05-05@1:45pm")
|
||||||
|
|
||||||
|
# Overflow - these tests only work on machines with 32-bit
|
||||||
|
# twos-complement signed integers. You may get test failures on
|
||||||
|
# machines with different architectures.
|
||||||
|
set a $IntMin - 1
|
||||||
|
set a $IntMin - $IntMax
|
||||||
|
set a $IntMax - $IntMin
|
||||||
|
set a $IntMax - (-1)
|
||||||
|
set a $IntMax + 1
|
||||||
|
set a $IntMax + $IntMax
|
||||||
|
set a $IntMin + (-1)
|
||||||
|
set a $IntMin + $IntMin
|
||||||
|
set a $IntMax * 2
|
||||||
|
set a $IntMax * $IntMax
|
||||||
|
set a $IntMax * $IntMin
|
||||||
|
set a $IntMin * 2
|
||||||
|
set a $IntMin * $IntMin
|
||||||
|
set a $IntMin * $IntMax
|
||||||
|
set a $IntMin / (-1)
|
||||||
|
set a $IntMin * (-1)
|
||||||
|
set a (-1) * $IntMin
|
||||||
|
set a abs($IntMin)
|
||||||
|
|
||||||
|
# Shellescape
|
||||||
|
set a shellescape(" !\"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")
|
||||||
|
|
||||||
|
msg [a]
|
||||||
|
|
||||||
# Don't want Remind to queue reminders
|
# Don't want Remind to queue reminders
|
||||||
EXIT
|
EXIT
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
echo "Unconfiguring Remind..."
|
echo "Unconfiguring Remind..."
|
||||||
echo rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h www/Makefile
|
echo rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h www/Makefile rem2html/Makefile
|
||||||
rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h www/Makefile
|
rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h www/Makefile rem2html/Makefile
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
# 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.
|
||||||
SCRIPTDIR = /var/www/cgi-bin
|
SCRIPTDIR = /usr/lib/cgi-bin
|
||||||
|
|
||||||
# Where the scripts live as seen by the web browser.
|
# Where the scripts live as seen by the web browser.
|
||||||
CGIDIR = /cgi-bin
|
CGIDIR = /cgi-bin
|
||||||
@@ -17,7 +17,7 @@ HTMLDIR = /var/www/remind
|
|||||||
# Where you stick images and CSS files, as seen by UNIX
|
# Where you stick images and CSS files, as seen by UNIX
|
||||||
IMAGEDIR = /var/www/remind/resources
|
IMAGEDIR = /var/www/remind/resources
|
||||||
|
|
||||||
# Where images are, as seen by web browers
|
# Where images and CSS fiels are, as seen by web browers
|
||||||
IMAGEBASE = /remind/resources
|
IMAGEBASE = /remind/resources
|
||||||
|
|
||||||
# Set by configure - don't touch.
|
# Set by configure - don't touch.
|
||||||
@@ -32,7 +32,7 @@ datarootdir=@datarootdir@
|
|||||||
# Where do Remind and Rem2PS executables live?
|
# Where do Remind and Rem2PS executables live?
|
||||||
REMIND = $(bindir)/remind
|
REMIND = $(bindir)/remind
|
||||||
REM2PS = $(bindir)/rem2ps
|
REM2PS = $(bindir)/rem2ps
|
||||||
|
REM2HTML = $(bindir)/rem2html
|
||||||
# If your Web server requires CGI programs to have a .cgi suffix, use
|
# If your Web server requires CGI programs to have a .cgi suffix, use
|
||||||
# the next line. Otherwise, comment it out
|
# the next line. Otherwise, comment it out
|
||||||
CGISUFFIX=.cgi
|
CGISUFFIX=.cgi
|
||||||
@@ -46,14 +46,8 @@ SEDSCRIPT = -e 's@%CGIDIR%@$(CGIDIR)@g' \
|
|||||||
-e 's@%REMIND%@$(REMIND)@g' \
|
-e 's@%REMIND%@$(REMIND)@g' \
|
||||||
-e 's@%IMAGEBASE%@$(IMAGEBASE)@g' \
|
-e 's@%IMAGEBASE%@$(IMAGEBASE)@g' \
|
||||||
-e 's@%REM2PS%@$(REM2PS)@g' \
|
-e 's@%REM2PS%@$(REM2PS)@g' \
|
||||||
|
-e 's@%REM2HTML%@$(REM2HTML)@g' \
|
||||||
-e 's@cal_dispatch@cal_dispatch$(CGISUFFIX)@g' \
|
-e 's@cal_dispatch@cal_dispatch$(CGISUFFIX)@g' \
|
||||||
-e 's@rem2html@rem2html$(CGISUFFIX)@g'
|
|
||||||
|
|
||||||
SEDSCRIPT2 = -e 's@%CGIDIR%@$(CGIDIR)@g' \
|
|
||||||
-e 's@%SCRIPTDIR%@$(SCRIPTDIR)@g' \
|
|
||||||
-e 's@%REMIND%@$(REMIND)@g' \
|
|
||||||
-e 's@%IMAGEBASE%@$(IMAGEBASE)@g' \
|
|
||||||
-e 's@%REM2PS%@$(REM2PS)@g'
|
|
||||||
|
|
||||||
all:
|
all:
|
||||||
@echo "Edit the Makefile; then type 'make install' to install"
|
@echo "Edit the Makefile; then type 'make install' to install"
|
||||||
@@ -72,7 +66,6 @@ install:
|
|||||||
cp blank.rem $(DESTDIR)$(SCRIPTDIR)/blank.rem
|
cp blank.rem $(DESTDIR)$(SCRIPTDIR)/blank.rem
|
||||||
sed $(SEDSCRIPT) < calendar.html-DIST > $(DESTDIR)$(HTMLDIR)/calendar.html
|
sed $(SEDSCRIPT) < calendar.html-DIST > $(DESTDIR)$(HTMLDIR)/calendar.html
|
||||||
sed $(SEDSCRIPT) < hebhtml > $(DESTDIR)$(SCRIPTDIR)/hebhtml
|
sed $(SEDSCRIPT) < hebhtml > $(DESTDIR)$(SCRIPTDIR)/hebhtml
|
||||||
sed $(SEDSCRIPT2) < rem2html > $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
|
|
||||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/sunrise.rem
|
chmod 644 $(DESTDIR)$(SCRIPTDIR)/sunrise.rem
|
||||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/moon.rem
|
chmod 644 $(DESTDIR)$(SCRIPTDIR)/moon.rem
|
||||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/hebdate.rem
|
chmod 644 $(DESTDIR)$(SCRIPTDIR)/hebdate.rem
|
||||||
@@ -80,20 +73,14 @@ install:
|
|||||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/blank.rem
|
chmod 644 $(DESTDIR)$(SCRIPTDIR)/blank.rem
|
||||||
chmod 644 $(DESTDIR)$(HTMLDIR)/calendar.html
|
chmod 644 $(DESTDIR)$(HTMLDIR)/calendar.html
|
||||||
chmod 755 $(DESTDIR)$(SCRIPTDIR)/cal_dispatch$(CGISUFFIX)
|
chmod 755 $(DESTDIR)$(SCRIPTDIR)/cal_dispatch$(CGISUFFIX)
|
||||||
chmod 755 $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
|
|
||||||
chmod 755 $(DESTDIR)$(SCRIPTDIR)/calps $(DESTDIR)$(SCRIPTDIR)/hebdate \
|
chmod 755 $(DESTDIR)$(SCRIPTDIR)/calps $(DESTDIR)$(SCRIPTDIR)/hebdate \
|
||||||
$(DESTDIR)$(SCRIPTDIR)/hebps $(DESTDIR)$(SCRIPTDIR)/moon \
|
$(DESTDIR)$(SCRIPTDIR)/hebps $(DESTDIR)$(SCRIPTDIR)/moon \
|
||||||
$(DESTDIR)$(SCRIPTDIR)/sunrise $(DESTDIR)$(SCRIPTDIR)/sunset \
|
$(DESTDIR)$(SCRIPTDIR)/sunrise $(DESTDIR)$(SCRIPTDIR)/sunset \
|
||||||
$(DESTDIR)$(SCRIPTDIR)/hebhtml \
|
$(DESTDIR)$(SCRIPTDIR)/hebhtml \
|
||||||
$(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
|
|
||||||
|
|
||||||
-mkdir -p $(DESTDIR)$(IMAGEDIR)
|
-mkdir -p $(DESTDIR)$(IMAGEDIR)
|
||||||
cp firstquarter.png fullmoon.png lastquarter.png newmoon.png rem-default.css $(DESTDIR)$(IMAGEDIR)
|
cp rem-default.css *.png $(DESTDIR)$(IMAGEDIR)
|
||||||
chmod 644 $(DESTDIR)$(IMAGEDIR)/firstquarter.png \
|
chmod 644 $(DESTDIR)$(IMAGEDIR)/rem-default.css $(DESTDIR)$(IMAGEDIR)/*.png
|
||||||
$(DESTDIR)$(IMAGEDIR)/fullmoon.png \
|
|
||||||
$(DESTDIR)$(IMAGEDIR)/lastquarter.png \
|
|
||||||
$(DESTDIR)$(IMAGEDIR)/newmoon.png \
|
|
||||||
$(DESTDIR)$(IMAGEDIR)/rem-default.css
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ server:
|
|||||||
1) Edit the Makefile in this directory. See the comments in the Makefile
|
1) Edit the Makefile in this directory. See the comments in the Makefile
|
||||||
for details.
|
for details.
|
||||||
|
|
||||||
2) Edit the first line of "rem2html" to reflect the location of
|
2) Make sure "rem2html" is installed.
|
||||||
Perl on your system. (Oh yeah, you need Perl for the
|
|
||||||
HTML Hebrew calendar...)
|
|
||||||
|
|
||||||
3) Type "make install"
|
3) Type "make install"
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
REM2HTML
|
|
||||||
--------
|
|
||||||
|
|
||||||
Rem2HTML is a Perl script that transforms the output of `remind -p
|
|
||||||
...' to HTML. Type `perl rem2html --help' for usage information.
|
|
||||||
|
|
||||||
Typical usage: remind -p ~/.reminders | rem2html > file.html
|
|
||||||
|
|
||||||
You may have to edit the "#!/usr/bin/perl" line to reflect the
|
|
||||||
location of your Perl interpreter.
|
|
||||||
|
|
||||||
--
|
|
||||||
Dianne Skoll
|
|
||||||
@@ -18,7 +18,7 @@ set lastyear iif(lastmon==12, thisyear-1, thisyear)
|
|||||||
set nextmon mon(nextmon)
|
set nextmon mon(nextmon)
|
||||||
set lastmon mon(lastmon)
|
set lastmon mon(lastmon)
|
||||||
BANNER %
|
BANNER %
|
||||||
REM RUN $REMIND -iHTML=1 -p $DIR/hebdate.rem %m %y | $DIR/rem2html --forwurl "cal_dispatch?hebhtml+[nextmon]+[nextyear]" --backurl "cal_dispatch?hebhtml+[lastmon]+[lastyear]"
|
REM RUN $REMIND -iHTML=1 -p $DIR/hebdate.rem %m %y | %REM2HTML% --forwurl "cal_dispatch?hebhtml+[nextmon]+[nextyear]" --backurl "cal_dispatch?hebhtml+[lastmon]+[lastyear]" --imgbase "%IMAGEBASE%" --stylesheet rem-default.css --pngs
|
||||||
EOR
|
EOR
|
||||||
|
|
||||||
else
|
else
|
||||||
@@ -33,7 +33,7 @@ set lastyear iif(lastmon==12, thisyear-1, thisyear)
|
|||||||
set nextmon mon(nextmon)
|
set nextmon mon(nextmon)
|
||||||
set lastmon mon(lastmon)
|
set lastmon mon(lastmon)
|
||||||
BANNER %
|
BANNER %
|
||||||
REM RUN $REMIND -iHTML=1 -p $DIR/hebdate.rem %m %y | $DIR/rem2html --forwurl "cal_dispatch?hebhtml+[nextmon]+[nextyear]" --backurl "cal_dispatch?hebhtml+[lastmon]+[lastyear]"
|
REM RUN $REMIND -iHTML=1 -p $DIR/hebdate.rem %m %y | %REM2HTML% --forwurl "cal_dispatch?hebhtml+[nextmon]+[nextyear]" --backurl "cal_dispatch?hebhtml+[lastmon]+[lastyear]" --imgbase "%IMAGEBASE%" --stylesheet rem-default.css --pngs
|
||||||
EOR
|
EOR
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ div.rem-daynumber {
|
|||||||
font-size: 14pt;
|
font-size: 14pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.rem-entry {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
div.rem-moon {
|
div.rem-moon {
|
||||||
float: left;
|
float: left;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@@ -66,4 +70,4 @@ td.rem-sc-empty-cell, td.rem-sc-cell {
|
|||||||
|
|
||||||
caption.rem-sc-caption {
|
caption.rem-sc-caption {
|
||||||
font-size: 12pt;
|
font-size: 12pt;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user