mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 14:28:40 +02:00
Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de4ebb8be6 | ||
|
|
11e2ce5093 | ||
|
|
2c560e6f2b | ||
|
|
643f394e6a | ||
|
|
6d047c2856 | ||
|
|
be86746685 | ||
|
|
da429b9629 | ||
|
|
b21a206c26 | ||
|
|
85bde8ba3a | ||
|
|
f84e658e6b | ||
|
|
8f0eba8bcd | ||
|
|
2faaaf78a8 | ||
|
|
7f659dace2 | ||
|
|
54cdd566c7 | ||
|
|
e212df87f9 | ||
|
|
4fb4db15e8 | ||
|
|
9a15a25a7b | ||
|
|
c02cfb9b17 | ||
|
|
3e726f21f7 | ||
|
|
21d4faa26f | ||
|
|
1d13d0ee07 | ||
|
|
329d13e480 | ||
|
|
2161c09b1d | ||
|
|
3f2e396c3c | ||
|
|
412e242109 | ||
|
|
e827516b72 | ||
|
|
7f953e98d7 | ||
|
|
821d3fe783 | ||
|
|
fdb4b302ac | ||
|
|
760d5d4a09 | ||
|
|
d561f98c42 | ||
|
|
ea74f276dc | ||
|
|
42cf82a5d5 | ||
|
|
825a6700da | ||
|
|
2f27645dac | ||
|
|
1e5b44d063 | ||
|
|
099ad9945d | ||
|
|
540ce3d946 | ||
|
|
ac2efcc993 | ||
|
|
b4bb1d9e37 | ||
|
|
9ec8b30934 | ||
|
|
fb38e5b35b | ||
|
|
5fa10e9d84 | ||
|
|
3bc1b5bd46 | ||
|
|
b266b399ba | ||
|
|
0e827a457d | ||
|
|
d05d85b243 | ||
|
|
a1faa8d804 | ||
|
|
70adbf90c2 | ||
|
|
501c04f4b6 | ||
|
|
d294e62be1 | ||
|
|
31f90b6c53 | ||
|
|
184d29c592 | ||
|
|
2d798bc4ec | ||
|
|
bd9a3761a6 | ||
|
|
b1063b0a9e | ||
|
|
cb2fffab92 | ||
|
|
55cca49428 | ||
|
|
5a0ab9ed8a | ||
|
|
1f2cfdfd84 |
@@ -3,7 +3,7 @@ THE REMIND COPYRIGHT
|
||||
1. REMIND refers to the entire set of files and documentation in the
|
||||
REMIND package.
|
||||
|
||||
2. REMIND is Copyright 1999-2008 Roaring Penguin Software Inc.,
|
||||
2. REMIND is Copyright 1999-2010 Roaring Penguin Software Inc.,
|
||||
except where noted in individual files.
|
||||
|
||||
3. DISTRIBUTION AND USE
|
||||
|
||||
2
Makefile
2
Makefile
@@ -25,7 +25,7 @@ clean:
|
||||
cd src; $(MAKE) clean
|
||||
|
||||
test:
|
||||
cd src && $(MAKE) test
|
||||
@cd src && $(MAKE) test
|
||||
|
||||
distclean: clean
|
||||
rm -f config.cache config.log config.status src/Makefile src/config.h tests/test.out www/Makefile
|
||||
|
||||
18
configure
vendored
18
configure
vendored
@@ -1702,8 +1702,8 @@ EOF
|
||||
for i in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ; do
|
||||
sleep 1
|
||||
done
|
||||
trap INT
|
||||
trap TERM
|
||||
trap - INT
|
||||
trap - TERM
|
||||
fi
|
||||
|
||||
if uname -s | grep -i -q 'cygwin' ; then
|
||||
@@ -1717,8 +1717,8 @@ EOF
|
||||
for i in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ; do
|
||||
sleep 1
|
||||
done
|
||||
trap INT
|
||||
trap TERM
|
||||
trap - INT
|
||||
trap - TERM
|
||||
fi
|
||||
|
||||
ac_ext=c
|
||||
@@ -4721,7 +4721,9 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
for ac_header in sys/file.h glob.h
|
||||
|
||||
|
||||
for ac_header in sys/file.h glob.h wctype.h locale.h
|
||||
do
|
||||
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||
@@ -5221,7 +5223,9 @@ fi
|
||||
|
||||
|
||||
|
||||
for ac_func in setenv unsetenv glob
|
||||
|
||||
|
||||
for ac_func in setenv unsetenv glob mbstowcs setlocale
|
||||
do
|
||||
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
{ echo "$as_me:$LINENO: checking for $ac_func" >&5
|
||||
@@ -5314,7 +5318,7 @@ _ACEOF
|
||||
fi
|
||||
done
|
||||
|
||||
VERSION=03.01.08
|
||||
VERSION=03.01.10
|
||||
|
||||
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h"
|
||||
|
||||
|
||||
14
configure.in
14
configure.in
@@ -25,8 +25,8 @@ EOF
|
||||
for i in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ; do
|
||||
sleep 1
|
||||
done
|
||||
trap INT
|
||||
trap TERM
|
||||
trap - INT
|
||||
trap - TERM
|
||||
fi
|
||||
|
||||
if uname -s | grep -i -q 'cygwin' ; then
|
||||
@@ -40,8 +40,8 @@ EOF
|
||||
for i in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ; do
|
||||
sleep 1
|
||||
done
|
||||
trap INT
|
||||
trap TERM
|
||||
trap - INT
|
||||
trap - TERM
|
||||
fi
|
||||
|
||||
dnl Checks for programs.
|
||||
@@ -61,7 +61,7 @@ AC_CHECK_SIZEOF(unsigned int)
|
||||
AC_CHECK_SIZEOF(unsigned long)
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_CHECK_HEADERS(sys/file.h glob.h)
|
||||
AC_CHECK_HEADERS(sys/file.h glob.h wctype.h locale.h)
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_STRUCT_TM
|
||||
@@ -74,7 +74,7 @@ if test "$GCC" = yes; then
|
||||
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes"
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(setenv unsetenv glob)
|
||||
VERSION=03.01.08
|
||||
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale)
|
||||
VERSION=03.01.10
|
||||
AC_SUBST(VERSION)
|
||||
AC_OUTPUT(src/Makefile www/Makefile src/version.h)
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
(sort
|
||||
(list "RUN" "REM" "ONCE" "SATISFY" "BEFORE" "UNSET" "OMIT"
|
||||
"OMIT" "DATE" "SKIP" "ONCE" "AFTER" "WARN" "PRIORITY" "AT" "SCHED" "IF" "ELSE" "ENDIF"
|
||||
"WARN" "UNTIL" "SCANFROM" "DURATION" "TAG" "MSG" "MSF" "CAL" "SPECIAL" "IFTRIG"
|
||||
"WARN" "UNTIL" "THROUGH" "SCANFROM" "DURATION" "TAG" "MSG" "MSF" "CAL" "SPECIAL" "IFTRIG"
|
||||
"PS" "PSFILE" "BANNER" "INCLUDE" "PUSH-OMIT-CONTEXT" "DEBUG" "DUMPVARS"
|
||||
"CLEAR-OMIT-CONTEXT" "POP-OMIT-CONTEXT" "SET" "ERRMSG" "FSET"
|
||||
"EXIT" "FLUSH" "PRESERVE" "MOON" "COLOR")
|
||||
|
||||
@@ -1,5 +1,45 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* Version 3.1 Patch 10 - 2010-11-01
|
||||
|
||||
- NOTE: This is the 20th anniversary of Remind's first public release.
|
||||
|
||||
- ENHANCEMENT: Add the THROUGH keyword. You can omit blocks of dates with:
|
||||
|
||||
OMIT start THROUGH end
|
||||
|
||||
and the syntax REM start THROUGH end is equivalent to REM start *1 UNTIL end
|
||||
|
||||
- ENHANCEMENT: Add support for multibyte characters (eg, UTF-8) in calendar
|
||||
output. Note that UTF-8 strings are still not supported in PostScript
|
||||
output.
|
||||
|
||||
- ENHANCEMENT: Add support for UTF-8 line-drawing characters in calendar
|
||||
output.
|
||||
|
||||
- ENHANCEMENT: You can have multiple TAG clauses in a REM statement.
|
||||
|
||||
- BUG FIX: Avoid spawning long-running background processes in "make test".
|
||||
|
||||
- BUG FIX: Don't declare variables in the middle of statements (old C
|
||||
compilers choke.)
|
||||
|
||||
* Version 3.1 Patch 9 - 2010-06-20
|
||||
|
||||
- MAJOR ENHANCEMENT: New "purge mode" to delete expired reminders. See
|
||||
the PURGE MODE section of the remind man page.
|
||||
|
||||
- ENHANCEMENT: Support DURATION in TkRemind. Thanks to Marek Marczykowski.
|
||||
|
||||
- BUG FIX: Don't change the order of PS and PSFILE reminders. Bug found
|
||||
by John McGowan.
|
||||
|
||||
- BUG FIX: "REM 1990-01-01 SATISFY 1" would yield a spurious parse error
|
||||
in earlier versions of Remind.
|
||||
|
||||
- BUG FIX: Yom HaShoah is moved to Thursday if it would normally fall on
|
||||
a Friday. Thanks to Jonathan Kamens for pointing this out.
|
||||
|
||||
* Version 3.1 Patch 8 - 2010-03-09
|
||||
|
||||
- ENHANCEMENT: Include some useful scripts in contrib/
|
||||
|
||||
@@ -508,7 +508,13 @@ IF !InIsrael && !Reform
|
||||
[_h(22, "Nisan")] MSG %"Pesach 8%"
|
||||
ENDIF
|
||||
|
||||
[_PastSun(27, "Nisan")] ++4 MSG %"Yom HaShoah%" is %b.
|
||||
REM [_PastSun(27, "Nisan")] SATISFY 1
|
||||
|
||||
IF $Tw == 5
|
||||
REM [_PastSun(26, "Nisan")] ++4 MSG %"Yom HaShoah%" is %b.
|
||||
ELSE
|
||||
REM [_PastSun(27, "Nisan")] ++4 MSG %"Yom HaShoah%" is %b.
|
||||
ENDIF
|
||||
|
||||
# If 4 Iyar is a Friday, then Yom Hazikaron is
|
||||
# the Wednesday before and Yom Ha'atzmaut is on
|
||||
|
||||
@@ -1,53 +1,79 @@
|
||||
" Vim syntax file
|
||||
" Language: Remind
|
||||
" Maintainer: Davide Alberani <alberanid@bigfoot.com>
|
||||
" Last change: 03 Dec 1999
|
||||
" Version: 0.1
|
||||
" URL: http://members.xoom.com/alberanid/vim/syntax/remind.vim
|
||||
" Maintainer: Davide Alberani <alberanid@libero.it>
|
||||
" Last Change: 18 Sep 2009
|
||||
" Version: 0.5
|
||||
" URL: http://erlug.linux.it/~da/vim/syntax/remind.vim
|
||||
"
|
||||
" remind is a sophisticated reminder service
|
||||
" you can download remind from ftp://ftp.doe.carleton.ca/pub/remind-3.0/
|
||||
" you can download remind from:
|
||||
" http://www.roaringpenguin.com/penguin/open_source_remind.php
|
||||
|
||||
" clear any unwanted syntax defs
|
||||
syn clear
|
||||
if version < 600
|
||||
syntax clear
|
||||
elseif exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
" shut case off
|
||||
" shut case off.
|
||||
syn case ignore
|
||||
|
||||
syn keyword remindCommands REM OMIT SET FSET UNSET
|
||||
syn keyword remindExpiry UNTIL SCANFROM SCAN WARN SCHED
|
||||
syn keyword remindExpiry UNTIL FROM SCANFROM SCAN WARN SCHED
|
||||
syn keyword remindTag PRIORITY TAG
|
||||
syn keyword remindTimed AT DURATION
|
||||
syn keyword remindMove ONCE SKIP BEFORE AFTER
|
||||
syn keyword remindSpecial INCLUDE INC BANNER PUSH-OMIT-CONTEXT PUSH CLEAR-OMIT-CONTEXT CLEAR POP-OMIT-CONTEXT POP
|
||||
syn keyword remindSpecial INCLUDE INC BANNER PUSH-OMIT-CONTEXT PUSH CLEAR-OMIT-CONTEXT CLEAR POP-OMIT-CONTEXT POP COLOR
|
||||
syn keyword remindRun MSG MSF RUN CAL SATISFY SPECIAL PS PSFILE SHADE MOON
|
||||
syn keyword remindConditional IF ELSE ENDIF IFTRIG
|
||||
syn keyword remindDebug DEBUG DUMPVARS DUMP ERRMSG FLUSH PRESERVE
|
||||
syn match remindComment "#.*$"
|
||||
syn region remindString start=+'+ end=+'+ skip=+\\\\\|\\'+ oneline
|
||||
syn region remindString start=+"+ end=+"+ skip=+\\\\\|\\"+ oneline
|
||||
syn keyword remindDebug DEBUG DUMPVARS DUMP ERRMSG FLUSH PRESERVE
|
||||
syn match remindVar "\$[_a-zA-Z][_a-zA-Z0-9]*"
|
||||
syn match remindSubst "%[^ ]"
|
||||
syn match remindAdvanceNumber "\(\*\|+\|-\|++\|--\)[0-9]\+"
|
||||
" XXX: use different separators for dates and times?
|
||||
syn match remindDateSeparators "[/:@\.-]" contained
|
||||
syn match remindTimes "[0-9]\{1,2}[:\.][0-9]\{1,2}" contains=remindDateSeparators
|
||||
" XXX: why not match only valid dates? Ok, checking for 'Feb the 30' would
|
||||
" be impossible, but at least check for valid months and times.
|
||||
syn match remindDates "'[0-9]\{4}[/-][0-9]\{1,2}[/-][0-9]\{1,2}\(@[0-9]\{1,2}[:\.][0-9]\{1,2}\)\?'" contains=remindDateSeparators
|
||||
" This will match trailing whitespaces that seem to break rem2ps.
|
||||
" Courtesy of Michael Dunn.
|
||||
syn match remindWarning display excludenl "\S\s\+$"ms=s+1
|
||||
|
||||
if !exists("did_remind_syntax_inits")
|
||||
let did_remind_syntax_inits = 1
|
||||
hi link remindCommands Function
|
||||
hi link remindExpiry Repeat
|
||||
hi link remindTag Label
|
||||
hi link remindTimed Statement
|
||||
hi link remindMove Statement
|
||||
hi link remindSpecial Include
|
||||
hi link remindRun Function
|
||||
hi link remindConditional Conditional
|
||||
hi link remindComment Comment
|
||||
hi link remindString String
|
||||
hi link remindDebug Debug
|
||||
hi link remindVar Identifier
|
||||
hi link remindSubst Constant
|
||||
hi link remindAdvanceNumber Number
|
||||
|
||||
if version >= 508 || !exists("did_remind_syn_inits")
|
||||
if version < 508
|
||||
let did_remind_syn_inits = 1
|
||||
command -nargs=+ HiLink hi link <args>
|
||||
else
|
||||
command -nargs=+ HiLink hi def link <args>
|
||||
endif
|
||||
|
||||
HiLink remindCommands Function
|
||||
HiLink remindExpiry Repeat
|
||||
HiLink remindTag Label
|
||||
HiLink remindTimed Statement
|
||||
HiLink remindMove Statement
|
||||
HiLink remindSpecial Include
|
||||
HiLink remindRun Function
|
||||
HiLink remindConditional Conditional
|
||||
HiLink remindComment Comment
|
||||
HiLink remindTimes String
|
||||
HiLink remindString String
|
||||
HiLink remindDebug Debug
|
||||
HiLink remindVar Identifier
|
||||
HiLink remindSubst Constant
|
||||
HiLink remindAdvanceNumber Number
|
||||
HiLink remindDateSeparators Comment
|
||||
HiLink remindDates String
|
||||
HiLink remindWarning Error
|
||||
|
||||
delcommand HiLink
|
||||
endif
|
||||
|
||||
let b:current_syntax = "remind"
|
||||
|
||||
"EOF vim: ts=8 noet tw=100 sw=8 sts=0
|
||||
" vim: ts=8 sw=2
|
||||
|
||||
@@ -362,7 +362,10 @@ Other back-ends may understand other specials. A back end should
|
||||
\fIsilently ignore\fR a reminder with a special it doesn't understand.
|
||||
.PP
|
||||
\fItag\fR is whatever tag the user provided with the \fBTAG\fR clause,
|
||||
or "*" if no tag was provided.
|
||||
or "*" if no tag was provided. If there is more than one \fBTAG\fR clause,
|
||||
the tags appear in a comma-separated list. For example, the command
|
||||
\fBREM TAG foo TAG bar TAG quux\fR would result in \fBfoo,bar,quux\fR
|
||||
in the \fItag\fR field.
|
||||
.PP
|
||||
\fIdur\fR is the \fBDURATION\fR value in minutes, or "*" if no duration
|
||||
was provided.
|
||||
|
||||
165
man/remind.1
165
man/remind.1
@@ -29,6 +29,10 @@ 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
|
||||
date by piping the output through \fBsort(1)\fR.
|
||||
.TP
|
||||
.B \-j\fR[\fIn\fR]
|
||||
Runs \fBRemind\fR in "purge" mode to get rid of expired reminders.
|
||||
See the section PURGE MODE for details.
|
||||
.TP
|
||||
.B \-r
|
||||
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.
|
||||
@@ -57,6 +61,11 @@ causes \fBRemind\fR to use VT100 line-drawing characters to draw
|
||||
the calendar. The characters are hard-coded and will only work
|
||||
on terminals that emulate the VT00 line-drawing character set.
|
||||
.TP
|
||||
.B 'u'
|
||||
is similar to 'l', but causes \fBRemind\fR to use UNICODE line-drawing
|
||||
characters to draw the calendar. The characters are hard-coded and will
|
||||
only work on terminals that are set to UTF-8 character encoding.
|
||||
.TP
|
||||
.B 'c'
|
||||
causes \fBRemind\fR to use VT100 escape sequences to approximate
|
||||
SPECIAL COLOR reminders. The approximation is (of necessity) very
|
||||
@@ -326,6 +335,16 @@ wish to pass a \fBRemind\fR script through the C pre-processor, which
|
||||
interprets the '#' character as the start of a pre-processing
|
||||
directive.
|
||||
.PP
|
||||
Note that \fBRemind\fR processes line continuations before anything else.
|
||||
For example:
|
||||
.PP
|
||||
.nf
|
||||
# This is a comment \\
|
||||
This line is part of the comment because of line continuation \\
|
||||
and so on.
|
||||
REM MSG This line is not ignored (no \\ above)
|
||||
.fi
|
||||
.PP
|
||||
\fBRemind\fR is not case sensitive; you can generally use any mixture of upper-
|
||||
or lower-case for commands, parameters, invocation options, etc.
|
||||
.SH THE REM COMMAND
|
||||
@@ -346,7 +365,7 @@ Its syntax is:
|
||||
[\fBAT\fR \fItime\fR [\fItdelta\fR] [\fItrepeat\fR]]
|
||||
[\fBSCHED\fR \fIsched_function\fR]
|
||||
[\fBWARN\fR \fIwarn_function\fR]
|
||||
[\fBUNTIL\fR \fIexpiry_date\fR]
|
||||
[\fBUNTIL\fR \fIexpiry_date\fR | \fBTHROUGH\fR \fIlast_date\fR]
|
||||
[\fBSCANFROM\fR \fIscan_date\fR | \fBFROM\fR \fIstart_date\fR]
|
||||
[\fBDURATION\fR \fIduration\fR]
|
||||
[\fBTAG\fR \fItag\fR]
|
||||
@@ -782,6 +801,15 @@ of your jury duty, as well as 2 days ahead of time:
|
||||
Note that the \fIrepeat\fR of *1 is necessary; without it, the reminder
|
||||
would be issued only on 30 November (and the two days preceding.)
|
||||
.PP
|
||||
As a special case, you can use the \fBTHROUGH\fR keyword instead of
|
||||
*1 and \fBUNTIL\fR. The following two \fBREM\fR commands are equivalent:
|
||||
.PP
|
||||
.nf
|
||||
REM 1992-11-30 *1 +2 UNTIL 1992-12-04 MSG Jury duty
|
||||
|
||||
REM 1992-11-30 +2 THROUGH 1992-12-04 MSG Jury duty
|
||||
.fi
|
||||
.PP
|
||||
.B THE ONCE KEYWORD
|
||||
.PP
|
||||
Sometimes, it is necessary to ensure that reminders are run only once
|
||||
@@ -985,11 +1013,11 @@ expressions and user-defined functions are explained. See the subsection
|
||||
The \fBTAG\fR keyword lets you "tag" certain reminders. This facility
|
||||
is used by certain back-ends or systems built around \fBRemind\fR,
|
||||
such as \fBTkRemind\fR. These back-ends have specific rules about
|
||||
tags; you should \fInot\fR use the \fBTAG\fR keyword yourself, or
|
||||
your script will interact badly with back-ends.
|
||||
tags; see their documentation for details.
|
||||
.PP
|
||||
The \fBTAG\fR keyword is followed by a tag consisting of up to
|
||||
48 characters.
|
||||
48 characters. You can have as many TAG clauses as you like in
|
||||
a given REM statement.
|
||||
.PP
|
||||
If you supply the \fB\-y\fR option to \fBRemind\fR, then any
|
||||
reminder that lacks a \fBTAG\fR will have one synthesized. The
|
||||
@@ -1285,6 +1313,10 @@ In addition to being a keyword in the \fBREM\fR command,
|
||||
.PP
|
||||
.RS
|
||||
\fBOMIT\fR \fIday\fR \fImonth\fR [\fIyear\fR]
|
||||
.PP
|
||||
or:
|
||||
.PP
|
||||
\fBOMIT\fR \fIday1\fR \fImonth1\fR \fIyear1\fR \fBTHROUGH\fR \fIday2\fR \fImonth2\fR \fIyear2\fR
|
||||
.RE
|
||||
.PP
|
||||
The \fBOMIT\fR command is used to "globally" omit certain days
|
||||
@@ -1312,7 +1344,7 @@ the following are equivalent:
|
||||
.fi
|
||||
.PP
|
||||
For convenience, you can use a \fIdelta\fR and \fBMSG\fR or \fBRUN\fR
|
||||
keyword in the \fBOMIT\fR command. The following sequences are exactly
|
||||
keyword in the \fBOMIT\fR command. The following sequences are
|
||||
equivalent:
|
||||
.PP
|
||||
.nf
|
||||
@@ -1324,6 +1356,36 @@ equivalent:
|
||||
OMIT 1 Jan +4 MSG New year's day is %b!
|
||||
.fi
|
||||
.PP
|
||||
The \fBTHROUGH\fR keyword lets you conveniently OMIT a range of days.
|
||||
The starting and ending points must be fully-specified (ie, they must
|
||||
include day, month and year.). For example, the following sequences
|
||||
are equivalent:
|
||||
.PP
|
||||
.nf
|
||||
OMIT 3 Jan 2011
|
||||
OMIT 4 Jan 2011
|
||||
OMIT 5 Jan 2011
|
||||
|
||||
and
|
||||
|
||||
OMIT 3 Jan 2011 THROUGH 5 Jan 2011
|
||||
.fi
|
||||
.PP
|
||||
You can make a THROUGH \fBOMIT\fR do double-duty as a \fBREM\fR command:
|
||||
.PP
|
||||
.nf
|
||||
OMIT 6 Sep 2010 THROUGH 10 Sep 2010 MSG Vacation
|
||||
.fi
|
||||
|
||||
.PP
|
||||
You can debug your global OMITs with the following command:
|
||||
.PP
|
||||
.nf
|
||||
OMIT DUMP
|
||||
.fi
|
||||
.PP
|
||||
The OMIT DUMP command prints the current global omits to standard output.
|
||||
.PP
|
||||
.B THE BEFORE, AFTER AND SKIP KEYWORDS
|
||||
.PP
|
||||
Normally, days that are omitted, whether by a global \fBOMIT\fR
|
||||
@@ -2148,6 +2210,10 @@ actual date and time, or may be the date and time supplied on the command line.
|
||||
The \fBdate()\fR function returns a \fBDATE\fR object with the year,
|
||||
month and day components specified by \fIy\fR, \fIm\fR and \fId\fR.
|
||||
.TP
|
||||
.B datepart(dq_datetime)
|
||||
Returns a \fBDATE\fR object representing the date portion of
|
||||
\fIdatetime\fR.
|
||||
.TP
|
||||
.B datetime(args)
|
||||
The \fBdatetime()\fR function can take anywhere from two to five arguments.
|
||||
It always returns a DATETIME generated from its arguments.
|
||||
@@ -2295,6 +2361,18 @@ environment variable is not defined. Note that the names of environment
|
||||
variables are generally case-sensitive; thus, getenv("HOME") is not
|
||||
the same as getenv("home").
|
||||
.TP
|
||||
.B hebdate(i_day, s_hebmon [,idq_yrstart [,i_jahr [,i_aflag]]])
|
||||
Support for Hebrew dates - see the section "The Hebrew Calendar"
|
||||
.TP
|
||||
.B hebday(dq_date)
|
||||
Support for Hebrew dates - see the section "The Hebrew Calendar"
|
||||
.TP
|
||||
.B hebmon(dq_date)
|
||||
Support for Hebrew dates - see the section "The Hebrew Calendar"
|
||||
.TP
|
||||
.B hebyear(dq_date)
|
||||
Support for Hebrew dates - see the section "The Hebrew Calendar"
|
||||
.TP
|
||||
.B hour(tq_time)
|
||||
Returns the hour component of \fItime\fR.
|
||||
.TP
|
||||
@@ -2338,18 +2416,6 @@ context. Returns 0 otherwise. (If a datetime is supplied, only the
|
||||
date part is used.) Note that any local \fBOMIT\fR or \fBOMITFUNC\fR
|
||||
clauses are \fInot\fR taken into account by this function.
|
||||
.TP
|
||||
.B hebdate(i_day, s_hebmon [,idq_yrstart [,i_jahr [,i_aflag]]])
|
||||
Support for Hebrew dates - see the section "The Hebrew Calendar"
|
||||
.TP
|
||||
.B hebday(dq_date)
|
||||
Support for Hebrew dates - see the section "The Hebrew Calendar"
|
||||
.TP
|
||||
.B hebmon(dq_date)
|
||||
Support for Hebrew dates - see the section "The Hebrew Calendar"
|
||||
.TP
|
||||
.B hebyear(dq_date)
|
||||
Support for Hebrew dates - see the section "The Hebrew Calendar"
|
||||
.TP
|
||||
.B language()
|
||||
Returns a \fBSTRING\fR naming the language supported by \fBRemind\fR.
|
||||
(See "Foreign Language Support.") By default, \fBRemind\fR is compiled
|
||||
@@ -2680,6 +2746,10 @@ than 60 degrees. The functions are available starting from version
|
||||
Creates a \fBTIME\fR with the hour and minute components specified by
|
||||
\fIhr\fR and \fImin\fR.
|
||||
.TP
|
||||
.B timepart(tq_datetime)
|
||||
Returns a \fBTIME\fR object representing the time portion of
|
||||
\fIdatetime\fR.
|
||||
.TP
|
||||
.B today()
|
||||
Returns \fBRemind\fR's notion of "today." This may be the actual system
|
||||
date, or a date supplied on the command line, or the date of the
|
||||
@@ -3626,7 +3696,68 @@ so to run in the daemon mode in the background, use:
|
||||
.PP
|
||||
If you use \fBsh\fR or \fBbash\fR, you may have to use the "nohup" command
|
||||
to ensure that the daemon is not killed when you log out.
|
||||
|
||||
.PP
|
||||
.SH PURGE MODE
|
||||
.PP
|
||||
|
||||
If you supply the \fB\-j\fR command-line option, \fBRemind\fR runs
|
||||
in \fIpurge mode\fR. In this mode, it tries to purge expired reminders
|
||||
from your reminder files.
|
||||
.PP
|
||||
In purge mode, \fBRemind\fR reads your reminder file and creates a new
|
||||
file by appending ".purged" to the original file name. Note that
|
||||
\fBRemind\fR \fInever\fR edits your original file; it always creates
|
||||
a new .purged file.
|
||||
.PP
|
||||
If you invoke \fBRemind\fR against a directory instead of a file, then
|
||||
a .purged file is created for each *.rem file in the directory.
|
||||
.PP
|
||||
Normally, \fBRemind\fR does not create .purged files for INCLUDed files.
|
||||
However, if you supply a numeric argument after \fB\-j\fR, then \fBRemind\fR
|
||||
will create .purged files for the specified level of INCLUDE. For example,
|
||||
if you invoke \fBRemind\fR with the argument \fB\-j2\fR, then .purged
|
||||
files will be created for the file (or directory) specified on the command
|
||||
line, any files included by them, and any files included by those files.
|
||||
However, .purged files will not be created for third-or-higher level
|
||||
INCLUDE files.
|
||||
.PP
|
||||
Determining which reminders have expired is extremely tricky. \fBRemind\fR
|
||||
does its best, but you should always compare the .purged file to the
|
||||
original file and hand-merge the changes back in.
|
||||
.PP
|
||||
Remind annotates the .purged file as follows:
|
||||
.PP
|
||||
An expired reminder is prefixed with: #!P: Expired:
|
||||
.PP
|
||||
In situations where \fBRemind\fR cannot reliably determine that
|
||||
something was expired, you may see the following comments inserted
|
||||
before the problematic line:
|
||||
.PP
|
||||
.nf
|
||||
#!P: Cannot purge SATISFY-type reminders
|
||||
|
||||
#!P: The next IF evaluated false...
|
||||
#!P: REM statements in IF block not checked for purging.
|
||||
|
||||
#!P: The previous IF evaluated true.
|
||||
#!P: REM statements in ELSE block not checked for purging
|
||||
|
||||
#!P: The next IFTRIG did not trigger.
|
||||
#!P: REM statements in IFTRIG block not checked for purging.
|
||||
|
||||
#!P: Next line has expired, but contains expression... please verify
|
||||
|
||||
#!P: Next line may have expired, but contains non-constant expression
|
||||
|
||||
#!P! Could not parse next line: Some-Error-Message-Here
|
||||
.fi
|
||||
.PP
|
||||
\fBRemind\fR always annotates .purged files with lines beginning with
|
||||
"#!P". If such lines are encountered in the \fIoriginal\fR file,
|
||||
they are not copied to the .purged file.
|
||||
.PP
|
||||
|
||||
.SH SORTING REMINDERS
|
||||
.PP
|
||||
|
||||
|
||||
@@ -289,7 +289,9 @@ file to store additional state. You can certainly mix
|
||||
if you are aware of the following rules and limitations:
|
||||
.TP
|
||||
o
|
||||
Do not use the \fBTAG\fR keyword in hand-crafted reminders.
|
||||
\fBTkRemind\fR uses \fBTAG\fRs of the form \fBTKTAG\fR\fInnn\fR
|
||||
where \fInnn\fR is a number. You should not use such \fBTAG\fRs
|
||||
in hand-crafted reminders.
|
||||
.TP
|
||||
o
|
||||
Do not edit lines starting with "# TKTAGnnn", "# TKEND", or any
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-1998 David F. Skoll
|
||||
# Copyright (C) 1999-2009 Roaring Penguin Software Inc.
|
||||
# Copyright (C) 1999-2010 Roaring Penguin Software Inc.
|
||||
#
|
||||
#--------------------------------------------------------------
|
||||
|
||||
@@ -392,11 +392,7 @@ proc ConfigureCalFrame { w firstDay numDays } {
|
||||
set first [expr $offset+1]
|
||||
set last [expr $offset+$numDays]
|
||||
|
||||
if {$tk_version >= 8.5} {
|
||||
set bg "#d9d9d9"
|
||||
} else {
|
||||
set bg [lindex [$w.t0 configure -background] 3]
|
||||
}
|
||||
set bg [lindex [. configure -background] 3]
|
||||
|
||||
for {set i 0} {$i < $first} {incr i} {
|
||||
grid $w.l$i $w.t$i
|
||||
@@ -1155,12 +1151,13 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
frame $w.exp -border 4
|
||||
frame $w.adv -border 4
|
||||
frame $w.weekend -border 4
|
||||
frame $w.durationbox -border 4
|
||||
frame $w.time -border 4
|
||||
frame $w.hol -border 4
|
||||
frame $w.msg
|
||||
frame $w.buttons
|
||||
pack $w.o1 $w.o2 $w.o3 -side top -anchor w -in $w.o
|
||||
pack $w.o $w.exp $w.adv $w.weekend $w.time $w.hol $w.msg -side top -anchor w -pady 4 -expand 1 -fill both
|
||||
pack $w.o $w.exp $w.adv $w.weekend $w.time $w.durationbox $w.hol $w.msg -side top -anchor w -pady 4 -expand 1 -fill both
|
||||
pack $w.buttons -side top -anchor w -pady 4 -expand 1 -fill x
|
||||
|
||||
# TYPE 1 REMINDER
|
||||
@@ -1301,6 +1298,22 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
pack $w.timebut $w.timehour $w.timemin $w.ampm $w.timeadvbut $w.timeadv $w.timelab1 $w.timerepbut $w.timerep $w.timelab2 -side left -anchor w -in $w.time
|
||||
}
|
||||
|
||||
# DURATION
|
||||
checkbutton $w.durationbut -text "Duration"
|
||||
$w.durationbut deselect
|
||||
menubutton $w.durationh -text "1" -menu $w.durationh.menu -relief raised
|
||||
menu $w.durationh.menu -tearoff 0
|
||||
foreach i {0 1 2 3 4 5 6 7 8 9 10 11 12} {
|
||||
$w.durationh.menu add command -label $i -command "$w.durationh configure -text $i"
|
||||
}
|
||||
label $w.durationcolon -text ":"
|
||||
menubutton $w.durationm -text "00" -menu $w.durationm.menu -relief raised
|
||||
menu $w.durationm.menu -tearoff 0
|
||||
foreach i {00 15 30 45} {
|
||||
$w.durationm.menu add command -label $i -command "$w.durationm configure -text $i"
|
||||
}
|
||||
pack $w.durationbut $w.durationh $w.durationcolon $w.durationm -side left -anchor w -in $w.durationbox
|
||||
|
||||
# SKIP TYPE
|
||||
label $w.labhol -text "On holidays or weekends:"
|
||||
radiobutton $w.issue -variable SkipType -value 1 -text "Issue reminder as usual"
|
||||
@@ -1343,7 +1356,7 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
#***********************************************************************
|
||||
proc RemindDialogToOptions { w } {
|
||||
global OptionType SkipType repbut expbut advbut advcount
|
||||
global timebut timeadvbut timerepbut
|
||||
global timebut timeadvbut timerepbut durationbut
|
||||
global dSaturday dSunday dMonday dTuesday dWednesday dThursday dFriday
|
||||
set ans {}
|
||||
lappend ans "-global-OptionType" $OptionType
|
||||
@@ -1377,7 +1390,7 @@ proc RemindDialogToOptions { w } {
|
||||
#***********************************************************************
|
||||
proc OptionsToRemindDialog { w opts } {
|
||||
global OptionType SkipType repbut expbut advbut advcount
|
||||
global timebut timeadvbut timerepbut TwentyFourHourMode
|
||||
global timebut timeadvbut timerepbut TwentyFourHourMode durationbut
|
||||
global dSaturday dSunday dMonday dTuesday dWednesday dThursday dFriday
|
||||
set hour ""
|
||||
set ampm ""
|
||||
@@ -1589,7 +1602,7 @@ proc CreateReminder {w} {
|
||||
# Delegate the first part to CreateReminder1, CreateReminder2, or
|
||||
# CreateReminder3
|
||||
global OptionType SkipType repbut expbut advbut advcount
|
||||
global timebut timeadvbut timerepbut
|
||||
global timebut timeadvbut timerepbut durationbut
|
||||
|
||||
set rem [CreateReminder$OptionType $w]
|
||||
|
||||
@@ -1631,6 +1644,9 @@ proc CreateReminder {w} {
|
||||
if {$timerepbut} {
|
||||
append rem " *[$w.timerep cget -text]"
|
||||
}
|
||||
if {$durationbut} {
|
||||
append rem " DURATION [$w.durationh cget -text]:[$w.durationm cget -text]"
|
||||
}
|
||||
}
|
||||
|
||||
global SkipType
|
||||
@@ -2303,7 +2319,7 @@ proc main {} {
|
||||
global AppendFile HighestTagSoFar DayNames
|
||||
catch {
|
||||
puts "\nTkRemind Copyright (C) 1996-1998 David F. Skoll"
|
||||
puts "Copyright (C) 1999-2009 Roaring Penguin Software Inc."
|
||||
puts "Copyright (C) 1999-2010 Roaring Penguin Software Inc."
|
||||
}
|
||||
catch { SetFonts }
|
||||
LoadOptions
|
||||
|
||||
@@ -38,7 +38,7 @@ REMINDOBJS= $(REMINDSRCS:.c=.o)
|
||||
all: remind rem2ps
|
||||
|
||||
test: remind
|
||||
sh ../tests/test-rem
|
||||
@sh ../tests/test-rem
|
||||
|
||||
.c.o:
|
||||
@CC@ -c @CFLAGS@ @DEFS@ $(CEXTRA) $(LANGDEF) -I. -I$(srcdir) $<
|
||||
|
||||
511
src/calendar.c
511
src/calendar.c
@@ -18,6 +18,10 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
#include <wctype.h>
|
||||
#endif
|
||||
|
||||
#include "types.h"
|
||||
#include "protos.h"
|
||||
#include "expr.h"
|
||||
@@ -30,11 +34,15 @@ typedef struct cal_entry {
|
||||
struct cal_entry *next;
|
||||
char const *text;
|
||||
char const *pos;
|
||||
#ifdef REM_USE_WCHAR
|
||||
wchar_t const *wc_text;
|
||||
wchar_t const *wc_pos;
|
||||
#endif
|
||||
int is_color;
|
||||
int r, g, b;
|
||||
int time;
|
||||
int priority;
|
||||
char tag[TAG_LEN+1];
|
||||
DynamicBuffer tags;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
int duration;
|
||||
char const *filename;
|
||||
@@ -45,17 +53,32 @@ typedef struct cal_entry {
|
||||
struct line_drawing {
|
||||
char const *graphics_on;
|
||||
char const *graphics_off;
|
||||
char tlr, bl, tbl, blr, tblr, tr, tb, br, tbr, tl, lr;
|
||||
char *tlr, *bl, *tbl, *blr, *tblr, *tr, *tb, *br, *tbr, *tl, *lr;
|
||||
};
|
||||
|
||||
static struct line_drawing NormalDrawing = {
|
||||
"", "", '+', '+', '+', '+', '+', '+', '|', '+', '+', '+', '-'
|
||||
"", "", "+", "+", "+", "+", "+", "+", "|", "+", "+", "+", "-"
|
||||
};
|
||||
|
||||
static struct line_drawing VT100Drawing = {
|
||||
"\x1B(0", "\x1B(B",
|
||||
'\x76', '\x6b', '\x75', '\x77', '\x6e', '\x6d', '\x78',
|
||||
'\x6c', '\x74', '\x6a', '\x71'
|
||||
"\x76", "\x6b", "\x75", "\x77", "\x6e", "\x6d", "\x78",
|
||||
"\x6c", "\x74", "\x6a", "\x71"
|
||||
};
|
||||
|
||||
static struct line_drawing UTF8Drawing = {
|
||||
"", "",
|
||||
"\xe2\x94\xb4",
|
||||
"\xe2\x94\x90",
|
||||
"\xe2\x94\xa4",
|
||||
"\xe2\x94\xac",
|
||||
"\xe2\x94\xbc",
|
||||
"\xe2\x94\x94",
|
||||
"\xe2\x94\x82",
|
||||
"\xe2\x94\x8c",
|
||||
"\xe2\x94\x9c",
|
||||
"\xe2\x94\x98",
|
||||
"\xe2\x94\x80"
|
||||
};
|
||||
|
||||
static char *VT100Colors[2][2][2][2] /* [Br][R][G][B] */ = {
|
||||
@@ -108,7 +131,7 @@ static char *VT100Colors[2][2][2][2] /* [Br][R][G][B] */ = {
|
||||
};
|
||||
|
||||
static struct line_drawing *linestruct;
|
||||
#define DRAW(x) putchar(linestruct->x)
|
||||
#define DRAW(x) fputs(linestruct->x, stdout)
|
||||
|
||||
/* Global variables */
|
||||
static CalEntry *CalColumn[7];
|
||||
@@ -124,7 +147,7 @@ static int WriteCalendarRow (void);
|
||||
static void WriteWeekHeaderLine (void);
|
||||
static void WritePostHeaderLine (void);
|
||||
static void PrintLeft (char const *s, int width, char pad);
|
||||
static void PrintCentered (char const *s, int width, char pad);
|
||||
static void PrintCentered (char const *s, int width, char *pad);
|
||||
static int WriteOneCalLine (void);
|
||||
static int WriteOneColLine (int col);
|
||||
static void GenerateCalEntries (int col);
|
||||
@@ -137,6 +160,40 @@ static void WriteBottomCalLine (void);
|
||||
static void WriteIntermediateCalLine (void);
|
||||
static void WriteCalDays (void);
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
static void PutWideChar(wchar_t const wc)
|
||||
{
|
||||
char buf[MB_CUR_MAX+1];
|
||||
int len;
|
||||
|
||||
len = wctomb(buf, wc);
|
||||
if (len > 0) {
|
||||
buf[len] = 0;
|
||||
fputs(buf, stdout);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int make_wchar_versions(CalEntry *e)
|
||||
{
|
||||
#ifdef REM_USE_WCHAR
|
||||
size_t len;
|
||||
wchar_t *buf;
|
||||
len = mbstowcs(NULL, e->text, 0);
|
||||
if (len == (size_t) -1) return 0;
|
||||
|
||||
buf = calloc(len+1, sizeof(wchar_t));
|
||||
if (!buf) return 0;
|
||||
|
||||
(void) mbstowcs(buf, e->text, len+1);
|
||||
e->wc_text = buf;
|
||||
e->wc_pos = buf;
|
||||
return 1;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gon(void)
|
||||
{
|
||||
printf("%s", linestruct->graphics_on);
|
||||
@@ -179,7 +236,9 @@ void ProduceCalendar(void)
|
||||
{
|
||||
int y, m, d;
|
||||
|
||||
if (UseVTChars) {
|
||||
if (UseUTF8Chars) {
|
||||
linestruct = &UTF8Drawing;
|
||||
} else if (UseVTChars) {
|
||||
linestruct = &VT100Drawing;
|
||||
} else {
|
||||
linestruct = &NormalDrawing;
|
||||
@@ -460,20 +519,55 @@ static void PrintLeft(char const *s, int width, char pad)
|
||||
/* */
|
||||
/* PrintCentered */
|
||||
/* */
|
||||
/* Center a piec of text */
|
||||
/* Center a piece of text */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void PrintCentered(char const *s, int width, char pad)
|
||||
static void PrintCentered(char const *s, int width, char *pad)
|
||||
{
|
||||
#ifndef REM_USE_WCHAR
|
||||
int len = strlen(s);
|
||||
int d = (width - len) / 2;
|
||||
int i;
|
||||
|
||||
for (i=0; i<d; i++) PutChar(pad);
|
||||
for (i=0; i<d; i++) fputs(pad, stdout);
|
||||
for (i=0; i<width; i++) {
|
||||
if (*s) PutChar(*s++); else break;
|
||||
}
|
||||
for (i=d+len; i<width; i++) PutChar(pad);
|
||||
for (i=d+len; i<width; i++) fputs(pad, stdout);
|
||||
#else
|
||||
size_t len = mbstowcs(NULL, s, 0);
|
||||
int i;
|
||||
wchar_t static_buf[128];
|
||||
wchar_t *buf;
|
||||
wchar_t *ws;
|
||||
int d;
|
||||
|
||||
if (!len) {
|
||||
for (i=0; i<width; i++) {
|
||||
fputs(pad, stdout);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (len + 1 <= 128) {
|
||||
buf = static_buf;
|
||||
} else {
|
||||
buf = calloc(len+1, sizeof(wchar_t));
|
||||
if (!buf) {
|
||||
/* Uh-oh... cannot recover */
|
||||
fprintf(stderr, "%s\n", ErrMsg[E_NO_MEM]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
(void) mbstowcs(buf, s, len+1);
|
||||
d = (width - len) / 2;
|
||||
ws = buf;
|
||||
for (i=0; i<d; i++) fputs(pad, stdout);
|
||||
for (i=0; i<width; i++) {
|
||||
if (*ws) PutWideChar(*ws++); else break;
|
||||
}
|
||||
for (i=d+len; i<width; i++) fputs(pad, stdout);
|
||||
if (buf != static_buf) free(buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -494,7 +588,7 @@ static int WriteOneCalLine(void)
|
||||
if (CalColumn[i]) {
|
||||
if (WriteOneColLine(i)) done = 0;
|
||||
} else {
|
||||
PrintCentered("", ColSpaces, ' ');
|
||||
PrintCentered("", ColSpaces, " ");
|
||||
}
|
||||
gon();
|
||||
DRAW(tb);
|
||||
@@ -519,74 +613,158 @@ static int WriteOneColLine(int col)
|
||||
CalEntry *e = CalColumn[col];
|
||||
char const *s;
|
||||
char const *space;
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
wchar_t const *ws;
|
||||
wchar_t const *wspace;
|
||||
#endif
|
||||
|
||||
int numwritten = 0;
|
||||
|
||||
/* Print as many characters as possible within the column */
|
||||
space = NULL;
|
||||
s = e->pos;
|
||||
/* Print as many characters as possible within the column */
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) {
|
||||
wspace = NULL;
|
||||
ws = e->wc_pos;
|
||||
|
||||
/* If we're at the end, and there's another entry, do a blank line and move
|
||||
to next entry. */
|
||||
if (!*s && e->next) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
CalColumn[col] = e->next;
|
||||
free((char *) e->text);
|
||||
free((char *) e->filename);
|
||||
free(e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find the last space char within the column. */
|
||||
while (s - e->pos <= ColSpaces) {
|
||||
if (!*s) {space = s; break;}
|
||||
if (*s == ' ') space = s;
|
||||
s++;
|
||||
}
|
||||
|
||||
/* Colorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Colorize(e);
|
||||
}
|
||||
|
||||
/* If we couldn't find a space char, print what we have. */
|
||||
if (!space) {
|
||||
for (s = e->pos; s - e->pos < ColSpaces; s++) {
|
||||
if (!*s) break;
|
||||
numwritten++;
|
||||
PutChar(*s);
|
||||
/* If we're at the end, and there's another entry, do a blank
|
||||
line and move to next entry. */
|
||||
if (!*ws && e->next) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
CalColumn[col] = e->next;
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
free(e);
|
||||
return 1;
|
||||
}
|
||||
e->pos = s;
|
||||
} else {
|
||||
|
||||
/* We found a space - print everything before it. */
|
||||
for (s = e->pos; s<space; s++) {
|
||||
if (!*s) break;
|
||||
numwritten++;
|
||||
PutChar(*s);
|
||||
/* Find the last space char within the column. */
|
||||
while (ws - e->wc_pos <= ColSpaces) {
|
||||
if (!*ws) {wspace = ws; break;}
|
||||
if (iswspace(*ws)) wspace = ws;
|
||||
ws++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decolorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Decolorize();
|
||||
}
|
||||
/* Colorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Colorize(e);
|
||||
}
|
||||
|
||||
/* Flesh out the rest of the column */
|
||||
while(numwritten++ < ColSpaces) PutChar(' ');
|
||||
/* If we couldn't find a space char, print what we have. */
|
||||
if (!wspace) {
|
||||
for (ws = e->wc_pos; ws - e->wc_pos < ColSpaces; ws++) {
|
||||
if (!*ws) break;
|
||||
numwritten++;
|
||||
PutWideChar(*ws);
|
||||
}
|
||||
e->wc_pos = ws;
|
||||
} else {
|
||||
/* We found a space - print everything before it. */
|
||||
for (ws = e->wc_pos; ws<wspace; ws++) {
|
||||
if (!*ws) break;
|
||||
numwritten++;
|
||||
PutWideChar(*ws);
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip any spaces before next word */
|
||||
while (*s == ' ') s++;
|
||||
/* Decolorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Decolorize();
|
||||
}
|
||||
|
||||
/* If done, free memory if no next entry. */
|
||||
if (!*s && !e->next) {
|
||||
CalColumn[col] = e->next;
|
||||
free((char *) e->text);
|
||||
free((char *) e->filename);
|
||||
free(e);
|
||||
/* Flesh out the rest of the column */
|
||||
while(numwritten++ < ColSpaces) PutChar(' ');
|
||||
|
||||
/* Skip any spaces before next word */
|
||||
while (iswspace(*ws)) ws++;
|
||||
|
||||
/* If done, free memory if no next entry. */
|
||||
if (!*ws && !e->next) {
|
||||
CalColumn[col] = e->next;
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
free(e);
|
||||
} else {
|
||||
e->wc_pos = ws;
|
||||
}
|
||||
if (CalColumn[col]) return 1; else return 0;
|
||||
} else {
|
||||
e->pos = s;
|
||||
#endif
|
||||
space = NULL;
|
||||
s = e->pos;
|
||||
|
||||
/* If we're at the end, and there's another entry, do a blank
|
||||
line and move to next entry. */
|
||||
if (!*s && e->next) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
CalColumn[col] = e->next;
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
#endif
|
||||
free(e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find the last space char within the column. */
|
||||
while (s - e->pos <= ColSpaces) {
|
||||
if (!*s) {space = s; break;}
|
||||
if (*s == ' ') space = s;
|
||||
s++;
|
||||
}
|
||||
|
||||
/* Colorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Colorize(e);
|
||||
}
|
||||
|
||||
/* If we couldn't find a space char, print what we have. */
|
||||
if (!space) {
|
||||
for (s = e->pos; s - e->pos < ColSpaces; s++) {
|
||||
if (!*s) break;
|
||||
numwritten++;
|
||||
PutChar(*s);
|
||||
}
|
||||
e->pos = s;
|
||||
} else {
|
||||
/* We found a space - print everything before it. */
|
||||
for (s = e->pos; s<space; s++) {
|
||||
if (!*s) break;
|
||||
numwritten++;
|
||||
PutChar(*s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Decolorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Decolorize();
|
||||
}
|
||||
|
||||
/* Flesh out the rest of the column */
|
||||
while(numwritten++ < ColSpaces) PutChar(' ');
|
||||
|
||||
/* Skip any spaces before next word */
|
||||
while (*s == ' ') s++;
|
||||
|
||||
/* If done, free memory if no next entry. */
|
||||
if (!*s && !e->next) {
|
||||
CalColumn[col] = e->next;
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
#endif
|
||||
free(e);
|
||||
} else {
|
||||
e->pos = s;
|
||||
}
|
||||
if (CalColumn[col]) return 1; else return 0;
|
||||
#ifdef REM_USE_WCHAR
|
||||
}
|
||||
if (CalColumn[col]) return 1; else return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -714,7 +892,7 @@ static void WriteCalHeader(void)
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
PrintCentered(buf, CalWidth-2, ' ');
|
||||
PrintCentered(buf, CalWidth-2, " ");
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
@@ -763,26 +941,52 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DBufInit(&pre_buf);
|
||||
|
||||
/* Parse the trigger date and time */
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Don't include timed reminders in calendar if -a option supplied. */
|
||||
if (DontIssueAts && tim.ttime != NO_TIME) return OK;
|
||||
if (trig.typ == NO_TYPE) return E_EOLN;
|
||||
if (DontIssueAts && tim.ttime != NO_TIME) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (trig.typ == NO_TYPE) {
|
||||
FreeTrig(&trig);
|
||||
return E_EOLN;
|
||||
}
|
||||
if (trig.typ == SAT_TYPE) {
|
||||
r=DoSatRemind(&trig, &tim, p);
|
||||
if (r) return r;
|
||||
if (!LastTrigValid) return OK;
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
if (r == E_EXPIRED) return OK;
|
||||
return r;
|
||||
}
|
||||
if (!LastTrigValid) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
r=ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
DBufFree(&buf);
|
||||
if (tok.type == T_Empty || tok.type == T_Comment) return OK;
|
||||
if (tok.type != T_RemType || tok.val == SAT_TYPE) return E_PARSE_ERR;
|
||||
if (tok.type == T_Empty || tok.type == T_Comment) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (tok.type != T_RemType || tok.val == SAT_TYPE) {
|
||||
FreeTrig(&trig);
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
if (tok.val == PASSTHRU_TYPE) {
|
||||
r=ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (!DBufLen(&buf)) {
|
||||
DBufFree(&buf);
|
||||
FreeTrig(&trig);
|
||||
return E_EOLN;
|
||||
}
|
||||
StrnCpy(trig.passthru, DBufValue(&buf), PASSTHRU_LEN);
|
||||
@@ -790,11 +994,17 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
}
|
||||
trig.typ = tok.val;
|
||||
jul = LastTriggerDate;
|
||||
if (!LastTrigValid) return OK;
|
||||
if (!LastTrigValid) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert PS and PSF to PASSTHRU */
|
||||
@@ -806,39 +1016,50 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
trig.typ = PASSTHRU_TYPE;
|
||||
}
|
||||
if (trig.typ == PASSTHRU_TYPE) {
|
||||
if (!PsCal && strcmp(trig.passthru, "COLOR")) return OK;
|
||||
if (!strcmp(trig.passthru, "COLOR")) {
|
||||
is_color = 1;
|
||||
/* Strip off the three color numbers */
|
||||
DBufFree(&buf);
|
||||
r=ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
r=ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
r=ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
(void) sscanf(DBufValue(&pre_buf), "%d %d %d",
|
||||
&col_r, &col_g, &col_b);
|
||||
if (col_r < 0) col_r = 0;
|
||||
else if (col_r > 255) col_r = 255;
|
||||
if (col_g < 0) col_g = 0;
|
||||
else if (col_g > 255) col_g = 255;
|
||||
if (col_b < 0) col_b = 0;
|
||||
else if (col_b > 255) col_b = 255;
|
||||
|
||||
if (!PsCal && !DoSimpleCalendar) {
|
||||
DBufFree(&pre_buf);
|
||||
}
|
||||
}
|
||||
if (!PsCal && strcmp(trig.passthru, "COLOR")) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (!strcmp(trig.passthru, "COLOR")) {
|
||||
is_color = 1;
|
||||
/* Strip off the three color numbers */
|
||||
DBufFree(&buf);
|
||||
r=ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
DBufFree(&buf);
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
r=ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
DBufFree(&buf);
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
r=ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
DBufFree(&buf);
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
(void) sscanf(DBufValue(&pre_buf), "%d %d %d",
|
||||
&col_r, &col_g, &col_b);
|
||||
if (col_r < 0) col_r = 0;
|
||||
else if (col_r > 255) col_r = 255;
|
||||
if (col_g < 0) col_g = 0;
|
||||
else if (col_g > 255) col_g = 255;
|
||||
if (col_b < 0) col_b = 0;
|
||||
else if (col_b > 255) col_b = 255;
|
||||
if (!PsCal && !DoSimpleCalendar) {
|
||||
DBufFree(&pre_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If trigger date == today, add it to the current entry */
|
||||
@@ -856,12 +1077,14 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
if (DBufPuts(&obuf, SimpleTime(NO_TIME)) != OK) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
} else {
|
||||
if (DBufPuts(&obuf, CalendarTime(tim.ttime, tim.duration)) != OK) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
}
|
||||
@@ -871,13 +1094,14 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
char evalBuf[64];
|
||||
sprintf(evalBuf, "calprefix(%d)", trig.priority);
|
||||
s2 = evalBuf;
|
||||
r = EvalExpr(&s2, &v);
|
||||
r = EvalExpr(&s2, &v, NULL);
|
||||
if (!r) {
|
||||
if (!DoCoerce(STR_TYPE, &v)) {
|
||||
if (DBufPuts(&obuf, v.v.str) != OK) {
|
||||
DestroyValue(v);
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
}
|
||||
@@ -896,11 +1120,13 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
if (r) {
|
||||
DBufFree(&pre_buf);
|
||||
DBufFree(&obuf);
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
if (DBufLen(&obuf) <= oldLen) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (trig.typ != PASSTHRU_TYPE &&
|
||||
@@ -908,13 +1134,14 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
char evalBuf[64];
|
||||
sprintf(evalBuf, "calsuffix(%d)", trig.priority);
|
||||
s2 = evalBuf;
|
||||
r = EvalExpr(&s2, &v);
|
||||
r = EvalExpr(&s2, &v, NULL);
|
||||
if (!r) {
|
||||
if (!DoCoerce(STR_TYPE, &v)) {
|
||||
if (DBufPuts(&obuf, v.v.str) != OK) {
|
||||
DestroyValue(v);
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
}
|
||||
@@ -922,34 +1149,41 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
}
|
||||
}
|
||||
s = DBufValue(&obuf);
|
||||
if (!DoSimpleCalendar) while (isspace(*s)) s++;
|
||||
if (!DoSimpleCalendar) while (isempty(*s)) s++;
|
||||
DBufPuts(&pre_buf, s);
|
||||
s = DBufValue(&pre_buf);
|
||||
e = NEW(CalEntry);
|
||||
if (!e) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
#ifdef REM_USE_WCHAR
|
||||
e->wc_pos = NULL;
|
||||
e->wc_text = NULL;
|
||||
#endif
|
||||
e->is_color = is_color;
|
||||
e->r = col_r;
|
||||
e->g = col_g;
|
||||
e->b = col_b;
|
||||
if (!e) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
e->text = StrDup(s);
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
if (!e->text) {
|
||||
free(e);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
StrnCpy(e->tag, trig.tag, TAG_LEN);
|
||||
if (!e->tag[0]) {
|
||||
if (SynthesizeTags) {
|
||||
SynthesizeTag(e->tag);
|
||||
} else {
|
||||
strcpy(e->tag, "*");
|
||||
}
|
||||
make_wchar_versions(e);
|
||||
DBufInit(&(e->tags));
|
||||
DBufPuts(&(e->tags), DBufValue(&(trig.tags)));
|
||||
if (SynthesizeTags) {
|
||||
AppendTag(&(e->tags), SynthesizeTag());
|
||||
}
|
||||
|
||||
/* Don't need tags any more */
|
||||
FreeTrig(&trig);
|
||||
e->duration = tim.duration;
|
||||
e->priority = trig.priority;
|
||||
e->filename = StrDup(FileName);
|
||||
@@ -999,7 +1233,11 @@ static void WriteSimpleEntries(int col, int jul)
|
||||
} else {
|
||||
printf(" *");
|
||||
}
|
||||
printf(" %s ", e->tag);
|
||||
if (*DBufValue(&(e->tags))) {
|
||||
printf(" %s ", DBufValue(&(e->tags)));
|
||||
} else {
|
||||
printf(" * ");
|
||||
}
|
||||
if (e->duration != NO_TIME) {
|
||||
printf("%d ", e->duration);
|
||||
} else {
|
||||
@@ -1011,8 +1249,11 @@ static void WriteSimpleEntries(int col, int jul)
|
||||
printf("* ");
|
||||
}
|
||||
printf("%s\n", e->text);
|
||||
free((char *) e->text);
|
||||
free((char *) e->filename);
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
#endif
|
||||
n = e->next;
|
||||
free(e);
|
||||
e = n;
|
||||
@@ -1112,9 +1353,9 @@ static void WriteCalDays(void)
|
||||
goff();
|
||||
for (i=0; i<7; i++) {
|
||||
if (!MondayFirst)
|
||||
PrintCentered(DayName[(i+6)%7], ColSpaces, ' ');
|
||||
PrintCentered(DayName[(i+6)%7], ColSpaces, " ");
|
||||
else
|
||||
PrintCentered(DayName[i%7], ColSpaces, ' ');
|
||||
PrintCentered(DayName[i%7], ColSpaces, " ");
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
@@ -1282,10 +1523,11 @@ static void SortCol(CalEntry **col)
|
||||
}
|
||||
}
|
||||
|
||||
void SynthesizeTag(char *out)
|
||||
char const *SynthesizeTag(void)
|
||||
{
|
||||
struct MD5Context ctx;
|
||||
unsigned char buf[16];
|
||||
static char out[128];
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, (unsigned char *) CurLine, strlen(CurLine));
|
||||
MD5Final(buf, &ctx);
|
||||
@@ -1298,5 +1540,6 @@ void SynthesizeTag(char *out)
|
||||
(unsigned int) buf[10], (unsigned int) buf[11],
|
||||
(unsigned int) buf[12], (unsigned int) buf[13],
|
||||
(unsigned int) buf[14], (unsigned int) buf[15]);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,20 @@
|
||||
/* Define if you have the <glob.h> header file */
|
||||
#undef HAVE_GLOB_H
|
||||
|
||||
#undef HAVE_WCTYPE_H
|
||||
|
||||
#undef HAVE_LOCALE_H
|
||||
|
||||
#undef HAVE_GLOB
|
||||
|
||||
#undef HAVE_SETENV
|
||||
|
||||
#undef HAVE_UNSETENV
|
||||
|
||||
#undef HAVE_MBSTOWCS
|
||||
|
||||
#undef HAVE_SETLOCALE
|
||||
|
||||
/* The number of bytes in a unsigned int. */
|
||||
#undef SIZEOF_UNSIGNED_INT
|
||||
|
||||
|
||||
10
src/custom.h
10
src/custom.h
@@ -183,12 +183,12 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many global omits of the form YYYY MM DD do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_FULL_OMITS 250
|
||||
#define MAX_FULL_OMITS 500
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many global omits of the form MM DD do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_PARTIAL_OMITS 250
|
||||
#define MAX_PARTIAL_OMITS 366
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* A newline - some systems need "\n\r" */
|
||||
@@ -221,3 +221,9 @@
|
||||
#define Putc putc
|
||||
#define PutChar putchar
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MBSTOWCS) && defined(HAVE_WCTYPE_H)
|
||||
#define REM_USE_WCHAR 1
|
||||
#else
|
||||
#undef REM_USE_WCHAR
|
||||
#endif
|
||||
|
||||
@@ -183,12 +183,12 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many global omits of the form YYYY MM DD do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_FULL_OMITS 250
|
||||
#define MAX_FULL_OMITS 500
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many global omits of the form MM DD do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_PARTIAL_OMITS 250
|
||||
#define MAX_PARTIAL_OMITS 366
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* A newline - some systems need "\n\r" */
|
||||
@@ -221,3 +221,9 @@
|
||||
#define Putc putc
|
||||
#define PutChar putchar
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MBSTOWCS) && defined(HAVE_WCTYPE_H)
|
||||
#define REM_USE_WCHAR 1
|
||||
#else
|
||||
#undef REM_USE_WCHAR
|
||||
#endif
|
||||
|
||||
147
src/dorem.c
147
src/dorem.c
@@ -56,29 +56,54 @@ int DoRem(ParsePtr p)
|
||||
DBufInit(&buf);
|
||||
|
||||
/* Parse the trigger date and time */
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (trig.typ == NO_TYPE) return E_EOLN;
|
||||
if (trig.typ == NO_TYPE) {
|
||||
PurgeEchoLine("%s\n%s\n", "#!P! Cannot parse next line", CurLine);
|
||||
FreeTrig(&trig);
|
||||
return E_EOLN;
|
||||
}
|
||||
if (trig.typ == SAT_TYPE) {
|
||||
PurgeEchoLine("%s\n", "#!P: Cannot purge SATISFY-type reminders");
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
r=DoSatRemind(&trig, &tim, p);
|
||||
if (r) return r;
|
||||
if (!LastTrigValid) return OK;
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
if (r == E_EXPIRED) return OK;
|
||||
return r;
|
||||
}
|
||||
if (!LastTrigValid) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
r=ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
DBufFree(&buf);
|
||||
if (tok.type == T_Empty || tok.type == T_Comment) {
|
||||
DBufFree(&buf);
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (tok.type != T_RemType || tok.val == SAT_TYPE) {
|
||||
DBufFree(&buf);
|
||||
FreeTrig(&trig);
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
if (tok.val == PASSTHRU_TYPE) {
|
||||
r=ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
if (!DBufLen(&buf)) {
|
||||
FreeTrig(&trig);
|
||||
DBufFree(&buf);
|
||||
return E_EOLN;
|
||||
}
|
||||
@@ -87,13 +112,42 @@ int DoRem(ParsePtr p)
|
||||
}
|
||||
trig.typ = tok.val;
|
||||
jul = LastTriggerDate;
|
||||
if (!LastTrigValid) return OK;
|
||||
if (!LastTrigValid || PurgeMode) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
if (PurgeMode) {
|
||||
PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]);
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
}
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (PurgeMode) {
|
||||
if (trig.expired || jul < JulianToday) {
|
||||
if (p->expr_happened) {
|
||||
if (p->nonconst_expr) {
|
||||
PurgeEchoLine("%s\n", "#!P: Next line may have expired, but contains non-constant expression");
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
} else {
|
||||
PurgeEchoLine("%s\n", "#!P: Next line has expired, but contains expression... please verify");
|
||||
PurgeEchoLine("#!P: Expired: %s\n", CurLine);
|
||||
}
|
||||
} else {
|
||||
PurgeEchoLine("#!P: Expired: %s\n", CurLine);
|
||||
}
|
||||
} else {
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
}
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
/* Queue the reminder, if necessary */
|
||||
if (jul == JulianToday &&
|
||||
!(!IgnoreOnce &&
|
||||
@@ -101,17 +155,21 @@ int DoRem(ParsePtr p)
|
||||
FileAccessDate == JulianToday))
|
||||
QueueReminder(p, &trig, &tim, trig.sched);
|
||||
/* If we're in daemon mode, do nothing over here */
|
||||
if (Daemon) return OK;
|
||||
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
|
||||
if ( (r=TriggerReminder(p, &trig, &tim, jul)) )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
if (Daemon) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
|
||||
if ( (r=TriggerReminder(p, &trig, &tim, jul)) ) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -126,7 +184,6 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
register int r;
|
||||
DynamicBuffer buf;
|
||||
Token tok;
|
||||
|
||||
int y, m, d;
|
||||
|
||||
DBufInit(&buf);
|
||||
@@ -148,7 +205,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
trig->sched[0] = 0;
|
||||
trig->warn[0] = 0;
|
||||
trig->omitfunc[0] = 0;
|
||||
trig->tag[0] = 0;
|
||||
DBufInit(&(trig->tags));
|
||||
trig->passthru[0] = 0;
|
||||
tim->ttime = NO_TIME;
|
||||
tim->delta = NO_DELTA;
|
||||
@@ -244,6 +301,14 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
}
|
||||
return OK;
|
||||
|
||||
case T_Through:
|
||||
DBufFree(&buf);
|
||||
if (trig->rep != NO_REP) return E_REP_TWICE;
|
||||
trig->rep = 1;
|
||||
r = ParseUntil(s, trig);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case T_Until:
|
||||
DBufFree(&buf);
|
||||
r=ParseUntil(s, trig);
|
||||
@@ -321,7 +386,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
case T_Tag:
|
||||
r = ParseToken(s, &buf);
|
||||
if (r) return r;
|
||||
StrnCpy(trig->tag, DBufValue(&buf), TAG_LEN);
|
||||
AppendTag(&(trig->tags), DBufValue(&buf));
|
||||
break;
|
||||
|
||||
case T_Duration:
|
||||
@@ -653,18 +718,24 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
if (t->typ == PASSTHRU_TYPE && !strcmp(t->passthru, "COLOR")) {
|
||||
/* Strip off three tokens */
|
||||
r = ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
if (!NextMode) {
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
}
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
r = ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
if (!NextMode) {
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
}
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
r = ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
if (!NextMode) {
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
}
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
t->typ = MSG_TYPE;
|
||||
@@ -704,16 +775,12 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
DBufFree(&pre_buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
if (t->tag[0]) {
|
||||
sprintf(tmpBuf, "%s ", t->tag);
|
||||
} else {
|
||||
sprintf(tmpBuf, "* ");
|
||||
}
|
||||
if (DBufPuts(&calRow, tmpBuf) != OK) {
|
||||
DBufFree(&calRow);
|
||||
DBufFree(&pre_buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
if (*DBufValue(&(t->tags))) {
|
||||
DBufPuts(&calRow, DBufValue(&(t->tags)));
|
||||
DBufPutc(&calRow, ' ');
|
||||
} else {
|
||||
DBufPuts(&calRow, "* ");
|
||||
}
|
||||
if (tim->duration != NO_TIME) {
|
||||
sprintf(tmpBuf, "%d ", tim->duration);
|
||||
} else {
|
||||
@@ -755,7 +822,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
if (UserFuncExists("msgprefix") == 1) {
|
||||
sprintf(PrioExpr, "msgprefix(%d)", t->priority);
|
||||
s = PrioExpr;
|
||||
r = EvalExpr(&s, &v);
|
||||
r = EvalExpr(&s, &v, NULL);
|
||||
if (!r) {
|
||||
if (!DoCoerce(STR_TYPE, &v)) {
|
||||
if (DBufPuts(&buf, v.v.str) != OK) {
|
||||
@@ -774,7 +841,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
if (UserFuncExists("msgsuffix") == 1) {
|
||||
sprintf(PrioExpr, "msgsuffix(%d)", t->priority);
|
||||
s = PrioExpr;
|
||||
r = EvalExpr(&s, &v);
|
||||
r = EvalExpr(&s, &v, NULL);
|
||||
if (!r) {
|
||||
if (!DoCoerce(STR_TYPE, &v)) {
|
||||
if (DBufPuts(&buf, v.v.str) != OK) {
|
||||
@@ -884,9 +951,9 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
|
||||
if (t->delta < 0)
|
||||
jul = jul + t->delta;
|
||||
else {
|
||||
r = t->delta;
|
||||
int iter = 0;
|
||||
int max = MaxSatIter;
|
||||
r = t->delta;
|
||||
if (max < r*2) max = r*2;
|
||||
while(iter++ < max) {
|
||||
if (!r || (jul <= JulianToday)) {
|
||||
@@ -932,7 +999,7 @@ int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
|
||||
if (r == E_CANT_TRIG) return OK; else return r;
|
||||
}
|
||||
if (jul == -1) {
|
||||
return OK;
|
||||
return E_EXPIRED;
|
||||
}
|
||||
s = p->pos;
|
||||
r = EvaluateExpr(p, &v);
|
||||
@@ -1073,7 +1140,7 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err)
|
||||
for (i=1; ; i++) {
|
||||
sprintf(buffer, "%s(%d)", t->warn, i);
|
||||
s = buffer;
|
||||
r = EvalExpr(&s, &v);
|
||||
r = EvalExpr(&s, &v, NULL);
|
||||
if (r) {
|
||||
Eprint("%s: `%s': %s", ErrMsg[M_BAD_WARN_FUNC],
|
||||
t->warn, ErrMsg[r]);
|
||||
|
||||
@@ -205,7 +205,7 @@ EXTERN char *ErrMsg[]
|
||||
"Back value specified twice",
|
||||
"ONCE keyword used twice. (Hah.)",
|
||||
"Expecting time after AT",
|
||||
"UNTIL keyword used twice",
|
||||
"THROUGH/UNTIL keyword used twice",
|
||||
"Incomplete date specification",
|
||||
"FROM/SCANFROM keyword used twice",
|
||||
"Variable",
|
||||
|
||||
44
src/expr.c
44
src/expr.c
@@ -41,7 +41,7 @@ static int Multiply(void), Divide(void), Mod(void), Add(void),
|
||||
UnMinus(void), LogNot(void),
|
||||
Compare(int);
|
||||
|
||||
static int MakeValue (char const *s, Value *v, Var *locals);
|
||||
static int MakeValue (char const *s, Value *v, Var *locals, ParsePtr p);
|
||||
|
||||
/* Binary operators - all left-associative */
|
||||
|
||||
@@ -132,7 +132,7 @@ static void CleanStack(void)
|
||||
static char PeekChar(char const **s)
|
||||
{
|
||||
char const *t = *s;
|
||||
while (*t && isspace(*t)) t++;
|
||||
while (*t && isempty(*t)) t++;
|
||||
return *t;
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ static int ParseExprToken(DynamicBuffer *buf, char const **in)
|
||||
|
||||
DBufFree(buf);
|
||||
/* Skip white space */
|
||||
while (**in && isspace(**in)) (*in)++;
|
||||
while (**in && isempty(**in)) (*in)++;
|
||||
|
||||
if (!**in) return OK;
|
||||
|
||||
@@ -283,7 +283,7 @@ static int ParseExprToken(DynamicBuffer *buf, char const **in)
|
||||
(*in)++;
|
||||
}
|
||||
/* Chew up any remaining white space */
|
||||
while (**in && isspace(**in)) (*in)++;
|
||||
while (**in && isempty(**in)) (*in)++;
|
||||
|
||||
/* Peek ahead - is it '('? Then we have a function call */
|
||||
if (**in == '(') {
|
||||
@@ -303,14 +303,14 @@ static int ParseExprToken(DynamicBuffer *buf, char const **in)
|
||||
/* Put the result into value pointed to by v. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int EvalExpr(char const **e, Value *v)
|
||||
int EvalExpr(char const **e, Value *v, ParsePtr p)
|
||||
{
|
||||
int r;
|
||||
|
||||
OpStackPtr = 0;
|
||||
ValStackPtr = 0;
|
||||
|
||||
r = Evaluate(e, NULL);
|
||||
r = Evaluate(e, NULL, p);
|
||||
|
||||
/* Put last character parsed back onto input stream */
|
||||
if (DBufLen(&ExprBuf)) (*e)--;
|
||||
@@ -326,7 +326,7 @@ int EvalExpr(char const **e, Value *v)
|
||||
}
|
||||
|
||||
/* Evaluate - do the actual work of evaluation. */
|
||||
int Evaluate(char const **s, Var *locals)
|
||||
int Evaluate(char const **s, Var *locals, ParsePtr p)
|
||||
{
|
||||
int OpBase, ValBase;
|
||||
int r;
|
||||
@@ -351,7 +351,7 @@ int Evaluate(char const **s, Var *locals)
|
||||
|
||||
if (*DBufValue(&ExprBuf) == '(') { /* Parenthesized expression */
|
||||
DBufFree(&ExprBuf);
|
||||
r = Evaluate(s, locals); /* Leaves the last parsed token in ExprBuf */
|
||||
r = Evaluate(s, locals, p); /* Leaves the last parsed token in ExprBuf */
|
||||
if (r) return r;
|
||||
r = OK;
|
||||
if (*DBufValue(&ExprBuf) != ')') {
|
||||
@@ -374,9 +374,11 @@ int Evaluate(char const **s, Var *locals)
|
||||
}
|
||||
args = 0;
|
||||
if (PeekChar(s) == ')') { /* Function has no arguments */
|
||||
if (f) r = CallFunc(f, 0);
|
||||
else {
|
||||
r = CallUserFunc(ufname, 0);
|
||||
if (f) {
|
||||
if (!f->is_constant && (p != NULL)) p->nonconst_expr = 1;
|
||||
r = CallFunc(f, 0);
|
||||
} else {
|
||||
r = CallUserFunc(ufname, 0, p);
|
||||
free((char *) ufname);
|
||||
}
|
||||
if (r) return r;
|
||||
@@ -385,7 +387,7 @@ int Evaluate(char const **s, Var *locals)
|
||||
} else { /* Function has some arguments */
|
||||
while(1) {
|
||||
args++;
|
||||
r = Evaluate(s, locals);
|
||||
r = Evaluate(s, locals, p);
|
||||
if (r) {
|
||||
if (!f) free((char *) ufname);
|
||||
return r;
|
||||
@@ -399,9 +401,11 @@ int Evaluate(char const **s, Var *locals)
|
||||
return E_EXPECT_COMMA;
|
||||
}
|
||||
}
|
||||
if (f) r = CallFunc(f, args);
|
||||
else {
|
||||
r = CallUserFunc(ufname, args);
|
||||
if (f) {
|
||||
if (!f->is_constant && (p != NULL)) p->nonconst_expr = 1;
|
||||
r = CallFunc(f, args);
|
||||
} else {
|
||||
r = CallUserFunc(ufname, args, p);
|
||||
free((char *) ufname);
|
||||
}
|
||||
DBufFree(&ExprBuf);
|
||||
@@ -422,7 +426,7 @@ int Evaluate(char const **s, Var *locals)
|
||||
DBufFree(&ExprBuf);
|
||||
return E_ILLEGAL_CHAR;
|
||||
} else { /* Must be a literal value */
|
||||
r = MakeValue(DBufValue(&ExprBuf), &va, locals);
|
||||
r = MakeValue(DBufValue(&ExprBuf), &va, locals, p);
|
||||
DBufFree(&ExprBuf);
|
||||
if (r) return r;
|
||||
PushValStack(va);
|
||||
@@ -486,7 +490,7 @@ int Evaluate(char const **s, Var *locals)
|
||||
/* a date or the value of a symbol. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int MakeValue(char const *s, Value *v, Var *locals)
|
||||
static int MakeValue(char const *s, Value *v, Var *locals, ParsePtr p)
|
||||
{
|
||||
int len;
|
||||
int h, m, r;
|
||||
@@ -541,6 +545,7 @@ static int MakeValue(char const *s, Value *v, Var *locals)
|
||||
v->v.val = len;
|
||||
return OK;
|
||||
} else if (*s == '$') { /* A system variable */
|
||||
if (p) p->nonconst_expr = 1;
|
||||
if (DebugFlag & DB_PRTEXPR)
|
||||
fprintf(ErrFp, "%s => ", s);
|
||||
r = GetSysVar(s+1, v);
|
||||
@@ -551,10 +556,11 @@ static int MakeValue(char const *s, Value *v, Var *locals)
|
||||
Putc('\n', ErrFp);
|
||||
}
|
||||
return r;
|
||||
} else /* Must be a symbol */
|
||||
} else { /* Must be a symbol */
|
||||
if (DebugFlag & DB_PRTEXPR)
|
||||
fprintf(ErrFp, "%s => ", s);
|
||||
r = GetVarValue(s, v, locals);
|
||||
}
|
||||
r = GetVarValue(s, v, locals, p);
|
||||
if (! (DebugFlag & DB_PRTEXPR)) return r;
|
||||
if (r == OK) {
|
||||
PrintValue(v, ErrFp);
|
||||
|
||||
80
src/files.c
80
src/files.c
@@ -17,6 +17,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -97,6 +98,32 @@ static void DestroyCache (CachedFile *cf);
|
||||
static int CheckSafety (void);
|
||||
static int PopFile (void);
|
||||
|
||||
static void OpenPurgeFile(char const *fname, char const *mode)
|
||||
{
|
||||
DynamicBuffer fname_buf;
|
||||
|
||||
if (PurgeFP != NULL && PurgeFP != stdout) {
|
||||
fclose(PurgeFP);
|
||||
}
|
||||
PurgeFP = NULL;
|
||||
|
||||
/* Do not open a purge file if we're below purge
|
||||
include depth */
|
||||
if (IStackPtr-2 >= PurgeIncludeDepth) {
|
||||
PurgeFP = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
DBufInit(&fname_buf);
|
||||
if (DBufPuts(&fname_buf, fname) != OK) return;
|
||||
if (DBufPuts(&fname_buf, ".purged") != OK) return;
|
||||
PurgeFP = fopen(DBufValue(&fname_buf), mode);
|
||||
if (!PurgeFP) {
|
||||
fprintf(ErrFp, "Cannot open `%s' for writing: %s\n", DBufValue(&fname_buf), strerror(errno));
|
||||
}
|
||||
DBufFree(&fname_buf);
|
||||
}
|
||||
|
||||
static void FreeChainItem(FilenameChain *chain)
|
||||
{
|
||||
if (chain->filename) free((void *) chain->filename);
|
||||
@@ -173,14 +200,32 @@ static int ReadLineFromFile(void)
|
||||
}
|
||||
if (feof(fp)) {
|
||||
FCLOSE(fp);
|
||||
if ((DBufLen(&buf) == 0) &&
|
||||
(DBufLen(&LineBuffer) == 0) && PurgeMode) {
|
||||
if (PurgeFP != NULL && PurgeFP != stdout) fclose(PurgeFP);
|
||||
PurgeFP = NULL;
|
||||
}
|
||||
}
|
||||
l = DBufLen(&buf);
|
||||
if (l && (DBufValue(&buf)[l-1] == '\\')) {
|
||||
DBufValue(&buf)[l-1] = '\n';
|
||||
if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) {
|
||||
DBufFree(&buf);
|
||||
DBufFree(&LineBuffer);
|
||||
return E_NO_MEM;
|
||||
if (PurgeMode) {
|
||||
if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) {
|
||||
DBufFree(&buf);
|
||||
DBufFree(&LineBuffer);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
if (DBufPutc(&LineBuffer, '\n') != OK) {
|
||||
DBufFree(&buf);
|
||||
DBufFree(&LineBuffer);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
} else {
|
||||
DBufValue(&buf)[l-1] = '\n';
|
||||
if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) {
|
||||
DBufFree(&buf);
|
||||
DBufFree(&LineBuffer);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -212,6 +257,13 @@ int OpenFile(char const *fname)
|
||||
CachedFile *h = CachedFiles;
|
||||
int r;
|
||||
|
||||
if (PurgeMode) {
|
||||
if (PurgeFP != NULL && PurgeFP != stdout) {
|
||||
fclose(PurgeFP);
|
||||
}
|
||||
PurgeFP = NULL;
|
||||
}
|
||||
|
||||
/* Assume we own the file for now */
|
||||
RunDisabled &= ~RUN_NOTOWNER;
|
||||
|
||||
@@ -236,6 +288,9 @@ int OpenFile(char const *fname)
|
||||
/* If it's a dash, then it's stdin */
|
||||
if (!strcmp(fname, "-")) {
|
||||
fp = stdin;
|
||||
if (PurgeMode) {
|
||||
PurgeFP = stdout;
|
||||
}
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Reading `-': Reading stdin\n");
|
||||
}
|
||||
@@ -244,6 +299,9 @@ int OpenFile(char const *fname)
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Reading `%s': Opening file on disk\n", fname);
|
||||
}
|
||||
if (PurgeMode) {
|
||||
OpenPurgeFile(fname, "w");
|
||||
}
|
||||
}
|
||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||
CLine = NULL;
|
||||
@@ -257,8 +315,10 @@ int OpenFile(char const *fname)
|
||||
if (strcmp(fname, "-")) {
|
||||
fp = fopen(fname, "r");
|
||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||
if (PurgeMode) OpenPurgeFile(fname, "w");
|
||||
} else {
|
||||
fp = stdin;
|
||||
if (PurgeMode) PurgeFP = stdout;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -289,7 +349,11 @@ static int CacheFile(char const *fname)
|
||||
/* Create a file header */
|
||||
cf = NEW(CachedFile);
|
||||
cf->cache = NULL;
|
||||
if (!cf) { ShouldCache = 0; FCLOSE(fp); return E_NO_MEM; }
|
||||
if (!cf) {
|
||||
ShouldCache = 0;
|
||||
FCLOSE(fp);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
cf->filename = StrDup(fname);
|
||||
if (!cf->filename) {
|
||||
ShouldCache = 0;
|
||||
@@ -315,7 +379,7 @@ static int CacheFile(char const *fname)
|
||||
}
|
||||
/* Skip blank chars */
|
||||
s = DBufValue(&LineBuffer);
|
||||
while (isspace(*s)) s++;
|
||||
while (isempty(*s)) s++;
|
||||
if (*s && *s!=';' && *s!='#') {
|
||||
/* Add the line to the cache */
|
||||
if (!cl) {
|
||||
@@ -424,8 +488,10 @@ static int PopFile(void)
|
||||
if (strcmp(i->filename, "-")) {
|
||||
fp = fopen(i->filename, "r");
|
||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||
if (PurgeMode) OpenPurgeFile(i->filename, "a");
|
||||
} else {
|
||||
fp = stdin;
|
||||
if (PurgeMode) PurgeFP = stdout;
|
||||
}
|
||||
if (fp != stdin)
|
||||
(void) fseek(fp, i->offset, 0); /* Trust that it works... */
|
||||
|
||||
179
src/funcs.c
179
src/funcs.c
@@ -184,89 +184,89 @@ extern int ValStackPtr;
|
||||
|
||||
/* The array holding the built-in functions. */
|
||||
BuiltinFunc Func[] = {
|
||||
/* Name minargs maxargs func */
|
||||
/* Name minargs maxargs is_constant func */
|
||||
|
||||
{ "abs", 1, 1, FAbs },
|
||||
{ "access", 2, 2, FAccess },
|
||||
{ "args", 1, 1, FArgs },
|
||||
{ "asc", 1, 1, FAsc },
|
||||
{ "baseyr", 0, 0, FBaseyr },
|
||||
{ "char", 1, NO_MAX, FChar },
|
||||
{ "choose", 2, NO_MAX, FChoose },
|
||||
{ "coerce", 2, 2, FCoerce },
|
||||
{ "current", 0, 0, FCurrent },
|
||||
{ "date", 3, 3, FDate },
|
||||
{ "datepart", 1, 1, FDatepart },
|
||||
{ "datetime", 2, 5, FDateTime },
|
||||
{ "dawn", 0, 1, FDawn},
|
||||
{ "day", 1, 1, FDay },
|
||||
{ "daysinmon", 2, 2, FDaysinmon },
|
||||
{ "defined", 1, 1, FDefined },
|
||||
{ "dosubst", 1, 3, FDosubst },
|
||||
{ "dusk", 0, 1, FDusk },
|
||||
{ "easterdate", 1, 1, FEasterdate },
|
||||
{ "evaltrig", 1, 2, FEvalTrig },
|
||||
{ "filedate", 1, 1, FFiledate },
|
||||
{ "filedatetime", 1, 1, FFiledatetime },
|
||||
{ "filedir", 0, 0, FFiledir },
|
||||
{ "filename", 0, 0, FFilename },
|
||||
{ "getenv", 1, 1, FGetenv },
|
||||
{ "hebdate", 2, 5, FHebdate },
|
||||
{ "hebday", 1, 1, FHebday },
|
||||
{ "hebmon", 1, 1, FHebmon },
|
||||
{ "hebyear", 1, 1, FHebyear },
|
||||
{ "hour", 1, 1, FHour },
|
||||
{ "iif", 1, NO_MAX, FIif },
|
||||
{ "index", 2, 3, FIndex },
|
||||
{ "isdst", 0, 2, FIsdst },
|
||||
{ "isleap", 1, 1, FIsleap },
|
||||
{ "isomitted", 1, 1, FIsomitted },
|
||||
{ "language", 0, 0, FLanguage },
|
||||
{ "lower", 1, 1, FLower },
|
||||
{ "max", 1, NO_MAX, FMax },
|
||||
{ "min", 1, NO_MAX, FMin },
|
||||
{ "minsfromutc", 0, 2, FMinsfromutc },
|
||||
{ "minute", 1, 1, FMinute },
|
||||
{ "mon", 1, 1, FMon },
|
||||
{ "monnum", 1, 1, FMonnum },
|
||||
{ "moondate", 1, 3, FMoondate },
|
||||
{ "moondatetime", 1, 3, FMoondatetime },
|
||||
{ "moonphase", 0, 2, FMoonphase },
|
||||
{ "moontime", 1, 3, FMoontime },
|
||||
{ "nonomitted", 2, NO_MAX, FNonomitted },
|
||||
{ "now", 0, 0, FNow },
|
||||
{ "ord", 1, 1, FOrd },
|
||||
{ "ostype", 0, 0, FOstype },
|
||||
{ "plural", 1, 3, FPlural },
|
||||
{ "psmoon", 1, 4, FPsmoon},
|
||||
{ "psshade", 1, 3, FPsshade},
|
||||
{ "realcurrent", 0, 0, FRealCurrent},
|
||||
{ "realnow", 0, 0, FRealnow},
|
||||
{ "realtoday", 0, 0, FRealtoday },
|
||||
{ "sgn", 1, 1, FSgn },
|
||||
{ "shell", 1, 2, FShell },
|
||||
{ "slide", 2, NO_MAX, FSlide },
|
||||
{ "strlen", 1, 1, FStrlen },
|
||||
{ "substr", 2, 3, FSubstr },
|
||||
{ "sunrise", 0, 1, FSunrise},
|
||||
{ "sunset", 0, 1, FSunset },
|
||||
{ "time", 2, 2, FTime },
|
||||
{ "timepart", 1, 1, FTimepart },
|
||||
{ "today", 0, 0, FToday },
|
||||
{ "trigdate", 0, 0, FTrigdate },
|
||||
{ "trigdatetime", 0, 0, FTrigdatetime },
|
||||
{ "trigger", 1, 3, FTrigger },
|
||||
{ "trigtime", 0, 0, FTrigtime },
|
||||
{ "trigvalid", 0, 0, FTrigvalid },
|
||||
{ "typeof", 1, 1, FTypeof },
|
||||
{ "tzconvert", 2, 3, FTzconvert },
|
||||
{ "upper", 1, 1, FUpper },
|
||||
{ "value", 1, 2, FValue },
|
||||
{ "version", 0, 0, FVersion },
|
||||
{ "weekno", 0, 3, FWeekno },
|
||||
{ "wkday", 1, 1, FWkday },
|
||||
{ "wkdaynum", 1, 1, FWkdaynum },
|
||||
{ "year", 1, 1, FYear }
|
||||
{ "abs", 1, 1, 1, FAbs },
|
||||
{ "access", 2, 2, 0, FAccess },
|
||||
{ "args", 1, 1, 0, FArgs },
|
||||
{ "asc", 1, 1, 1, FAsc },
|
||||
{ "baseyr", 0, 0, 1, FBaseyr },
|
||||
{ "char", 1, NO_MAX, 1, FChar },
|
||||
{ "choose", 2, NO_MAX, 1, FChoose },
|
||||
{ "coerce", 2, 2, 1, FCoerce },
|
||||
{ "current", 0, 0, 0, FCurrent },
|
||||
{ "date", 3, 3, 1, FDate },
|
||||
{ "datepart", 1, 1, 1, FDatepart },
|
||||
{ "datetime", 2, 5, 1, FDateTime },
|
||||
{ "dawn", 0, 1, 0, FDawn},
|
||||
{ "day", 1, 1, 1, FDay },
|
||||
{ "daysinmon", 2, 2, 1, FDaysinmon },
|
||||
{ "defined", 1, 1, 0, FDefined },
|
||||
{ "dosubst", 1, 3, 0, FDosubst },
|
||||
{ "dusk", 0, 1, 0, FDusk },
|
||||
{ "easterdate", 1, 1, 0, FEasterdate },
|
||||
{ "evaltrig", 1, 2, 0, FEvalTrig },
|
||||
{ "filedate", 1, 1, 0, FFiledate },
|
||||
{ "filedatetime", 1, 1, 0, FFiledatetime },
|
||||
{ "filedir", 0, 0, 0, FFiledir },
|
||||
{ "filename", 0, 0, 0, FFilename },
|
||||
{ "getenv", 1, 1, 0, FGetenv },
|
||||
{ "hebdate", 2, 5, 0, FHebdate },
|
||||
{ "hebday", 1, 1, 0, FHebday },
|
||||
{ "hebmon", 1, 1, 0, FHebmon },
|
||||
{ "hebyear", 1, 1, 0, FHebyear },
|
||||
{ "hour", 1, 1, 1, FHour },
|
||||
{ "iif", 1, NO_MAX, 1, FIif },
|
||||
{ "index", 2, 3, 1, FIndex },
|
||||
{ "isdst", 0, 2, 0, FIsdst },
|
||||
{ "isleap", 1, 1, 1, FIsleap },
|
||||
{ "isomitted", 1, 1, 0, FIsomitted },
|
||||
{ "language", 0, 0, 1, FLanguage },
|
||||
{ "lower", 1, 1, 1, FLower },
|
||||
{ "max", 1, NO_MAX, 1, FMax },
|
||||
{ "min", 1, NO_MAX, 1, FMin },
|
||||
{ "minsfromutc", 0, 2, 0, FMinsfromutc },
|
||||
{ "minute", 1, 1, 1, FMinute },
|
||||
{ "mon", 1, 1, 1, FMon },
|
||||
{ "monnum", 1, 1, 1, FMonnum },
|
||||
{ "moondate", 1, 3, 0, FMoondate },
|
||||
{ "moondatetime", 1, 3, 0, FMoondatetime },
|
||||
{ "moonphase", 0, 2, 0, FMoonphase },
|
||||
{ "moontime", 1, 3, 0, FMoontime },
|
||||
{ "nonomitted", 2, NO_MAX, 0, FNonomitted },
|
||||
{ "now", 0, 0, 0, FNow },
|
||||
{ "ord", 1, 1, 1, FOrd },
|
||||
{ "ostype", 0, 0, 1, FOstype },
|
||||
{ "plural", 1, 3, 1, FPlural },
|
||||
{ "psmoon", 1, 4, 1, FPsmoon},
|
||||
{ "psshade", 1, 3, 1, FPsshade},
|
||||
{ "realcurrent", 0, 0, 0, FRealCurrent},
|
||||
{ "realnow", 0, 0, 0, FRealnow},
|
||||
{ "realtoday", 0, 0, 0, FRealtoday },
|
||||
{ "sgn", 1, 1, 1, FSgn },
|
||||
{ "shell", 1, 2, 0, FShell },
|
||||
{ "slide", 2, NO_MAX, 0, FSlide },
|
||||
{ "strlen", 1, 1, 1, FStrlen },
|
||||
{ "substr", 2, 3, 1, FSubstr },
|
||||
{ "sunrise", 0, 1, 0, FSunrise},
|
||||
{ "sunset", 0, 1, 0, FSunset },
|
||||
{ "time", 2, 2, 1, FTime },
|
||||
{ "timepart", 1, 1, 1, FTimepart },
|
||||
{ "today", 0, 0, 0, FToday },
|
||||
{ "trigdate", 0, 0, 0, FTrigdate },
|
||||
{ "trigdatetime", 0, 0, 0, FTrigdatetime },
|
||||
{ "trigger", 1, 3, 0, FTrigger },
|
||||
{ "trigtime", 0, 0, 0, FTrigtime },
|
||||
{ "trigvalid", 0, 0, 0, FTrigvalid },
|
||||
{ "typeof", 1, 1, 1, FTypeof },
|
||||
{ "tzconvert", 2, 3, 0, FTzconvert },
|
||||
{ "upper", 1, 1, 1, FUpper },
|
||||
{ "value", 1, 2, 0, FValue },
|
||||
{ "version", 0, 0, 1, FVersion },
|
||||
{ "weekno", 0, 3, 1, FWeekno },
|
||||
{ "wkday", 1, 1, 1, FWkday },
|
||||
{ "wkdaynum", 1, 1, 1, FWkdaynum },
|
||||
{ "year", 1, 1, 1, FYear }
|
||||
};
|
||||
|
||||
/* Need a variable here - Func[] array not really visible to outside. */
|
||||
@@ -1076,7 +1076,7 @@ static int FValue(func_info *info)
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
switch(Nargs) {
|
||||
case 1:
|
||||
return GetVarValue(ARGSTR(0), &RetVal, NULL);
|
||||
return GetVarValue(ARGSTR(0), &RetVal, NULL, NULL);
|
||||
|
||||
case 2:
|
||||
v = FindVar(ARGSTR(0), 0);
|
||||
@@ -1335,10 +1335,11 @@ static int FShell(func_info *info)
|
||||
/***************************************************************/
|
||||
static int FIsomitted(func_info *info)
|
||||
{
|
||||
int r;
|
||||
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||
|
||||
RetVal.type = INT_TYPE;
|
||||
int r = IsOmitted(DATEPART(ARG(0)), 0, NULL, &RETVAL);
|
||||
r = IsOmitted(DATEPART(ARG(0)), 0, NULL, &RETVAL);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -2324,7 +2325,7 @@ static int MoonStuff(int type_wanted, func_info *info)
|
||||
|
||||
static int FTimepart(func_info *info)
|
||||
{
|
||||
ASSERT_TYPE(0, DATETIME_TYPE);
|
||||
if (!HASTIME(ARG(0))) return E_BAD_TYPE;
|
||||
RetVal.type = TIME_TYPE;
|
||||
RETVAL = TIMEPART(ARG(0));
|
||||
return OK;
|
||||
@@ -2332,7 +2333,7 @@ static int FTimepart(func_info *info)
|
||||
|
||||
static int FDatepart(func_info *info)
|
||||
{
|
||||
ASSERT_TYPE(0, DATETIME_TYPE);
|
||||
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||
RetVal.type = DATE_TYPE;
|
||||
RETVAL = DATEPART(ARG(0));
|
||||
return OK;
|
||||
@@ -2659,7 +2660,10 @@ FEvalTrig(func_info *info)
|
||||
p.allownested = 0;
|
||||
r = ParseRem(&p, &trig, &tim, 0);
|
||||
if (r) return r;
|
||||
if (trig.typ != NO_TYPE) return E_PARSE_ERR;
|
||||
if (trig.typ != NO_TYPE) {
|
||||
FreeTrig(&trig);
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
if (scanfrom == NO_DATE) {
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 0);
|
||||
} else {
|
||||
@@ -2669,6 +2673,7 @@ FEvalTrig(func_info *info)
|
||||
}
|
||||
jul = ComputeTrigger(scanfrom, &trig, &r, 0);
|
||||
}
|
||||
FreeTrig(&trig);
|
||||
if (r) return r;
|
||||
if (jul < 0) {
|
||||
RetVal.type = INT_TYPE;
|
||||
|
||||
@@ -79,7 +79,10 @@ EXTERN INIT( int MaxSatIter, 150);
|
||||
EXTERN INIT( int MaxStringLen, MAX_STR_LEN);
|
||||
EXTERN INIT( char *FileName, NULL);
|
||||
EXTERN INIT( int UseStdin, 0);
|
||||
EXTERN INIT( int PurgeMode, 0);
|
||||
EXTERN INIT( int PurgeIncludeDepth, 0);
|
||||
EXTERN FILE *ErrFp;
|
||||
EXTERN INIT( FILE *PurgeFP, NULL);
|
||||
EXTERN INIT( int NumIfs, 0);
|
||||
EXTERN INIT( unsigned int IfFlags, 0);
|
||||
EXTERN INIT( int LastTriggerDate, 0);
|
||||
@@ -93,6 +96,7 @@ EXTERN char const **ArgV;
|
||||
EXTERN INIT( int CalLines, CAL_LINES);
|
||||
EXTERN INIT( int CalPad, 1);
|
||||
EXTERN INIT( int UseVTChars, 0);
|
||||
EXTERN INIT( int UseUTF8Chars, 0);
|
||||
EXTERN INIT( int UseVTColors, 0);
|
||||
|
||||
/* Latitude and longitude */
|
||||
|
||||
74
src/init.c
74
src/init.c
@@ -8,7 +8,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2007 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1999-2010 by Roaring Penguin Software Inc. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -67,9 +67,13 @@
|
||||
* -kcmd = Run 'cmd' for MSG-type reminders instead of printing to stdout
|
||||
* -iVAR=EXPR = Initialize and preserve VAR.
|
||||
* -m = Start calendar with Monday instead of Sunday.
|
||||
* -j[n] = Purge all junk from reminder files (n = INCLUDE depth)
|
||||
* A minus sign alone indicates to take input from stdin
|
||||
*
|
||||
**************************************************************/
|
||||
#if defined(__APPLE__) || defined(__CYGWIN__)
|
||||
static void rkrphgvba(int x);
|
||||
#endif
|
||||
|
||||
/* For parsing an integer */
|
||||
#define PARSENUM(var, s) \
|
||||
@@ -135,6 +139,12 @@ void InitRemind(int argc, char const *argv[])
|
||||
|
||||
int jul, tim;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
rkrphgvba(0);
|
||||
#elif defined(__CYGWIN__)
|
||||
rkrphgvba(1);
|
||||
#endif
|
||||
|
||||
jul = NO_DATE;
|
||||
tim = NO_TIME;
|
||||
|
||||
@@ -145,6 +155,8 @@ void InitRemind(int argc, char const *argv[])
|
||||
|
||||
DBufPuts(&Banner, L_BANNER);
|
||||
|
||||
PurgeFP = NULL;
|
||||
|
||||
/* Make sure remind is not installed set-uid or set-gid */
|
||||
if (getgid() != getegid() ||
|
||||
getuid() != geteuid()) {
|
||||
@@ -194,6 +206,13 @@ void InitRemind(int argc, char const *argv[])
|
||||
while (*arg) {
|
||||
switch(*arg++) {
|
||||
|
||||
case 'j':
|
||||
case 'J':
|
||||
PurgeMode = 1;
|
||||
if (*arg) {
|
||||
PARSENUM(PurgeIncludeDepth, arg);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
case 'I':
|
||||
InitializeVar(arg);
|
||||
@@ -333,6 +352,11 @@ void InitRemind(int argc, char const *argv[])
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == 'u' || *arg == 'U') {
|
||||
UseUTF8Chars = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == 'c' || *arg == 'C') {
|
||||
UseVTColors = 1;
|
||||
arg++;
|
||||
@@ -578,7 +602,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1998 David F. Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "Copyright 1999-2009 Roaring Penguin Software Inc.\n");
|
||||
fprintf(ErrFp, "Copyright 1999-2010 Roaring Penguin Software Inc.\n");
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
@@ -609,6 +633,7 @@ void Usage(void)
|
||||
fprintf(ErrFp, " -ivar=val Initialize var to val and preserve var\n");
|
||||
fprintf(ErrFp, " -m Start calendar with Monday rather than Sunday\n");
|
||||
fprintf(ErrFp, " -y Synthesize tags for tagless reminders\n");
|
||||
fprintf(ErrFp, " -j[n] Run in 'purge' mode. [n = INCLUDE depth]\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif /* L_USAGE_OVERRIDE */
|
||||
@@ -743,7 +768,7 @@ static void InitializeVar(char const *str)
|
||||
return;
|
||||
}
|
||||
|
||||
r=EvalExpr(&expr, &val);
|
||||
r=EvalExpr(&expr, &val, NULL);
|
||||
if (r) {
|
||||
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
|
||||
return;
|
||||
@@ -765,3 +790,46 @@ static void InitializeVar(char const *str)
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__) || defined(__CYGWIN__)
|
||||
static char const pmsg1[] = {
|
||||
0x4c, 0x62, 0x68, 0x20, 0x6e, 0x63, 0x63, 0x72, 0x6e, 0x65, 0x20,
|
||||
0x67, 0x62, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x68, 0x61, 0x61, 0x76,
|
||||
0x61, 0x74, 0x20, 0x45, 0x72, 0x7a, 0x76, 0x61, 0x71, 0x20, 0x62,
|
||||
0x61, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x63, 0x63, 0x79, 0x72, 0x20,
|
||||
0x63, 0x65, 0x62, 0x71, 0x68, 0x70, 0x67, 0x2e, 0x20, 0x20, 0x56,
|
||||
0x27, 0x71, 0x20, 0x65, 0x6e, 0x67, 0x75, 0x72, 0x65, 0x20, 0x67,
|
||||
0x75, 0x6e, 0x67, 0x0a, 0x6c, 0x62, 0x68, 0x20, 0x71, 0x76, 0x71,
|
||||
0x61, 0x27, 0x67, 0x2e, 0x20, 0x20, 0x45, 0x72, 0x7a, 0x76, 0x61,
|
||||
0x71, 0x20, 0x72, 0x6b, 0x72, 0x70, 0x68, 0x67, 0x76, 0x62, 0x61,
|
||||
0x20, 0x6a, 0x76, 0x79, 0x79, 0x20, 0x70, 0x62, 0x61, 0x67, 0x76,
|
||||
0x61, 0x68, 0x72, 0x20, 0x7a, 0x62, 0x7a, 0x72, 0x61, 0x67, 0x6e,
|
||||
0x65, 0x76, 0x79, 0x6c, 0x2e, 0x0a, 0x00
|
||||
};
|
||||
|
||||
static char const pmsg2[] = {
|
||||
0x4c, 0x62, 0x68, 0x20, 0x6e, 0x63, 0x63, 0x72, 0x6e, 0x65, 0x20,
|
||||
0x67, 0x62, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x68, 0x61, 0x61, 0x76,
|
||||
0x61, 0x74, 0x20, 0x45, 0x72, 0x7a, 0x76, 0x61, 0x71, 0x20, 0x62,
|
||||
0x61, 0x20, 0x6e, 0x20, 0x5a, 0x76, 0x70, 0x65, 0x62, 0x66, 0x62,
|
||||
0x73, 0x67, 0x20, 0x66, 0x6c, 0x66, 0x67, 0x72, 0x7a, 0x2e, 0x20,
|
||||
0x20, 0x56, 0x27, 0x71, 0x20, 0x65, 0x6e, 0x67, 0x75, 0x72, 0x65,
|
||||
0x20, 0x67, 0x75, 0x6e, 0x67, 0x0a, 0x6c, 0x62, 0x68, 0x20, 0x71,
|
||||
0x76, 0x71, 0x61, 0x27, 0x67, 0x2e, 0x20, 0x20, 0x45, 0x72, 0x7a,
|
||||
0x76, 0x61, 0x71, 0x20, 0x72, 0x6b, 0x72, 0x70, 0x68, 0x67, 0x76,
|
||||
0x62, 0x61, 0x20, 0x6a, 0x76, 0x79, 0x79, 0x20, 0x70, 0x62, 0x61,
|
||||
0x67, 0x76, 0x61, 0x68, 0x72, 0x20, 0x7a, 0x62, 0x7a, 0x72, 0x61,
|
||||
0x67, 0x6e, 0x65, 0x76, 0x79, 0x6c, 0x2e, 0x0a, 0x00
|
||||
};
|
||||
|
||||
static void
|
||||
rkrphgvba(int x)
|
||||
{
|
||||
char const *s = (x ? pmsg2 : pmsg1);
|
||||
while(*s) {
|
||||
int c = (int) *s++;
|
||||
c=isalpha(c)?tolower(c)<0x6e?c+13:c-13:c;
|
||||
putchar(c);
|
||||
}
|
||||
sleep(5);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -280,7 +280,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Peruutusarvo annettu kahdesti",
|
||||
"ONCE-avainsanaa k\xE4ytetty kahdesti. (Hah.)",
|
||||
"AT-sanan per\xE4st\xE4 puuttuu aika",
|
||||
"UNTIL-sanaa k\xE4ytetty kahdesti",
|
||||
"THROUGH/UNTIL-sanaa k\xE4ytetty kahdesti",
|
||||
"Ep\xE4t\xE4ydellinen p\xE4iv\xE4ys",
|
||||
"FROM/SCANFROM-sanaa k\xE4ytetty kahdesti",
|
||||
"Muuttuja",
|
||||
@@ -384,7 +384,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Peruutusarvo annettu kahdesti",
|
||||
"ONCE-avainsanaa k\x84ytetty kahdesti. (Hah.)",
|
||||
"AT-sanan per\x84st\x84 puuttuu aika",
|
||||
"UNTIL-sanaa k\x84ytetty kahdesti",
|
||||
"THROUGH/UNTIL-sanaa k\x84ytetty kahdesti",
|
||||
"Ep\x84t\x84ydellinen p\x84iv\x84ys",
|
||||
"FROM/SCANFROM-sanaa k\x84ytetty kahdesti",
|
||||
"Muuttuja",
|
||||
@@ -488,7 +488,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Peruutusarvo annettu kahdesti",
|
||||
"ONCE-avainsanaa k{ytetty kahdesti. (Hah.)",
|
||||
"AT-sanan per{st{ puuttuu aika",
|
||||
"UNTIL-sanaa k{ytetty kahdesti",
|
||||
"THROUGH/UNTIL-sanaa k{ytetty kahdesti",
|
||||
"Ep{t{ydellinen p{iv{ys",
|
||||
"FROM/SCANFROM-sanaa k{ytetty kahdesti",
|
||||
"Muuttuja",
|
||||
|
||||
@@ -217,7 +217,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Valeur de retour sp\351cifi\351e deux fois",
|
||||
"Mot-cl\351 ONCE utilis\351 deux fois. (Hah.)",
|
||||
"Heure attendue apr\350s AT",
|
||||
"Mot-cl\351 UNTIL utilis\351 deux fois",
|
||||
"Mot-cl\351 THROUGH/UNTIL utilis\351 deux fois",
|
||||
"Sp\351cification de date incompl\350te",
|
||||
"Mot-cl\351 FROM/SCANFROM utilis\351 deux fois",
|
||||
"Variable",
|
||||
@@ -321,7 +321,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Valeur de retour specifiee deux fois",
|
||||
"Mot-cle ONCE utilise deux fois. (Hah.)",
|
||||
"Heure attendue apres AT",
|
||||
"Mot-cle UNTIL utilise deux fois",
|
||||
"Mot-cle THROUGH/UNTIL utilise deux fois",
|
||||
"Specification de date incomplete",
|
||||
"Mot-cle FROM/SCANFROM utilise deux fois",
|
||||
"Variable",
|
||||
|
||||
@@ -252,7 +252,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Warto\266\346 cofni\352cia podana dw\363krotnie",
|
||||
"S\263owo ONCE u\277yte dw\363krotnie.",
|
||||
"Po AT oczekiwany jest czas",
|
||||
"S\263owo UNTIL u\277yte dw\363krotnie",
|
||||
"S\263owo THROUGH/UNTIL u\277yte dw\363krotnie",
|
||||
"Niekompletna specyfikacja daty",
|
||||
"S\263owo FROM/SCANFROM u\277yte dw\363krotnie",
|
||||
"Zmienna",
|
||||
@@ -355,7 +355,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Wartosc cofniecia podana dwokrotnie",
|
||||
"Slowo ONCE uzyte dwokrotnie.",
|
||||
"Po AT oczekiwany jest czas",
|
||||
"Slowo UNTIL uzyte dwokrotnie",
|
||||
"Slowo THROUGH/UNTIL uzyte dwokrotnie",
|
||||
"Niekompletna specyfikacja daty",
|
||||
"Slowo FROM/SCANFROM uzyte dwokrotnie",
|
||||
"Zmienna",
|
||||
|
||||
@@ -218,7 +218,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Valor de Back especificado duas vezes",
|
||||
"ONCE usado duas vezes (Eheheh)",
|
||||
"Esperando hora apos AT",
|
||||
"Keyword UNTIL usada duas vezes",
|
||||
"Keyword THROUGH/UNTIL usada duas vezes",
|
||||
"Especificacao de data incompleta",
|
||||
"Keyword FROM/SCANFROM usada duas vezes",
|
||||
"Variavel",
|
||||
|
||||
137
src/main.c
137
src/main.c
@@ -7,7 +7,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2009 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1999-2010 by Roaring Penguin Software Inc. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
@@ -57,6 +60,10 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
int pid;
|
||||
|
||||
#ifdef HAVE_SETLOCALE
|
||||
setlocale(LC_ALL, "");
|
||||
#endif
|
||||
|
||||
/* The very first thing to do is to set up ErrFp to be stderr */
|
||||
ErrFp = stderr;
|
||||
|
||||
@@ -70,6 +77,12 @@ int main(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Are we purging old reminders? Then just run through the loop once! */
|
||||
if (PurgeMode) {
|
||||
DoReminders();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Not doing a calendar. Do the regular remind loop */
|
||||
ShouldCache = (Iterations > 1);
|
||||
|
||||
@@ -123,6 +136,17 @@ int main(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PurgeEchoLine(char const *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr, fmt);
|
||||
if (PurgeFP != NULL) {
|
||||
(void) vfprintf(PurgeFP, fmt, argptr);
|
||||
}
|
||||
va_end(argptr);
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoReminders */
|
||||
@@ -136,6 +160,7 @@ static void DoReminders(void)
|
||||
Token tok;
|
||||
char const *s;
|
||||
Parser p;
|
||||
int purge_handled;
|
||||
|
||||
if (!UseStdin) {
|
||||
FileAccessDate = GetAccessDate(InitialFile);
|
||||
@@ -173,23 +198,40 @@ static void DoReminders(void)
|
||||
ShouldIgnoreLine())
|
||||
{
|
||||
/*** IGNORE THE LINE ***/
|
||||
if (PurgeMode) {
|
||||
if (strncmp(CurLine, "#!P", 3)) {
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
purge_handled = 0;
|
||||
/* Create a parser to parse the line */
|
||||
CreateParser(s, &p);
|
||||
switch(tok.type) {
|
||||
|
||||
case T_Empty:
|
||||
case T_Comment:
|
||||
if (!strncmp(CurLine, "#!P", 3)) {
|
||||
purge_handled = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case T_Rem: r=DoRem(&p); break;
|
||||
case T_Rem: r=DoRem(&p); purge_handled = 1; break;
|
||||
case T_ErrMsg: r=DoErrMsg(&p); break;
|
||||
case T_If: r=DoIf(&p); break;
|
||||
case T_IfTrig: r=DoIfTrig(&p); break;
|
||||
case T_Else: r=DoElse(&p); break;
|
||||
case T_EndIf: r=DoEndif(&p); break;
|
||||
case T_Include: r=DoInclude(&p); break;
|
||||
case T_Include:
|
||||
/* In purge mode, include closes file, so we
|
||||
need to echo it here! */
|
||||
if (PurgeMode) {
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
}
|
||||
r=DoInclude(&p);
|
||||
purge_handled = 1;
|
||||
break;
|
||||
case T_Exit: DoExit(&p); break;
|
||||
case T_Flush: r=DoFlush(&p); break;
|
||||
case T_Set: r=DoSet(&p); break;
|
||||
@@ -204,32 +246,42 @@ static void DoReminders(void)
|
||||
DestroyParser(&p);
|
||||
CreateParser(s, &p);
|
||||
r=DoRem(&p);
|
||||
purge_handled = 1;
|
||||
}
|
||||
break;
|
||||
case T_Pop: r=PopOmitContext(&p); break;
|
||||
case T_Preserve: r=DoPreserve(&p); break;
|
||||
case T_Push: r=PushOmitContext(&p); break;
|
||||
case T_RemType: if (tok.val == RUN_TYPE) {
|
||||
r=DoRun(&p);
|
||||
r=DoRun(&p);
|
||||
} else {
|
||||
CreateParser(CurLine, &p);
|
||||
r=DoRem(&p);
|
||||
purge_handled = 1;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
CreateParser(CurLine, &p);
|
||||
r=DoRem(&p);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* If we don't recognize the command, do a REM by default */
|
||||
/* Note: Since the parser hasn't been used yet, we don't */
|
||||
/* need to destroy it here. */
|
||||
|
||||
default: CreateParser(CurLine, &p); r=DoRem(&p); break;
|
||||
default: CreateParser(CurLine, &p); purge_handled = 1; r=DoRem(&p); break;
|
||||
|
||||
}
|
||||
if (r && (!Hush || r != E_RUN_DISABLED)) {
|
||||
Eprint("%s", ErrMsg[r]);
|
||||
}
|
||||
|
||||
if (PurgeMode) {
|
||||
if (!purge_handled) {
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
} else {
|
||||
if (r) {
|
||||
PurgeEchoLine("#!P! Could not parse next line: %s\n", ErrMsg[r]);
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Destroy the parser - free up resources it may be tying up */
|
||||
DestroyParser(&p);
|
||||
}
|
||||
@@ -347,7 +399,7 @@ int ParseChar(ParsePtr p, int *err, int peek)
|
||||
}
|
||||
p->expr_happened = 1;
|
||||
p->pos++;
|
||||
r = EvalExpr(&(p->pos), &val);
|
||||
r = EvalExpr(&(p->pos), &val, p);
|
||||
if (r) {
|
||||
*err = r;
|
||||
DestroyParser(p);
|
||||
@@ -383,7 +435,7 @@ int ParseNonSpaceChar(ParsePtr p, int *err, int peek)
|
||||
ch = ParseChar(p, err, 1);
|
||||
if (*err) return 0;
|
||||
|
||||
while (isspace(ch)) {
|
||||
while (isempty(ch)) {
|
||||
ParseChar(p, err, 0); /* Guaranteed to work */
|
||||
ch = ParseChar(p, err, 1);
|
||||
if (*err) return 0;
|
||||
@@ -407,12 +459,12 @@ int ParseToken(ParsePtr p, DynamicBuffer *dbuf)
|
||||
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) return err;
|
||||
while (c && isspace(c)) {
|
||||
while (c && isempty(c)) {
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) return err;
|
||||
}
|
||||
if (!c) return OK;
|
||||
while (c && !isspace(c)) {
|
||||
while (c && !isempty(c)) {
|
||||
if (DBufPutc(dbuf, c) != OK) {
|
||||
DBufFree(dbuf);
|
||||
return E_NO_MEM;
|
||||
@@ -443,7 +495,7 @@ int ParseIdentifier(ParsePtr p, DynamicBuffer *dbuf)
|
||||
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) return err;
|
||||
while (c && isspace(c)) {
|
||||
while (c && isempty(c)) {
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) return err;
|
||||
}
|
||||
@@ -484,13 +536,13 @@ int EvaluateExpr(ParsePtr p, Value *v)
|
||||
int r;
|
||||
|
||||
if (p->isnested) return E_PARSE_ERR; /* Can't nest expressions */
|
||||
while (isspace(*p->pos)) (p->pos)++;
|
||||
while (isempty(*p->pos)) (p->pos)++;
|
||||
if (!p->pos) return E_PARSE_ERR; /* Missing expression */
|
||||
if (*p->pos == BEG_OF_EXPR) {
|
||||
(p->pos)++;
|
||||
bracketed = 1;
|
||||
}
|
||||
r = EvalExpr(&(p->pos), v);
|
||||
r = EvalExpr(&(p->pos), v, p);
|
||||
if (r) return r;
|
||||
if (bracketed) {
|
||||
if (*p->pos != END_OF_EXPR) return E_MISS_END;
|
||||
@@ -567,6 +619,7 @@ void CreateParser(char const *s, ParsePtr p)
|
||||
p->allownested = 1;
|
||||
p->tokenPushed = NULL;
|
||||
p->expr_happened = 0;
|
||||
p->nonconst_expr = 0;
|
||||
DBufInit(&p->pushedToken);
|
||||
}
|
||||
|
||||
@@ -670,10 +723,15 @@ int DoIf(ParsePtr p)
|
||||
Eprint("%s", ErrMsg[r]);
|
||||
} else
|
||||
if ( (v.type != STR_TYPE && v.v.val) ||
|
||||
(v.type == STR_TYPE && strcmp(v.v.str, "")) )
|
||||
(v.type == STR_TYPE && strcmp(v.v.str, "")) ) {
|
||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else
|
||||
} else {
|
||||
syndrome = IF_FALSE | BEFORE_ELSE;
|
||||
if (PurgeMode) {
|
||||
PurgeEchoLine("%s\n", "#!P: The next IF evaluated false...");
|
||||
PurgeEchoLine("%s\n", "#!P: REM statements in IF block not checked for purging.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NumIfs++;
|
||||
@@ -693,6 +751,8 @@ int DoElse(ParsePtr p)
|
||||
{
|
||||
unsigned syndrome;
|
||||
|
||||
int was_ignoring = ShouldIgnoreLine();
|
||||
|
||||
if (!NumIfs) return E_ELSE_NO_IF;
|
||||
|
||||
syndrome = IfFlags >> (2 * NumIfs - 2);
|
||||
@@ -700,6 +760,10 @@ int DoElse(ParsePtr p)
|
||||
if ((syndrome & IF_ELSE_MASK) == AFTER_ELSE) return E_ELSE_NO_IF;
|
||||
|
||||
IfFlags |= AFTER_ELSE << (2 * NumIfs - 2);
|
||||
if (PurgeMode && ShouldIgnoreLine() && !was_ignoring) {
|
||||
PurgeEchoLine("%s\n", "#!P: The previous IF evaluated true.");
|
||||
PurgeEchoLine("%s\n", "#!P: REM statements in ELSE block not checked for purging");
|
||||
}
|
||||
return VerifyEoln(p);
|
||||
}
|
||||
|
||||
@@ -739,11 +803,17 @@ int DoIfTrig(ParsePtr p)
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
if (r) syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else {
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err))
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
|
||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else
|
||||
} else {
|
||||
syndrome = IF_FALSE | BEFORE_ELSE;
|
||||
if (PurgeMode) {
|
||||
PurgeEchoLine("%s\n", "#!P: The next IFTRIG did not trigger.");
|
||||
PurgeEchoLine("%s\n", "#!P: REM statements in IFTRIG block not checked for purging.");
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeTrig(&trig);
|
||||
}
|
||||
NumIfs++;
|
||||
IfFlags &= ~(IF_MASK << (2*NumIfs - 2));
|
||||
@@ -889,7 +959,7 @@ int DoBanner(ParsePtr p)
|
||||
DBufInit(&buf);
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) return err;
|
||||
while (isspace(c)) {
|
||||
while (isempty(c)) {
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) return err;
|
||||
}
|
||||
@@ -969,6 +1039,8 @@ void DoExit(ParsePtr p)
|
||||
int r;
|
||||
Value v;
|
||||
|
||||
if (PurgeMode) return;
|
||||
|
||||
r = EvaluateExpr(p, &v);
|
||||
if (r || v.type != INT_TYPE) exit(99);
|
||||
exit(v.v.val);
|
||||
@@ -990,6 +1062,8 @@ int DoErrMsg(ParsePtr p)
|
||||
|
||||
DynamicBuffer buf;
|
||||
|
||||
if (PurgeMode) return OK;
|
||||
|
||||
DBufInit(&buf);
|
||||
t.typ = MSG_TYPE;
|
||||
tt.ttime = SystemTime(0) / 60;
|
||||
@@ -997,7 +1071,7 @@ int DoErrMsg(ParsePtr p)
|
||||
return r;
|
||||
}
|
||||
s = DBufValue(&buf);
|
||||
while (isspace(*s)) s++;
|
||||
while (isempty(*s)) s++;
|
||||
fprintf(ErrFp, "%s\n", s);
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
@@ -1233,3 +1307,18 @@ void SigIntHandler(int d)
|
||||
GotSigInt();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
AppendTag(DynamicBuffer *buf, char const *s)
|
||||
{
|
||||
if (*(DBufValue(buf))) {
|
||||
DBufPutc(buf, ',');
|
||||
}
|
||||
DBufPuts(buf, s);
|
||||
}
|
||||
|
||||
void
|
||||
FreeTrig(Trigger *t)
|
||||
{
|
||||
DBufFree(&(t->tags));
|
||||
}
|
||||
|
||||
140
src/omit.c
140
src/omit.c
@@ -125,7 +125,7 @@ int PushOmitContext(ParsePtr p)
|
||||
free(context);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
|
||||
|
||||
/* Copy the context over */
|
||||
for (i=0; i<NumFullOmits; i++)
|
||||
*(context->fullsave + i) = FullOmitArray[i];
|
||||
@@ -198,7 +198,7 @@ int IsOmitted(int jul, int localomit, char const *omitfunc, int *omit)
|
||||
sprintf(expr, "%s('%04d-%02d-%02d')",
|
||||
omitfunc, y, m+1, d);
|
||||
s = expr;
|
||||
r = EvalExpr(&s, &v);
|
||||
r = EvalExpr(&s, &v, NULL);
|
||||
if (r) return r;
|
||||
if (v.type == INT_TYPE && v.v.val != 0) {
|
||||
*omit = 1;
|
||||
@@ -272,6 +272,9 @@ static void InsertIntoSortedArray(int *array, int num, int key)
|
||||
*cur = key;
|
||||
}
|
||||
|
||||
static int DoThroughOmit(ParsePtr p, int y, int m, int d);
|
||||
static void DumpOmits(void);
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoOmit */
|
||||
@@ -285,15 +288,25 @@ int DoOmit(ParsePtr p)
|
||||
Token tok;
|
||||
int parsing=1;
|
||||
int syndrome;
|
||||
int not_first_token = -1;
|
||||
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
|
||||
/* Parse the OMIT. We need a month and day; year is optional. */
|
||||
while(parsing) {
|
||||
not_first_token++;
|
||||
if ( (r=ParseToken(p, &buf)) ) return r;
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
switch (tok.type) {
|
||||
case T_Dumpvars:
|
||||
if (not_first_token) return E_PARSE_ERR;
|
||||
DBufFree(&buf);
|
||||
r = VerifyEoln(p);
|
||||
if (r != OK) return r;
|
||||
DumpOmits();
|
||||
return OK;
|
||||
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) return E_YR_TWICE;
|
||||
@@ -324,6 +337,11 @@ int DoOmit(ParsePtr p)
|
||||
DBufFree(&buf);
|
||||
break;
|
||||
|
||||
case T_Through:
|
||||
DBufFree(&buf);
|
||||
if (y == NO_YR || m == NO_MON || d == NO_DAY) return E_INCOMPLETE;
|
||||
return DoThroughOmit(p, y, m, d);
|
||||
|
||||
case T_Empty:
|
||||
case T_Comment:
|
||||
case T_RemType:
|
||||
@@ -362,7 +380,123 @@ int DoOmit(ParsePtr p)
|
||||
NumFullOmits++;
|
||||
}
|
||||
}
|
||||
if (tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
|
||||
if (tok.type == T_Tag || tok.type == T_Duration || tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
DoThroughOmit(ParsePtr p, int ystart, int mstart, int dstart)
|
||||
{
|
||||
int yend = NO_YR, mend = NO_MON, dend = NO_DAY, r;
|
||||
int start, end, tmp;
|
||||
|
||||
Token tok;
|
||||
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
int parsing = 1;
|
||||
|
||||
while(parsing) {
|
||||
if ( (r=ParseToken(p, &buf)) ) return r;
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
|
||||
switch(tok.type) {
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (yend != NO_YR) return E_YR_TWICE;
|
||||
if (mend != NO_MON) return E_MON_TWICE;
|
||||
if (dend != NO_DAY) return E_DAY_TWICE;
|
||||
FromJulian(tok.val, ¥d, &mend, &dend);
|
||||
break;
|
||||
|
||||
case T_Year:
|
||||
DBufFree(&buf);
|
||||
if (yend != NO_YR) return E_YR_TWICE;
|
||||
yend = tok.val;
|
||||
break;
|
||||
|
||||
case T_Month:
|
||||
DBufFree(&buf);
|
||||
if (mend != NO_MON) return E_MON_TWICE;
|
||||
mend = tok.val;
|
||||
break;
|
||||
|
||||
case T_Day:
|
||||
DBufFree(&buf);
|
||||
if (dend != NO_DAY) return E_DAY_TWICE;
|
||||
dend = tok.val;
|
||||
break;
|
||||
|
||||
case T_Empty:
|
||||
case T_Comment:
|
||||
case T_RemType:
|
||||
case T_Priority:
|
||||
case T_Tag:
|
||||
case T_Duration:
|
||||
DBufFree(&buf);
|
||||
parsing = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
Eprint("%s: `%s' (OMIT)", ErrMsg[E_UNKNOWN_TOKEN],
|
||||
DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return E_UNKNOWN_TOKEN;
|
||||
|
||||
}
|
||||
}
|
||||
if (yend == NO_YR || mend == NO_MON || dend == NO_DAY) return E_INCOMPLETE;
|
||||
if (dend > DaysInMonth(mend, yend)) return E_BAD_DATE;
|
||||
if (dstart > DaysInMonth(mstart, ystart)) return E_BAD_DATE;
|
||||
|
||||
start = Julian(ystart, mstart, dstart);
|
||||
end = Julian(yend, mend, dend);
|
||||
|
||||
if (end < start) {
|
||||
tmp = start;
|
||||
start = end;
|
||||
end = tmp;
|
||||
}
|
||||
|
||||
tmp = end - start + 1;
|
||||
|
||||
/* Don't create any OMITs if there would be too many. */
|
||||
if (NumFullOmits + tmp >= MAX_FULL_OMITS) return E_2MANY_FULL;
|
||||
for (tmp = start; tmp <= end; tmp++) {
|
||||
if (!BexistsIntArray(FullOmitArray, NumFullOmits, tmp)) {
|
||||
InsertIntoSortedArray(FullOmitArray, NumFullOmits, tmp);
|
||||
NumFullOmits++;
|
||||
}
|
||||
}
|
||||
if (tok.type == T_Tag || tok.type == T_Duration || tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
|
||||
return OK;
|
||||
}
|
||||
|
||||
void
|
||||
DumpOmits(void)
|
||||
{
|
||||
int i;
|
||||
int y, m, d;
|
||||
printf("Global Full OMITs (%d of maximum allowed %d):\n", NumFullOmits, MAX_FULL_OMITS);
|
||||
if (!NumFullOmits) {
|
||||
printf("\tNone.\n");
|
||||
} else {
|
||||
for (i=0; i<NumFullOmits; i++) {
|
||||
FromJulian(FullOmitArray[i], &y, &m, &d);
|
||||
printf("\t%04d%c%02d%c%02d\n",
|
||||
y, DateSep, m+1, DateSep, d);
|
||||
}
|
||||
}
|
||||
printf("Global Partial OMITs (%d of maximum allowed %d):\n", NumPartialOmits, MAX_PARTIAL_OMITS);
|
||||
if (!NumPartialOmits) {
|
||||
printf("\tNone.\n");
|
||||
} else {
|
||||
for (i=0; i<NumPartialOmits; i++) {
|
||||
m = PartialOmitArray[i] >> 5 & 0xf;
|
||||
d = PartialOmitArray[i] & 0x1f;
|
||||
printf("\t%02d%c%02d\n", m+1, DateSep, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
16
src/protos.h
16
src/protos.h
@@ -16,9 +16,12 @@
|
||||
/* Define a general malloc routine for creating pointers to objects */
|
||||
#define NEW(type) (malloc(sizeof(type)))
|
||||
|
||||
/* Characters to ignore */
|
||||
#define isempty(c) (isspace(c) || ((c) == '\\'))
|
||||
|
||||
#include "dynbuf.h"
|
||||
|
||||
int CallUserFunc (char const *name, int nargs);
|
||||
int CallUserFunc (char const *name, int nargs, ParsePtr p);
|
||||
int DoFset (ParsePtr p);
|
||||
void ProduceCalendar (void);
|
||||
char const *SimpleTime (int tim);
|
||||
@@ -32,7 +35,7 @@ int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int jul, int *err);
|
||||
int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul, int mode);
|
||||
int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int jul, int tim);
|
||||
int ParseLiteralDate (char const **s, int *jul, int *tim);
|
||||
int EvalExpr (char const **e, Value *v);
|
||||
int EvalExpr (char const **e, Value *v, ParsePtr p);
|
||||
int DoCoerce (char type, Value *v);
|
||||
void PrintValue (Value *v, FILE *fp);
|
||||
int CopyValue (Value *dest, const Value *src);
|
||||
@@ -52,7 +55,7 @@ int ParseChar (ParsePtr p, int *err, int peek);
|
||||
int ParseToken (ParsePtr p, DynamicBuffer *dbuf);
|
||||
int ParseIdentifier (ParsePtr p, DynamicBuffer *dbuf);
|
||||
int EvaluateExpr (ParsePtr p, Value *v);
|
||||
int Evaluate (char const **s, Var *locals);
|
||||
int Evaluate (char const **s, Var *locals, ParsePtr p);
|
||||
int FnPopValStack (Value *val);
|
||||
void Eprint (char const *fmt, ...);
|
||||
void OutputLine (FILE *fp);
|
||||
@@ -92,7 +95,7 @@ int StrCmpi (char const *s1, char const *s2);
|
||||
Var *FindVar (char const *str, int create);
|
||||
int DeleteVar (char const *str);
|
||||
int SetVar (char const *str, Value *val);
|
||||
int GetVarValue (char const *str, Value *val, Var *locals);
|
||||
int GetVarValue (char const *str, Value *val, Var *locals, ParsePtr p);
|
||||
int DoSet (Parser *p);
|
||||
int DoUnset (Parser *p);
|
||||
int DoDump (ParsePtr p);
|
||||
@@ -133,4 +136,7 @@ void HuntPhase (int startdate, int starttim, int phas, int *date, int *time);
|
||||
int CompareRems (int dat1, int tim1, int prio1, int dat2, int tim2, int prio2, int bydate, int bytime, int byprio, int untimed_first);
|
||||
void SigIntHandler (int d);
|
||||
void GotSigInt (void);
|
||||
void SynthesizeTag(char *);
|
||||
void PurgeEchoLine(char const *fmt, ...);
|
||||
void FreeTrig(Trigger *t);
|
||||
void AppendTag(DynamicBuffer *buf, char const *s);
|
||||
char const *SynthesizeTag(void);
|
||||
|
||||
18
src/queue.c
18
src/queue.c
@@ -43,7 +43,7 @@ typedef struct queuedrem {
|
||||
char const *text;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
char sched[VAR_NAME_LEN+1];
|
||||
char tag[TAG_LEN+1];
|
||||
DynamicBuffer tags;
|
||||
TimeTrig tt;
|
||||
} QueuedRem;
|
||||
|
||||
@@ -96,9 +96,10 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
||||
qelem->RunDisabled = RunDisabled;
|
||||
qelem->ntrig = 0;
|
||||
strcpy(qelem->sched, sched);
|
||||
strcpy(qelem->tag, trig->tag);
|
||||
if (! *qelem->tag && SynthesizeTags) {
|
||||
SynthesizeTag(qelem->tag);
|
||||
DBufInit(&(qelem->tags));
|
||||
DBufPuts(&(qelem->tags), DBufValue(&(trig->tags)));
|
||||
if (SynthesizeTags) {
|
||||
AppendTag(&(qelem->tags), SynthesizeTag());
|
||||
}
|
||||
QueueHead = qelem;
|
||||
return OK;
|
||||
@@ -235,12 +236,11 @@ void HandleQueuedReminders(void)
|
||||
printf("NOTE reminder %s",
|
||||
SimpleTime(q->tt.ttime));
|
||||
printf("%s", SimpleTime(SystemTime(0)/60));
|
||||
if (!*q->tag) {
|
||||
printf("*");
|
||||
if (!*DBufValue(&q->tags)) {
|
||||
printf("*\n");
|
||||
} else {
|
||||
printf("%s", q->tag);
|
||||
printf("%s\n", DBufValue(&(q->tags)));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Set up global variables so some functions like trigdate()
|
||||
@@ -411,7 +411,7 @@ static int CalculateNextTimeUsingSched(QueuedRem *q)
|
||||
char exprBuf[VAR_NAME_LEN+32];
|
||||
sprintf(exprBuf, "%s(%d)", q->sched, q->ntrig);
|
||||
s = exprBuf;
|
||||
r = EvalExpr(&s, &v);
|
||||
r = EvalExpr(&s, &v, NULL);
|
||||
if (r) {
|
||||
q->sched[0] = 0;
|
||||
return NO_TIME;
|
||||
|
||||
15
src/rem2ps.c
15
src/rem2ps.c
@@ -32,6 +32,17 @@
|
||||
#define SPECIAL_WEEK 5
|
||||
#define SPECIAL_SHADE 6
|
||||
|
||||
/* Array holding how specials sort */
|
||||
static int SpecialSortOrder[] = {
|
||||
0, /* NORMAL */
|
||||
1, /* POSTSCRIPT */
|
||||
1, /* PSFILE */
|
||||
2, /* MOON */
|
||||
0, /* COLOR */
|
||||
4, /* WEEK */
|
||||
5 /* SHADE */
|
||||
};
|
||||
|
||||
typedef struct calentry {
|
||||
struct calentry *next;
|
||||
int special;
|
||||
@@ -338,11 +349,11 @@ void DoPsCal(void)
|
||||
d = PsEntries[DayNum];
|
||||
p = NULL;
|
||||
/* Slot it into the right place */
|
||||
while (d->next && (c->special <= d->special)) {
|
||||
while (d->next && (SpecialSortOrder[c->special] <= SpecialSortOrder[d->special])) {
|
||||
p = d;
|
||||
d = d->next;
|
||||
}
|
||||
if (c->special <= d->special) {
|
||||
if (SpecialSortOrder[c->special] <= SpecialSortOrder[d->special]) {
|
||||
c->next = d->next;
|
||||
d->next = c;
|
||||
} else {
|
||||
|
||||
@@ -181,7 +181,7 @@ static void IssueSortBanner(int jul)
|
||||
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
sprintf(BanExpr, "sortbanner('%04d/%02d/%02d')", y, m+1, d);
|
||||
y = EvalExpr(&s, &v);
|
||||
y = EvalExpr(&s, &v, NULL);
|
||||
if (y) return;
|
||||
if (DoCoerce(STR_TYPE, &v)) return;
|
||||
DBufInit(&buf);
|
||||
|
||||
@@ -94,6 +94,7 @@ Token TokArray[] = {
|
||||
{ "special", 7, T_RemType, PASSTHRU_TYPE },
|
||||
{ "sunday", 3, T_WkDay, 6 },
|
||||
{ "tag", 3, T_Tag, 0 },
|
||||
{ "through", 7, T_Through, 0 },
|
||||
{ "thursday", 3, T_WkDay, 3 },
|
||||
{ "tuesday", 3, T_WkDay, 1 },
|
||||
{ "unset", 5, T_UnSet, 0 },
|
||||
@@ -146,9 +147,9 @@ char const *FindInitialToken(Token *tok, char const *s)
|
||||
|
||||
tok->type = T_Illegal;
|
||||
|
||||
while (isspace(*s)) s++;
|
||||
while (isempty(*s)) s++;
|
||||
|
||||
while (*s && !isspace(*s)) {
|
||||
while (*s && !isempty(*s)) {
|
||||
if (DBufPutc(&buf, *s++) != OK) return s;
|
||||
}
|
||||
|
||||
@@ -359,7 +360,7 @@ static int TokStrCmp(Token const *t, char const *s)
|
||||
register int r;
|
||||
char const *tk = t->name;
|
||||
while(*tk && *s && !(*s == ',' && *(s+1) == 0)) {
|
||||
r = *tk - tolower(*s);
|
||||
r = tolower(*tk) - tolower(*s);
|
||||
tk++;
|
||||
s++;
|
||||
if (r) return r;
|
||||
@@ -367,5 +368,5 @@ static int TokStrCmp(Token const *t, char const *s)
|
||||
/* Ignore trailing commas on s */
|
||||
|
||||
if (!*s || (*s == ',' && !*(s+1))) return 0;
|
||||
return (*tk - *s);
|
||||
return (tolower(*tk) - tolower(*s));
|
||||
}
|
||||
|
||||
@@ -301,7 +301,10 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
|
||||
/* First: Have we passed the UNTIL date? */
|
||||
if (trig->until != NO_UNTIL &&
|
||||
trig->until < start) return -1; /* expired */
|
||||
trig->until < start) {
|
||||
trig->expired = 1;
|
||||
return -1; /* expired */
|
||||
}
|
||||
|
||||
/* Next: If it's an "AFTER"-type skip, back up
|
||||
until we're at the start of a block of holidays */
|
||||
@@ -422,6 +425,7 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
|
||||
y, m, d, omit,
|
||||
result;
|
||||
|
||||
trig->expired = 0;
|
||||
if (save_in_globals) LastTrigValid = 0;
|
||||
|
||||
/* Assume everything works */
|
||||
@@ -449,6 +453,7 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
|
||||
/* If there's an error, die immediately */
|
||||
if (*err) return -1;
|
||||
if (result == -1) {
|
||||
trig->expired = 1;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%d): %s\n",
|
||||
FileName, LineNo, ErrMsg[E_EXPIRED]);
|
||||
@@ -485,6 +490,7 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
|
||||
if (trig->back == NO_BACK &&
|
||||
trig->skip == NO_SKIP &&
|
||||
trig->rep == NO_REP) {
|
||||
trig->expired = 1;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%d): %s\n",
|
||||
FileName, LineNo, ErrMsg[E_EXPIRED]);
|
||||
@@ -513,6 +519,7 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
|
||||
LastTrigValid = 1;
|
||||
}
|
||||
}
|
||||
trig->expired = 1;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%d): %s\n",
|
||||
FileName, LineNo, ErrMsg[E_EXPIRED]);
|
||||
|
||||
@@ -41,6 +41,7 @@ typedef struct {
|
||||
char const *name;
|
||||
char minargs;
|
||||
char maxargs;
|
||||
char is_constant;
|
||||
int (*func)(func_info *);
|
||||
} BuiltinFunc;
|
||||
|
||||
@@ -54,6 +55,7 @@ typedef struct var {
|
||||
|
||||
/* A trigger */
|
||||
typedef struct {
|
||||
int expired;
|
||||
int wd;
|
||||
int d;
|
||||
int m;
|
||||
@@ -71,7 +73,7 @@ typedef struct {
|
||||
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
|
||||
char warn[VAR_NAME_LEN+1]; /* Warning function */
|
||||
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
|
||||
char tag[TAG_LEN+1];
|
||||
DynamicBuffer tags;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
} Trigger;
|
||||
|
||||
@@ -95,6 +97,7 @@ typedef struct {
|
||||
DynamicBuffer pushedToken; /* Pushed-back token */
|
||||
char const *tokenPushed; /* NULL if no pushed-back token */
|
||||
char expr_happened; /* Did we encounter an [expression] ? */
|
||||
char nonconst_expr; /* Did we encounter a non-constant [expression] ? */
|
||||
} Parser;
|
||||
|
||||
typedef Parser *ParsePtr; /* Pointer to parser structure */
|
||||
@@ -164,7 +167,8 @@ enum TokTypes
|
||||
T_Tag,
|
||||
T_Duration,
|
||||
T_LongTime,
|
||||
T_OmitFunc
|
||||
T_OmitFunc,
|
||||
T_Through
|
||||
};
|
||||
|
||||
/* The structure of a token */
|
||||
|
||||
@@ -243,7 +243,7 @@ static void FSet(UserFunc *f)
|
||||
/* Call a user-defined function. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int CallUserFunc(char const *name, int nargs)
|
||||
int CallUserFunc(char const *name, int nargs, ParsePtr p)
|
||||
{
|
||||
UserFunc *f;
|
||||
int h = HashVal(name) % FUNC_HASH_SIZE;
|
||||
@@ -299,9 +299,9 @@ int CallUserFunc(char const *name, int nargs)
|
||||
s = f->text;
|
||||
|
||||
/* Skip the opening bracket, if there's one */
|
||||
while (isspace(*s)) s++;
|
||||
while (isempty(*s)) s++;
|
||||
if (*s == BEG_OF_EXPR) s++;
|
||||
h = Evaluate(&s, f->locals);
|
||||
h = Evaluate(&s, f->locals, p);
|
||||
f->IsActive = 0;
|
||||
DestroyLocalVals(f);
|
||||
if (DebugFlag &DB_PRTEXPR) {
|
||||
|
||||
@@ -290,7 +290,7 @@ int SetVar(char const *str, Value *val)
|
||||
/* Get a copy of the value of the variable. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int GetVarValue(char const *str, Value *val, Var *locals)
|
||||
int GetVarValue(char const *str, Value *val, Var *locals, ParsePtr p)
|
||||
{
|
||||
Var *v;
|
||||
|
||||
@@ -302,6 +302,8 @@ int GetVarValue(char const *str, Value *val, Var *locals)
|
||||
v = v->next;
|
||||
}
|
||||
|
||||
/* Global variable... mark expression as non-constant */
|
||||
if (p) p->nonconst_expr = 1;
|
||||
v=FindVar(str, 0);
|
||||
|
||||
if (!v) {
|
||||
@@ -390,6 +392,8 @@ int DoDump(ParsePtr p)
|
||||
Var *v;
|
||||
DynamicBuffer buf;
|
||||
|
||||
if (PurgeMode) return OK;
|
||||
|
||||
DBufInit(&buf);
|
||||
r = ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
|
||||
1
tests/file.ps
Normal file
1
tests/file.ps
Normal file
@@ -0,0 +1 @@
|
||||
(Second-Bit-Of-PS)
|
||||
1
tests/file2.ps
Normal file
1
tests/file2.ps
Normal file
@@ -0,0 +1 @@
|
||||
(Fourth-Bit-Of-PS)
|
||||
7
tests/purge_dir/f1.rem
Normal file
7
tests/purge_dir/f1.rem
Normal file
@@ -0,0 +1,7 @@
|
||||
# This is f1.rem
|
||||
INCLUDE [filedir()]/f2.rem
|
||||
INCLUDE [filedir()]/f2.rem
|
||||
|
||||
REM 1 Oct 1991 MSG old1.
|
||||
|
||||
REM Monday UNTIL 1 Oct 1991 MSG old2.
|
||||
6
tests/purge_dir/f2.rem
Normal file
6
tests/purge_dir/f2.rem
Normal file
@@ -0,0 +1,6 @@
|
||||
# This is f2.rem
|
||||
|
||||
REM 3 feb 2012 MSG new
|
||||
REM 3 1998 MSG old
|
||||
|
||||
INCLUDE [filedir()]/f3.rem
|
||||
92
tests/purge_dir/f3.rem
Normal file
92
tests/purge_dir/f3.rem
Normal file
@@ -0,0 +1,92 @@
|
||||
# This is f3.rem
|
||||
|
||||
REM Mon MSG repeat
|
||||
|
||||
REM Mon SATISFY [1] MSG repeat
|
||||
|
||||
IF 0
|
||||
REM 1991 MSG wookie
|
||||
ENDIF
|
||||
|
||||
IF 1
|
||||
REM 1991 MSG wookie
|
||||
ENDIF
|
||||
|
||||
IFTRIG 1991
|
||||
REM MSG wookie
|
||||
ENDIF
|
||||
|
||||
# More complex conditional statements
|
||||
IF 1
|
||||
IF 0
|
||||
REM 1991 MSG wookie
|
||||
ELSE
|
||||
REM 1991 MSG wookie
|
||||
ENDIF
|
||||
ELSE
|
||||
IF 1
|
||||
REM 1991 MSG wookie
|
||||
ELSE
|
||||
REM 1991 MSG wookie
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
REM [1990+1] MSG old-with-constant-expression
|
||||
|
||||
REM [1990+1] \
|
||||
MSG Continued line-old-with-constant-expression
|
||||
|
||||
REM 1990 \
|
||||
MSG expired-continued-line
|
||||
|
||||
set y 1990
|
||||
|
||||
REM [y+1] MSG old-with-nonconstant-expression
|
||||
|
||||
# A comment that should be preserved
|
||||
|
||||
#!P A comment that should be nuked because it \
|
||||
starts with #!P
|
||||
|
||||
REM [y+1] \
|
||||
MSG Continued-line-old-with-nonconstant-expression
|
||||
|
||||
OMIT 25 Dec MSG woaaahh!
|
||||
OMIT 24 Dec
|
||||
|
||||
OMIT 1 Jan 1992 MSG woaaahah... expired
|
||||
OMIT 2 Jan 1992
|
||||
|
||||
# Complicated expressions
|
||||
SET a 3
|
||||
FSET const(x) x+3
|
||||
FSET nonconst(x) x+a
|
||||
|
||||
REM [const(5)] Jan 1992 MSG expired... should be commented out
|
||||
REM [const(a)] Jan 1992 MSG nonconstant expression
|
||||
REM [nonconst(5)] Jan 1992 MSG nonconstant expression
|
||||
REM [value("a")] Jan 1992 MSG nonconstant expression
|
||||
|
||||
IF 0
|
||||
# A comment in a false IF block
|
||||
#!P This should be nuked
|
||||
ENDIF
|
||||
|
||||
# Busted line
|
||||
REM [0/0] Jan 1992 MSG ouch
|
||||
|
||||
ERRMSG blorky
|
||||
FLUSH
|
||||
SET a 1
|
||||
FSET a(x) x*x
|
||||
UNSET a
|
||||
CLEAR-OMIT-CONTEXT
|
||||
PUSH-OMIT-CONTEXT
|
||||
POP-OMIT-CONTEXT
|
||||
BANNER wow
|
||||
DEBUG +x
|
||||
DEBUG -x
|
||||
DUMP $
|
||||
EXIT 0
|
||||
PRESERVE i
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
set $MinsFromUTC -240
|
||||
set $CalcUTC 0
|
||||
set $Location "Ottawa"
|
||||
set $LongDeg 75
|
||||
set $LongMin 39
|
||||
set $LongSec 0
|
||||
set $LatDeg 45
|
||||
set $LatMin 24
|
||||
set $LatSec 0
|
||||
|
||||
IF $PSCAL
|
||||
[trigger(moondate(0))] SPECIAL MOON 0 -1 -1 [moontime(0)]
|
||||
[trigger(moondate(1))] SPECIAL MOON 1 -1 -1 [moontime(1)]
|
||||
@@ -5,6 +15,11 @@ IF $PSCAL
|
||||
[trigger(moondate(3))] SPECIAL MOON 3 -1 -1 [moontime(3)]
|
||||
ENDIF
|
||||
|
||||
REM 4 PS (First-Bit-Of-PS)
|
||||
REM 4 PSFILE file.ps
|
||||
REM 4 PS (Third-Bit-Of-PS)
|
||||
REM 4 PSFILE file2.ps
|
||||
|
||||
REM Mon SPECIAL SHADE 255 255 255
|
||||
REM Tue SPECIAL SHADE 255 255 204
|
||||
REM Wed SPECIAL SHADE 255 204 255
|
||||
|
||||
@@ -22,28 +22,28 @@ chmod 000 include_dir/04cantread.rem
|
||||
TEST_GETENV="foo bar baz" ; export TEST_GETENV
|
||||
echo "Test 1" > ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -e -dxte ../tests/test.rem 16 feb 1991 >> ../tests/test.out
|
||||
../src/remind -e -dxte ../tests/test.rem 16 feb 1991 >> ../tests/test.out 2>&1
|
||||
echo "" >> ../tests/test.out
|
||||
echo "Test 2" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -l ../tests/test2.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -p -l ../tests/test2.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "" >> ../tests/test.out
|
||||
echo "Test 3" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -s ../tests/test2.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -s ../tests/test2.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "" >> ../tests/test.out
|
||||
echo "Test 4" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -sa ../tests/test2.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -sa ../tests/test2.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "Test 5" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -l -b0 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -p -l -b0 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "Test 6" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -l -b1 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -p -l -b1 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "Test 7" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -l -b2 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -p -l -b2 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Test 8" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
@@ -58,15 +58,25 @@ echo "" >> ../tests/test.out
|
||||
chmod 644 include_dir/04cantread.rem
|
||||
|
||||
echo "Color Test" >> ../tests/test.out
|
||||
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "MON WKDAY DAY across year test" >> ../tests/test.out
|
||||
echo 'REM Mon 29 Dec MSG x' | ../src/remind -dt - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Sort Test" >> ../tests/test.out
|
||||
(echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -gaaa - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
(echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -gaaad - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
(echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -q -gaaa - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
(echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -q -gaaad - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Purge Test" >> ../tests/test.out
|
||||
../src/remind -j999 ../tests/purge_dir/f1.rem >> ../tests/test.out 2>&1
|
||||
echo "F1" >> ../tests/test.out
|
||||
cat ../tests/purge_dir/f1.rem.purged >> ../tests/test.out
|
||||
echo "F2" >> ../tests/test.out
|
||||
cat ../tests/purge_dir/f2.rem.purged >> ../tests/test.out
|
||||
echo "F3" >> ../tests/test.out
|
||||
cat ../tests/purge_dir/f3.rem.purged >> ../tests/test.out
|
||||
|
||||
rm -f ../tests/purge_dir/*.rem.purged >> ../tests/test.out 2>&1
|
||||
../src/remind ../tests/runtest.rem >> ../tests/test.out 2>&1
|
||||
|
||||
../src/remind -p ../tests/shade.rem 1 August 2009 | ../src/rem2ps -e -l -c3 >> ../tests/test.out 2>&1
|
||||
|
||||
347
tests/test.cmp
347
tests/test.cmp
@@ -274,217 +274,221 @@ hebdate(29, "Adar A", 1991-02-16, 5756) => ../tests/test.rem(46): No Adar A in 5
|
||||
Invalid Hebrew date
|
||||
Leaving UserFN _i() => Invalid Hebrew date
|
||||
|
||||
# This causes a parse error on version 03.01.01
|
||||
REM 1990-01-01 SATISFY 1
|
||||
../tests/test.rem(49): Expired
|
||||
|
||||
# Test each possible case of the basic reminders.
|
||||
|
||||
REM MSG Every Day
|
||||
../tests/test.rem(50): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(53): Trig = Saturday, 16 February, 1991
|
||||
Every Day
|
||||
|
||||
|
||||
REM 18 MSG Every 18th
|
||||
../tests/test.rem(52): Trig = Monday, 18 February, 1991
|
||||
../tests/test.rem(55): Trig = Monday, 18 February, 1991
|
||||
REM 15 MSG Every 15th
|
||||
../tests/test.rem(53): Trig = Friday, 15 March, 1991
|
||||
../tests/test.rem(56): Trig = Friday, 15 March, 1991
|
||||
|
||||
REM Feb MSG February
|
||||
../tests/test.rem(55): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(58): Trig = Saturday, 16 February, 1991
|
||||
February
|
||||
|
||||
REM Jan MSG January
|
||||
../tests/test.rem(56): Trig = Wednesday, 1 January, 1992
|
||||
../tests/test.rem(59): Trig = Wednesday, 1 January, 1992
|
||||
REM March MSG March
|
||||
../tests/test.rem(57): Trig = Friday, 1 March, 1991
|
||||
../tests/test.rem(60): Trig = Friday, 1 March, 1991
|
||||
|
||||
REM 13 Jan MSG 13 Jan
|
||||
../tests/test.rem(59): Trig = Monday, 13 January, 1992
|
||||
../tests/test.rem(62): Trig = Monday, 13 January, 1992
|
||||
REM 15 Feb MSG 15 Feb
|
||||
../tests/test.rem(60): Trig = Saturday, 15 February, 1992
|
||||
../tests/test.rem(63): Trig = Saturday, 15 February, 1992
|
||||
REM 28 Feb MSG 28 Feb
|
||||
../tests/test.rem(61): Trig = Thursday, 28 February, 1991
|
||||
../tests/test.rem(64): Trig = Thursday, 28 February, 1991
|
||||
REM 29 Feb MSG 29 Feb
|
||||
../tests/test.rem(62): Trig = Saturday, 29 February, 1992
|
||||
../tests/test.rem(65): Trig = Saturday, 29 February, 1992
|
||||
REM 5 Mar MSG 5 Mar
|
||||
../tests/test.rem(63): Trig = Tuesday, 5 March, 1991
|
||||
../tests/test.rem(66): Trig = Tuesday, 5 March, 1991
|
||||
|
||||
REM 1990 MSG 1990
|
||||
../tests/test.rem(65): Expired
|
||||
../tests/test.rem(68): Expired
|
||||
REM 1991 MSG 1991
|
||||
../tests/test.rem(66): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(69): Trig = Saturday, 16 February, 1991
|
||||
1991
|
||||
|
||||
REM 1992 MSG 1991
|
||||
../tests/test.rem(67): Trig = Wednesday, 1 January, 1992
|
||||
../tests/test.rem(70): Trig = Wednesday, 1 January, 1992
|
||||
|
||||
REM 1 1990 MSG 1 1990
|
||||
../tests/test.rem(69): Expired
|
||||
../tests/test.rem(72): Expired
|
||||
REM 29 1991 MSG 29 1991
|
||||
../tests/test.rem(70): Trig = Friday, 29 March, 1991
|
||||
../tests/test.rem(73): Trig = Friday, 29 March, 1991
|
||||
REM 29 1992 MSG 29 1992
|
||||
../tests/test.rem(71): Trig = Wednesday, 29 January, 1992
|
||||
../tests/test.rem(74): Trig = Wednesday, 29 January, 1992
|
||||
REM 16 1991 MSG 16 1991
|
||||
../tests/test.rem(72): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(75): Trig = Saturday, 16 February, 1991
|
||||
16 1991
|
||||
|
||||
|
||||
REM Jan 1990 MSG Jan 1990
|
||||
../tests/test.rem(74): Expired
|
||||
../tests/test.rem(77): Expired
|
||||
REM Feb 1991 MSG Feb 1991
|
||||
../tests/test.rem(75): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(78): Trig = Saturday, 16 February, 1991
|
||||
Feb 1991
|
||||
|
||||
REM Dec 1991 MSG Dec 1991
|
||||
../tests/test.rem(76): Trig = Sunday, 1 December, 1991
|
||||
../tests/test.rem(79): Trig = Sunday, 1 December, 1991
|
||||
REM May 1992 MSG May 1992
|
||||
../tests/test.rem(77): Trig = Friday, 1 May, 1992
|
||||
../tests/test.rem(80): Trig = Friday, 1 May, 1992
|
||||
|
||||
REM 1 Jan 1991 MSG 1 Jan 1991
|
||||
../tests/test.rem(79): Expired
|
||||
../tests/test.rem(82): Expired
|
||||
REM 16 Feb 1991 MSG 16 Feb 1991
|
||||
../tests/test.rem(80): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(83): Trig = Saturday, 16 February, 1991
|
||||
16 Feb 1991
|
||||
|
||||
REM 29 Dec 1992 MSG 29 Dec 1992
|
||||
../tests/test.rem(81): Trig = Tuesday, 29 December, 1992
|
||||
../tests/test.rem(84): Trig = Tuesday, 29 December, 1992
|
||||
|
||||
REM Sun MSG Sun
|
||||
../tests/test.rem(83): Trig = Sunday, 17 February, 1991
|
||||
../tests/test.rem(86): Trig = Sunday, 17 February, 1991
|
||||
REM Fri Sat Tue MSG Fri Sat Tue
|
||||
../tests/test.rem(84): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(87): Trig = Saturday, 16 February, 1991
|
||||
Fri Sat Tue
|
||||
|
||||
|
||||
REM Sun 16 MSG Sun 16
|
||||
../tests/test.rem(86): Trig = Sunday, 17 February, 1991
|
||||
../tests/test.rem(89): Trig = Sunday, 17 February, 1991
|
||||
REM Mon Tue Wed Thu Fri 1 MSG Mon Tue Wed Thu Fri 1
|
||||
../tests/test.rem(87): Trig = Friday, 1 March, 1991
|
||||
../tests/test.rem(90): Trig = Friday, 1 March, 1991
|
||||
|
||||
REM Sun Feb MSG Sun Feb
|
||||
../tests/test.rem(89): Trig = Sunday, 17 February, 1991
|
||||
../tests/test.rem(92): Trig = Sunday, 17 February, 1991
|
||||
REM Mon Tue March MSG Mon Tue March
|
||||
../tests/test.rem(90): Trig = Monday, 4 March, 1991
|
||||
../tests/test.rem(93): Trig = Monday, 4 March, 1991
|
||||
|
||||
REM Sun 16 Feb MSG Sun 16 Feb
|
||||
../tests/test.rem(92): Trig = Sunday, 17 February, 1991
|
||||
../tests/test.rem(95): Trig = Sunday, 17 February, 1991
|
||||
REM Mon Tue 10 March MSG Mon Tue 10 March
|
||||
../tests/test.rem(93): Trig = Monday, 11 March, 1991
|
||||
../tests/test.rem(96): Trig = Monday, 11 March, 1991
|
||||
|
||||
REM Sat Sun 1991 MSG Sat Sun 1991
|
||||
../tests/test.rem(95): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(98): Trig = Saturday, 16 February, 1991
|
||||
Sat Sun 1991
|
||||
|
||||
REM Mon Tue 1992 MSG Mon Tue 1992
|
||||
../tests/test.rem(96): Trig = Monday, 6 January, 1992
|
||||
../tests/test.rem(99): Trig = Monday, 6 January, 1992
|
||||
|
||||
REM Sun 16 1991 MSG Sun 16 1991
|
||||
../tests/test.rem(98): Trig = Sunday, 17 February, 1991
|
||||
../tests/test.rem(101): Trig = Sunday, 17 February, 1991
|
||||
REM Mon Tue Wed Thu Fri 1 1992 MSG Mon Tue Wed Thu Fri 1 1992
|
||||
../tests/test.rem(99): Trig = Wednesday, 1 January, 1992
|
||||
../tests/test.rem(102): Trig = Wednesday, 1 January, 1992
|
||||
|
||||
REM Mon Feb 1991 MSG Mon Feb 1991
|
||||
../tests/test.rem(101): Trig = Monday, 18 February, 1991
|
||||
../tests/test.rem(104): Trig = Monday, 18 February, 1991
|
||||
REM Tue Jan 1992 MSG Tue Jan 1992
|
||||
../tests/test.rem(102): Trig = Tuesday, 7 January, 1992
|
||||
../tests/test.rem(105): Trig = Tuesday, 7 January, 1992
|
||||
|
||||
REM Sun Mon 16 Feb 1991 MSG Sun Mon 16 Feb 1991
|
||||
../tests/test.rem(104): Trig = Sunday, 17 February, 1991
|
||||
../tests/test.rem(107): Trig = Sunday, 17 February, 1991
|
||||
REM Tue 28 Jan 1992 MSG Tue 28 Jan 1992
|
||||
../tests/test.rem(105): Trig = Tuesday, 28 January, 1992
|
||||
../tests/test.rem(108): Trig = Tuesday, 28 January, 1992
|
||||
|
||||
# Try some Backs
|
||||
CLEAR-OMIT-CONTEXT
|
||||
REM 1 -1 OMIT sat sun MSG 1 -1 OMIT Sat Sun
|
||||
../tests/test.rem(109): Trig = Thursday, 28 February, 1991
|
||||
../tests/test.rem(112): Trig = Thursday, 28 February, 1991
|
||||
REM 1 --1 OMIT sat sun MSG 1 --1 OMIT Sat Sun
|
||||
../tests/test.rem(110): Trig = Thursday, 28 February, 1991
|
||||
../tests/test.rem(113): Trig = Thursday, 28 February, 1991
|
||||
|
||||
OMIT 28 Feb
|
||||
REM 1 -1 OMIT sat sun MSG 1 -1 OMIT Sat Sun (28 Feb omitted)
|
||||
../tests/test.rem(113): Trig = Wednesday, 27 February, 1991
|
||||
../tests/test.rem(116): Trig = Wednesday, 27 February, 1991
|
||||
REM 1 --1 OMIT sat sun MSG 1 --1 OMIT Sat Sun (28 Feb omitted)
|
||||
../tests/test.rem(114): Trig = Thursday, 28 February, 1991
|
||||
../tests/test.rem(117): Trig = Thursday, 28 February, 1991
|
||||
|
||||
CLEAR-OMIT-CONTEXT
|
||||
|
||||
# Try out UNTIL
|
||||
REM Wed UNTIL 21 Feb 1991 MSG Wed UNTIL 21 Feb 1991
|
||||
../tests/test.rem(119): Trig = Wednesday, 20 February, 1991
|
||||
../tests/test.rem(122): Trig = Wednesday, 20 February, 1991
|
||||
|
||||
# Try playing with the OMIT context
|
||||
|
||||
OMIT 28 Feb 1991
|
||||
REM 1 Mar -1 MSG 1 mar -1 (28feb91 omitted)
|
||||
../tests/test.rem(124): Trig = Wednesday, 27 February, 1991
|
||||
../tests/test.rem(127): Trig = Wednesday, 27 February, 1991
|
||||
REM 1 Mar --1 MSG 1 mar --1 (28Feb91 omitted)
|
||||
../tests/test.rem(125): Trig = Thursday, 28 February, 1991
|
||||
../tests/test.rem(128): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb BEFORE MSG 28 Feb BEFORE (28Feb91 omitted)
|
||||
../tests/test.rem(126): Trig = Wednesday, 27 February, 1991
|
||||
../tests/test.rem(129): Trig = Wednesday, 27 February, 1991
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP (28Feb91 omitted)
|
||||
../tests/test.rem(127): Trig = Friday, 28 February, 1992
|
||||
../tests/test.rem(130): Trig = Friday, 28 February, 1992
|
||||
REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
|
||||
../tests/test.rem(128): Trig = Friday, 1 March, 1991
|
||||
../tests/test.rem(131): Trig = Friday, 1 March, 1991
|
||||
|
||||
PUSH-OMIT-CONTEXT
|
||||
CLEAR-OMIT-CONTEXT
|
||||
REM 1 Mar -1 MSG 1 mar -1
|
||||
../tests/test.rem(132): Trig = Thursday, 28 February, 1991
|
||||
REM 1 Mar --1 MSG 1 mar --1
|
||||
../tests/test.rem(133): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb BEFORE MSG 28 Feb BEFORE
|
||||
../tests/test.rem(134): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP
|
||||
../tests/test.rem(135): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb AFTER MSG 28 Feb AFTER
|
||||
REM 1 Mar --1 MSG 1 mar --1
|
||||
../tests/test.rem(136): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb BEFORE MSG 28 Feb BEFORE
|
||||
../tests/test.rem(137): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP
|
||||
../tests/test.rem(138): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb AFTER MSG 28 Feb AFTER
|
||||
../tests/test.rem(139): Trig = Thursday, 28 February, 1991
|
||||
|
||||
POP-OMIT-CONTEXT
|
||||
REM 1 Mar -1 MSG 1 mar -1 (28feb91 omitted)
|
||||
../tests/test.rem(139): Trig = Wednesday, 27 February, 1991
|
||||
../tests/test.rem(142): Trig = Wednesday, 27 February, 1991
|
||||
REM 1 Mar --1 MSG 1 mar --1 (28Feb91 omitted)
|
||||
../tests/test.rem(140): Trig = Thursday, 28 February, 1991
|
||||
../tests/test.rem(143): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb BEFORE MSG 28 Feb BEFORE (28Feb91 omitted)
|
||||
../tests/test.rem(141): Trig = Wednesday, 27 February, 1991
|
||||
../tests/test.rem(144): Trig = Wednesday, 27 February, 1991
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP (28Feb91 omitted)
|
||||
../tests/test.rem(142): Trig = Friday, 28 February, 1992
|
||||
../tests/test.rem(145): Trig = Friday, 28 February, 1992
|
||||
REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
|
||||
../tests/test.rem(143): Trig = Friday, 1 March, 1991
|
||||
../tests/test.rem(146): Trig = Friday, 1 March, 1991
|
||||
|
||||
|
||||
REM 13 March 1991 *1 UNTIL 19 March 1991 MSG 13-19 Mar 91
|
||||
../tests/test.rem(146): Trig = Wednesday, 13 March, 1991
|
||||
../tests/test.rem(149): Trig = Wednesday, 13 March, 1991
|
||||
|
||||
# Test BACK
|
||||
CLEAR-OMIT-CONTEXT
|
||||
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1
|
||||
../tests/test.rem(150): Trig = Monday, 18 February, 1991
|
||||
../tests/test.rem(153): Trig = Monday, 18 February, 1991
|
||||
|
||||
OMIT 17 Feb 1991
|
||||
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1 (17Feb91 omitted)
|
||||
../tests/test.rem(153): Trig = Monday, 18 February, 1991
|
||||
../tests/test.rem(156): Trig = Monday, 18 February, 1991
|
||||
18 Feb 1991 +1 (17Feb91 omitted)
|
||||
|
||||
REM 18 Feb 1991 ++1 MSG 18 Feb 1991 ++1 (17Feb91 omitted)
|
||||
../tests/test.rem(154): Trig = Monday, 18 February, 1991
|
||||
../tests/test.rem(157): Trig = Monday, 18 February, 1991
|
||||
|
||||
CLEAR-OMIT-CONTEXT
|
||||
# Test the scanfrom clause
|
||||
REM Fri SATISFY 1
|
||||
../tests/test.rem(158): Trig = Friday, 22 February, 1991
|
||||
../tests/test.rem(161): Trig = Friday, 22 February, 1991
|
||||
OMIT [trigger(trigdate())]
|
||||
trigdate() => 1991-02-22
|
||||
trigger(1991-02-22) => "22 February 1991"
|
||||
REM Fri after MSG 23 Feb 1991
|
||||
../tests/test.rem(160): Trig = Saturday, 23 February, 1991
|
||||
../tests/test.rem(163): Trig = Saturday, 23 February, 1991
|
||||
CLEAR-OMIT-CONTEXT
|
||||
REM Fri SCANFROM [trigger(today()-7)] SATISFY 1
|
||||
today() => 1991-02-16
|
||||
1991-02-16 - 7 => 1991-02-09
|
||||
trigger(1991-02-09) => "9 February 1991"
|
||||
../tests/test.rem(162): Trig = Friday, 15 February, 1991
|
||||
../tests/test.rem(165): Trig = Friday, 15 February, 1991
|
||||
OMIT [trigger(trigdate())]
|
||||
trigdate() => 1991-02-15
|
||||
trigger(1991-02-15) => "15 February 1991"
|
||||
REM Fri after MSG 16 Feb 1991
|
||||
../tests/test.rem(164): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(167): Trig = Saturday, 16 February, 1991
|
||||
16 Feb 1991
|
||||
|
||||
CLEAR-OMIT-CONTEXT
|
||||
@@ -582,7 +586,7 @@ day(1991-03-08) => 8
|
||||
8 % 2 => 0
|
||||
0 || 0 => 0
|
||||
Leaving UserFN _ofunc() => 0
|
||||
../tests/test.rem(169): Trig = Friday, 8 March, 1991
|
||||
../tests/test.rem(172): Trig = Friday, 8 March, 1991
|
||||
REM 8 March OMITFUNC _ofunc -1 MSG OmitFunc Test 2
|
||||
Entering UserFN _ofunc(1991-03-07)
|
||||
x => 1991-03-07
|
||||
@@ -656,31 +660,31 @@ day(1991-02-28) => 28
|
||||
28 % 2 => 0
|
||||
0 || 0 => 0
|
||||
Leaving UserFN _ofunc() => 0
|
||||
../tests/test.rem(170): Trig = Thursday, 28 February, 1991
|
||||
../tests/test.rem(173): Trig = Thursday, 28 February, 1991
|
||||
|
||||
# omitfunc ignores local/global omits
|
||||
fset _ofunc(x) 0
|
||||
OMIT 1 March
|
||||
OMIT 2 March 1991
|
||||
REM 1 March OMIT Sun OMITFUNC _ofunc AFTER MSG Should trigger 1 March
|
||||
../tests/test.rem(176): Warning: OMIT is ignored if you use OMITFUNC
|
||||
../tests/test.rem(179): Warning: OMIT is ignored if you use OMITFUNC
|
||||
Entering UserFN _ofunc(1991-02-15)
|
||||
Leaving UserFN _ofunc() => 0
|
||||
Entering UserFN _ofunc(1991-03-01)
|
||||
Leaving UserFN _ofunc() => 0
|
||||
../tests/test.rem(176): Trig = Friday, 1 March, 1991
|
||||
../tests/test.rem(179): Trig = Friday, 1 March, 1991
|
||||
REM 1 March OMIT Sun AFTER MSG Should trigger 4 March
|
||||
../tests/test.rem(177): Trig = Monday, 4 March, 1991
|
||||
../tests/test.rem(180): Trig = Monday, 4 March, 1991
|
||||
|
||||
# Test shorthand reminders
|
||||
REM 1991-02-28 MSG Feb 28
|
||||
../tests/test.rem(180): Trig = Thursday, 28 February, 1991
|
||||
../tests/test.rem(183): Trig = Thursday, 28 February, 1991
|
||||
REM 1991/02/28@14:45 MSG Feb 28
|
||||
../tests/test.rem(181): Trig = Thursday, 28 February, 1991
|
||||
../tests/test.rem(184): Trig = Thursday, 28 February, 1991
|
||||
REM Wed UNTIL 1991-01-01 MSG Expired
|
||||
../tests/test.rem(182): Expired
|
||||
../tests/test.rem(185): Expired
|
||||
REM Wed SCANFROM 1991-02-26 MSG SCANFROM
|
||||
../tests/test.rem(183): Trig = Wednesday, 27 February, 1991
|
||||
../tests/test.rem(186): Trig = Wednesday, 27 February, 1991
|
||||
|
||||
set a000 abs(1)
|
||||
abs(1) => 1
|
||||
@@ -704,7 +708,7 @@ set a008 coerce("string", 11:44)
|
||||
coerce("string", 11:44) => "11:44"
|
||||
set a009 coerce("int", "badnews")
|
||||
coerce("int", "badnews") => Can't coerce
|
||||
../tests/test.rem(194): Can't coerce
|
||||
../tests/test.rem(197): Can't coerce
|
||||
set a010 coerce("int", "12")
|
||||
coerce("int", "12") => 12
|
||||
set a011 coerce("int", 11:44)
|
||||
@@ -716,7 +720,7 @@ set a013 date(1992, 2, 2)
|
||||
date(1992, 2, 2) => 1992-02-02
|
||||
set a014 date(1993, 2, 29)
|
||||
date(1993, 2, 29) => Bad date specification
|
||||
../tests/test.rem(199): Bad date specification
|
||||
../tests/test.rem(202): Bad date specification
|
||||
set a015 day(today())
|
||||
today() => 1991-02-16
|
||||
day(1991-02-16) => 16
|
||||
@@ -811,15 +815,15 @@ strlen("sadjflkhsldkfhsdlfjhk") => 21
|
||||
set a050 substr(a049, 2)
|
||||
a049 => 21
|
||||
substr(21, 2) => Type mismatch
|
||||
../tests/test.rem(237): Type mismatch
|
||||
../tests/test.rem(240): Type mismatch
|
||||
set a051 substr(a050, 2, 6)
|
||||
a050 => ../tests/test.rem(238): Undefined variable: a050
|
||||
a050 => ../tests/test.rem(241): Undefined variable: a050
|
||||
set a052 time(1+2, 3+4)
|
||||
1 + 2 => 3
|
||||
3 + 4 => 7
|
||||
time(3, 7) => 03:07
|
||||
rem 10 jan 1992 AT 11:22 CAL
|
||||
../tests/test.rem(240): Trig = Friday, 10 January, 1992
|
||||
../tests/test.rem(243): Trig = Friday, 10 January, 1992
|
||||
set a053 trigdate()
|
||||
trigdate() => 1992-01-10
|
||||
set a054 trigtime()
|
||||
@@ -832,7 +836,7 @@ set a057 value("a05"+"6")
|
||||
"a05" + "6" => "a056"
|
||||
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
set a058 version()
|
||||
version() => "03.01.08"
|
||||
version() => "03.01.10"
|
||||
set a059 wkday(today())
|
||||
today() => 1991-02-16
|
||||
wkday(1991-02-16) => "Saturday"
|
||||
@@ -911,31 +915,31 @@ y => 11:33
|
||||
x => "foo"
|
||||
y => 11:33
|
||||
"foo" * 11:33 => Type mismatch
|
||||
../tests/test.rem(263): `*': Type mismatch
|
||||
../tests/test.rem(266): `*': Type mismatch
|
||||
Leaving UserFN h() => Type mismatch
|
||||
set a074 dosubst("%a %b %c %d %e %f %g %h", '1992/5/5')
|
||||
dosubst("%a %b %c %d %e %f %g %h", 1992-05-05) => "on Tuesday, 5 May, 1992 in 444 days' tim"...
|
||||
msg [a074]%
|
||||
../tests/test.rem(265): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(268): Trig = Saturday, 16 February, 1991
|
||||
a074 => "on Tuesday, 5 May, 1992 in 444 days' tim"...
|
||||
on Tuesday, 5 May, 1992 in 444 days' time on Tuesday 5 on 05-05-1992 on 05-05-1992 on Tuesday, 5 May on 05-05
|
||||
set a075 dosubst("%i %j %k %l %m %n %o %p", '1992/5/5')
|
||||
dosubst("%i %j %k %l %m %n %o %p", 1992-05-05) => "on 05-05 on Tuesday, May 5th, 1992 on Tu"...
|
||||
msg [a075]%
|
||||
../tests/test.rem(267): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(270): Trig = Saturday, 16 February, 1991
|
||||
a075 => "on 05-05 on Tuesday, May 5th, 1992 on Tu"...
|
||||
on 05-05 on Tuesday, May 5th, 1992 on Tuesday, May 5th on 1992-05-05 May 5 s
|
||||
set a076 dosubst("%q %r %s %t %u %v %w %x", '1992/5/5')
|
||||
dosubst("%q %r %s %t %u %v %w %x", 1992-05-05) => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
|
||||
msg [a076]%
|
||||
../tests/test.rem(269): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(272): Trig = Saturday, 16 February, 1991
|
||||
a076 => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
|
||||
s' 05 th 05 on Tuesday, 5th May, 1992 on Tuesday, 5th May Tuesday 444
|
||||
set a077 dosubst("%y %z", '1992/5/5')
|
||||
dosubst("%y %z", 1992-05-05) => "1992 92
|
||||
"
|
||||
msg [a077]%
|
||||
../tests/test.rem(271): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(274): Trig = Saturday, 16 February, 1991
|
||||
a077 => "1992 92
|
||||
"
|
||||
1992 92
|
||||
@@ -985,7 +989,7 @@ dump
|
||||
a048 "foo"
|
||||
a067 "INT"
|
||||
a039 "February"
|
||||
a058 "03.01.08"
|
||||
a058 "03.01.10"
|
||||
a077 "1992 92
|
||||
"
|
||||
a049 21
|
||||
@@ -1042,6 +1046,32 @@ dump
|
||||
a045 "iess"
|
||||
a064 1
|
||||
a083 1991-03-24
|
||||
OMIT 2010-09-03 THROUGH 2010-09-15
|
||||
OMIT December 25 MSG X
|
||||
../tests/test.rem(286): Trig = Wednesday, 25 December, 1991
|
||||
# Next should give a parse error
|
||||
OMIT 26 Dec 2010 THROUGH 27 Dec 2010 MSG This is not legal
|
||||
../tests/test.rem(288): Trig = Sunday, 26 December, 2010
|
||||
OMIT DUMP
|
||||
Global Full OMITs (16 of maximum allowed 500):
|
||||
1991-03-11
|
||||
2010-09-03
|
||||
2010-09-04
|
||||
2010-09-05
|
||||
2010-09-06
|
||||
2010-09-07
|
||||
2010-09-08
|
||||
2010-09-09
|
||||
2010-09-10
|
||||
2010-09-11
|
||||
2010-09-12
|
||||
2010-09-13
|
||||
2010-09-14
|
||||
2010-09-15
|
||||
2010-12-26
|
||||
2010-12-27
|
||||
Global Partial OMITs (1 of maximum allowed 366):
|
||||
12-25
|
||||
|
||||
|
||||
Test 2
|
||||
@@ -2150,6 +2180,134 @@ Timed
|
||||
|
||||
Untimed
|
||||
|
||||
Purge Test
|
||||
../tests/purge_dir/f3.rem(76): `/': Division by zero
|
||||
../tests/purge_dir/f3.rem(76): `/': Division by zero
|
||||
F1
|
||||
# This is f1.rem
|
||||
INCLUDE [filedir()]/f2.rem
|
||||
INCLUDE [filedir()]/f2.rem
|
||||
|
||||
#!P: Expired: REM 1 Oct 1991 MSG old1.
|
||||
|
||||
#!P: Expired: REM Monday UNTIL 1 Oct 1991 MSG old2.
|
||||
F2
|
||||
# This is f2.rem
|
||||
|
||||
REM 3 feb 2012 MSG new
|
||||
#!P: Expired: REM 3 1998 MSG old
|
||||
|
||||
INCLUDE [filedir()]/f3.rem
|
||||
F3
|
||||
# This is f3.rem
|
||||
|
||||
REM Mon MSG repeat
|
||||
|
||||
#!P: Cannot purge SATISFY-type reminders
|
||||
REM Mon SATISFY [1] MSG repeat
|
||||
|
||||
#!P: The next IF evaluated false...
|
||||
#!P: REM statements in IF block not checked for purging.
|
||||
IF 0
|
||||
REM 1991 MSG wookie
|
||||
ENDIF
|
||||
|
||||
IF 1
|
||||
#!P: Expired: REM 1991 MSG wookie
|
||||
ENDIF
|
||||
|
||||
#!P: The next IFTRIG did not trigger.
|
||||
#!P: REM statements in IFTRIG block not checked for purging.
|
||||
IFTRIG 1991
|
||||
REM MSG wookie
|
||||
ENDIF
|
||||
|
||||
# More complex conditional statements
|
||||
IF 1
|
||||
#!P: The next IF evaluated false...
|
||||
#!P: REM statements in IF block not checked for purging.
|
||||
IF 0
|
||||
REM 1991 MSG wookie
|
||||
ELSE
|
||||
#!P: Expired: REM 1991 MSG wookie
|
||||
ENDIF
|
||||
#!P: The previous IF evaluated true.
|
||||
#!P: REM statements in ELSE block not checked for purging
|
||||
ELSE
|
||||
IF 1
|
||||
REM 1991 MSG wookie
|
||||
ELSE
|
||||
REM 1991 MSG wookie
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
#!P: Next line has expired, but contains expression... please verify
|
||||
#!P: Expired: REM [1990+1] MSG old-with-constant-expression
|
||||
|
||||
#!P: Next line has expired, but contains expression... please verify
|
||||
#!P: Expired: REM [1990+1] \
|
||||
MSG Continued line-old-with-constant-expression
|
||||
|
||||
#!P: Expired: REM 1990 \
|
||||
MSG expired-continued-line
|
||||
|
||||
set y 1990
|
||||
|
||||
#!P: Next line may have expired, but contains non-constant expression
|
||||
REM [y+1] MSG old-with-nonconstant-expression
|
||||
|
||||
# A comment that should be preserved
|
||||
|
||||
|
||||
#!P: Next line may have expired, but contains non-constant expression
|
||||
REM [y+1] \
|
||||
MSG Continued-line-old-with-nonconstant-expression
|
||||
|
||||
OMIT 25 Dec MSG woaaahh!
|
||||
OMIT 24 Dec
|
||||
|
||||
#!P: Expired: OMIT 1 Jan 1992 MSG woaaahah... expired
|
||||
OMIT 2 Jan 1992
|
||||
|
||||
# Complicated expressions
|
||||
SET a 3
|
||||
FSET const(x) x+3
|
||||
FSET nonconst(x) x+a
|
||||
|
||||
#!P: Next line has expired, but contains expression... please verify
|
||||
#!P: Expired: REM [const(5)] Jan 1992 MSG expired... should be commented out
|
||||
#!P: Next line may have expired, but contains non-constant expression
|
||||
REM [const(a)] Jan 1992 MSG nonconstant expression
|
||||
#!P: Next line may have expired, but contains non-constant expression
|
||||
REM [nonconst(5)] Jan 1992 MSG nonconstant expression
|
||||
#!P: Next line may have expired, but contains non-constant expression
|
||||
REM [value("a")] Jan 1992 MSG nonconstant expression
|
||||
|
||||
#!P: The next IF evaluated false...
|
||||
#!P: REM statements in IF block not checked for purging.
|
||||
IF 0
|
||||
# A comment in a false IF block
|
||||
ENDIF
|
||||
|
||||
# Busted line
|
||||
#!P! Could not parse next line: Division by zero
|
||||
REM [0/0] Jan 1992 MSG ouch
|
||||
|
||||
ERRMSG blorky
|
||||
FLUSH
|
||||
SET a 1
|
||||
FSET a(x) x*x
|
||||
UNSET a
|
||||
CLEAR-OMIT-CONTEXT
|
||||
PUSH-OMIT-CONTEXT
|
||||
POP-OMIT-CONTEXT
|
||||
BANNER wow
|
||||
DEBUG +x
|
||||
DEBUG -x
|
||||
DUMP $
|
||||
EXIT 0
|
||||
PRESERVE i
|
||||
|
||||
../tests/runtest.rem(2): shell(): RUN disabled
|
||||
../tests/runinc.rem(1): shell(): RUN disabled
|
||||
../tests/runinc.rem(3): shell(): RUN disabled
|
||||
@@ -2527,7 +2685,10 @@ _A BoxHeight _A sub lineto closepath
|
||||
BoxWidth _A sub _A lineto BoxWidth _A sub BoxHeight _A sub lineto
|
||||
_A BoxHeight _A sub lineto closepath
|
||||
1 1 0.8 setrgbcolor fill 0.0 setgray
|
||||
|
||||
(First-Bit-Of-PS)
|
||||
(Second-Bit-Of-PS)
|
||||
(Third-Bit-Of-PS)
|
||||
(Fourth-Bit-Of-PS)
|
||||
SAVESTATE restore
|
||||
/SAVESTATE save def
|
||||
3 xincr mul MinX add ytop translate
|
||||
|
||||
@@ -45,6 +45,9 @@ fset _i(x,y,z,a) trigger(hebdate(x,y,z,a))
|
||||
[_i(29, "Adar A", today(), 5755)] MSG Leap
|
||||
[_i(29, "Adar A", today(), 5756)] MSG Illegal
|
||||
|
||||
# This causes a parse error on version 03.01.01
|
||||
REM 1990-01-01 SATISFY 1
|
||||
|
||||
# Test each possible case of the basic reminders.
|
||||
|
||||
REM MSG Every Day
|
||||
@@ -279,3 +282,8 @@ set a083 slide('1991-04-01', -7, "Sat")
|
||||
set a084 nonomitted('1991-03-01', '1991-03-13', "Sat", "Sun")
|
||||
set a085 nonomitted('1991-03-24', '1991-04-01', "Sat")
|
||||
dump
|
||||
OMIT 2010-09-03 THROUGH 2010-09-15
|
||||
OMIT December 25 MSG X
|
||||
# Next should give a parse error
|
||||
OMIT 26 Dec 2010 THROUGH 27 Dec 2010 MSG This is not legal
|
||||
OMIT DUMP
|
||||
|
||||
Reference in New Issue
Block a user