mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 14:28:40 +02:00
Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a146a0c819 | ||
|
|
0f5a93cdf1 | ||
|
|
7db51e913e | ||
|
|
93ac1aebf7 | ||
|
|
56ebedb9de | ||
|
|
e87d33de50 | ||
|
|
a5774fd793 | ||
|
|
adb60f3400 | ||
|
|
47a0f63caa | ||
|
|
30a385a7bb | ||
|
|
9f2ae1773c | ||
|
|
f470297958 | ||
|
|
93dfc7995c | ||
|
|
c96869817f | ||
|
|
1bffa0e00b | ||
|
|
36035dda01 | ||
|
|
50a15cf089 | ||
|
|
b59d4ed4a4 | ||
|
|
4c53710279 | ||
|
|
2274e88485 | ||
|
|
984a4677f2 | ||
|
|
5e3dc54725 | ||
|
|
53a7bf9773 | ||
|
|
1dcc3897d6 | ||
|
|
fbc0375739 | ||
|
|
4a74c03fa4 | ||
|
|
d8833e6ce2 | ||
|
|
2b8b9a56aa | ||
|
|
85a8ebb357 | ||
|
|
a67d9e2524 | ||
|
|
6845e72fd5 | ||
|
|
0ab977fa05 | ||
|
|
ad64a12b2a | ||
|
|
cfde4b50bb | ||
|
|
f302c8eb95 | ||
|
|
7ecc355358 | ||
|
|
a52216d7e7 | ||
|
|
8d8d4b667d | ||
|
|
670369121e | ||
|
|
4365e580ee | ||
|
|
a8a09a905e | ||
|
|
dbb7381eb1 | ||
|
|
aa3531a6bf | ||
|
|
2848203d75 | ||
|
|
f0aef0703c | ||
|
|
7356a511e0 | ||
|
|
5be26a3cff | ||
|
|
36a80acb0c | ||
|
|
37ab03b49d | ||
|
|
75209cb40e | ||
|
|
4b2d274748 | ||
|
|
1423495b88 | ||
|
|
42e4ec8890 | ||
|
|
58fbd51ef4 | ||
|
|
7552dbb812 | ||
|
|
31e0ecb71d | ||
|
|
f6743a4f87 | ||
|
|
5f574949e6 | ||
|
|
724bce4fb9 | ||
|
|
8d59f025af | ||
|
|
aad44f4716 | ||
|
|
0a38d7d213 | ||
|
|
4fcd60fd95 | ||
|
|
38beeb8cb0 | ||
|
|
26f0acab35 | ||
|
|
3897973bc1 | ||
|
|
7b3da27461 | ||
|
|
a85ee5f31c | ||
|
|
b272863aa0 | ||
|
|
8249964380 | ||
|
|
af81bbb299 | ||
|
|
d818dd9c80 | ||
|
|
fe8e34dece | ||
|
|
ba928989f7 | ||
|
|
742f973028 | ||
|
|
043932fcbe | ||
|
|
ad5e096caa | ||
|
|
06c8fc8f78 |
@@ -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-2007 Roaring Penguin Software Inc.,
|
||||
2. REMIND is Copyright 1999-2008 Roaring Penguin Software Inc.,
|
||||
except where noted in individual files.
|
||||
|
||||
3. DISTRIBUTION AND USE
|
||||
|
||||
8
configure
vendored
8
configure
vendored
@@ -4690,7 +4690,8 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
for ac_header in sys/file.h
|
||||
|
||||
for ac_header in sys/file.h glob.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
|
||||
@@ -5189,7 +5190,8 @@ fi
|
||||
|
||||
|
||||
|
||||
for ac_func in setenv unsetenv
|
||||
|
||||
for ac_func in setenv unsetenv glob
|
||||
do
|
||||
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
{ echo "$as_me:$LINENO: checking for $ac_func" >&5
|
||||
@@ -5282,7 +5284,7 @@ _ACEOF
|
||||
fi
|
||||
done
|
||||
|
||||
VERSION=03.01.04
|
||||
VERSION=03.01.06
|
||||
|
||||
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h"
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ AC_CHECK_SIZEOF(unsigned int)
|
||||
AC_CHECK_SIZEOF(unsigned long)
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_CHECK_HEADERS(sys/file.h)
|
||||
AC_CHECK_HEADERS(sys/file.h glob.h)
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_STRUCT_TM
|
||||
@@ -44,7 +44,7 @@ if test "$GCC" = yes; then
|
||||
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes"
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(setenv unsetenv)
|
||||
VERSION=03.01.04
|
||||
AC_CHECK_FUNCS(setenv unsetenv glob)
|
||||
VERSION=03.01.06
|
||||
AC_SUBST(VERSION)
|
||||
AC_OUTPUT(src/Makefile www/Makefile src/version.h)
|
||||
|
||||
@@ -1,5 +1,63 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* Version 3.1 Patch 6 - 2008-11-16
|
||||
|
||||
- MAJOR ENHANCEMENT: A new OMITFUNC clause gives you additional
|
||||
control and flexibility over "omitted days" calculations. This is
|
||||
useful when holidays influence the timing of events several days
|
||||
later. See "COMPUTED LOCAL OMITS" in the man page.
|
||||
|
||||
- ENHANCEMENT: The new evaltrig() built-in function lets you evaluate triggers
|
||||
from within an expression.
|
||||
|
||||
- ENHANCEMENT: The new weekno() built-in function returns the ISO 8601
|
||||
week number of a date.
|
||||
|
||||
- ENHANCEMENT: The "WEEK" special lets you annotate calendar output with the
|
||||
week number. The TkRemind, rem2ps and rem2html back-ends support WEEK.
|
||||
|
||||
- MINOR ENHANCEMENT: You can control whether timed reminders come before or
|
||||
after non-timed reminders with the "-g" flag.
|
||||
|
||||
- BUG FIX: TkRemind did not work correctly if ~/.reminders was a directory.
|
||||
|
||||
- BUG FIX: TkRemind incorrectly invoked Remind with the "-a" flag when
|
||||
showing today's reminders.
|
||||
|
||||
- BUG FIX: In certain cases, a trigger containing a day, month and
|
||||
weekday would fail if it needed to cross a year boundary. This has
|
||||
been fixed.
|
||||
|
||||
* Version 3.1 Patch 5 - 2008-04-15
|
||||
|
||||
- MAJOR ENHANCEMENT: If you supply a directory name on the command line
|
||||
or for an INCLUDE command, then Remind reads all *.rem file in that
|
||||
directory (in the order returned by "glob")
|
||||
|
||||
- ENHANCEMENT: The plain-text calendar ("-c") can draw lines using VT-100
|
||||
line-drawing characters if invoked as "-cl"
|
||||
|
||||
- ENHANCEMENT: The plain-text calendar can approximate SPECIAL COLOR reminders
|
||||
using VT-100 color escape sequences if invoked as "-cc". (You can combine
|
||||
the colors and line-drawing characters with -clc or -ccl.)
|
||||
|
||||
- ENHANCEMENT: The "-t" option can take a numeric argument n. In this case,
|
||||
all reminders are assumed to have a delta of +n. (Without the argument,
|
||||
an infinite delta is assumed, as before.) If a numeric argument is given,
|
||||
the new system variable $DeltaOffset is set to the argument.
|
||||
|
||||
- MINOR ENHANCEMENT: The "-i" command-line option can be used to define
|
||||
a function as well as set a variable.
|
||||
|
||||
- MINOR ENHANCEMENT: String constants can have embedded quotes "Like \"this"
|
||||
|
||||
- MINOR ENHANCEMENT: tkremind works better on small screens like that of
|
||||
the Eee-PC.
|
||||
|
||||
- BUG FIX: Minor fix to HTML output courtesy of Ian! Allen.
|
||||
|
||||
- BUG FIX: Parse error in calendar mode was fixed.
|
||||
|
||||
* Version 3.1 Patch 4 - 2008-02-03
|
||||
|
||||
- ENHANCMENT: tkremind respects the "-b1" option and operates in 24-hour
|
||||
@@ -19,6 +77,9 @@ CHANGES TO REMIND
|
||||
- BUG FIX: rem2html would output a horribly-wrong calendar for a 28-day
|
||||
February starting on Sunday (such as February 2009.) This has been fixed.
|
||||
|
||||
- BUG FIX: The "-ivar=value" command-line option failed if Remind re-execed
|
||||
itself because we overwrote argv[]. This has been fixed.
|
||||
|
||||
* Version 3.1 Patch 3 - 2007-10-15
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
319
man/remind.1
319
man/remind.1
@@ -1,4 +1,4 @@
|
||||
.TH REMIND 1 "1 July 2007"
|
||||
.TH REMIND 1 "31 August 2008"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
remind \- a sophisticated reminder service
|
||||
@@ -13,6 +13,13 @@ a program to be executed.
|
||||
If \fIfilename\fR is specified as a single dash '-', then \fBRemind\fR
|
||||
takes its input from standard input. This also implicitly enables
|
||||
the \fB\-o\fR option, described below.
|
||||
.PP
|
||||
If \fIfilename\fR happens to
|
||||
be a directory rather than a plain file, then \fBRemind\fR reads all of
|
||||
the files in that directory that match the pattern "*.rem". The files
|
||||
are read in sorted order; the sort order may depend on your locale, but
|
||||
should match the sort order used by the shell to expand "*.rem".
|
||||
|
||||
.SH OPTIONS
|
||||
\fBRemind\fR has a slew of options. If you're new to the program,
|
||||
ignore them for now and skip to the section "Reminder Files".
|
||||
@@ -26,12 +33,38 @@ date by piping the output through \fBsort(1)\fR.
|
||||
The \fB\-r\fR option disables \fBRUN\fR directives and the \fBshell()\fR
|
||||
function. As of Remind 3.00.17, using \fB\-u\fR implies \fB\-r\fR.
|
||||
.TP
|
||||
.B \-c\fR\fIn\fR
|
||||
The \fB\-c\fR option causes \fBRemind\fR to produce a calendar that is sent to
|
||||
standard output. If you supply a number \fIn\fR, then a calendar will
|
||||
be generated for \fIn\fR months, starting with the current month. By
|
||||
default, a calendar for only the current month is produced. If \fIn\fR
|
||||
starts with '+', then a calendar for \fIn\fR weeks is produced.
|
||||
.B \-c\fI[flags]\fIn\fR
|
||||
The \fB\-c\fR option causes \fBRemind\fR to produce a calendar that is
|
||||
sent to standard output. If you supply a number \fIn\fR, then a
|
||||
calendar will be generated for \fIn\fR months, starting with the
|
||||
current month. By default, a calendar for only the current month is
|
||||
produced.
|
||||
.PP
|
||||
You can precede \fIn\fR (if any) with a set of flags. The flags
|
||||
are as follows:
|
||||
.TP
|
||||
.B '+'
|
||||
causes a calendar for \fIn\fR
|
||||
weeks to be produced.
|
||||
.TP
|
||||
.B 'a'
|
||||
causes \fBRemind\fR to display reminders on the calendar on the
|
||||
day they actually occur \fIas well as\fR on any preceding days
|
||||
specified by the reminder's \fIdelta\fR.
|
||||
.TP
|
||||
.B 'l'
|
||||
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 'c'
|
||||
causes \fBRemind\fR to use VT100 escape sequences to approximate
|
||||
SPECIAL COLOR reminders. The approximation is (of necessity) very
|
||||
coarse, because the VT100 only has eight different color sequences,
|
||||
each with one of two brightnesses. A color component greater than
|
||||
64 is considered "on", and if any of the three color components is
|
||||
greater than 128, the color is considered "bright".
|
||||
|
||||
.TP
|
||||
.B \-w\fR\fIcol\fR[,\fIpad\fR[,\fIspc\fR]]]
|
||||
The \fB\-w\fR option specifies the output width, padding and spacing
|
||||
@@ -97,6 +130,11 @@ The \fB\-o\fR option causes \fBRemind\fR to ignore all \fBONCE\fR directives.
|
||||
The \fB\-t\fR option causes \fBRemind\fR to trigger all non-expired reminders,
|
||||
regardless of the \fIdelta\fR supplied for each reminder.
|
||||
.TP
|
||||
.B \-t\fR\fIn\fR
|
||||
If you supply a number \fIn\fR after the \fB\-t\fR option, then
|
||||
\fBRemind\fR pretends that each non-expired reminder has a \fIdelta\fR
|
||||
of \fIn\fR days and triggers reminders accordingly.
|
||||
.TP
|
||||
.B \-h
|
||||
The \fB\-h\fR option ("hush...") suppresses certain warning and information
|
||||
messages. In particular, if no reminders are triggered, this mode
|
||||
@@ -139,15 +177,19 @@ Dump the variable table after execution of the reminder script
|
||||
.TP
|
||||
.B l
|
||||
Echo lines when displaying error messages
|
||||
.TP
|
||||
.B f
|
||||
Trace the reading of reminder files
|
||||
.RE
|
||||
.TP
|
||||
\fB\-g\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR]]]
|
||||
Normally, reminders are issued in the order in which they are encountered
|
||||
in the reminder script. The \fB\-g\fR option cause \fBRemind\fR to
|
||||
sort reminders by date and time prior to issuing them. The optional
|
||||
\fBa\fR and \fBd\fR characters specify the sort order (ascending or
|
||||
descending) for the date, time and priority fields. See the section "Sorting
|
||||
Reminders" for more information.
|
||||
\fB\-g\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR]]]]
|
||||
Normally, reminders are issued in the order in which they are
|
||||
encountered in the reminder script. The \fB\-g\fR option cause
|
||||
\fBRemind\fR to sort reminders by date and time prior to issuing them.
|
||||
The optional \fBa\fR and \fBd\fR characters specify the sort order
|
||||
(ascending or descending) for the date, time and priority fields. See
|
||||
the section "Sorting Reminders" for more information.
|
||||
|
||||
.TP
|
||||
\fB\-b\fR[\fIn\fR]
|
||||
Set the time format for the calendar and simple-calendar outputs. \fIN\fR
|
||||
@@ -225,6 +267,9 @@ TAG clause.
|
||||
Sets the value of the specified \fIvar\fR to \fIexpr\fR, and \fBpreserves\fR
|
||||
\fIvar\fR. \fIExpr\fR can be any valid \fBRemind\fR expression. See the
|
||||
section "Initializing Variables on the Command Line" for more details.
|
||||
.TP
|
||||
\fB\-i\fR\fIfunc\fR(\fIargs\fR)=\fIdefinition\fR
|
||||
Allows you to define a function on the command line.
|
||||
.PP
|
||||
If you supply a \fIdate\fR on the command line, it must consist of
|
||||
\fIday month year\fR, where \fIday\fR is the day of the month,
|
||||
@@ -293,6 +338,7 @@ Its syntax is:
|
||||
[\fBPRIORITY\fR \fIprio\fR]
|
||||
[\fBSKIP\fR | \fBBEFORE\fR | \fBAFTER\fR]
|
||||
[\fBOMIT\fR \fIomit_list\fR]
|
||||
[\fBOMITFUNC\fR \fIomit_function\fR]
|
||||
[\fBAT\fR \fItime\fR [\fItdelta\fR] [\fItrepeat\fR]]
|
||||
[\fBSCHED\fR \fIsched_function\fR]
|
||||
[\fBWARN\fR \fIwarn_function\fR]
|
||||
@@ -750,6 +796,50 @@ also. See "The OMIT command" for more details.)
|
||||
By comparison, if we had used "\-\-1", the reminder would be triggered on
|
||||
the last day of the month, regardless of the \fBOMIT\fR.
|
||||
.PP
|
||||
.B COMPUTED LOCAL OMITS
|
||||
.PP
|
||||
The \fBOMITFUNC\fR phrase of the \fBREM\fR command allows you to
|
||||
supply a function that determines whether or not a date is omitted.
|
||||
The function is passed a single parameter of type \fBDATE\fR, and must
|
||||
return a non-zero integer if the date is considered "omitted" and 0
|
||||
otherwise. Here's an example:
|
||||
.PP
|
||||
.nf
|
||||
FSET _third(x) (day(x) % 3) || \\
|
||||
(wkdaynum(x) == 0) || \\
|
||||
(wkdaynum(x) == 6)
|
||||
REM OMITFUNC _third AFTER MSG Working day divisible by 3
|
||||
.fi
|
||||
.PP
|
||||
In the example above, the reminder is triggered every Monday to Friday whose
|
||||
day-of-month number is divisible by three. Here's how it works:
|
||||
.TP
|
||||
.B o
|
||||
The \fBOMITFUNC _third\fR portion causes all days for which \fB_third(x)\fR
|
||||
returns non-zero to be considered "omitted". This causes all days whose
|
||||
day-of-month number is \fInot\fR a multiple of three to be omitted. Note
|
||||
that _third also returns non-zero if the weekday is Sunday or Saturday.
|
||||
.TP
|
||||
.B o
|
||||
The \fBAFTER\fR keyword causes the reminder to be moved after a block of
|
||||
omitted days.
|
||||
.PP
|
||||
The combination of OMITFUNC and AFTER keyword causes the reminder to
|
||||
be issued on all days whose day-of-month number is divisible by three,
|
||||
but not on Saturday or Sunday.
|
||||
.PP
|
||||
Note that if you use \fBOMITFUNC\fR, then a local \fBOMIT\fR is
|
||||
\fIignored\fR as are \fIall global OMITs\fR. If you want to omit specific
|
||||
weekdays, your omit function will need to test for them specifically. If
|
||||
you want to take into account the global \fBOMIT\fR context, then your omit
|
||||
function will need to test for that explicitly (using the \fBisomitted()\fR
|
||||
function.)
|
||||
.PP
|
||||
Note that an incorrect \fBOMITFUNC\fR might cause all days to be considered
|
||||
omitted. For that reason, when \fBRemind\fR searches through omitted days,
|
||||
it terminates the search after the \fBSATISFY\fR iteration limit
|
||||
(command-line option \fB\-x\fR.)
|
||||
.PP
|
||||
.B TIMED REMINDERS
|
||||
.PP
|
||||
Timed reminders are those that have an \fBAT\fR keyword followed
|
||||
@@ -1182,11 +1272,11 @@ equivalent:
|
||||
.PP
|
||||
.B THE BEFORE, AFTER AND SKIP KEYWORDS
|
||||
.PP
|
||||
Normally, days that are omitted, whether by a global \fBOMIT\fR command
|
||||
or the local \fBOMIT\fR keyword in a \fBREM\fR statement, only affect the
|
||||
counting of the \-\fIback\fR or the +\fIdelta\fR. For example, suppose
|
||||
you have a meeting every Wednesday. Suppose, too, that you have indicated
|
||||
11 Nov as a holiday:
|
||||
Normally, days that are omitted, whether by a global \fBOMIT\fR
|
||||
command or the local \fBOMIT\fR or \fBOMITFUNC\fR keywords in a
|
||||
\fBREM\fR statement, only affect the counting of the \-\fIback\fR or
|
||||
the +\fIdelta\fR. For example, suppose you have a meeting every
|
||||
Wednesday. Suppose, too, that you have indicated 11 Nov as a holiday:
|
||||
.PP
|
||||
.nf
|
||||
OMIT 11 Nov +4 MSG Remembrance Day
|
||||
@@ -1248,6 +1338,12 @@ administrator.)
|
||||
.PP
|
||||
If you specify a filename of "-" in the \fBINCLUDE\fR command, \fBRemind\fR
|
||||
will begin reading from standard input.
|
||||
.PP
|
||||
If you specify a \fIdirectory\fR as the argument to \fBINCLDUE\fR, then
|
||||
\fBRemind\fR will process all files in that directory that match the shell
|
||||
patterm "*.rem". The files are processed in sorted order; the sort order
|
||||
matches that used by the shell when it expands "*.rem".
|
||||
|
||||
.SH THE RUN COMMAND
|
||||
.PP
|
||||
If you include other files in your reminder script, you may not always
|
||||
@@ -1838,6 +1934,10 @@ $IgnoreOnce, $InfDelta, and $NextMode are not meaningful.
|
||||
This variable can be set only to ":" or ".". It holds the character
|
||||
used to separate portions of a time when \fBRemind\fR prints a TIME or
|
||||
DATETIME value.
|
||||
.TP
|
||||
.B $UntimedFirst (read-only)
|
||||
Set to 1 if the \fB\-g\fR option is used with a fourth sort character
|
||||
of "d"; set to 0 otherwise.
|
||||
.PP
|
||||
.B BUILT-IN FUNCTIONS
|
||||
.PP
|
||||
@@ -2043,6 +2143,37 @@ for the specified year. If \fIarg\fR is a \fBDATE\fR or
|
||||
\fBDATETIME\fR, then returns the date of the next Easter Sunday on or
|
||||
after \fIarg\fR. (The time component of a datetime is ignored.)
|
||||
.TP
|
||||
.B evaltrig(s_trigger [,dq_start])
|
||||
Evaluates \fItrigger\fR as if it were a REM or IFTRIG trigger specification
|
||||
and returns the trigger date as a \fBDATE\fR (or as a \fBDATETIME\fR if
|
||||
there is an \fBAT\fR clause.) Returns a negative \fBINT\fR if no trigger
|
||||
could be computed.
|
||||
.RS
|
||||
.PP
|
||||
Normally, \fBevaltrig\fR finds a trigger date on or after today. If
|
||||
you supply the \fIstart\fR argument, then it scans starting from there.
|
||||
.PP
|
||||
For example, the expression:
|
||||
.PP
|
||||
.nf
|
||||
evaltrig("Mon 1", '2008-10-07')
|
||||
.fi
|
||||
.PP
|
||||
returns '2008-11-03', since that is the first date on or after
|
||||
7 October 2008 that satisfies "Mon 1".
|
||||
.PP
|
||||
If you want to see how many days it is from the first Monday in October, 2008
|
||||
to the first Monday in November, 2008, use:
|
||||
.PP
|
||||
.nf
|
||||
evaltrig("Mon 1", '2008-11-01') - evaltrig("Mon 1", '2008-10-01')
|
||||
.fi
|
||||
.PP
|
||||
and the answer is 28. The trigger argument to \fBevaltrig\fR can have
|
||||
all the usual trigger clauses (\fBOMIT\fR, \fBAT\fR, \fBSKIP\fR, etc.) but
|
||||
\fIcannot\fR have a \fBSATISFY\fR, \fBMSG\fR, etc. reminder-type clause.
|
||||
.RE
|
||||
.TP
|
||||
.B filedate(s_filename)
|
||||
Returns the modification date of \fIfilename\fR. If \fIfilename\fR
|
||||
does not exist, or its modification date is before the year
|
||||
@@ -2120,7 +2251,8 @@ or \fBDATETIME\fR is supplied, then the year component is used in the test.
|
||||
.B isomitted(dq_date)
|
||||
Returns 1 if \fIdate\fR is omitted, given the current global \fBOMIT\fR
|
||||
context. Returns 0 otherwise. (If a datetime is supplied, only the
|
||||
date part is used.)
|
||||
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"
|
||||
@@ -2234,10 +2366,11 @@ This function returns the number of \fInon-\fRomitted days between
|
||||
counted. \fIend\fR is never counted.
|
||||
.RS
|
||||
.PP
|
||||
Note that \fIend\fR must be greater than or
|
||||
equal to \fIstart\fR or an error is reported. In addition to using
|
||||
the global OMIT context, you can supply additional arguments that are
|
||||
names of weekdays to be omitted.
|
||||
Note that \fIend\fR must be greater than or equal to \fIstart\fR or an
|
||||
error is reported. In addition to using the global OMIT context, you
|
||||
can supply additional arguments that are names of weekdays to be
|
||||
omitted. However, in a \fBREM\fR command, any local \fBOMITFUNC\fR
|
||||
clause is \fInot\fR taken into account by this function.
|
||||
.PP
|
||||
For example, the following line sets a to 11 (assuming no global OMITs):
|
||||
.PP
|
||||
@@ -2260,36 +2393,30 @@ reminder will label day numbers in a calendar:
|
||||
ENDIF
|
||||
.fi
|
||||
.PP
|
||||
Here's a more complex example: Suppose your normal garbage-collection
|
||||
day is Thursday, but if any of Monday through Thursday of a week is a holiday,
|
||||
the collection day moves to Friday. Here's one way to solve it:
|
||||
.PP
|
||||
.nf
|
||||
FSET prev_monday(x) x - wkdaynum(x-1)
|
||||
|
||||
REM Thu Fri SATISFY [wkdaynum(trigdate()) == 4 && \\
|
||||
nonomitted(prev_monday(today()), today()+1) == 4 || \\
|
||||
wkdaynum(trigdate()) == 5 && \\
|
||||
nonomitted(prev_monday(today()), today()+1) <= 4] \\
|
||||
MSG Garbage Day
|
||||
.fi
|
||||
.PP
|
||||
Whew! (You'll need to see "THE SATISFY CLAUSE" later on.) We'd
|
||||
better explain that one: The prev_monday helper function takes a date
|
||||
and returns the date of the previous Monday. The REM command will
|
||||
trigger on the first Thursday or Friday that satisfies one of the
|
||||
following conditions:
|
||||
.PP
|
||||
1) Either it's a Thursday and there are exactly four non-omitted days between
|
||||
the previous Monday and tomorrow, or
|
||||
.PP
|
||||
2) It's a Friday and there are four or fewer non-omitted days between the
|
||||
previous Monday and tomorrow. We need the "or fewer" condition to handle
|
||||
the case of more than one holiday in a given week. If that happens,
|
||||
garbage day still only moves by one day.
|
||||
.PP
|
||||
Obviously, the answer you get from \fBnonomitted\fR depends on the global
|
||||
OMIT context. If you use moveable OMITs, you may get inconsistent results.
|
||||
.PP
|
||||
Here is a more complex use for \fBnonomitted\fR. My garbage collection
|
||||
follows two interleaved 14-day cycles: One Friday, garbage and paper
|
||||
recycling ("Black Box") are collected. The next Friday, garbage and
|
||||
plastic recycling ("Blue Box") are collected. If any of Monday-Friday
|
||||
is a holiday, collection is delayed until the Saturday. Here's a way
|
||||
to encode these rules:
|
||||
.PP
|
||||
.nf
|
||||
fset _garbhol(x) wkdaynum(x) == 5 && nonomitted(x-4, x+1) < 5
|
||||
REM 12 November 1999 *14 AFTER OMITFUNC _garbhol MSG Black Box
|
||||
REM 19 November 1999 *14 AFTER OMITFUNC _garbhol MSG Blue Box
|
||||
.fi
|
||||
.PP
|
||||
Here's how it works: The _garbhol(x) user-defined function returns 1
|
||||
if and only if (1) \fIx\fR is a Friday and (2) there is at least one
|
||||
OMITted day from the previous Monday up to and including the Friday.
|
||||
.PP
|
||||
The first REM statement sets up the 14-day black-box cycle. The AFTER
|
||||
keyword makes it move collection to the Saturday if _garbhol returns 1.
|
||||
The second REM statement sets up the 14-day blue-box cycle with a similar
|
||||
adjustment made by AFTER in conjunction with _garbhol.
|
||||
.RE
|
||||
.TP
|
||||
.B now()
|
||||
@@ -2399,11 +2526,13 @@ character in the output is converted to a space. Note that if \fBRUN
|
||||
OFF\fR has been executed, or the \fB\-r\fR command-line option has
|
||||
been used, \fBshell()\fR will result in an error, and \fIcmd\fR will
|
||||
not be executed.
|
||||
.RS
|
||||
.PP
|
||||
If \fImaxlen\fR is specified, then \fBshell()\fR returns the first
|
||||
\fImaxlen\fR characters of output (rather than the first 511). If
|
||||
\fImaxlen\fR is specified as a negative number, then \fIall\fR the
|
||||
output from \fIcmd\fR is returned.
|
||||
.RE
|
||||
.TP
|
||||
.B strlen(s_str)
|
||||
Returns the length of \fIstr\fR.
|
||||
@@ -2546,6 +2675,21 @@ Returns a string specifying the version of \fBRemind\fR. For version
|
||||
\fBRemind\fR are released, the value returned by \fBversion()\fR will
|
||||
strictly increase, according to the rules for string ordering.
|
||||
.TP
|
||||
.B weekno([dq_date, [i_wkstart, [i_daystart]]])
|
||||
Returns the week number of the year. If no arguments are supplied,
|
||||
returns the ISO 8601 week number for \fBtoday()\fR. If one
|
||||
argument \fIdate\fR is supplied, then returns the ISO 8601 week
|
||||
number for that date. If two arguments are supplied, then
|
||||
\fIwkstart\fR must range from 0 to 6, and represents the first
|
||||
day of the week (with 0 being Sunday and 6 being Saturday.). If
|
||||
\fIwkstart\fR is not supplied, then it defaults to 1. If the
|
||||
third argument \fIdaystart\fR is supplied, then it specifies
|
||||
when Week 1 starts. If \fIdaystart\fR is less than or equal to 7,
|
||||
then Week 1 starts on the first \fIwkstart\fR on or after
|
||||
January \fIdaystart\fR. Otherwise, Week 1 starts on the first
|
||||
\fIwkstart\fR on or after December \fIdaystart\fR. If omitted,
|
||||
\fIdaystart\fR defaults to 29 (following the ISO 8601 definition.)
|
||||
.TP
|
||||
.B wkday(dqi_arg)
|
||||
If \fIarg\fR is a \fBDATE\fR or \fBDATETIME\fR, returns a string
|
||||
representing the day of the week of the date. If \fIarg\fR is an
|
||||
@@ -2594,8 +2738,16 @@ exceptions:
|
||||
.TP
|
||||
o
|
||||
If \fBRemind\fR is expecting an expression, as in the \fBSET\fR command,
|
||||
or the \fBIF\fR command, then no expression pasting takes place. The
|
||||
expression is simply evaluated as if the square brackets were not there.
|
||||
or the \fBIF\fR command, you should \fBnot\fR include square brackets.
|
||||
FOr example, use:
|
||||
.PP
|
||||
.nf
|
||||
SET a 4+5
|
||||
.fi
|
||||
and not:
|
||||
.nf
|
||||
SET a [4+5]
|
||||
.fi
|
||||
.TP
|
||||
o
|
||||
You cannot use expression pasting for the first token on a line.
|
||||
@@ -3023,6 +3175,10 @@ occurring on odd-numbered days of the month with the following:
|
||||
MSG Here it is!!!
|
||||
.fi
|
||||
.PP
|
||||
Note that \fBSATISFY\fR and \fBOMITFUNC\fR can often be used to solve the
|
||||
same problem, though in different ways. Sometimes a \fBSATISFY\fR is cleaner
|
||||
and sometimes an \fBOMITFUNC\fR; experiment and use whichever seems clearer.
|
||||
.PP
|
||||
.SH DEBUGGING REMINDER SCRIPTS
|
||||
.PP
|
||||
Although the command-line \fB\-d\fR option is useful for debugging, it
|
||||
@@ -3033,7 +3189,7 @@ under program control. The format is:
|
||||
.PP
|
||||
\fBDEBUG\fR [+\fIflagson\fR] [\-\fIflagsoff\fR]
|
||||
.PP
|
||||
\fIFlagson\fR and \fIflagsoff\fR consist of strings of the characters "extvl"
|
||||
\fIFlagson\fR and \fIflagsoff\fR consist of strings of the characters "extvlf"
|
||||
that correspond to the debugging options discussed in the command-line
|
||||
options section. If preceded with a "+", the corresponding group of
|
||||
debugging options is switched on. Otherwise, they are switched off.
|
||||
@@ -3244,6 +3400,11 @@ You should not have any spaces between the \fB\-i\fR option and the equal
|
||||
sign; otherwise, strange variable names are created that can only be accessed
|
||||
with the \fBvalue()\fR or \fBdefined()\fR functions.
|
||||
.PP
|
||||
You can also define a function on the command line by using:
|
||||
.PP
|
||||
\fB\-i\fR\fIfunc\fR(\fIargs\fR)=\fIdefinition\fR
|
||||
.PP
|
||||
Be sure to protect special characters from shell interpretation.
|
||||
.SH MORE ABOUT POSTSCRIPT
|
||||
.PP
|
||||
The \fBPS\fR and \fBPSFILE\fR reminders pass PostScript code directly
|
||||
@@ -3357,24 +3518,26 @@ to ensure that the daemon is not killed when you log out.
|
||||
.PP
|
||||
.SH SORTING REMINDERS
|
||||
.PP
|
||||
The \fB\-g\fR option causes \fBRemind\fR to sort reminders by
|
||||
trigger date, time and priority before issuing them. Note that reminders are
|
||||
still calculated in the order encountered in the script. However, rather
|
||||
than being issued immediately, they are saved in an internal buffer.
|
||||
When \fBRemind\fR has finished processing the script, it issues the
|
||||
saved reminders in sorted order. The \fB\-g\fR option can be followed
|
||||
by up to three characters that must all be "a" or "d". The first character
|
||||
specifies the sort order by trigger date (ascending or descending),
|
||||
the second specifies the sort order by trigger time and the third
|
||||
specifies the sort order by priority. The default is
|
||||
to sort all fields in ascending order.
|
||||
|
||||
The \fB\-g\fR option causes \fBRemind\fR to sort reminders by trigger
|
||||
date, time and priority before issuing them. Note that reminders are
|
||||
still calculated in the order encountered in the script. However,
|
||||
rather than being issued immediately, they are saved in an internal
|
||||
buffer. When \fBRemind\fR has finished processing the script, it
|
||||
issues the saved reminders in sorted order. The \fB\-g\fR option can
|
||||
be followed by up to four characters that must all be "a" or "d". The
|
||||
first character specifies the sort order by trigger date (ascending or
|
||||
descending), the second specifies the sort order by trigger time and
|
||||
the third specifies the sort order by priority. If the fourth
|
||||
character is "d", the untimed reminders are sorted before timed
|
||||
reminders. The default is to sort all fields in ascending order and
|
||||
to sort untimed reminders after timed reminders.
|
||||
.PP
|
||||
In ascending order, reminders are issued with the most imminent first.
|
||||
Descending order is the reverse. Reminders are always sorted by
|
||||
trigger date, and reminders with the same trigger date are then sorted
|
||||
by trigger time. Non-timed reminders are always issued after timed
|
||||
reminders in this mode. If two reminders have the same date and time,
|
||||
then the priority is used to break ties. Reminders with the same date,
|
||||
by trigger time. If two reminders have the same date and time, then
|
||||
the priority is used to break ties. Reminders with the same date,
|
||||
time and priority are issued in the order they were encountered.
|
||||
.PP
|
||||
You can define a user-defined function called SORTBANNER that takes one
|
||||
@@ -3766,6 +3929,19 @@ The rest of the line is the text to put in the calendar.
|
||||
.PP
|
||||
The COLOR special is "doubly special", because in its normal operating
|
||||
mode, \fBremind\fR treats a COLOR special just like a MSG-type reminder.
|
||||
Also, if you invoke \fBRemind\fR with \fB\-cc\fR..., then it approximates
|
||||
SPECIAL COLOR reminders on your terminal.
|
||||
.PP
|
||||
The \fBWEEK\fR special lets you place annotations such as the week
|
||||
number in the calendar. For example, this would number each Monday
|
||||
with the ISO 8601 week number. The week number is shown like this:
|
||||
"(W\fIn\fR)" in this example, but you can put whatever text you like
|
||||
after the WEEK keyword.
|
||||
|
||||
.nf
|
||||
REM Monday SPECIAL WEEK (W[weekno()])
|
||||
.fi
|
||||
|
||||
.SH MISCELLANEOUS
|
||||
.PP
|
||||
.B COMMAND ABBREVIATIONS
|
||||
@@ -4021,8 +4197,9 @@ Hebrew dates in \fBRemind\fR change at midnight instead of sunset.
|
||||
.PP
|
||||
Language should be selectable at run-time, not compile-time. Don't
|
||||
expect this to happen soon!
|
||||
\fBRemind\fR has some built-in limits (for example,
|
||||
number of global \fBOMIT\fRs.)
|
||||
.PP
|
||||
\fBRemind\fR has some built-in limits (for example, number of global
|
||||
\fBOMIT\fRs.)
|
||||
.PP
|
||||
.SH BIBLIOGRAPHY
|
||||
.PP
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-1998 David F. Skoll
|
||||
# Copyright (C) 1999-2005 Roaring Penguin Software Inc.
|
||||
# Copyright (C) 1999-2008 Roaring Penguin Software Inc.
|
||||
#
|
||||
#--------------------------------------------------------------
|
||||
|
||||
@@ -93,6 +93,7 @@ set EditorPid -1
|
||||
set AppendFile {NOSUCHFILE}
|
||||
catch {set AppendFile $ReminderFile}
|
||||
|
||||
set SetFontsWorked 0
|
||||
#---------------- DON'T CHANGE STUFF BELOW HERE ------------------
|
||||
|
||||
# 24-hour clock mode
|
||||
@@ -186,6 +187,14 @@ proc Initialize {} {
|
||||
}
|
||||
}
|
||||
|
||||
# If reminder file is a directory and appendfile is the same as
|
||||
# reminder file, choose append file to be $ReminderFile/100-tkremind.rem
|
||||
if {[file isdirectory $ReminderFile]} {
|
||||
if {"$ReminderFile" == "$AppendFile"} {
|
||||
set AppendFile [file join $ReminderFile "100-tkremind.rem"]
|
||||
}
|
||||
}
|
||||
|
||||
# Check system sanity
|
||||
if {! [file readable $ReminderFile]} {
|
||||
set ans [tk_dialog .error "TkRemind: Warning" "Can't read reminder file `$ReminderFile'" warning 0 "Create it and continue" "Exit"]
|
||||
@@ -199,6 +208,12 @@ proc Initialize {} {
|
||||
exit 1
|
||||
}
|
||||
|
||||
if {[file isdirectory $ReminderFile] && ! [file exists $AppendFile]} {
|
||||
if {![catch {close [open "$AppendFile" "a"]}]} {
|
||||
tk_dialog .error "Created File" "Created blank file `$AppendFile'" info 0 "OK"
|
||||
}
|
||||
}
|
||||
|
||||
if {! [file writable $AppendFile]} {
|
||||
tk_dialog .error Error "Can't write reminder file `$AppendFile'" error 0 Ok
|
||||
exit 1
|
||||
@@ -277,9 +292,14 @@ proc CalEntryOffset { firstDay } {
|
||||
#***********************************************************************
|
||||
proc CreateCalFrame { w dayNames } {
|
||||
# Figure out reasonable height for text frames
|
||||
global SetFontsWorked
|
||||
set h [winfo screenheight .]
|
||||
if {$h <= 480} {
|
||||
set h 2
|
||||
if {$SetFontsWorked} {
|
||||
set h 3
|
||||
} else {
|
||||
set h 2
|
||||
}
|
||||
} elseif {$h <= 600} {
|
||||
set h 4
|
||||
} else {
|
||||
@@ -733,6 +753,13 @@ proc FillCalWindow {} {
|
||||
set month [string trimleft $month 0]
|
||||
set extratags ""
|
||||
switch -exact -- $type {
|
||||
"WEEK" {
|
||||
set stuff [string trimleft $stuff]
|
||||
set stuff [string trimright $stuff]
|
||||
set label [expr $firstWkday + $day - 1]
|
||||
.cal.l$label configure -text "$day $stuff"
|
||||
continue
|
||||
}
|
||||
"SHADE" {
|
||||
DoShadeSpecial $n $stuff
|
||||
continue
|
||||
@@ -1358,7 +1385,9 @@ proc OptionsToRemindDialog { w opts } {
|
||||
$w.timehour configure -text $hour
|
||||
$w.ampm configure -text "PM"
|
||||
} else {
|
||||
$w.ampm configure -text "AM"
|
||||
if {"$ampm" == ""} {
|
||||
$w.ampm configure -text "AM"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2242,8 +2271,9 @@ proc main {} {
|
||||
global AppendFile HighestTagSoFar DayNames
|
||||
catch {
|
||||
puts "\nTkRemind Copyright (C) 1996-1998 David F. Skoll"
|
||||
puts "Copyright (C) 1999-2007 Roaring Penguin Software Inc."
|
||||
puts "Copyright (C) 1999-2008 Roaring Penguin Software Inc."
|
||||
}
|
||||
catch { SetFonts }
|
||||
LoadOptions
|
||||
CreateMoonImages
|
||||
Initialize
|
||||
@@ -2779,7 +2809,7 @@ proc ShowTodaysReminders {} {
|
||||
CenterWindow $w
|
||||
|
||||
# Grab the reminders
|
||||
set stuff [exec -keepnewline $Remind -g -q -a -r $ReminderFile 2>/dev/null]
|
||||
set stuff [exec -keepnewline $Remind -g -q -r $ReminderFile 2>/dev/null]
|
||||
$w.text insert end $stuff
|
||||
$w.text configure -state disabled
|
||||
}
|
||||
@@ -2839,4 +2869,16 @@ proc ClosePopup { w after_token mail_addr close_win ignore_or_kill tag reminder
|
||||
}
|
||||
}
|
||||
|
||||
# Adjust font defaults for screen size
|
||||
proc SetFonts {} {
|
||||
global SetFontsWorked
|
||||
set h [winfo screenheight .]
|
||||
if {$h <= 480} {
|
||||
# Small screen (maybe eeepc?)
|
||||
font configure TkDefaultFont -size 6
|
||||
font configure TkFixedFont -size 6
|
||||
}
|
||||
set SetFontsWorked 1
|
||||
}
|
||||
|
||||
main
|
||||
|
||||
330
src/calendar.c
330
src/calendar.c
@@ -30,6 +30,8 @@ typedef struct cal_entry {
|
||||
struct cal_entry *next;
|
||||
char const *text;
|
||||
char const *pos;
|
||||
int is_color;
|
||||
int r, g, b;
|
||||
int time;
|
||||
int priority;
|
||||
char tag[TAG_LEN+1];
|
||||
@@ -39,15 +41,88 @@ typedef struct cal_entry {
|
||||
int lineno;
|
||||
} CalEntry;
|
||||
|
||||
/* Line-drawing sequences */
|
||||
struct line_drawing {
|
||||
char const *graphics_on;
|
||||
char const *graphics_off;
|
||||
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'
|
||||
};
|
||||
|
||||
static char *VT100Colors[2][2][2][2] /* [Br][R][G][B] */ = {
|
||||
{
|
||||
/*** DIM COLORS ***/
|
||||
{
|
||||
{
|
||||
/* 0, 0, 0 = Black */ "\x1B[0;30m",
|
||||
/* 0, 0, 1 = Blue */ "\x1B[0;34m"
|
||||
},
|
||||
{
|
||||
/* 0, 1, 0 = Green */ "\x1B[0;32m",
|
||||
/* 0, 1, 1 = Cyan */ "\x1B[0;36m"
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
/* 1, 0, 0 = Red */ "\x1B[0;31m",
|
||||
/* 1, 0, 1 = Magenta */ "\x1B[0;35m"
|
||||
},
|
||||
{
|
||||
/* 1, 1, 0 = Yellow */ "\x1B[0;33m",
|
||||
/* 1, 1, 1 = White */ "\x1B[0;37m"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
/*** BRIGHT COLORS ***/
|
||||
{
|
||||
{
|
||||
/* 0, 0, 0 = Grey */ "\x1B[30;1m",
|
||||
/* 0, 0, 1 = Blue */ "\x1B[34;1m"
|
||||
},
|
||||
{
|
||||
/* 0, 1, 0 = Green */ "\x1B[32;1m",
|
||||
/* 0, 1, 1 = Cyan */ "\x1B[36;1m"
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
/* 1, 0, 0 = Red */ "\x1B[31;1m",
|
||||
/* 1, 0, 1 = Magenta */ "\x1B[35;1m"
|
||||
},
|
||||
{
|
||||
/* 1, 1, 0 = Yellow */ "\x1B[33;1m",
|
||||
/* 1, 1, 1 = White */ "\x1B[37;1m"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static struct line_drawing *linestruct;
|
||||
#define DRAW(x) putchar(linestruct->x)
|
||||
|
||||
/* Global variables */
|
||||
static CalEntry *CalColumn[7];
|
||||
|
||||
static int ColSpaces;
|
||||
|
||||
static void Colorize(CalEntry const *e);
|
||||
static void Decolorize(void);
|
||||
static void SortCol (CalEntry **col);
|
||||
static void DoCalendarOneWeek (void);
|
||||
static void DoCalendarOneWeek (int nleft);
|
||||
static void DoCalendarOneMonth (void);
|
||||
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 int WriteOneCalLine (void);
|
||||
@@ -57,10 +132,42 @@ static void WriteCalHeader (void);
|
||||
static void WriteCalTrailer (void);
|
||||
static int DoCalRem (ParsePtr p, int col);
|
||||
static void WriteSimpleEntries (int col, int jul);
|
||||
static void WriteSolidCalLine (void);
|
||||
static void WriteTopCalLine (void);
|
||||
static void WriteBottomCalLine (void);
|
||||
static void WriteIntermediateCalLine (void);
|
||||
static void WriteCalDays (void);
|
||||
|
||||
static void gon(void)
|
||||
{
|
||||
printf("%s", linestruct->graphics_on);
|
||||
}
|
||||
static void goff(void)
|
||||
{
|
||||
printf("%s", linestruct->graphics_off);
|
||||
}
|
||||
|
||||
static void Decolorize(void)
|
||||
{
|
||||
printf("%s", "\x1B[0m");
|
||||
}
|
||||
|
||||
static void Colorize(CalEntry const *e)
|
||||
{
|
||||
int bright = 0;
|
||||
int r, g, b;
|
||||
if (e->r > 128 || e->g > 128 || e->b > 128) {
|
||||
bright = 1;
|
||||
}
|
||||
if (e->r > 64) r = 1;
|
||||
else r = 0;
|
||||
if (e->g > 64) g = 1;
|
||||
else g = 0;
|
||||
if (e->b > 64) b = 1;
|
||||
else b = 0;
|
||||
|
||||
printf("%s", VT100Colors[bright][r][g][b]);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* ProduceCalendar */
|
||||
@@ -72,6 +179,11 @@ void ProduceCalendar(void)
|
||||
{
|
||||
int y, m, d;
|
||||
|
||||
if (UseVTChars) {
|
||||
linestruct = &VT100Drawing;
|
||||
} else {
|
||||
linestruct = &NormalDrawing;
|
||||
}
|
||||
ShouldCache = 1;
|
||||
|
||||
ColSpaces = (CalWidth - 9) / 7;
|
||||
@@ -88,13 +200,13 @@ void ProduceCalendar(void)
|
||||
else JulianToday -= ((JulianToday+1)%7);
|
||||
|
||||
if (!DoSimpleCalendar) {
|
||||
WriteIntermediateCalLine();
|
||||
WriteWeekHeaderLine();
|
||||
WriteCalDays();
|
||||
WriteIntermediateCalLine();
|
||||
}
|
||||
|
||||
while (CalWeeks--)
|
||||
DoCalendarOneWeek();
|
||||
DoCalendarOneWeek(CalWeeks);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -106,7 +218,7 @@ void ProduceCalendar(void)
|
||||
/* Write a calendar for a single week */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void DoCalendarOneWeek(void)
|
||||
static void DoCalendarOneWeek(nleft)
|
||||
{
|
||||
int y, m, d, done, i, l, wd;
|
||||
char buf[81];
|
||||
@@ -132,7 +244,9 @@ static void DoCalendarOneWeek(void)
|
||||
}
|
||||
|
||||
/* Here come the first few lines... */
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
for (i=0; i<7; i++) {
|
||||
FromJulian(OrigJul+i, &y, &m, &d);
|
||||
sprintf(buf, "%d %c%c%c ", d, MonthName[m][0], MonthName[m][1],
|
||||
@@ -141,14 +255,20 @@ static void DoCalendarOneWeek(void)
|
||||
PrintLeft(buf, ColSpaces, '*');
|
||||
else
|
||||
PrintLeft(buf, ColSpaces, ' ');
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
}
|
||||
PutChar('\n');
|
||||
for (l=0; l<CalPad; l++) {
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
for (i=0; i<7; i++) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
}
|
||||
PutChar('\n');
|
||||
}
|
||||
@@ -162,16 +282,24 @@ static void DoCalendarOneWeek(void)
|
||||
|
||||
/* Write any blank lines required */
|
||||
while (LinesWritten++ < CalLines) {
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
for (i=0; i<7; i++) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
}
|
||||
PutChar('\n');
|
||||
}
|
||||
|
||||
/* Write the final line */
|
||||
WriteIntermediateCalLine();
|
||||
if (nleft) {
|
||||
WriteIntermediateCalLine();
|
||||
} else {
|
||||
WriteBottomCalLine();
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -228,6 +356,7 @@ static int WriteCalendarRow(void)
|
||||
char buf[81];
|
||||
int OrigJul = JulianToday;
|
||||
int LinesWritten = 0;
|
||||
int moreleft;
|
||||
|
||||
/* Get the date of the first day */
|
||||
FromJulian(JulianToday, &y, &m, &d);
|
||||
@@ -253,7 +382,9 @@ static int WriteCalendarRow(void)
|
||||
|
||||
|
||||
/* Here come the first few lines... */
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
for (i=0; i<7; i++) {
|
||||
if (i < wd || d+i-wd>DaysInMonth(m, y))
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
@@ -261,14 +392,20 @@ static int WriteCalendarRow(void)
|
||||
sprintf(buf, "%d", d+i-wd);
|
||||
PrintLeft(buf, ColSpaces, ' ');
|
||||
}
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
}
|
||||
PutChar('\n');
|
||||
for (l=0; l<CalPad; l++) {
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
for (i=0; i<7; i++) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
}
|
||||
PutChar('\n');
|
||||
}
|
||||
@@ -282,18 +419,27 @@ static int WriteCalendarRow(void)
|
||||
|
||||
/* Write any blank lines required */
|
||||
while (LinesWritten++ < CalLines) {
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
for (i=0; i<7; i++) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
}
|
||||
PutChar('\n');
|
||||
}
|
||||
|
||||
WriteIntermediateCalLine();
|
||||
moreleft = (d+7-wd <= DaysInMonth(m, y));
|
||||
if (moreleft) {
|
||||
WriteIntermediateCalLine();
|
||||
} else {
|
||||
WriteBottomCalLine();
|
||||
}
|
||||
|
||||
/* Return non-zero if we have not yet finished */
|
||||
return (d+7-wd <= DaysInMonth(m, y));
|
||||
return moreleft;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -341,14 +487,18 @@ static int WriteOneCalLine(void)
|
||||
{
|
||||
int done = 1, i;
|
||||
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
for (i=0; i<7; i++) {
|
||||
if (CalColumn[i]) {
|
||||
if (WriteOneColLine(i)) done = 0;
|
||||
} else {
|
||||
PrintCentered("", ColSpaces, ' ');
|
||||
}
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
}
|
||||
PutChar('\n');
|
||||
|
||||
@@ -393,6 +543,11 @@ static int WriteOneColLine(int col)
|
||||
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++) {
|
||||
@@ -411,6 +566,11 @@ static int WriteOneColLine(int col)
|
||||
}
|
||||
}
|
||||
|
||||
/* Decolorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Decolorize();
|
||||
}
|
||||
|
||||
/* Flesh out the rest of the column */
|
||||
while(numwritten++ < ColSpaces) PutChar(' ');
|
||||
|
||||
@@ -449,7 +609,7 @@ static void GenerateCalEntries(int col)
|
||||
DestroyVars(0);
|
||||
NumTriggered = 0;
|
||||
|
||||
r=OpenFile(InitialFile);
|
||||
r=IncludeFile(InitialFile);
|
||||
if (r) {
|
||||
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING], InitialFile, ErrMsg[r]);
|
||||
exit(1);
|
||||
@@ -549,14 +709,18 @@ static void WriteCalHeader(void)
|
||||
FromJulian(JulianToday, &y, &m, &d);
|
||||
sprintf(buf, "%s %d", MonthName[m], y);
|
||||
|
||||
WriteSolidCalLine();
|
||||
WriteTopCalLine();
|
||||
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
PrintCentered(buf, CalWidth-2, ' ');
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
PutChar('\n');
|
||||
|
||||
WriteIntermediateCalLine();
|
||||
WritePostHeaderLine();
|
||||
WriteCalDays();
|
||||
WriteIntermediateCalLine();
|
||||
}
|
||||
@@ -584,7 +748,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
Trigger trig;
|
||||
TimeTrig tim;
|
||||
Value v;
|
||||
int r;
|
||||
int r, err;
|
||||
int jul;
|
||||
CalEntry *CurCol = CalColumn[col];
|
||||
CalEntry *e;
|
||||
@@ -592,11 +756,14 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DynamicBuffer buf, obuf, pre_buf;
|
||||
Token tok;
|
||||
|
||||
int is_color, col_r, col_g, col_b;
|
||||
|
||||
is_color = 0;
|
||||
DBufInit(&buf);
|
||||
DBufInit(&pre_buf);
|
||||
|
||||
/* Parse the trigger date and time */
|
||||
if ( (r=ParseRem(p, &trig, &tim)) ) return r;
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
||||
|
||||
/* Don't include timed reminders in calendar if -a option supplied. */
|
||||
if (DontIssueAts && tim.ttime != NO_TIME) return OK;
|
||||
@@ -604,6 +771,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
if (trig.typ == SAT_TYPE) {
|
||||
r=DoSatRemind(&trig, &tim, p);
|
||||
if (r) return r;
|
||||
if (!LastTrigValid) return OK;
|
||||
r=ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
@@ -625,7 +793,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
if (!LastTrigValid) return OK;
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r);
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
if (r) return r;
|
||||
}
|
||||
|
||||
@@ -640,6 +808,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
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);
|
||||
@@ -657,6 +826,15 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
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);
|
||||
}
|
||||
@@ -666,9 +844,8 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
/* If trigger date == today, add it to the current entry */
|
||||
DBufInit(&obuf);
|
||||
if ((jul == JulianToday) ||
|
||||
(DoSimpleCalendar &&
|
||||
DoSimpleCalDelta &&
|
||||
ShouldTriggerReminder(&trig, &tim, jul))) {
|
||||
(DoSimpleCalDelta &&
|
||||
ShouldTriggerReminder(&trig, &tim, jul, &err))) {
|
||||
NumTriggered++;
|
||||
|
||||
if (DoSimpleCalendar || tim.ttime != NO_TIME) {
|
||||
@@ -749,6 +926,10 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DBufPuts(&pre_buf, s);
|
||||
s = DBufValue(&pre_buf);
|
||||
e = NEW(CalEntry);
|
||||
e->is_color = is_color;
|
||||
e->r = col_r;
|
||||
e->g = col_g;
|
||||
e->b = col_b;
|
||||
if (!e) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
@@ -844,11 +1025,64 @@ static void WriteSimpleEntries(int col, int jul)
|
||||
/* Various functions for writing different types of lines. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void WriteSolidCalLine(void)
|
||||
static void WriteTopCalLine(void)
|
||||
{
|
||||
PutChar('+');
|
||||
PrintCentered("", CalWidth-2, '-');
|
||||
PutChar('+');
|
||||
gon();
|
||||
DRAW(br);
|
||||
PrintCentered("", CalWidth-2, linestruct->lr);
|
||||
DRAW(bl);
|
||||
goff();
|
||||
PutChar('\n');
|
||||
}
|
||||
|
||||
static void WriteBottomCalLine(void)
|
||||
{
|
||||
int i;
|
||||
gon();
|
||||
DRAW(tr);
|
||||
for (i=0; i<7; i++) {
|
||||
PrintCentered("", ColSpaces, linestruct->lr);
|
||||
if (i != 6) {
|
||||
DRAW(tlr);
|
||||
} else {
|
||||
DRAW(tl);
|
||||
}
|
||||
}
|
||||
goff();
|
||||
PutChar('\n');
|
||||
}
|
||||
|
||||
static void WritePostHeaderLine(void)
|
||||
{
|
||||
int i;
|
||||
gon();
|
||||
DRAW(tbr);
|
||||
for (i=0; i<7; i++) {
|
||||
PrintCentered("", ColSpaces, linestruct->lr);
|
||||
if (i != 6) {
|
||||
DRAW(blr);
|
||||
} else {
|
||||
DRAW(tbl);
|
||||
}
|
||||
}
|
||||
goff();
|
||||
PutChar('\n');
|
||||
}
|
||||
|
||||
static void WriteWeekHeaderLine(void)
|
||||
{
|
||||
int i;
|
||||
gon();
|
||||
DRAW(br);
|
||||
for (i=0; i<7; i++) {
|
||||
PrintCentered("", ColSpaces, linestruct->lr);
|
||||
if (i != 6) {
|
||||
DRAW(blr);
|
||||
} else {
|
||||
DRAW(bl);
|
||||
}
|
||||
}
|
||||
goff();
|
||||
PutChar('\n');
|
||||
}
|
||||
|
||||
@@ -856,24 +1090,34 @@ static void WriteIntermediateCalLine(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
PutChar('+');
|
||||
gon();
|
||||
DRAW(tbr);
|
||||
for (i=0; i<7; i++) {
|
||||
PrintCentered("", ColSpaces, '-');
|
||||
PutChar('+');
|
||||
PrintCentered("", ColSpaces, linestruct->lr);
|
||||
if (i != 6) {
|
||||
DRAW(tblr);
|
||||
} else {
|
||||
DRAW(tbl);
|
||||
}
|
||||
}
|
||||
goff();
|
||||
PutChar('\n');
|
||||
}
|
||||
|
||||
static void WriteCalDays(void)
|
||||
{
|
||||
int i;
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
for (i=0; i<7; i++) {
|
||||
if (!MondayFirst)
|
||||
PrintCentered(DayName[(i+6)%7], ColSpaces, ' ');
|
||||
else
|
||||
PrintCentered(DayName[i%7], ColSpaces, ' ');
|
||||
PutChar('|');
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
}
|
||||
PutChar('\n');
|
||||
}
|
||||
@@ -1021,7 +1265,7 @@ static void SortCol(CalEntry **col)
|
||||
while (cur->next &&
|
||||
CompareRems(0, cur->time, cur->priority,
|
||||
0, cur->next->time, cur->next->priority,
|
||||
SortByDate, SortByTime, SortByPrio) <= 0) {
|
||||
SortByDate, SortByTime, SortByPrio, UntimedBeforeTimed) <= 0) {
|
||||
next = cur->next;
|
||||
/* Swap cur and next */
|
||||
if (!prev) {
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
/* Define if you have the <sys/file.h> header file. */
|
||||
#undef HAVE_SYS_FILE_H
|
||||
|
||||
/* Define if you have the <glob.h> header file */
|
||||
#undef HAVE_GLOB_H
|
||||
|
||||
#undef HAVE_GLOB
|
||||
|
||||
#undef HAVE_SETENV
|
||||
|
||||
#undef HAVE_UNSETENV
|
||||
|
||||
@@ -148,6 +148,12 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_PRT_LEN 40
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* MAX_STR_LEN: If non-zero, Remind will limit the maximum length */
|
||||
/* of string values to avoid eating up all of memory... */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_STR_LEN 65535
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* OP_STACK_SIZE: The size of the operator stack for expr. parsing */
|
||||
/*---------------------------------------------------------------------*/
|
||||
@@ -161,7 +167,7 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define INCLUDE_NEST 8
|
||||
#define INCLUDE_NEST 9
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* IF_NEST: How many nested IFs do we handle? Maximum is the number */
|
||||
|
||||
@@ -148,6 +148,12 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_PRT_LEN 40
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* MAX_STR_LEN: If non-zero, Remind will limit the maximum length */
|
||||
/* of string values to avoid eating up all of memory... */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_STR_LEN 65535
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* OP_STACK_SIZE: The size of the operator stack for expr. parsing */
|
||||
/*---------------------------------------------------------------------*/
|
||||
@@ -161,7 +167,7 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define INCLUDE_NEST 8
|
||||
#define INCLUDE_NEST 9
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* IF_NEST: How many nested IFs do we handle? Maximum is the number */
|
||||
|
||||
100
src/dorem.c
100
src/dorem.c
@@ -29,12 +29,12 @@
|
||||
static char const DontEscapeMe[] =
|
||||
"1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,";
|
||||
|
||||
static int ParseTimeTrig (ParsePtr s, TimeTrig *tim);
|
||||
static int ParseTimeTrig (ParsePtr s, TimeTrig *tim, int save_in_globals);
|
||||
static int ParseLocalOmit (ParsePtr s, Trigger *t);
|
||||
static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
|
||||
static int ParsePriority (ParsePtr s, Trigger *t);
|
||||
static int ParseUntil (ParsePtr s, Trigger *t);
|
||||
static int ShouldTriggerBasedOnWarn (Trigger *t, int jul);
|
||||
static int ShouldTriggerBasedOnWarn (Trigger *t, int jul, int *err);
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -48,7 +48,7 @@ int DoRem(ParsePtr p)
|
||||
|
||||
Trigger trig;
|
||||
TimeTrig tim;
|
||||
int r;
|
||||
int r, err;
|
||||
int jul;
|
||||
DynamicBuffer buf;
|
||||
Token tok;
|
||||
@@ -56,7 +56,7 @@ int DoRem(ParsePtr p)
|
||||
DBufInit(&buf);
|
||||
|
||||
/* Parse the trigger date and time */
|
||||
if ( (r=ParseRem(p, &trig, &tim)) ) return r;
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
||||
|
||||
if (trig.typ == NO_TYPE) return E_EOLN;
|
||||
if (trig.typ == SAT_TYPE) {
|
||||
@@ -90,7 +90,7 @@ int DoRem(ParsePtr p)
|
||||
if (!LastTrigValid) return OK;
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r);
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
if (r) return r;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ int DoRem(ParsePtr p)
|
||||
/* If we're in daemon mode, do nothing over here */
|
||||
if (Daemon) return OK;
|
||||
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul)) {
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
|
||||
if ( (r=TriggerReminder(p, &trig, &tim, jul)) )
|
||||
{
|
||||
return r;
|
||||
@@ -121,7 +121,7 @@ int DoRem(ParsePtr p)
|
||||
/* trigger structure. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
{
|
||||
register int r;
|
||||
DynamicBuffer buf;
|
||||
@@ -145,13 +145,16 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
trig->priority = DefaultPrio;
|
||||
trig->sched[0] = 0;
|
||||
trig->warn[0] = 0;
|
||||
trig->omitfunc[0] = 0;
|
||||
trig->tag[0] = 0;
|
||||
trig->passthru[0] = 0;
|
||||
tim->ttime = NO_TIME;
|
||||
tim->delta = NO_DELTA;
|
||||
tim->rep = NO_REP;
|
||||
tim->duration = NO_TIME;
|
||||
LastTriggerTime = NO_TIME;
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = NO_TIME;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
/* Read space-delimited string */
|
||||
@@ -187,7 +190,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
|
||||
case T_At:
|
||||
DBufFree(&buf);
|
||||
r=ParseTimeTrig(s, tim);
|
||||
r=ParseTimeTrig(s, tim, save_in_globals);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
@@ -257,6 +260,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
|
||||
case T_Omit:
|
||||
DBufFree(&buf);
|
||||
if (trig->omitfunc[0]) {
|
||||
Eprint("Warning: OMIT is ignored if you use OMITFUNC");
|
||||
}
|
||||
|
||||
r = ParseLocalOmit(s, trig);
|
||||
if (r) return r;
|
||||
break;
|
||||
@@ -266,6 +273,16 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday;
|
||||
return OK;
|
||||
|
||||
case T_OmitFunc:
|
||||
if (trig->localomit) {
|
||||
Eprint("Warning: OMIT is ignored if you use OMITFUNC");
|
||||
}
|
||||
r=ParseToken(s, &buf);
|
||||
if (r) return r;
|
||||
StrnCpy(trig->omitfunc, DBufValue(&buf), VAR_NAME_LEN);
|
||||
DBufFree(&buf);
|
||||
break;
|
||||
|
||||
case T_Warn:
|
||||
r=ParseToken(s, &buf);
|
||||
if(r) return r;
|
||||
@@ -322,7 +339,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
/* ParseTimeTrig - parse the AT part of a timed reminder */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
|
||||
static int ParseTimeTrig(ParsePtr s, TimeTrig *tim, int save_in_globals)
|
||||
{
|
||||
Token tok;
|
||||
int r;
|
||||
@@ -354,7 +371,9 @@ static int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
|
||||
if (tim->ttime == NO_TIME) return E_EXPECT_TIME;
|
||||
|
||||
/* Save trigger time in global variable */
|
||||
LastTriggerTime = tim->ttime;
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = tim->ttime;
|
||||
}
|
||||
PushToken(DBufValue(&buf), s);
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
@@ -551,7 +570,7 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
{
|
||||
int r, y, m, d;
|
||||
char PrioExpr[25];
|
||||
char PrioExpr[VAR_NAME_LEN+25];
|
||||
char tmpBuf[64];
|
||||
DynamicBuffer buf, calRow;
|
||||
DynamicBuffer pre_buf;
|
||||
@@ -744,7 +763,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
DBufFree(&buf);
|
||||
NumTriggered++;
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -752,12 +771,13 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
/* */
|
||||
/* Return 1 if we should trigger a reminder, based on today's */
|
||||
/* date and the trigger. Return 0 if reminder should not be */
|
||||
/* triggered. */
|
||||
/* triggered. Sets *err non-zero in event of an error. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
|
||||
int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
|
||||
{
|
||||
int r;
|
||||
int r, omit;
|
||||
*err = 0;
|
||||
|
||||
/* Handle the ONCE modifier in the reminder. */
|
||||
if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday)
|
||||
@@ -781,7 +801,12 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
|
||||
|
||||
/* If there's a "warn" function, it overrides any deltas */
|
||||
if (t->warn[0] != 0) {
|
||||
return ShouldTriggerBasedOnWarn(t, jul);
|
||||
if (DeltaOffset) {
|
||||
if (jul <= JulianToday + DeltaOffset) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return ShouldTriggerBasedOnWarn(t, jul, err);
|
||||
}
|
||||
|
||||
/* Move back by delta days, if any */
|
||||
@@ -790,15 +815,28 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
|
||||
jul = jul + t->delta;
|
||||
else {
|
||||
r = t->delta;
|
||||
while(r && jul > JulianToday) {
|
||||
int iter = 0;
|
||||
int max = MaxSatIter;
|
||||
if (max < r*2) max = r*2;
|
||||
while(iter++ < max) {
|
||||
if (!r || (jul <= JulianToday)) {
|
||||
break;
|
||||
}
|
||||
jul--;
|
||||
if (!IsOmitted(jul, t->localomit)) r--;
|
||||
*err = IsOmitted(jul, t->localomit, t->omitfunc, &omit);
|
||||
if (*err) return 0;
|
||||
if (!omit) r--;
|
||||
}
|
||||
if (iter > max) {
|
||||
*err = E_CANT_TRIG;
|
||||
Eprint("Delta: Bad OMITFUNC? %s", ErrMsg[E_CANT_TRIG]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Should we trigger the reminder? */
|
||||
return (jul <= JulianToday);
|
||||
return (jul <= JulianToday + DeltaOffset);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -819,7 +857,7 @@ int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
|
||||
iter = 0;
|
||||
jul = trig->scanfrom;
|
||||
while (iter++ < MaxSatIter) {
|
||||
jul = ComputeTrigger(jul, trig, &r);
|
||||
jul = ComputeTrigger(jul, trig, &r, 1);
|
||||
if (r) {
|
||||
if (r == E_CANT_TRIG) return OK; else return r;
|
||||
}
|
||||
@@ -948,12 +986,12 @@ finished:
|
||||
/* function. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int ShouldTriggerBasedOnWarn(Trigger *t, int jul)
|
||||
static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err)
|
||||
{
|
||||
char buffer[VAR_NAME_LEN+32];
|
||||
int i;
|
||||
char const *s;
|
||||
int r;
|
||||
int r, omit;
|
||||
Value v;
|
||||
int lastReturnVal = 0; /* Silence compiler warning */
|
||||
|
||||
@@ -991,9 +1029,21 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul)
|
||||
if (JulianToday + v.v.val == jul) return 1;
|
||||
} else {
|
||||
int j = jul;
|
||||
while (v.v.val) {
|
||||
int iter = 0;
|
||||
int max = MaxSatIter;
|
||||
if (max < v.v.val * 2) max = v.v.val*2;
|
||||
while(iter++ <= max) {
|
||||
j--;
|
||||
if (!IsOmitted(j, t->localomit)) v.v.val++;
|
||||
*err = IsOmitted(j, t->localomit, t->omitfunc, &omit);
|
||||
if (*err) return 0;
|
||||
if (!omit) v.v.val++;
|
||||
if (!v.v.val) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iter > max) {
|
||||
Eprint("Delta: Bad OMITFUNC? %s", ErrMsg[E_CANT_TRIG]);
|
||||
return 0;
|
||||
}
|
||||
if (j == JulianToday) return 1;
|
||||
}
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
#define E_EXPECTING_NUMBER 97
|
||||
#define M_BAD_WARN_FUNC 98
|
||||
#define E_CANT_CONVERT_TZ 99
|
||||
#define E_NO_MATCHING_REMS 100
|
||||
#define E_STRING_TOO_LONG 101
|
||||
|
||||
#ifdef MK_GLOBALS
|
||||
#undef EXTERN
|
||||
@@ -189,7 +191,7 @@ EXTERN char *ErrMsg[]
|
||||
"Too many partial OMITs",
|
||||
"Too many full OMITs",
|
||||
"Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT",
|
||||
"Error reading file",
|
||||
"Error reading",
|
||||
"Expecting end-of-line",
|
||||
"Invalid Hebrew date",
|
||||
"IIF needs odd number of arguments",
|
||||
@@ -230,7 +232,9 @@ EXTERN char *ErrMsg[]
|
||||
"%d reminder(s) queued for later today.\n",
|
||||
"Expecting number",
|
||||
"Bad function in WARN clause",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
}
|
||||
#endif /* MK_GLOBALS */
|
||||
;
|
||||
|
||||
50
src/expr.c
50
src/expr.c
@@ -204,6 +204,46 @@ static int ParseExprToken(DynamicBuffer *buf, char const **in)
|
||||
if (c == '\"') {
|
||||
if (!**in) return E_MISS_QUOTE;
|
||||
while (**in) {
|
||||
/* Allow backslash-escapes */
|
||||
if (**in == '\\') {
|
||||
int r;
|
||||
(*in)++;
|
||||
if (!**in) {
|
||||
DBufFree(buf);
|
||||
return E_MISS_QUOTE;
|
||||
}
|
||||
switch(**in) {
|
||||
case 'a':
|
||||
r = DBufPutc(buf, '\a');
|
||||
break;
|
||||
case 'b':
|
||||
r = DBufPutc(buf, '\b');
|
||||
break;
|
||||
case 'f':
|
||||
r = DBufPutc(buf, '\f');
|
||||
break;
|
||||
case 'n':
|
||||
r = DBufPutc(buf, '\n');
|
||||
break;
|
||||
case 'r':
|
||||
r = DBufPutc(buf, '\r');
|
||||
break;
|
||||
case 't':
|
||||
r = DBufPutc(buf, '\t');
|
||||
break;
|
||||
case 'v':
|
||||
r = DBufPutc(buf, '\v');
|
||||
break;
|
||||
default:
|
||||
r = DBufPutc(buf, **in);
|
||||
}
|
||||
(*in)++;
|
||||
if (r != OK) {
|
||||
DBufFree(buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c = *(*in)++;
|
||||
if (DBufPutc(buf, c) != OK) {
|
||||
DBufFree(buf);
|
||||
@@ -697,6 +737,8 @@ static int Add(void)
|
||||
Value v1, v2, v3;
|
||||
int r;
|
||||
|
||||
size_t l1, l2;
|
||||
|
||||
PopValStack(v2);
|
||||
if ( (r = FnPopValStack(&v1)) ) {
|
||||
DestroyValue(v2);
|
||||
@@ -751,7 +793,13 @@ static int Add(void)
|
||||
return r;
|
||||
}
|
||||
v3.type = STR_TYPE;
|
||||
v3.v.str = malloc(strlen(v1.v.str) + strlen(v2.v.str) + 1);
|
||||
l1 = strlen(v1.v.str);
|
||||
l2 = strlen(v2.v.str);
|
||||
if (MaxStringLen && (l1 + l2 > MaxStringLen)) {
|
||||
DestroyValue(v1); DestroyValue(v2);
|
||||
return E_STRING_TOO_LONG;
|
||||
}
|
||||
v3.v.str = malloc(l1 + l2 + 1);
|
||||
if (!v3.v.str) {
|
||||
DestroyValue(v1); DestroyValue(v2);
|
||||
return E_NO_MEM;
|
||||
|
||||
257
src/files.c
257
src/files.c
@@ -30,6 +30,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_GLOB_H
|
||||
#include <glob.h>
|
||||
#endif
|
||||
|
||||
#include "types.h"
|
||||
#include "protos.h"
|
||||
#include "globals.h"
|
||||
@@ -53,9 +57,23 @@ typedef struct cheader {
|
||||
int ownedByMe;
|
||||
} CachedFile;
|
||||
|
||||
/* A linked list of filenames if we INCLUDE /some/directory/ */
|
||||
typedef struct fname_chain {
|
||||
struct fname_chain *next;
|
||||
char const *filename;
|
||||
} FilenameChain;
|
||||
|
||||
/* Cache filename chains for directories */
|
||||
typedef struct directory_fname_chain {
|
||||
struct directory_fname_chain *next;
|
||||
FilenameChain *chain;
|
||||
char const *dirname;
|
||||
} DirectoryFilenameChain;
|
||||
|
||||
/* Define the structures needed by the INCLUDE file system */
|
||||
typedef struct {
|
||||
char const *filename;
|
||||
FilenameChain *chain;
|
||||
int LineNo;
|
||||
unsigned int IfFlags;
|
||||
int NumIfs;
|
||||
@@ -66,6 +84,7 @@ typedef struct {
|
||||
|
||||
static CachedFile *CachedFiles = (CachedFile *) NULL;
|
||||
static CachedLine *CLine = (CachedLine *) NULL;
|
||||
static DirectoryFilenameChain *CachedDirectoryChains = NULL;
|
||||
|
||||
static FILE *fp;
|
||||
|
||||
@@ -76,6 +95,23 @@ static int ReadLineFromFile (void);
|
||||
static int CacheFile (char const *fname);
|
||||
static void DestroyCache (CachedFile *cf);
|
||||
static int CheckSafety (void);
|
||||
static int PopFile (void);
|
||||
|
||||
static void FreeChainItem(FilenameChain *chain)
|
||||
{
|
||||
if (chain->filename) free((void *) chain->filename);
|
||||
free(chain);
|
||||
}
|
||||
|
||||
static void FreeChain(FilenameChain *chain)
|
||||
{
|
||||
FilenameChain *next;
|
||||
while(chain) {
|
||||
next = chain->next;
|
||||
FreeChainItem(chain);
|
||||
chain = next;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -140,7 +176,7 @@ static int ReadLineFromFile(void)
|
||||
}
|
||||
l = DBufLen(&buf);
|
||||
if (l && (DBufValue(&buf)[l-1] == '\\')) {
|
||||
DBufValue(&buf)[l-1] = 0;
|
||||
DBufValue(&buf)[l-1] = '\n';
|
||||
if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) {
|
||||
DBufFree(&buf);
|
||||
DBufFree(&LineBuffer);
|
||||
@@ -183,6 +219,9 @@ int OpenFile(char const *fname)
|
||||
|
||||
while (h) {
|
||||
if (!strcmp(fname, h->filename)) {
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Reading `%s': Found in cache\n", fname);
|
||||
}
|
||||
CLine = h->cache;
|
||||
STRSET(FileName, fname);
|
||||
LineNo = 0;
|
||||
@@ -197,8 +236,14 @@ int OpenFile(char const *fname)
|
||||
/* If it's a dash, then it's stdin */
|
||||
if (!strcmp(fname, "-")) {
|
||||
fp = stdin;
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Reading `-': Reading stdin\n");
|
||||
}
|
||||
} else {
|
||||
fp = fopen(fname, "r");
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Reading `%s': Opening file on disk\n", fname);
|
||||
}
|
||||
}
|
||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||
CLine = NULL;
|
||||
@@ -237,6 +282,9 @@ static int CacheFile(char const *fname)
|
||||
CachedLine *cl;
|
||||
char const *s;
|
||||
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Caching file `%s' in memory\n", fname);
|
||||
}
|
||||
cl = NULL;
|
||||
/* Create a file header */
|
||||
cf = NEW(CachedFile);
|
||||
@@ -311,13 +359,33 @@ static int CacheFile(char const *fname)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* NextChainedFile - move to the next chained file in a glob */
|
||||
/* list. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int NextChainedFile(IncludeStruct *i)
|
||||
{
|
||||
while(i->chain) {
|
||||
FilenameChain *cur = i->chain;
|
||||
i->chain = i->chain->next;
|
||||
if (OpenFile(cur->filename) == OK) {
|
||||
return OK;
|
||||
} else {
|
||||
Eprint("%s: %s", ErrMsg[E_CANT_OPEN], cur->filename);
|
||||
}
|
||||
}
|
||||
return E_EOF;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* PopFile - we've reached the end. Pop up to the previous */
|
||||
/* file, or return E_EOF */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int PopFile(void)
|
||||
static int PopFile(void)
|
||||
{
|
||||
IncludeStruct *i;
|
||||
|
||||
@@ -326,8 +394,21 @@ int PopFile(void)
|
||||
|
||||
if (!Hush && NumIfs) Eprint("%s", ErrMsg[E_MISS_ENDIF]);
|
||||
if (!IStackPtr) return E_EOF;
|
||||
i = &IStack[IStackPtr-1];
|
||||
|
||||
if (i->chain) {
|
||||
int oldRunDisabled = RunDisabled;
|
||||
if (NextChainedFile(i) == OK) {
|
||||
return OK;
|
||||
}
|
||||
RunDisabled = oldRunDisabled;
|
||||
}
|
||||
|
||||
if (IStackPtr <= 1) {
|
||||
return E_EOF;
|
||||
}
|
||||
|
||||
IStackPtr--;
|
||||
i = &IStack[IStackPtr];
|
||||
|
||||
LineNo = i->LineNo;
|
||||
IfFlags = i->IfFlags;
|
||||
@@ -361,13 +442,13 @@ int PopFile(void)
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DoInclude(ParsePtr p)
|
||||
{
|
||||
{
|
||||
DynamicBuffer buf;
|
||||
int r, e;
|
||||
|
||||
DBufInit(&buf);
|
||||
if ( (r=ParseToken(p, &buf)) ) return r;
|
||||
e = VerifyEoln(p);
|
||||
e = VerifyEoln(p);
|
||||
if (e) Eprint("%s", ErrMsg[e]);
|
||||
if ( (r=IncludeFile(DBufValue(&buf))) ) {
|
||||
DBufFree(&buf);
|
||||
@@ -379,6 +460,114 @@ int DoInclude(ParsePtr p)
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GLOB
|
||||
static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
||||
{
|
||||
DynamicBuffer pattern;
|
||||
char *dir;
|
||||
size_t l;
|
||||
int r;
|
||||
glob_t glob_buf;
|
||||
DirectoryFilenameChain *dc = CachedDirectoryChains;
|
||||
|
||||
i->chain = NULL;
|
||||
if (!*dirname) return E_CANT_OPEN;
|
||||
|
||||
dir = StrDup(dirname);
|
||||
if (!dir) return E_NO_MEM;
|
||||
|
||||
/* Strip trailing slashes off directory */
|
||||
l = strlen(dir);
|
||||
while(l) {
|
||||
if (*(dir+l-1) == '/') {
|
||||
l--;
|
||||
*(dir+l) = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Repair root directory :-) */
|
||||
if (!l) {
|
||||
*dir = '/';
|
||||
}
|
||||
|
||||
/* Check the cache */
|
||||
while(dc) {
|
||||
if (!strcmp(dc->dirname, dir)) {
|
||||
free(dir);
|
||||
i->chain = dc->chain;
|
||||
return OK;
|
||||
}
|
||||
dc = dc->next;
|
||||
}
|
||||
|
||||
if (ShouldCache) {
|
||||
dc = malloc(sizeof(DirectoryFilenameChain));
|
||||
if (dc) {
|
||||
dc->dirname = StrDup(dir);
|
||||
if (!dc->dirname) {
|
||||
free(dc);
|
||||
dc = NULL;
|
||||
}
|
||||
}
|
||||
if (dc) {
|
||||
dc->chain = NULL;
|
||||
dc->next = CachedDirectoryChains;
|
||||
CachedDirectoryChains = dc;
|
||||
}
|
||||
}
|
||||
|
||||
DBufInit(&pattern);
|
||||
DBufPuts(&pattern, dir);
|
||||
DBufPuts(&pattern, "/*.rem");
|
||||
free(dir);
|
||||
|
||||
r = glob(DBufValue(&pattern), 0, NULL, &glob_buf);
|
||||
DBufFree(&pattern);
|
||||
|
||||
if (r == GLOB_NOMATCH) {
|
||||
globfree(&glob_buf);
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (r != 0) {
|
||||
globfree(&glob_buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Add the files to the chain backwards to preserve sort order */
|
||||
for (r=glob_buf.gl_pathc-1; r>=0; r--) {
|
||||
FilenameChain *ch = malloc(sizeof(FilenameChain));
|
||||
if (!ch) {
|
||||
globfree(&glob_buf);
|
||||
FreeChain(i->chain);
|
||||
i->chain = NULL;
|
||||
return E_NO_MEM;
|
||||
}
|
||||
|
||||
/* TODO: stat the file and only add if it's a plain file and
|
||||
readable by us */
|
||||
ch->filename = StrDup(glob_buf.gl_pathv[r]);
|
||||
if (!ch->filename) {
|
||||
globfree(&glob_buf);
|
||||
FreeChain(i->chain);
|
||||
i->chain = NULL;
|
||||
free(ch);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
ch->next = i->chain;
|
||||
i->chain = ch;
|
||||
}
|
||||
if (dc) {
|
||||
dc->chain = i->chain;
|
||||
}
|
||||
|
||||
globfree(&glob_buf);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* IncludeFile */
|
||||
@@ -390,19 +579,25 @@ int DoInclude(ParsePtr p)
|
||||
int IncludeFile(char const *fname)
|
||||
{
|
||||
IncludeStruct *i;
|
||||
int r;
|
||||
int oldRunDisabled;
|
||||
struct stat statbuf;
|
||||
|
||||
FreshLine = 1;
|
||||
if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE;
|
||||
i = &IStack[IStackPtr];
|
||||
|
||||
i->filename = StrDup(FileName);
|
||||
if (!i->filename) return E_NO_MEM;
|
||||
if (FileName) {
|
||||
i->filename = StrDup(FileName);
|
||||
if (!i->filename) return E_NO_MEM;
|
||||
} else {
|
||||
i->filename = NULL;
|
||||
}
|
||||
i->LineNo = LineNo;
|
||||
i->NumIfs = NumIfs;
|
||||
i->IfFlags = IfFlags;
|
||||
i->CLine = CLine;
|
||||
i->offset = -1L;
|
||||
i->chain = NULL;
|
||||
if (RunDisabled & RUN_NOTOWNER) {
|
||||
i->ownedByMe = 0;
|
||||
} else {
|
||||
@@ -415,15 +610,55 @@ int IncludeFile(char const *fname)
|
||||
|
||||
IStackPtr++;
|
||||
|
||||
#ifdef HAVE_GLOB
|
||||
/* If it's a directory, set up the glob chain here. */
|
||||
if (stat(fname, &statbuf) == 0) {
|
||||
FilenameChain *fc;
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Scanning directory `%s' for *.rem files\n", fname);
|
||||
}
|
||||
if (SetupGlobChain(fname, i) == OK) { /* Glob succeeded */
|
||||
if (!i->chain) { /* Oops... no matching files */
|
||||
if (!Hush) {
|
||||
Eprint("%s: %s", fname, ErrMsg[E_NO_MATCHING_REMS]);
|
||||
}
|
||||
PopFile();
|
||||
return E_NO_MATCHING_REMS;
|
||||
}
|
||||
while(i->chain) {
|
||||
fc = i->chain;
|
||||
i->chain = i->chain->next;
|
||||
|
||||
/* Munch first file */
|
||||
oldRunDisabled = RunDisabled;
|
||||
if (!OpenFile(fc->filename)) {
|
||||
return OK;
|
||||
}
|
||||
Eprint("%s: %s", ErrMsg[E_CANT_OPEN], fc->filename);
|
||||
RunDisabled = oldRunDisabled;
|
||||
}
|
||||
/* Couldn't open anything... bail */
|
||||
return PopFile();
|
||||
} else {
|
||||
if (!Hush) {
|
||||
Eprint("%s: %s", fname, ErrMsg[E_NO_MATCHING_REMS]);
|
||||
}
|
||||
}
|
||||
return E_NO_MATCHING_REMS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
oldRunDisabled = RunDisabled;
|
||||
/* Try to open the new file */
|
||||
if (!OpenFile(fname)) {
|
||||
return OK;
|
||||
}
|
||||
RunDisabled = oldRunDisabled;
|
||||
/* Ugh! We failed! */
|
||||
if ( (r=PopFile()) ) return r;
|
||||
Eprint("%s: %s", ErrMsg[E_CANT_OPEN], fname);
|
||||
/* Ugh! We failed! */
|
||||
PopFile();
|
||||
return E_CANT_OPEN;
|
||||
}
|
||||
|
||||
@@ -488,7 +723,7 @@ static void DestroyCache(CachedFile *cf)
|
||||
/***************************************************************/
|
||||
int TopLevel(void)
|
||||
{
|
||||
return !IStackPtr;
|
||||
return IStackPtr <= 1;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
435
src/funcs.c
435
src/funcs.c
@@ -70,6 +70,7 @@ static int FDaysinmon (void);
|
||||
static int FDefined (void);
|
||||
static int FDosubst (void);
|
||||
static int FEasterdate (void);
|
||||
static int FEvalTrig (void);
|
||||
static int FFiledate (void);
|
||||
static int FFiledatetime (void);
|
||||
static int FFiledir (void);
|
||||
@@ -128,6 +129,7 @@ static int FRealtoday (void);
|
||||
static int FToday (void);
|
||||
static int FTrigger (void);
|
||||
static int FTzconvert (void);
|
||||
static int FWeekno (void);
|
||||
static int CheckArgs (Operator *f, int nargs);
|
||||
static int CleanUpAfterFunc (void);
|
||||
static int SunStuff (int rise, double cosz, int jul);
|
||||
@@ -163,6 +165,11 @@ extern int ValStackPtr;
|
||||
from 0 to (Nargs - 1) */
|
||||
#define ARG(x) (ValStack[ValStackPtr - Nargs + (x)])
|
||||
|
||||
#define ARGV(x) ARG(x).v.val
|
||||
#define ARGSTR(x) ARG(x).v.str
|
||||
|
||||
#define ASSERT_TYPE(x, t) if (ARG(x).type != t) return E_BAD_TYPE
|
||||
|
||||
/* Macro for getting date part of a date or datetime value */
|
||||
#define DATEPART(x) ((x).type == DATE_TYPE ? (x).v.val : ((x).v.val / MINUTES_PER_DAY))
|
||||
|
||||
@@ -202,6 +209,7 @@ Operator Func[] = {
|
||||
{ "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 },
|
||||
@@ -258,6 +266,7 @@ Operator Func[] = {
|
||||
{ "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 }
|
||||
@@ -409,15 +418,37 @@ static int FBaseyr(void)
|
||||
static int FDate(void)
|
||||
{
|
||||
int y, m, d;
|
||||
if (ARG(0).type != INT_TYPE ||
|
||||
ARG(1).type != INT_TYPE ||
|
||||
ARG(2).type != INT_TYPE) return E_BAD_TYPE;
|
||||
y = ARG(0).v.val;
|
||||
m = ARG(1).v.val - 1;
|
||||
d = ARG(2).v.val;
|
||||
int ytemp, mtemp, dtemp;
|
||||
|
||||
if (!DateOK(y, m, d)) return E_BAD_DATE;
|
||||
/* Any arg can be a date (in which case we use the corresponding
|
||||
component) or an integer */
|
||||
if (HASDATE(ARG(0))) {
|
||||
FromJulian(DATEPART(ARG(0)), &ytemp, &mtemp, &dtemp);
|
||||
y = ytemp;
|
||||
} else {
|
||||
ASSERT_TYPE(0, INT_TYPE);
|
||||
y = ARGV(0);
|
||||
}
|
||||
|
||||
if (HASDATE(ARG(1))) {
|
||||
FromJulian(DATEPART(ARG(1)), &ytemp, &mtemp, &dtemp);
|
||||
m = mtemp;
|
||||
} else {
|
||||
ASSERT_TYPE(1, INT_TYPE);
|
||||
m = ARGV(1) - 1;
|
||||
}
|
||||
|
||||
if (HASDATE(ARG(2))) {
|
||||
FromJulian(DATEPART(ARG(2)), &ytemp, &mtemp, &dtemp);
|
||||
d = dtemp;
|
||||
} else {
|
||||
ASSERT_TYPE(2, INT_TYPE);
|
||||
d = ARGV(2);
|
||||
}
|
||||
|
||||
if (!DateOK(y, m, d)) {
|
||||
return E_BAD_DATE;
|
||||
}
|
||||
RetVal.type = DATE_TYPE;
|
||||
RetVal.v.val = Julian(y, m, d);
|
||||
return OK;
|
||||
@@ -442,27 +473,27 @@ static int FDateTime(void)
|
||||
case 2:
|
||||
if (ARG(0).type != DATE_TYPE ||
|
||||
ARG(1).type != TIME_TYPE) return E_BAD_TYPE;
|
||||
RetVal.v.val = (MINUTES_PER_DAY * ARG(0).v.val) + ARG(1).v.val;
|
||||
RetVal.v.val = (MINUTES_PER_DAY * ARGV(0)) + ARGV(1);
|
||||
return OK;
|
||||
case 3:
|
||||
if (ARG(0).type != DATE_TYPE ||
|
||||
ARG(1).type != INT_TYPE ||
|
||||
ARG(2).type != INT_TYPE) return E_BAD_TYPE;
|
||||
if (ARG(1).v.val < 0 || ARG(2).v.val < 0) return E_2LOW;
|
||||
if (ARG(1).v.val > 23 || ARG(2).v.val > 59) return E_2HIGH;
|
||||
RetVal.v.val = (MINUTES_PER_DAY * ARG(0).v.val) + 60 * ARG(1).v.val + ARG(2).v.val;
|
||||
if (ARGV(1) < 0 || ARGV(2) < 0) return E_2LOW;
|
||||
if (ARGV(1) > 23 || ARGV(2) > 59) return E_2HIGH;
|
||||
RetVal.v.val = (MINUTES_PER_DAY * ARGV(0)) + 60 * ARGV(1) + ARGV(2);
|
||||
return OK;
|
||||
case 4:
|
||||
if (ARG(0).type != INT_TYPE ||
|
||||
ARG(1).type != INT_TYPE ||
|
||||
ARG(2).type != INT_TYPE ||
|
||||
ARG(3).type != TIME_TYPE) return E_BAD_TYPE;
|
||||
y = ARG(0).v.val;
|
||||
m = ARG(1).v.val - 1;
|
||||
d = ARG(2).v.val;
|
||||
y = ARGV(0);
|
||||
m = ARGV(1) - 1;
|
||||
d = ARGV(2);
|
||||
|
||||
if (!DateOK(y, m, d)) return E_BAD_DATE;
|
||||
RetVal.v.val = Julian(y, m, d) * MINUTES_PER_DAY + ARG(3).v.val;
|
||||
RetVal.v.val = Julian(y, m, d) * MINUTES_PER_DAY + ARGV(3);
|
||||
return OK;
|
||||
case 5:
|
||||
if (ARG(0).type != INT_TYPE ||
|
||||
@@ -471,14 +502,14 @@ static int FDateTime(void)
|
||||
ARG(3).type != INT_TYPE ||
|
||||
ARG(4).type != INT_TYPE) return E_BAD_TYPE;
|
||||
|
||||
y = ARG(0).v.val;
|
||||
m = ARG(1).v.val - 1;
|
||||
d = ARG(2).v.val;
|
||||
y = ARGV(0);
|
||||
m = ARGV(1) - 1;
|
||||
d = ARGV(2);
|
||||
if (!DateOK(y, m, d)) return E_BAD_DATE;
|
||||
|
||||
if (ARG(3).v.val < 0 || ARG(4).v.val < 0) return E_2LOW;
|
||||
if (ARG(3).v.val > 23 || ARG(4).v.val > 59) return E_2HIGH;
|
||||
RetVal.v.val = Julian(y, m, d) * MINUTES_PER_DAY + ARG(3).v.val * 60 + ARG(4).v.val;
|
||||
if (ARGV(3) < 0 || ARGV(4) < 0) return E_2LOW;
|
||||
if (ARGV(3) > 23 || ARGV(4) > 59) return E_2HIGH;
|
||||
RetVal.v.val = Julian(y, m, d) * MINUTES_PER_DAY + ARGV(3) * 60 + ARGV(4);
|
||||
return OK;
|
||||
|
||||
default:
|
||||
@@ -495,8 +526,8 @@ static int FCoerce(void)
|
||||
{
|
||||
char const *s;
|
||||
|
||||
if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
|
||||
s = ARG(0).v.str;
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
s = ARGSTR(0);
|
||||
|
||||
/* Copy the value of ARG(1) into RetVal, and make ARG(1) invalid so
|
||||
it won't be destroyed */
|
||||
@@ -569,9 +600,9 @@ static int FMin(void)
|
||||
/***************************************************************/
|
||||
static int FAsc(void)
|
||||
{
|
||||
if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
RetVal.type = INT_TYPE;
|
||||
RetVal.v.val = *(ARG(0).v.str);
|
||||
RetVal.v.val = *(ARGSTR(0));
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -587,14 +618,14 @@ static int FChar(void)
|
||||
|
||||
/* Special case of one arg - if given ascii value 0, create empty string */
|
||||
if (Nargs == 1) {
|
||||
if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
|
||||
if (ARG(0).v.val < -128) return E_2LOW;
|
||||
if (ARG(0).v.val > 255) return E_2HIGH;
|
||||
len = ARG(0).v.val ? 2 : 1;
|
||||
ASSERT_TYPE(0, INT_TYPE);
|
||||
if (ARGV(0) < -128) return E_2LOW;
|
||||
if (ARGV(0) > 255) return E_2HIGH;
|
||||
len = ARGV(0) ? 2 : 1;
|
||||
RetVal.v.str = malloc(len);
|
||||
if (!RetVal.v.str) return E_NO_MEM;
|
||||
RetVal.type = STR_TYPE;
|
||||
*(RetVal.v.str) = ARG(0).v.val;
|
||||
*(RetVal.v.str) = ARGV(0);
|
||||
if (len>1) *(RetVal.v.str + 1) = 0;
|
||||
return OK;
|
||||
}
|
||||
@@ -714,12 +745,12 @@ static int FWkday(void)
|
||||
|
||||
if (!HASDATE(ARG(0)) && ARG(0).type != INT_TYPE) return E_BAD_TYPE;
|
||||
if (ARG(0).type == INT_TYPE) {
|
||||
if (ARG(0).v.val < 0) return E_2LOW;
|
||||
if (ARG(0).v.val > 6) return E_2HIGH;
|
||||
if (ARGV(0) < 0) return E_2LOW;
|
||||
if (ARGV(0) > 6) return E_2HIGH;
|
||||
/* Convert 0=Sun to 0=Mon */
|
||||
ARG(0).v.val--;
|
||||
if (ARG(0).v.val < 0) ARG(0).v.val = 6;
|
||||
s = DayName[ARG(0).v.val];
|
||||
ARGV(0)--;
|
||||
if (ARGV(0) < 0) ARGV(0) = 6;
|
||||
s = DayName[ARGV(0)];
|
||||
} else s = DayName[DATEPART(ARG(0)) % 7];
|
||||
return RetStrVal(s);
|
||||
}
|
||||
@@ -732,7 +763,7 @@ static int FMon(void)
|
||||
if (!HASDATE(ARG(0)) && ARG(0).type != INT_TYPE) return E_BAD_TYPE;
|
||||
|
||||
if (ARG(0).type == INT_TYPE) {
|
||||
m = ARG(0).v.val - 1;
|
||||
m = ARGV(0) - 1;
|
||||
if (m < 0) return E_2LOW;
|
||||
if (m > 11) return E_2HIGH;
|
||||
} else {
|
||||
@@ -784,8 +815,8 @@ static int FTime(void)
|
||||
|
||||
if (ARG(0).type != INT_TYPE || ARG(1).type != INT_TYPE) return E_BAD_TYPE;
|
||||
|
||||
h = ARG(0).v.val;
|
||||
m = ARG(1).v.val;
|
||||
h = ARGV(0);
|
||||
m = ARGV(1);
|
||||
if (h<0 || m<0) return E_2LOW;
|
||||
if (h>23 || m>59) return E_2HIGH;
|
||||
RetVal.type = TIME_TYPE;
|
||||
@@ -803,8 +834,8 @@ static int FAbs(void)
|
||||
{
|
||||
int v;
|
||||
|
||||
if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
|
||||
v = ARG(0).v.val;
|
||||
ASSERT_TYPE(0, INT_TYPE);
|
||||
v = ARGV(0);
|
||||
RetVal.type = INT_TYPE;
|
||||
RetVal.v.val = (v < 0) ? (-v) : v;
|
||||
return OK;
|
||||
@@ -814,8 +845,8 @@ static int FSgn(void)
|
||||
{
|
||||
int v;
|
||||
|
||||
if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
|
||||
v = ARG(0).v.val;
|
||||
ASSERT_TYPE(0, INT_TYPE);
|
||||
v = ARGV(0);
|
||||
RetVal.type = INT_TYPE;
|
||||
if (v>0) RetVal.v.val = 1;
|
||||
else if (v<0) RetVal.v.val = -1;
|
||||
@@ -835,9 +866,9 @@ static int FOrd(void)
|
||||
int t, u, v;
|
||||
char const *s;
|
||||
|
||||
if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, INT_TYPE);
|
||||
|
||||
v = ARG(0).v.val;
|
||||
v = ARGV(0);
|
||||
t = v % 100;
|
||||
if (t < 0) t = -t;
|
||||
u = t % 10;
|
||||
@@ -860,33 +891,33 @@ static int FOrd(void)
|
||||
/***************************************************************/
|
||||
static int FPlural(void)
|
||||
{
|
||||
if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, INT_TYPE);
|
||||
|
||||
switch(Nargs) {
|
||||
case 1:
|
||||
if (ARG(0).v.val == 1) return RetStrVal("");
|
||||
if (ARGV(0) == 1) return RetStrVal("");
|
||||
else return RetStrVal("s");
|
||||
|
||||
case 2:
|
||||
if (ARG(1).type != STR_TYPE) return E_BAD_TYPE;
|
||||
if (ARG(0).v.val == 1) {
|
||||
ASSERT_TYPE(1, STR_TYPE);
|
||||
if (ARGV(0) == 1) {
|
||||
DCOPYVAL(RetVal, ARG(1));
|
||||
return OK;
|
||||
}
|
||||
RetVal.type = STR_TYPE;
|
||||
RetVal.v.str = malloc(strlen(ARG(1).v.str)+2);
|
||||
RetVal.v.str = malloc(strlen(ARGSTR(1))+2);
|
||||
if (!RetVal.v.str) {
|
||||
RetVal.type = ERR_TYPE;
|
||||
return E_NO_MEM;
|
||||
}
|
||||
strcpy(RetVal.v.str, ARG(1).v.str);
|
||||
strcpy(RetVal.v.str, ARGSTR(1));
|
||||
strcat(RetVal.v.str, "s");
|
||||
return OK;
|
||||
|
||||
default:
|
||||
if (ARG(1).type != STR_TYPE || ARG(2).type != STR_TYPE)
|
||||
return E_BAD_TYPE;
|
||||
if (ARG(0).v.val == 1) DCOPYVAL(RetVal, ARG(1));
|
||||
if (ARGV(0) == 1) DCOPYVAL(RetVal, ARG(1));
|
||||
else DCOPYVAL(RetVal, ARG(2));
|
||||
return OK;
|
||||
}
|
||||
@@ -904,8 +935,8 @@ static int FChoose(void)
|
||||
{
|
||||
int v;
|
||||
|
||||
if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
|
||||
v = ARG(0).v.val;
|
||||
ASSERT_TYPE(0, INT_TYPE);
|
||||
v = ARGV(0);
|
||||
if (v < 1) v = 1;
|
||||
if (v > Nargs-1) v = Nargs-1;
|
||||
DCOPYVAL(RetVal, ARG(v));
|
||||
@@ -943,7 +974,7 @@ static int FUpper(void)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
DCOPYVAL(RetVal, ARG(0));
|
||||
s = RetVal.v.str;
|
||||
while (*s) {
|
||||
@@ -957,7 +988,7 @@ static int FLower(void)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
DCOPYVAL(RetVal, ARG(0));
|
||||
s = RetVal.v.str;
|
||||
while (*s) {
|
||||
@@ -1024,8 +1055,8 @@ static int FRealCurrent(void)
|
||||
/***************************************************************/
|
||||
static int FGetenv(void)
|
||||
{
|
||||
if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
|
||||
return RetStrVal(getenv(ARG(0).v.str));
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
return RetStrVal(getenv(ARGSTR(0)));
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -1040,13 +1071,13 @@ static int FValue(void)
|
||||
{
|
||||
Var *v;
|
||||
|
||||
if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
switch(Nargs) {
|
||||
case 1:
|
||||
return GetVarValue(ARG(0).v.str, &RetVal, NULL);
|
||||
return GetVarValue(ARGSTR(0), &RetVal, NULL);
|
||||
|
||||
case 2:
|
||||
v = FindVar(ARG(0).v.str, 0);
|
||||
v = FindVar(ARGSTR(0), 0);
|
||||
if (!v) {
|
||||
DCOPYVAL(RetVal, ARG(1));
|
||||
return OK;
|
||||
@@ -1066,11 +1097,11 @@ static int FValue(void)
|
||||
/***************************************************************/
|
||||
static int FDefined(void)
|
||||
{
|
||||
if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
|
||||
RetVal.type = INT_TYPE;
|
||||
|
||||
if (FindVar(ARG(0).v.str, 0))
|
||||
if (FindVar(ARGSTR(0), 0))
|
||||
RetVal.v.val = 1;
|
||||
else
|
||||
RetVal.v.val = 0;
|
||||
@@ -1142,12 +1173,12 @@ static int FDaysinmon(void)
|
||||
{
|
||||
if (ARG(0).type != INT_TYPE || ARG(1).type != INT_TYPE) return E_BAD_TYPE;
|
||||
|
||||
if (ARG(0).v.val > 12 || ARG(0).v.val < 1 ||
|
||||
ARG(1).v.val < BASE || ARG(1).v.val > BASE+YR_RANGE)
|
||||
if (ARGV(0) > 12 || ARGV(0) < 1 ||
|
||||
ARGV(1) < BASE || ARGV(1) > BASE+YR_RANGE)
|
||||
return E_DOMAIN_ERR;
|
||||
|
||||
RetVal.type = INT_TYPE;
|
||||
RetVal.v.val = DaysInMonth(ARG(0).v.val-1, ARG(1).v.val);
|
||||
RetVal.v.val = DaysInMonth(ARGV(0)-1, ARGV(1));
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -1168,7 +1199,7 @@ static int FIsleap(void)
|
||||
if (HASDATE(ARG(0)))
|
||||
FromJulian(DATEPART(ARG(0)), &y, &m, &d);
|
||||
else
|
||||
y = ARG(0).v.val;
|
||||
y = ARGV(0);
|
||||
|
||||
RetVal.type = INT_TYPE;
|
||||
RetVal.v.val = IsLeapYear(y);
|
||||
@@ -1193,34 +1224,34 @@ static int FTrigger(void)
|
||||
ARG(0).type != DATETIME_TYPE) return E_BAD_TYPE;
|
||||
|
||||
if (ARG(0).type == DATE_TYPE) {
|
||||
date = ARG(0).v.val;
|
||||
date = ARGV(0);
|
||||
} else {
|
||||
date = ARG(0).v.val / MINUTES_PER_DAY;
|
||||
tim = ARG(0).v.val % MINUTES_PER_DAY;
|
||||
date = ARGV(0) / MINUTES_PER_DAY;
|
||||
tim = ARGV(0) % MINUTES_PER_DAY;
|
||||
}
|
||||
|
||||
if (ARG(0).type == DATE_TYPE) {
|
||||
if (Nargs > 2) {
|
||||
/* Date Time UTCFlag */
|
||||
if (ARG(0).type == DATETIME_TYPE) return E_BAD_TYPE;
|
||||
if (ARG(2).type != INT_TYPE) return E_BAD_TYPE;
|
||||
if (ARG(1).type != TIME_TYPE) return E_BAD_TYPE;
|
||||
tim = ARG(1).v.val;
|
||||
if (ARG(2).v.val) {
|
||||
ASSERT_TYPE(2, INT_TYPE);
|
||||
ASSERT_TYPE(1, TIME_TYPE);
|
||||
tim = ARGV(1);
|
||||
if (ARGV(2)) {
|
||||
UTCToLocal(date, tim, &date, &tim);
|
||||
}
|
||||
} else if (Nargs > 1) {
|
||||
/* Date Time */
|
||||
if (ARG(1).type != TIME_TYPE) return E_BAD_TYPE;
|
||||
tim = ARG(1).v.val;
|
||||
ASSERT_TYPE(1, TIME_TYPE);
|
||||
tim = ARGV(1);
|
||||
}
|
||||
} else {
|
||||
if (Nargs > 2) {
|
||||
return E_2MANY_ARGS;
|
||||
} else if (Nargs > 1) {
|
||||
/* DateTime UTCFlag */
|
||||
if (ARG(1).type != INT_TYPE) return E_BAD_TYPE;
|
||||
if (ARG(1).v.val) {
|
||||
ASSERT_TYPE(1, INT_TYPE);
|
||||
if (ARGV(1)) {
|
||||
UTCToLocal(date, tim, &date, &tim);
|
||||
}
|
||||
}
|
||||
@@ -1257,12 +1288,12 @@ static int FShell(void)
|
||||
|
||||
DBufInit(&buf);
|
||||
if (RunDisabled) return E_RUN_DISABLED;
|
||||
if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
if (Nargs >= 2) {
|
||||
if (ARG(1).type != INT_TYPE) return E_BAD_TYPE;
|
||||
maxlen = ARG(1).v.val;
|
||||
ASSERT_TYPE(1, INT_TYPE);
|
||||
maxlen = ARGV(1);
|
||||
}
|
||||
fp = popen(ARG(0).v.str, "r");
|
||||
fp = popen(ARGSTR(0), "r");
|
||||
if (!fp) return E_IO_ERR;
|
||||
while (1) {
|
||||
ch = getc(fp);
|
||||
@@ -1285,6 +1316,8 @@ static int FShell(void)
|
||||
DBufValue(&buf)[DBufLen(&buf)-1] = 0;
|
||||
}
|
||||
|
||||
/* XXX Should we consume remaining output from cmd? */
|
||||
|
||||
pclose(fp);
|
||||
r = RetStrVal(DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
@@ -1301,9 +1334,10 @@ static int FShell(void)
|
||||
static int FIsomitted(void)
|
||||
{
|
||||
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||
|
||||
RetVal.type = INT_TYPE;
|
||||
RetVal.v.val = IsOmitted(DATEPART(ARG(0)), 0);
|
||||
return OK;
|
||||
int r = IsOmitted(DATEPART(ARG(0)), 0, NULL, &RetVal.v.val);
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -1322,9 +1356,9 @@ static int FSubstr(void)
|
||||
if (ARG(0).type != STR_TYPE || ARG(1).type != INT_TYPE) return E_BAD_TYPE;
|
||||
if (Nargs == 3 && ARG(2).type != INT_TYPE) return E_BAD_TYPE;
|
||||
|
||||
s = ARG(0).v.str;
|
||||
s = ARGSTR(0);
|
||||
start = 1;
|
||||
while (start < ARG(1).v.val) {
|
||||
while (start < ARGV(1)) {
|
||||
if (!*s) break;
|
||||
s++;
|
||||
start++;
|
||||
@@ -1332,7 +1366,7 @@ static int FSubstr(void)
|
||||
if (Nargs == 2 || !*s) return RetStrVal(s);
|
||||
end = start;
|
||||
t = s;
|
||||
while (end <= ARG(2).v.val) {
|
||||
while (end <= ARGV(2)) {
|
||||
if (!*s) break;
|
||||
s++;
|
||||
end++;
|
||||
@@ -1356,12 +1390,12 @@ static int FIndex(void)
|
||||
if (ARG(0).type != STR_TYPE || ARG(1).type != STR_TYPE ||
|
||||
(Nargs == 3 && ARG(2).type != INT_TYPE)) return E_BAD_TYPE;
|
||||
|
||||
s = ARG(0).v.str;
|
||||
s = ARGSTR(0);
|
||||
|
||||
/* If 3 args, bump up the start */
|
||||
if (Nargs == 3) {
|
||||
start = 1;
|
||||
while (start < ARG(2).v.val) {
|
||||
while (start < ARGV(2)) {
|
||||
if (!*s) break;
|
||||
s++;
|
||||
start++;
|
||||
@@ -1369,13 +1403,13 @@ static int FIndex(void)
|
||||
}
|
||||
|
||||
/* Find the string */
|
||||
s = strstr(s, ARG(1).v.str);
|
||||
s = strstr(s, ARGSTR(1));
|
||||
RetVal.type = INT_TYPE;
|
||||
if (!s) {
|
||||
RetVal.v.val = 0;
|
||||
return OK;
|
||||
}
|
||||
RetVal.v.val = (s - ARG(0).v.str) + 1;
|
||||
RetVal.v.val = (s - ARGSTR(0)) + 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -1469,10 +1503,10 @@ static int FAccess(void)
|
||||
if (ARG(0).type != STR_TYPE ||
|
||||
(ARG(1).type != INT_TYPE && ARG(1).type != STR_TYPE)) return E_BAD_TYPE;
|
||||
|
||||
if (ARG(1).type == INT_TYPE) amode = ARG(1).v.val;
|
||||
if (ARG(1).type == INT_TYPE) amode = ARGV(1);
|
||||
else {
|
||||
amode = 0;
|
||||
s = ARG(1).v.str;
|
||||
s = ARGSTR(1);
|
||||
while (*s) {
|
||||
switch(*s++) {
|
||||
case 'r':
|
||||
@@ -1485,7 +1519,7 @@ static int FAccess(void)
|
||||
}
|
||||
}
|
||||
RetVal.type = INT_TYPE;
|
||||
RetVal.v.val = access(ARG(0).v.str, amode);
|
||||
RetVal.v.val = access(ARGSTR(0), amode);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -1529,9 +1563,9 @@ static int FLanguage(void)
|
||||
/***************************************************************/
|
||||
static int FArgs(void)
|
||||
{
|
||||
if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
RetVal.type = INT_TYPE;
|
||||
RetVal.v.val = UserFuncExists(ARG(0).v.str);
|
||||
RetVal.v.val = UserFuncExists(ARGSTR(0));
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -1551,25 +1585,25 @@ static int FDosubst(void)
|
||||
|
||||
jul = NO_DATE;
|
||||
tim = NO_TIME;
|
||||
if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
if (Nargs >= 2) {
|
||||
if (ARG(1).type == DATETIME_TYPE) {
|
||||
jul = DATEPART(ARG(1));
|
||||
tim = TIMEPART(ARG(1));
|
||||
} else {
|
||||
if (ARG(1).type != DATE_TYPE) return E_BAD_TYPE;
|
||||
jul = ARG(1).v.val;
|
||||
ASSERT_TYPE(1, DATE_TYPE);
|
||||
jul = ARGV(1);
|
||||
}
|
||||
if (Nargs >= 3) {
|
||||
if (ARG(1).type == DATETIME_TYPE) {
|
||||
return E_2MANY_ARGS;
|
||||
}
|
||||
if (ARG(2).type != TIME_TYPE) return E_BAD_TYPE;
|
||||
tim = ARG(2).v.val;
|
||||
ASSERT_TYPE(2, TIME_TYPE);
|
||||
tim = ARGV(2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((r=DoSubstFromString(ARG(0).v.str, &buf, jul, tim))) return r;
|
||||
if ((r=DoSubstFromString(ARGSTR(0), &buf, jul, tim))) return r;
|
||||
r = RetStrVal(DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return r;
|
||||
@@ -1593,8 +1627,8 @@ static int FHebdate(void)
|
||||
int adarbehave;
|
||||
|
||||
if (ARG(0).type != INT_TYPE || ARG(1).type != STR_TYPE) return E_BAD_TYPE;
|
||||
day = ARG(0).v.val;
|
||||
mon = HebNameToNum(ARG(1).v.str);
|
||||
day = ARGV(0);
|
||||
mon = HebNameToNum(ARGSTR(1));
|
||||
if (mon < 0) return E_BAD_HEBDATE;
|
||||
if (Nargs == 2) {
|
||||
r = GetNextHebrewDate(JulianToday, mon, day, 0, 0, &ans);
|
||||
@@ -1604,15 +1638,15 @@ static int FHebdate(void)
|
||||
return OK;
|
||||
}
|
||||
if (Nargs == 5) {
|
||||
if (ARG(4).type != INT_TYPE) return E_BAD_TYPE;
|
||||
adarbehave = ARG(4).v.val;
|
||||
ASSERT_TYPE(4, INT_TYPE);
|
||||
adarbehave = ARGV(4);
|
||||
if (adarbehave < 0) return E_2LOW;
|
||||
if (adarbehave > 2) return E_2HIGH;
|
||||
} else adarbehave = 0;
|
||||
|
||||
if (Nargs >= 4) {
|
||||
if (ARG(3).type != INT_TYPE) return E_BAD_TYPE;
|
||||
jahr = ARG(3).v.val;
|
||||
ASSERT_TYPE(3, INT_TYPE);
|
||||
jahr = ARGV(3);
|
||||
if (jahr < 0) return E_2LOW;
|
||||
if (jahr > 2) {
|
||||
r = ComputeJahr(jahr, mon, day, &jahr);
|
||||
@@ -1622,7 +1656,7 @@ static int FHebdate(void)
|
||||
|
||||
|
||||
if (ARG(2).type == INT_TYPE) {
|
||||
year = ARG(2).v.val;
|
||||
year = ARGV(2);
|
||||
r = GetValidHebDate(year, mon, day, 0, &mout, &dout, jahr);
|
||||
if (r) return r;
|
||||
r = HebToJul(year, mout, dout);
|
||||
@@ -1718,7 +1752,7 @@ static int FEasterdate(void)
|
||||
int y, m, d;
|
||||
int g, c, x, z, e, n;
|
||||
if (ARG(0).type == INT_TYPE) {
|
||||
y = ARG(0).v.val;
|
||||
y = ARGV(0);
|
||||
if (y < BASE) return E_2LOW;
|
||||
else if (y > BASE+YR_RANGE) return E_2HIGH;
|
||||
} else if (HASDATE(ARG(0))) {
|
||||
@@ -1785,8 +1819,8 @@ static int FTimeStuff(int wantmins)
|
||||
}
|
||||
if (Nargs >= 2) {
|
||||
if (HASTIME(ARG(0))) return E_2MANY_ARGS;
|
||||
if (ARG(1).type != TIME_TYPE) return E_BAD_TYPE;
|
||||
tim = ARG(1).v.val;
|
||||
ASSERT_TYPE(1, TIME_TYPE);
|
||||
tim = ARGV(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1992,9 +2026,9 @@ static int FFiledate(void)
|
||||
|
||||
RetVal.type = DATE_TYPE;
|
||||
|
||||
if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
|
||||
if (stat(ARG(0).v.str, &statbuf)) {
|
||||
if (stat(ARGSTR(0), &statbuf)) {
|
||||
RetVal.v.val = 0;
|
||||
return OK;
|
||||
}
|
||||
@@ -2023,9 +2057,9 @@ static int FFiledatetime(void)
|
||||
|
||||
RetVal.type = DATETIME_TYPE;
|
||||
|
||||
if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
|
||||
if (stat(ARG(0).v.str, &statbuf)) {
|
||||
if (stat(ARGSTR(0), &statbuf)) {
|
||||
RetVal.v.val = 0;
|
||||
return OK;
|
||||
}
|
||||
@@ -2075,9 +2109,9 @@ static int FPsshade(void)
|
||||
sprintf(s, "BoxWidth _A sub _A lineto BoxWidth _A sub BoxHeight _A sub lineto ");
|
||||
s += strlen(s);
|
||||
if (Nargs == 1) {
|
||||
sprintf(s, "_A BoxHeight _A sub lineto closepath %d 100 div setgray fill 0.0 setgray", ARG(0).v.val);
|
||||
sprintf(s, "_A BoxHeight _A sub lineto closepath %d 100 div setgray fill 0.0 setgray", ARGV(0));
|
||||
} else {
|
||||
sprintf(s, "_A BoxHeight _A sub lineto closepath %d 100 div %d 100 div %d 100 div setrgbcolor fill 0.0 setgray", ARG(0).v.val, ARG(1).v.val, ARG(2).v.val);
|
||||
sprintf(s, "_A BoxHeight _A sub lineto closepath %d 100 div %d 100 div %d 100 div setrgbcolor fill 0.0 setgray", ARGV(0), ARGV(1), ARGV(2));
|
||||
}
|
||||
return RetStrVal(psbuff);
|
||||
}
|
||||
@@ -2101,20 +2135,20 @@ static int FPsmoon(void)
|
||||
int size = -1;
|
||||
int fontsize = -1;
|
||||
|
||||
if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
|
||||
if (ARG(0).v.val < 0) return E_2LOW;
|
||||
if (ARG(0).v.val > 3) return E_2HIGH;
|
||||
ASSERT_TYPE(0, INT_TYPE);
|
||||
if (ARGV(0) < 0) return E_2LOW;
|
||||
if (ARGV(0) > 3) return E_2HIGH;
|
||||
if (Nargs > 1) {
|
||||
if (ARG(1).type != INT_TYPE) return E_BAD_TYPE;
|
||||
if (ARG(1).v.val < -1) return E_2LOW;
|
||||
size = ARG(1).v.val;
|
||||
ASSERT_TYPE(1, INT_TYPE);
|
||||
if (ARGV(1) < -1) return E_2LOW;
|
||||
size = ARGV(1);
|
||||
if (Nargs > 2) {
|
||||
if (ARG(2).type != STR_TYPE) return E_BAD_TYPE;
|
||||
extra = ARG(2).v.str;
|
||||
ASSERT_TYPE(2, STR_TYPE);
|
||||
extra = ARGSTR(2);
|
||||
if (Nargs > 3) {
|
||||
if (ARG(3).type != INT_TYPE) return E_BAD_TYPE;
|
||||
if (ARG(3).v.val <= 0) return E_2LOW;
|
||||
fontsize = ARG(3).v.val;
|
||||
ASSERT_TYPE(3, INT_TYPE);
|
||||
if (ARGV(3) <= 0) return E_2LOW;
|
||||
fontsize = ARGV(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2139,7 +2173,7 @@ static int FPsmoon(void)
|
||||
s += strlen(s);
|
||||
sprintf(s, " %s 0 360 arc closepath", sizebuf);
|
||||
s += strlen(s);
|
||||
switch(ARG(0).v.val) {
|
||||
switch(ARGV(0)) {
|
||||
case 0:
|
||||
sprintf(s, " fill");
|
||||
s += strlen(s);
|
||||
@@ -2208,8 +2242,8 @@ static int FMoonphase(void)
|
||||
case 2:
|
||||
if (ARG(0).type == DATETIME_TYPE) return E_2MANY_ARGS;
|
||||
if (ARG(0).type != DATE_TYPE && ARG(1).type != TIME_TYPE) return E_BAD_TYPE;
|
||||
date = ARG(0).v.val;
|
||||
time = ARG(1).v.val;
|
||||
date = ARGV(0);
|
||||
time = ARGV(1);
|
||||
break;
|
||||
|
||||
default: return E_SWERR;
|
||||
@@ -2251,9 +2285,9 @@ static int MoonStuff(int type_wanted)
|
||||
startdate = JulianToday;
|
||||
starttim = 0;
|
||||
|
||||
if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
|
||||
if (ARG(0).v.val < 0) return E_2LOW;
|
||||
if (ARG(0).v.val > 3) return E_2HIGH;
|
||||
ASSERT_TYPE(0, INT_TYPE);
|
||||
if (ARGV(0) < 0) return E_2LOW;
|
||||
if (ARGV(0) > 3) return E_2HIGH;
|
||||
if (Nargs >= 2) {
|
||||
if (!HASDATE(ARG(1))) return E_BAD_TYPE;
|
||||
startdate = DATEPART(ARG(1));
|
||||
@@ -2263,12 +2297,12 @@ static int MoonStuff(int type_wanted)
|
||||
|
||||
if (Nargs >= 3) {
|
||||
if (HASTIME(ARG(1))) return E_2MANY_ARGS;
|
||||
if (ARG(2).type != TIME_TYPE) return E_BAD_TYPE;
|
||||
starttim = ARG(2).v.val;
|
||||
ASSERT_TYPE(2, TIME_TYPE);
|
||||
starttim = ARGV(2);
|
||||
}
|
||||
}
|
||||
|
||||
HuntPhase(startdate, starttim, ARG(0).v.val, &d, &t);
|
||||
HuntPhase(startdate, starttim, ARGV(0), &d, &t);
|
||||
RetVal.type = type_wanted;
|
||||
switch(type_wanted) {
|
||||
case TIME_TYPE:
|
||||
@@ -2288,7 +2322,7 @@ static int MoonStuff(int type_wanted)
|
||||
|
||||
static int FTimepart(void)
|
||||
{
|
||||
if (ARG(0).type != DATETIME_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, DATETIME_TYPE);
|
||||
RetVal.type = TIME_TYPE;
|
||||
RetVal.v.val = TIMEPART(ARG(0));
|
||||
return OK;
|
||||
@@ -2296,7 +2330,7 @@ static int FTimepart(void)
|
||||
|
||||
static int FDatepart(void)
|
||||
{
|
||||
if (ARG(0).type != DATETIME_TYPE) return E_BAD_TYPE;
|
||||
ASSERT_TYPE(0, DATETIME_TYPE);
|
||||
RetVal.type = DATE_TYPE;
|
||||
RetVal.v.val = DATEPART(ARG(0));
|
||||
return OK;
|
||||
@@ -2439,10 +2473,10 @@ static int FTzconvert(void)
|
||||
|
||||
if (Nargs == 2) {
|
||||
r = tz_convert(year, month, day, hour, minute,
|
||||
ARG(1).v.str, NULL, &tm);
|
||||
ARGSTR(1), NULL, &tm);
|
||||
} else {
|
||||
r = tz_convert(year, month, day, hour, minute,
|
||||
ARG(1).v.str, ARG(2).v.str, &tm);
|
||||
ARGSTR(1), ARGSTR(2), &tm);
|
||||
}
|
||||
|
||||
if (r == -1) return E_CANT_CONVERT_TZ;
|
||||
@@ -2458,7 +2492,7 @@ static int
|
||||
FNonomitted(void)
|
||||
{
|
||||
int d1, d2, ans, localomit, i;
|
||||
|
||||
int omit, r;
|
||||
Token tok;
|
||||
|
||||
if (!HASDATE(ARG(0)) ||
|
||||
@@ -2478,7 +2512,9 @@ FNonomitted(void)
|
||||
|
||||
ans = 0;
|
||||
while (d1 < d2) {
|
||||
if (!IsOmitted(d1++, localomit)) {
|
||||
r = IsOmitted(d1++, localomit, NULL, &omit);
|
||||
if (r) return r;
|
||||
if (!omit) {
|
||||
ans++;
|
||||
}
|
||||
}
|
||||
@@ -2486,3 +2522,116 @@ FNonomitted(void)
|
||||
RetVal.v.val = ans;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int
|
||||
FWeekno(void)
|
||||
{
|
||||
int jul = JulianToday;
|
||||
int wkstart = 0; /* Week start on Monday */
|
||||
int daystart = 29; /* First week starts on wkstart on or after Dec. 29 */
|
||||
int monstart;
|
||||
int candidate;
|
||||
|
||||
int y, m, d;
|
||||
|
||||
if (Nargs >= 1) {
|
||||
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||
jul = DATEPART(ARG(0));
|
||||
}
|
||||
if (Nargs >= 2) {
|
||||
ASSERT_TYPE(1, INT_TYPE);
|
||||
if (ARGV(1) < 0) return E_2LOW;
|
||||
if (ARGV(1) > 6) return E_2HIGH;
|
||||
wkstart = ARGV(1);
|
||||
/* Convert 0=Sun to 0=Mon */
|
||||
wkstart--;
|
||||
if (wkstart < 0) wkstart = 6;
|
||||
if (Nargs >= 3) {
|
||||
ASSERT_TYPE(2, INT_TYPE);
|
||||
if (ARGV(2) < 1) return E_2LOW;
|
||||
if (ARGV(2) > 31) return E_2HIGH;
|
||||
daystart = ARGV(2);
|
||||
}
|
||||
}
|
||||
|
||||
RetVal.type = INT_TYPE;
|
||||
/* If start day is 7, first week starts after Jan,
|
||||
otherwise after Dec. */
|
||||
if (daystart <= 7) {
|
||||
monstart = 0;
|
||||
} else {
|
||||
monstart = 11;
|
||||
}
|
||||
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
|
||||
/* Try this year */
|
||||
candidate = Julian(y, monstart, daystart);
|
||||
while((candidate % 7) != wkstart) candidate++;
|
||||
|
||||
if (candidate <= jul) {
|
||||
RetVal.v.val = ((jul - candidate) / 7) + 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (y-1 < BASE) return E_DATE_OVER;
|
||||
/* Must be last year */
|
||||
candidate = Julian(y-1, monstart, daystart);
|
||||
while((candidate % 7) != wkstart) candidate++;
|
||||
if (candidate <= jul) {
|
||||
RetVal.v.val = ((jul - candidate) / 7) + 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (y-2 < BASE) return E_DATE_OVER;
|
||||
/* Holy cow! */
|
||||
candidate = Julian(y-2, monstart, daystart);
|
||||
while((candidate % 7) != wkstart) candidate++;
|
||||
RetVal.v.val = ((jul - candidate) / 7) + 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int
|
||||
FEvalTrig(void)
|
||||
{
|
||||
Parser p;
|
||||
Trigger trig;
|
||||
TimeTrig tim;
|
||||
int jul, scanfrom;
|
||||
int r;
|
||||
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
if (Nargs >= 2) {
|
||||
if (!HASDATE(ARG(1))) return E_BAD_TYPE;
|
||||
scanfrom = DATEPART(ARG(1));
|
||||
} else {
|
||||
scanfrom = NO_DATE;
|
||||
}
|
||||
|
||||
CreateParser(ARGSTR(0), &p);
|
||||
p.allownested = 0;
|
||||
r = ParseRem(&p, &trig, &tim, 0);
|
||||
if (r) return r;
|
||||
if (trig.typ != NO_TYPE) return E_PARSE_ERR;
|
||||
if (scanfrom == NO_DATE) {
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 0);
|
||||
} else {
|
||||
/* Hokey... */
|
||||
if (trig.scanfrom != JulianToday) {
|
||||
Eprint("Warning: SCANFROM is ignored in two-argument form of evaltrig()");
|
||||
}
|
||||
jul = ComputeTrigger(scanfrom, &trig, &r, 0);
|
||||
}
|
||||
if (r) return r;
|
||||
if (jul < 0) {
|
||||
RetVal.type = INT_TYPE;
|
||||
RetVal.v.val = jul;
|
||||
} else if (tim.ttime == NO_TIME) {
|
||||
RetVal.type = DATE_TYPE;
|
||||
RetVal.v.val = jul;
|
||||
} else {
|
||||
RetVal.type = DATETIME_TYPE;
|
||||
RetVal.v.val = (MINUTES_PER_DAY * jul) + tim.ttime;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -53,11 +53,13 @@ EXTERN INIT( int CalMonths, 0);
|
||||
EXTERN INIT( int Hush, 0);
|
||||
EXTERN INIT( int NextMode, 0);
|
||||
EXTERN INIT( int InfiniteDelta, 0);
|
||||
EXTERN INIT( int DeltaOffset, 0);
|
||||
EXTERN INIT( int RunDisabled, 0);
|
||||
EXTERN INIT( int IgnoreOnce, 0);
|
||||
EXTERN INIT( int SortByTime, 0);
|
||||
EXTERN INIT( int SortByDate, 0);
|
||||
EXTERN INIT( int SortByPrio, 0);
|
||||
EXTERN INIT( int UntimedBeforeTimed, 0);
|
||||
EXTERN INIT( int DefaultPrio, NO_PRIORITY);
|
||||
EXTERN INIT( long SysTime, -1L);
|
||||
|
||||
@@ -74,6 +76,7 @@ EXTERN INIT( char TimeSep, TIMESEP);
|
||||
EXTERN INIT( int SynthesizeTags, 0);
|
||||
EXTERN INIT( int ScFormat, SC_AMPM);
|
||||
EXTERN INIT( int MaxSatIter, 150);
|
||||
EXTERN INIT( int MaxStringLen, MAX_STR_LEN);
|
||||
EXTERN INIT( char *FileName, NULL);
|
||||
EXTERN INIT( int UseStdin, 0);
|
||||
EXTERN FILE *ErrFp;
|
||||
@@ -89,6 +92,8 @@ EXTERN int ArgC;
|
||||
EXTERN char const **ArgV;
|
||||
EXTERN INIT( int CalLines, CAL_LINES);
|
||||
EXTERN INIT( int CalPad, 1);
|
||||
EXTERN INIT( int UseVTChars, 0);
|
||||
EXTERN INIT( int UseVTColors, 0);
|
||||
|
||||
/* Latitude and longitude */
|
||||
EXTERN INIT( int LatDeg, LAT_DEG);
|
||||
|
||||
106
src/init.c
106
src/init.c
@@ -52,6 +52,7 @@
|
||||
* -h = Hush mode
|
||||
* -f = Do not fork
|
||||
* -dchars = Debugging mode: Chars are:
|
||||
* f = Trace file openings
|
||||
* e = Echo input lines
|
||||
* x = Display expression evaluation
|
||||
* t = Display trigger dates
|
||||
@@ -130,6 +131,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
Token tok;
|
||||
int InvokedAsRem = 0;
|
||||
char const *s;
|
||||
int weeks;
|
||||
|
||||
/* Initialize global dynamic buffers */
|
||||
DBufInit(&Banner);
|
||||
@@ -222,9 +224,15 @@ void InitRemind(int argc, char const *argv[])
|
||||
|
||||
case 't':
|
||||
case 'T':
|
||||
InfiniteDelta = 1;
|
||||
if (!*arg) {
|
||||
InfiniteDelta = 1;
|
||||
} else {
|
||||
PARSENUM(DeltaOffset, arg);
|
||||
if (DeltaOffset < 0) {
|
||||
DeltaOffset = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
ErrFp = stdout;
|
||||
@@ -240,6 +248,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
SortByDate = SORT_ASCEND;
|
||||
SortByTime = SORT_ASCEND;
|
||||
SortByPrio = SORT_ASCEND;
|
||||
UntimedBeforeTimed = 0;
|
||||
if (*arg) {
|
||||
if (*arg == 'D' || *arg == 'd')
|
||||
SortByDate = SORT_DESCEND;
|
||||
@@ -255,6 +264,11 @@ void InitRemind(int argc, char const *argv[])
|
||||
SortByPrio = SORT_DESCEND;
|
||||
arg++;
|
||||
}
|
||||
if (*arg) {
|
||||
if (*arg == 'D' || *arg == 'd')
|
||||
UntimedBeforeTimed = 1;
|
||||
arg++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
@@ -295,8 +309,33 @@ void InitRemind(int argc, char const *argv[])
|
||||
case 'c':
|
||||
case 'C':
|
||||
DoCalendar = 1;
|
||||
if (*arg == '+') {
|
||||
arg++;
|
||||
weeks = 0;
|
||||
/* Parse the flags */
|
||||
while(*arg) {
|
||||
if (*arg == 'a' ||
|
||||
*arg == 'A') {
|
||||
DoSimpleCalDelta = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == '+') {
|
||||
weeks = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == 'l' || *arg == 'L') {
|
||||
UseVTChars = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == 'c' || *arg == 'C') {
|
||||
UseVTColors = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (weeks) {
|
||||
PARSENUM(CalWeeks, arg);
|
||||
if (!CalWeeks) CalWeeks = 1;
|
||||
} else {
|
||||
@@ -308,12 +347,21 @@ void InitRemind(int argc, char const *argv[])
|
||||
case 's':
|
||||
case 'S':
|
||||
DoSimpleCalendar = 1;
|
||||
if (*arg == 'a' || *arg == 'A') {
|
||||
weeks = 0;
|
||||
while(*arg) {
|
||||
if (*arg == 'a' || *arg == 'A') {
|
||||
DoSimpleCalDelta = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == '+') {
|
||||
arg++;
|
||||
weeks = 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (*arg == '+') {
|
||||
arg++;
|
||||
if (weeks) {
|
||||
PARSENUM(CalWeeks, arg);
|
||||
if (!CalWeeks) CalWeeks = 1;
|
||||
} else {
|
||||
@@ -363,11 +411,12 @@ void InitRemind(int argc, char const *argv[])
|
||||
case 'D':
|
||||
while (*arg) {
|
||||
switch(*arg++) {
|
||||
case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
|
||||
case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break;
|
||||
case 't': case 'T': DebugFlag |= DB_PRTTRIG; break;
|
||||
case 'v': case 'V': DebugFlag |= DB_DUMP_VARS; break;
|
||||
case 'l': case 'L': DebugFlag |= DB_PRTLINE; break;
|
||||
case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
|
||||
case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break;
|
||||
case 't': case 'T': DebugFlag |= DB_PRTTRIG; break;
|
||||
case 'v': case 'V': DebugFlag |= DB_DUMP_VARS; break;
|
||||
case 'l': case 'L': DebugFlag |= DB_PRTLINE; break;
|
||||
case 'f': case 'F': DebugFlag |= DB_TRACE_FILES; break;
|
||||
default:
|
||||
fprintf(ErrFp, ErrMsg[M_BAD_DB_FLAG], *(arg-1));
|
||||
}
|
||||
@@ -506,7 +555,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-2007 Roaring Penguin Software Inc.\n");
|
||||
fprintf(ErrFp, "Copyright 1999-2008 Roaring Penguin Software Inc.\n");
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
@@ -514,26 +563,26 @@ void Usage(void)
|
||||
fprintf(ErrFp, "Options:\n");
|
||||
fprintf(ErrFp, " -n Output next occurrence of reminders in simple format\n");
|
||||
fprintf(ErrFp, " -r Disable RUN directives\n");
|
||||
fprintf(ErrFp, " -c[n] Produce a calendar for n (default 1) months\n");
|
||||
fprintf(ErrFp, " -c+[n] Produce a calendar for n (default 1) weeks\n");
|
||||
fprintf(ErrFp, " -c[a][n] Produce a calendar for n (default 1) months\n");
|
||||
fprintf(ErrFp, " -c[a]+[n] Produce a calendar for n (default 1) weeks\n");
|
||||
fprintf(ErrFp, " -w[n[,p[,s]]] Specify width, padding and spacing of calendar\n");
|
||||
fprintf(ErrFp, " -s[a][+][n] Produce `simple calendar' for n (1) months (weeks)\n");
|
||||
fprintf(ErrFp, " -p[a][n] Same as -s, but input compatible with rem2ps\n");
|
||||
fprintf(ErrFp, " -l Prefix each simple calendar line with line number and filename comment\n");
|
||||
fprintf(ErrFp, " -v Verbose mode\n");
|
||||
fprintf(ErrFp, " -o Ignore ONCE directives\n");
|
||||
fprintf(ErrFp, " -t Trigger all future reminders regardless of delta\n");
|
||||
fprintf(ErrFp, " -t[n] Trigger all future (or those within `n' days)\n");
|
||||
fprintf(ErrFp, " -h `Hush' mode - be very quiet\n");
|
||||
fprintf(ErrFp, " -a Don't trigger timed reminders immediately - just queue them\n");
|
||||
fprintf(ErrFp, " -q Don't queue timed reminders\n");
|
||||
fprintf(ErrFp, " -f Trigger timed reminders by staying in foreground\n");
|
||||
fprintf(ErrFp, " -z[n] Enter daemon mode, waking every n (5) minutes.\n");
|
||||
fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
|
||||
fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline f=tracefiles\n");
|
||||
fprintf(ErrFp, " -e Divert messages normally sent to stderr to stdout\n");
|
||||
fprintf(ErrFp, " -b[n] Time format for cal: 0=am/pm, 1=24hr, 2=none\n");
|
||||
fprintf(ErrFp, " -x[n] Iteration limit for SATISFY clause (def=150)\n");
|
||||
fprintf(ErrFp, " -kcmd Run `cmd' for MSG-type reminders\n");
|
||||
fprintf(ErrFp, " -g[ddd] Sort reminders by date, time and priority before issuing\n");
|
||||
fprintf(ErrFp, " -g[dddd] Sort reminders by date, time, priority, and 'timedness'\n");
|
||||
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");
|
||||
@@ -612,6 +661,20 @@ static void ChgUser(char const *user)
|
||||
putenv(logname);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DefineFunction(char const *str)
|
||||
{
|
||||
Parser p;
|
||||
int r;
|
||||
|
||||
CreateParser(str, &p);
|
||||
r = DoFset(&p);
|
||||
DestroyParser(&p);
|
||||
if (r != OK) {
|
||||
fprintf(ErrFp, "-i option: %s: %s\n", str, ErrMsg[r]);
|
||||
}
|
||||
}
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* InitializeVar */
|
||||
@@ -622,7 +685,7 @@ static void ChgUser(char const *user)
|
||||
static void InitializeVar(char const *str)
|
||||
{
|
||||
char const *expr;
|
||||
|
||||
char const *ostr = str;
|
||||
char varname[VAR_NAME_LEN+1];
|
||||
|
||||
Value val;
|
||||
@@ -635,6 +698,11 @@ static void InitializeVar(char const *str)
|
||||
if (r < VAR_NAME_LEN) {
|
||||
varname[r++] = *str;
|
||||
}
|
||||
if (*str == '(') {
|
||||
/* Do a function definition if we see a paren */
|
||||
DefineFunction(ostr);
|
||||
return;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
varname[r] = 0;
|
||||
|
||||
@@ -307,7 +307,9 @@ EXTERN char *ErrMsg[] =
|
||||
"%d viesti(\xE4) t\xE4m\xE4n p\xE4iv\xE4n jonossa.\n",
|
||||
"Numero puuttuu",
|
||||
"Virheellinen funktio WARN-lausekkeessa",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
|
||||
#elif IBMEXTENDED
|
||||
"Ok",
|
||||
@@ -409,7 +411,10 @@ EXTERN char *ErrMsg[] =
|
||||
"%d viesti(\x84) t\x84m\x84n p\x84iv\x84n jonossa.\n",
|
||||
"Numero puuttuu"
|
||||
"Virheellinen funktio WARN-lausekkeessa",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
|
||||
#else
|
||||
"Ok",
|
||||
"Puuttuva ']'",
|
||||
@@ -510,7 +515,10 @@ EXTERN char *ErrMsg[] =
|
||||
"%d viesti({) t{m{n p{iv{n jonossa.\n",
|
||||
"Numero puuttuu",
|
||||
"Virheellinen funktio WARN-lausekkeessa",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -244,7 +244,10 @@ EXTERN char *ErrMsg[] =
|
||||
"%d rappel(s) en file pour aujourd'hui.\n",
|
||||
"Nombre attendu",
|
||||
"Fonction ill\351gale apr\350s WARN",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
|
||||
#else /* ISOLATIN1 */
|
||||
"Ok",
|
||||
"']' manquant",
|
||||
@@ -345,7 +348,9 @@ EXTERN char *ErrMsg[] =
|
||||
"%d rappel(s) en file pour aujourd'hui.\n",
|
||||
"Nombre attendu",
|
||||
"Fonction illegale apres WARN",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
#endif /* ISOLATIN1 */
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
|
||||
@@ -279,7 +279,9 @@ EXTERN char *ErrMsg[] =
|
||||
"%d Przypomnienia zakolejkowane na p\363\274niej.\n",
|
||||
"Spodziewana liczba",
|
||||
"Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
#else /* ISOLATIN1 */
|
||||
"OK",
|
||||
"Brakujacy ']'",
|
||||
@@ -380,7 +382,9 @@ EXTERN char *ErrMsg[] =
|
||||
"%d Przypomnienia zakolejkowane na pozniej.\n",
|
||||
"Spodziewana liczba",
|
||||
"Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
#endif /* ISOLATIN1 */
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
|
||||
@@ -245,7 +245,9 @@ EXTERN char *ErrMsg[] =
|
||||
"%d compromisso(s) colocados na fila para mais tarde.\n",
|
||||
"Esperando numero",
|
||||
"Funcao ilegal na clausula WARN",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
|
||||
|
||||
23
src/main.c
23
src/main.c
@@ -148,7 +148,7 @@ static void DoReminders(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
r=OpenFile(InitialFile);
|
||||
r=IncludeFile(InitialFile);
|
||||
if (r) {
|
||||
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING],
|
||||
InitialFile, ErrMsg[r]);
|
||||
@@ -345,6 +345,7 @@ int ParseChar(ParsePtr p, int *err, int peek)
|
||||
return *(p->pos++);
|
||||
}
|
||||
}
|
||||
p->expr_happened = 1;
|
||||
p->pos++;
|
||||
r = EvalExpr(&(p->pos), &val);
|
||||
if (r) {
|
||||
@@ -510,14 +511,16 @@ void Eprint(char const *fmt, ...)
|
||||
/* Check if more than one error msg. from this line */
|
||||
if (!FreshLine && !ShowAllErrors) return;
|
||||
|
||||
if (FreshLine) {
|
||||
if (FreshLine && FileName) {
|
||||
FreshLine = 0;
|
||||
if (strcmp(FileName, "-"))
|
||||
(void) fprintf(ErrFp, "%s(%d): ", FileName, LineNo);
|
||||
else
|
||||
(void) fprintf(ErrFp, "-stdin-(%d): ", LineNo);
|
||||
if (DebugFlag & DB_PRTLINE) OutputLine(ErrFp);
|
||||
} else fprintf(ErrFp, " ");
|
||||
} else if (FileName) {
|
||||
fprintf(ErrFp, " ");
|
||||
}
|
||||
|
||||
va_start(argptr, fmt);
|
||||
(void) vfprintf(ErrFp, fmt, argptr);
|
||||
@@ -563,6 +566,7 @@ void CreateParser(char const *s, ParsePtr p)
|
||||
p->etext = NULL;
|
||||
p->allownested = 1;
|
||||
p->tokenPushed = NULL;
|
||||
p->expr_happened = 0;
|
||||
DBufInit(&p->pushedToken);
|
||||
}
|
||||
|
||||
@@ -720,7 +724,7 @@ int DoEndif(ParsePtr p)
|
||||
/***************************************************************/
|
||||
int DoIfTrig(ParsePtr p)
|
||||
{
|
||||
int r;
|
||||
int r, err;
|
||||
unsigned syndrome;
|
||||
Trigger trig;
|
||||
TimeTrig tim;
|
||||
@@ -730,12 +734,12 @@ int DoIfTrig(ParsePtr p)
|
||||
if (NumIfs >= IF_NEST) return E_NESTED_IF;
|
||||
if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else {
|
||||
if ( (r=ParseRem(p, &trig, &tim)) ) return r;
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
||||
if (trig.typ != NO_TYPE) return E_PARSE_ERR;
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r);
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
if (r) syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else {
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul))
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err))
|
||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else
|
||||
syndrome = IF_FALSE | BEFORE_ELSE;
|
||||
@@ -859,6 +863,11 @@ int DoDebug(ParsePtr p)
|
||||
else DebugFlag &= ~DB_PRTLINE;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
case 'F':
|
||||
if (val) DebugFlag |= DB_TRACE_FILES;
|
||||
else DebugFlag &= ~DB_TRACE_FILES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
src/omit.c
48
src/omit.c
@@ -20,6 +20,7 @@
|
||||
#include "protos.h"
|
||||
#include "globals.h"
|
||||
#include "err.h"
|
||||
#include "expr.h"
|
||||
|
||||
static int BexistsIntArray (int array[], int num, int key);
|
||||
static void InsertIntoSortedArray (int *array, int num, int key);
|
||||
@@ -177,26 +178,57 @@ int PopOmitContext(ParsePtr p)
|
||||
/* */
|
||||
/* IsOmitted */
|
||||
/* */
|
||||
/* Return non-zero if date is OMITted, zero if it is not. */
|
||||
/* Set *omit to non-zero if date is omitted, else 0. Returns */
|
||||
/* OK or an error code. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int IsOmitted(int jul, int localomit)
|
||||
int IsOmitted(int jul, int localomit, char const *omitfunc, int *omit)
|
||||
{
|
||||
int y, m, d;
|
||||
|
||||
/* If we have an omitfunc, we *only* use it and ignore local/global
|
||||
OMITs */
|
||||
if (omitfunc && *omitfunc && UserFuncExists(omitfunc)) {
|
||||
char expr[VAR_NAME_LEN + 32];
|
||||
char const *s;
|
||||
int r;
|
||||
Value v;
|
||||
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
sprintf(expr, "%s('%04d-%02d-%02d')",
|
||||
omitfunc, y, m+1, d);
|
||||
s = expr;
|
||||
r = EvalExpr(&s, &v);
|
||||
if (r) return r;
|
||||
if (v.type == INT_TYPE && v.v.val != 0) {
|
||||
*omit = 1;
|
||||
} else {
|
||||
*omit = 0;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Is it omitted because of local omits? */
|
||||
if (localomit & (1 << (jul % 7))) return 1;
|
||||
if (localomit & (1 << (jul % 7))) {
|
||||
*omit = 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Is it omitted because of fully-specified omits? */
|
||||
if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) return 1;
|
||||
if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) {
|
||||
*omit = 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Get the syndrome */
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d))
|
||||
return 1;
|
||||
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d)) {
|
||||
*omit = 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Not omitted */
|
||||
return 0;
|
||||
*omit = 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
11
src/protos.h
11
src/protos.h
@@ -26,9 +26,9 @@ char const *CalendarTime (int tim, int duration);
|
||||
int DoRem (ParsePtr p);
|
||||
int DoFlush (ParsePtr p);
|
||||
void DoExit (ParsePtr p);
|
||||
int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim);
|
||||
int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals);
|
||||
int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig *tim, int jul);
|
||||
int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int jul);
|
||||
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 EvalExpr (char const **e, Value *v);
|
||||
@@ -37,7 +37,6 @@ void PrintValue (Value *v, FILE *fp);
|
||||
int CopyValue (Value *dest, const Value *src);
|
||||
int ReadLine (void);
|
||||
int OpenFile (char const *fname);
|
||||
int PopFile (void);
|
||||
int DoInclude (ParsePtr p);
|
||||
int IncludeFile (char const *fname);
|
||||
int GetAccessDate (char const *file);
|
||||
@@ -76,14 +75,14 @@ int DoClear (ParsePtr p);
|
||||
int DestroyOmitContexts (void);
|
||||
int PushOmitContext (ParsePtr p);
|
||||
int PopOmitContext (ParsePtr p);
|
||||
int IsOmitted (int jul, int localomit);
|
||||
int IsOmitted (int jul, int localomit, char const *omitfunc, int *omit);
|
||||
int DoOmit (ParsePtr p);
|
||||
int QueueReminder (ParsePtr p, Trigger *trig, TimeTrig *tim, char const *sched);
|
||||
void HandleQueuedReminders (void);
|
||||
char const *FindInitialToken (Token *tok, char const *s);
|
||||
void FindToken (char const *s, Token *tok);
|
||||
void FindNumericToken (char const *s, Token *t);
|
||||
int ComputeTrigger (int today, Trigger *trig, int *err);
|
||||
int ComputeTrigger (int today, Trigger *trig, int *err, int save_in_globals);
|
||||
char *StrnCpy (char *dest, char const *source, int n);
|
||||
int StrMatch (char const *s1, char const *s2, int n);
|
||||
int StrinCmp (char const *s1, char const *s2, int n);
|
||||
@@ -129,7 +128,7 @@ void LocalToUTC (int locdate, int loctime, int *utcdate, int *utctime);
|
||||
void UTCToLocal (int utcdate, int utctime, int *locdate, int *loctime);
|
||||
int MoonPhase (int date, int time);
|
||||
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 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 *);
|
||||
|
||||
21
src/rem2ps.c
21
src/rem2ps.c
@@ -30,6 +30,7 @@
|
||||
#define SPECIAL_MOON 3
|
||||
#define SPECIAL_SHADE 4
|
||||
#define SPECIAL_COLOR 5
|
||||
#define SPECIAL_WEEK 6
|
||||
|
||||
typedef struct calentry {
|
||||
struct calentry *next;
|
||||
@@ -306,6 +307,7 @@ void DoPsCal(void)
|
||||
if (!strcmp(passthru, "PostScript") ||
|
||||
!strcmp(passthru, "PSFile") ||
|
||||
!strcmp(passthru, "MOON") ||
|
||||
!strcmp(passthru, "WEEK") ||
|
||||
!strcmp(passthru, "SHADE")) {
|
||||
is_ps = 1;
|
||||
}
|
||||
@@ -324,6 +326,8 @@ void DoPsCal(void)
|
||||
c->special = SPECIAL_SHADE;
|
||||
} else if (!strcmp(passthru, "MOON")) {
|
||||
c->special = SPECIAL_MOON;
|
||||
} else if (!strcmp(passthru, "WEEK")) {
|
||||
c->special = SPECIAL_WEEK;
|
||||
} else {
|
||||
c->special = SPECIAL_PSFILE;
|
||||
}
|
||||
@@ -887,6 +891,7 @@ int DoQueuedPs(void)
|
||||
int fnoff;
|
||||
char buffer[512];
|
||||
char const *size, *extra;
|
||||
char const *s;
|
||||
int num, r, g, b, phase, fontsize, moonsize;
|
||||
unsigned char c;
|
||||
|
||||
@@ -954,6 +959,22 @@ int DoQueuedPs(void)
|
||||
r/255.0, g/255.0, b/255.0);
|
||||
break;
|
||||
|
||||
case SPECIAL_WEEK: /* Week number */
|
||||
printf("gsave Border Border 2 div moveto /EntryFont findfont EntrySize 1.2 div scalefont setfont (");
|
||||
s = e->entry+fnoff;
|
||||
while(*s && isspace(*s)) {
|
||||
s++;
|
||||
}
|
||||
while(*s) {
|
||||
if (*s == '\\' || *s == '(' || *s == ')') {
|
||||
PutChar('\\');
|
||||
}
|
||||
PutChar(*s);
|
||||
s++;
|
||||
}
|
||||
printf(") show grestore\n");
|
||||
break;
|
||||
|
||||
case SPECIAL_MOON: /* Moon phase */
|
||||
num = sscanf(e->entry+fnoff, "%d %d %d", &phase, &moonsize,
|
||||
&fontsize);
|
||||
|
||||
21
src/sort.c
21
src/sort.c
@@ -83,6 +83,7 @@ int InsertIntoSortBuffer(int jul, int tim, char const *body, int typ, int prio)
|
||||
SortByDate = 0;
|
||||
SortByTime = 0;
|
||||
SortByPrio = 0;
|
||||
UntimedBeforeTimed = 0;
|
||||
return E_NO_MEM;
|
||||
}
|
||||
|
||||
@@ -94,8 +95,8 @@ int InsertIntoSortBuffer(int jul, int tim, char const *body, int typ, int prio)
|
||||
while (cur) {
|
||||
ShouldGoAfter = CompareRems(new->trigdate, new->trigtime, new->priority,
|
||||
cur->trigdate, cur->trigtime, cur->priority,
|
||||
SortByDate, SortByTime, SortByPrio);
|
||||
|
||||
SortByDate, SortByTime, SortByPrio, UntimedBeforeTimed);
|
||||
|
||||
if (ShouldGoAfter <= 0) {
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
@@ -203,19 +204,27 @@ static void IssueSortBanner(int jul)
|
||||
/***************************************************************/
|
||||
int CompareRems(int dat1, int tim1, int prio1,
|
||||
int dat2, int tim2, int prio2,
|
||||
int bydate, int bytime, int byprio)
|
||||
int bydate, int bytime, int byprio,
|
||||
int untimed_first)
|
||||
{
|
||||
int dafter, tafter, pafter;
|
||||
int dafter, tafter, pafter, uafter;
|
||||
|
||||
dafter = (bydate != SORT_DESCEND) ? 1 : -1;
|
||||
tafter = (bytime != SORT_DESCEND) ? 1 : -1;
|
||||
pafter = (byprio != SORT_DESCEND) ? 1 : -1;
|
||||
uafter = (untimed_first) ? -1 : 1;
|
||||
|
||||
if (dat1 < dat2) return dafter;
|
||||
if (dat1 > dat2) return -dafter;
|
||||
|
||||
if (tim1 == NO_TIME && tim2 != NO_TIME) return -1;
|
||||
if (tim1 != NO_TIME && tim2 == NO_TIME) return 1;
|
||||
if (tim1 == NO_TIME && tim2 != NO_TIME) {
|
||||
return -uafter;
|
||||
}
|
||||
|
||||
if (tim1 != NO_TIME && tim2 == NO_TIME) {
|
||||
return uafter;
|
||||
}
|
||||
|
||||
if (tim1 < tim2) return tafter;
|
||||
if (tim1 > tim2) return -tafter;
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ Token TokArray[] = {
|
||||
{ "november", 3, T_Month, 10 },
|
||||
{ "october", 3, T_Month, 9 },
|
||||
{ "omit", 3, T_Omit, 0 },
|
||||
{ "omitfunc", 8, T_OmitFunc, 0 },
|
||||
{ "once", 3, T_Once, 0 },
|
||||
{ "pop-omit-context", 3, T_Pop, 0 },
|
||||
{ "preserve", 8, T_Preserve, 0 },
|
||||
|
||||
132
src/trigger.c
132
src/trigger.c
@@ -206,16 +206,27 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
*err = E_BAD_DATE;
|
||||
return -1;
|
||||
}
|
||||
/* Back up a year in case we'll cross a year boundary*/
|
||||
if (y > BASE) {
|
||||
y--;
|
||||
}
|
||||
|
||||
/* Move up to the first valid year */
|
||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||
|
||||
/* Try last year */
|
||||
j = Julian(y, trig->m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
if (j >= startdate) return j;
|
||||
|
||||
/* Try this year */
|
||||
y++;
|
||||
j = Julian(y, trig->m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
if (j >= startdate) return j;
|
||||
|
||||
/* Must be next year */
|
||||
y = y + 1;
|
||||
y++;
|
||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||
j = Julian(y, trig->m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
@@ -286,7 +297,7 @@ static int JYear(int jul)
|
||||
/***************************************************************/
|
||||
static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart)
|
||||
{
|
||||
int simple, mod;
|
||||
int simple, mod, omit;
|
||||
|
||||
/* First: Have we passed the UNTIL date? */
|
||||
if (trig->until != NO_UNTIL &&
|
||||
@@ -294,8 +305,22 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
|
||||
/* Next: If it's an "AFTER"-type skip, back up
|
||||
until we're at the start of a block of holidays */
|
||||
if (trig->skip == AFTER_SKIP)
|
||||
while (IsOmitted(start-1, trig->localomit)) start--;
|
||||
if (trig->skip == AFTER_SKIP) {
|
||||
int iter = 0;
|
||||
while (iter++ <= MaxSatIter) {
|
||||
*err = IsOmitted(start-1, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -2;
|
||||
if (!omit) {
|
||||
break;
|
||||
}
|
||||
start--;
|
||||
}
|
||||
if (iter > MaxSatIter) {
|
||||
/* omitfunc must have returned "true" too often */
|
||||
*err = E_CANT_TRIG;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the next simple trigger */
|
||||
simple = NextSimpleTrig(start, trig, err);
|
||||
@@ -309,12 +334,29 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
/* If there's a BACK, back up... */
|
||||
if (trig->back != NO_BACK) {
|
||||
mod = trig->back;
|
||||
if (mod < 0) simple += mod;
|
||||
else
|
||||
while(mod) {
|
||||
simple--;
|
||||
if (!IsOmitted(simple, trig->localomit)) mod--;
|
||||
if (mod < 0) {
|
||||
simple += mod;
|
||||
}
|
||||
else {
|
||||
int iter = 0;
|
||||
int max = MaxSatIter;
|
||||
if (max < mod*2) {
|
||||
max = mod*2;
|
||||
}
|
||||
while(iter++ <= max) {
|
||||
if (!mod) {
|
||||
break;
|
||||
}
|
||||
simple--;
|
||||
*err = IsOmitted(simple, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -2;
|
||||
if (!omit) mod--;
|
||||
}
|
||||
if (iter > max) {
|
||||
*err = E_CANT_TRIG;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If there's a REP, calculate the next occurrence */
|
||||
@@ -327,12 +369,38 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
}
|
||||
|
||||
/* If it's a "BEFORE"-type skip, back up */
|
||||
if (trig->skip == BEFORE_SKIP)
|
||||
while(IsOmitted(simple, trig->localomit)) simple--;
|
||||
if (trig->skip == BEFORE_SKIP) {
|
||||
int iter = 0;
|
||||
while(iter++ <= MaxSatIter) {
|
||||
*err = IsOmitted(simple, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -2;
|
||||
if (!omit) {
|
||||
break;
|
||||
}
|
||||
simple--;
|
||||
}
|
||||
if (iter > MaxSatIter) {
|
||||
*err = E_CANT_TRIG;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/* If it's an "AFTER"-type skip, jump ahead */
|
||||
if (trig->skip == AFTER_SKIP)
|
||||
while (IsOmitted(simple, trig->localomit)) simple++;
|
||||
if (trig->skip == AFTER_SKIP) {
|
||||
int iter = 0;
|
||||
while (iter++ <= MaxSatIter) {
|
||||
*err = IsOmitted(simple, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -2;
|
||||
if (!omit) {
|
||||
break;
|
||||
}
|
||||
simple++;
|
||||
}
|
||||
if (iter > MaxSatIter) {
|
||||
*err = E_CANT_TRIG;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the date */
|
||||
return simple;
|
||||
@@ -346,15 +414,15 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
/* today's date. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
|
||||
{
|
||||
int nattempts = 0,
|
||||
start = today,
|
||||
nextstart = 0,
|
||||
y, m, d,
|
||||
y, m, d, omit,
|
||||
result;
|
||||
|
||||
LastTrigValid = 0;
|
||||
if (save_in_globals) LastTrigValid = 0;
|
||||
|
||||
/* Assume everything works */
|
||||
*err = OK;
|
||||
@@ -373,8 +441,8 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
*err = E_REP_FULSPEC;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
while (nattempts++ < TRIG_ATTEMPTS) {
|
||||
result = GetNextTriggerDate(trig, start, err, &nextstart);
|
||||
|
||||
@@ -389,10 +457,18 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
}
|
||||
|
||||
/* If result is >= today, great! */
|
||||
if (trig->skip == SKIP_SKIP) {
|
||||
*err = IsOmitted(result, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -1;
|
||||
} else {
|
||||
omit = 0;
|
||||
}
|
||||
if (result >= today &&
|
||||
(trig->skip != SKIP_SKIP || !IsOmitted(result, trig->localomit))) {
|
||||
LastTriggerDate = result; /* Save in global var */
|
||||
LastTrigValid = 1;
|
||||
(trig->skip != SKIP_SKIP || !omit)) {
|
||||
if (save_in_globals) {
|
||||
LastTriggerDate = result; /* Save in global var */
|
||||
LastTrigValid = 1;
|
||||
}
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
FromJulian(result, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d\n",
|
||||
@@ -414,14 +490,16 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
FileName, LineNo, ErrMsg[E_EXPIRED]);
|
||||
}
|
||||
if (result != -1) {
|
||||
LastTriggerDate = result;
|
||||
LastTrigValid = 1;
|
||||
if (save_in_globals) {
|
||||
LastTriggerDate = result;
|
||||
LastTrigValid = 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (trig->skip == SKIP_SKIP &&
|
||||
IsOmitted(result, trig->localomit) &&
|
||||
omit &&
|
||||
nextstart <= start &&
|
||||
result >= start) {
|
||||
nextstart = result + 1;
|
||||
@@ -430,8 +508,10 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
/* Keep scanning... unless there's no point in doing it.*/
|
||||
if (nextstart <= start) {
|
||||
if (result != -1) {
|
||||
LastTriggerDate = result;
|
||||
LastTrigValid = 1;
|
||||
if (save_in_globals) {
|
||||
LastTriggerDate = result;
|
||||
LastTrigValid = 1;
|
||||
}
|
||||
}
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%d): %s\n",
|
||||
|
||||
18
src/types.h
18
src/types.h
@@ -56,6 +56,7 @@ typedef struct {
|
||||
int priority;
|
||||
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];
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
} Trigger;
|
||||
@@ -71,7 +72,7 @@ typedef struct {
|
||||
|
||||
/* The parse pointer */
|
||||
typedef struct {
|
||||
char isnested; /* Is it a nested expression? */
|
||||
char isnested; /* Is it a nested expression? */
|
||||
char allownested;
|
||||
char const *text; /* Start of text */
|
||||
char const *pos; /* Current position */
|
||||
@@ -79,6 +80,7 @@ typedef struct {
|
||||
char const *epos; /* Position in substituted text */
|
||||
DynamicBuffer pushedToken; /* Pushed-back token */
|
||||
char const *tokenPushed; /* NULL if no pushed-back token */
|
||||
char expr_happened; /* Did we encounter an [expression] ? */
|
||||
} Parser;
|
||||
|
||||
typedef Parser *ParsePtr; /* Pointer to parser structure */
|
||||
@@ -116,11 +118,12 @@ typedef Parser *ParsePtr; /* Pointer to parser structure */
|
||||
|
||||
|
||||
/* DEFINES for debugging flags */
|
||||
#define DB_PRTLINE 1
|
||||
#define DB_PRTEXPR 2
|
||||
#define DB_PRTTRIG 4
|
||||
#define DB_DUMP_VARS 8
|
||||
#define DB_ECHO_LINE 16
|
||||
#define DB_PRTLINE 1
|
||||
#define DB_PRTEXPR 2
|
||||
#define DB_PRTTRIG 4
|
||||
#define DB_DUMP_VARS 8
|
||||
#define DB_ECHO_LINE 16
|
||||
#define DB_TRACE_FILES 32
|
||||
|
||||
/* Enumeration of the tokens */
|
||||
enum TokTypes
|
||||
@@ -146,7 +149,8 @@ enum TokTypes
|
||||
T_Warn,
|
||||
T_Tag,
|
||||
T_Duration,
|
||||
T_LongTime
|
||||
T_LongTime,
|
||||
T_OmitFunc
|
||||
};
|
||||
|
||||
/* The structure of a token */
|
||||
|
||||
@@ -142,6 +142,11 @@ int DoFset(ParsePtr p)
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow an optional = sign: FSET f(x) = x*x */
|
||||
c = ParseNonSpaceChar(p, &r, 1);
|
||||
if (c == '=') {
|
||||
c = ParseNonSpaceChar(p, &r, 0);
|
||||
}
|
||||
/* Copy the text over */
|
||||
if (p->isnested) {
|
||||
Eprint("%s", ErrMsg[E_CANTNEST_FDEF]);
|
||||
|
||||
10
src/var.c
10
src/var.c
@@ -223,6 +223,11 @@ int DoSet (Parser *p)
|
||||
r = ParseIdentifier(p, &buf);
|
||||
if (r) return r;
|
||||
|
||||
/* Allow optional equals-sign: SET var = value */
|
||||
if (ParseNonSpaceChar(p, &r, 1) == '=') {
|
||||
ParseNonSpaceChar(p, &r, 0);
|
||||
}
|
||||
|
||||
r = EvaluateExpr(p, &v);
|
||||
if (r) {
|
||||
DBufFree(&buf);
|
||||
@@ -463,6 +468,7 @@ static SysVar SysVarArr[] = {
|
||||
{ "Daemon", 0, INT_TYPE, &Daemon, 0, 0 },
|
||||
{ "DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0 },
|
||||
{ "DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999 },
|
||||
{ "DeltaOffset", 0, INT_TYPE, &DeltaOffset, 0, 0 },
|
||||
{ "DontFork", 0, INT_TYPE, &DontFork, 0, 0 },
|
||||
{ "DontQueue", 0, INT_TYPE, &DontQueue, 0, 0 },
|
||||
{ "DontTrigAts", 0, INT_TYPE, &DontIssueAts, 0, 0 },
|
||||
@@ -482,6 +488,7 @@ static SysVar SysVarArr[] = {
|
||||
{ "LongMin", 1, INT_TYPE, &LongMin, -59, 59 },
|
||||
{ "LongSec", 1, INT_TYPE, &LongSec, -59, 59 },
|
||||
{ "MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY },
|
||||
{ "MaxStringLen", 1, INT_TYPE, &MaxStringLen, -1, ANY },
|
||||
{ "MinsFromUTC", 1, INT_TYPE, &MinsFromUTC, -13*60, 13*60 },
|
||||
{ "NextMode", 0, INT_TYPE, &NextMode, 0, 0 },
|
||||
{ "NumQueued", 0, INT_TYPE, &NumQueued, 0, 0 },
|
||||
@@ -494,7 +501,8 @@ static SysVar SysVarArr[] = {
|
||||
{ "SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0},
|
||||
{ "SortByTime", 0, INT_TYPE, &SortByTime, 0, 0},
|
||||
{ "SubsIndent", 1, INT_TYPE, &SubsIndent, 0, 132},
|
||||
{ "TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0 }
|
||||
{ "TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0 },
|
||||
{ "UntimedFirst", 0, INT_TYPE, &UntimedBeforeTimed, 0, 0 }
|
||||
};
|
||||
|
||||
#define NUMSYSVARS ( sizeof(SysVarArr) / sizeof(SysVar) )
|
||||
|
||||
17
tests/colors.rem
Normal file
17
tests/colors.rem
Normal file
@@ -0,0 +1,17 @@
|
||||
REM 28 SPECIAL COLOR 0 0 0 Black
|
||||
REM 28 SPECIAL COLOR 65 0 0 Dim Red
|
||||
REM 28 SPECIAL COLOR 0 65 0 Dim Green
|
||||
REM 28 SPECIAL COLOR 0 0 65 Dim Blue
|
||||
REM 28 SPECIAL COLOR 0 65 65 Dim Cyan
|
||||
REM 28 SPECIAL COLOR 65 0 65 Dim Magenta
|
||||
REM 28 SPECIAL COLOR 65 65 0 Dim Yellow
|
||||
REM 28 SPECIAL COLOR 65 65 65 Dim White
|
||||
|
||||
REM 28 SPECIAL COLOR 129 0 0 Bright Red
|
||||
REM 28 SPECIAL COLOR 0 129 0 Bright Green
|
||||
REM 28 SPECIAL COLOR 0 0 129 Bright Blue
|
||||
REM 28 SPECIAL COLOR 0 129 129 Bright Cyan
|
||||
REM 28 SPECIAL COLOR 129 0 129 Bright Magenta
|
||||
REM 28 SPECIAL COLOR 129 129 0 Bright Yellow
|
||||
REM 28 SPECIAL COLOR 129 129 129 Bright White
|
||||
|
||||
1
tests/include_dir/01.rem
Normal file
1
tests/include_dir/01.rem
Normal file
@@ -0,0 +1 @@
|
||||
REM 15 MSG 01
|
||||
1
tests/include_dir/02.rem
Normal file
1
tests/include_dir/02.rem
Normal file
@@ -0,0 +1 @@
|
||||
REM 15 MSG 02
|
||||
1
tests/include_dir/03.notrem
Normal file
1
tests/include_dir/03.notrem
Normal file
@@ -0,0 +1 @@
|
||||
REM MSG IGNORE
|
||||
1
tests/include_dir/04cantread.rem
Normal file
1
tests/include_dir/04cantread.rem
Normal file
@@ -0,0 +1 @@
|
||||
REM 15 MSG You can't read this file.
|
||||
1
tests/include_dir_no_rems/03.notrem
Normal file
1
tests/include_dir_no_rems/03.notrem
Normal file
@@ -0,0 +1 @@
|
||||
REM MSG IGNORE
|
||||
5
tests/include_test.rem
Normal file
5
tests/include_test.rem
Normal file
@@ -0,0 +1,5 @@
|
||||
INCLUDE include_dir
|
||||
INCLUDE include_dir_no_rems
|
||||
INCLUDE nonexistent_include_dir
|
||||
|
||||
REM 15 MSG Whee!!!!
|
||||
3
tests/runinc.rem
Normal file
3
tests/runinc.rem
Normal file
@@ -0,0 +1,3 @@
|
||||
set s shell("echo 3")
|
||||
run on
|
||||
set s shell("echo 3")
|
||||
6
tests/runtest.rem
Normal file
6
tests/runtest.rem
Normal file
@@ -0,0 +1,6 @@
|
||||
run off
|
||||
set a shell("echo 2")
|
||||
run on
|
||||
set a shell("echo 2")
|
||||
run off
|
||||
include ../tests/runinc.rem
|
||||
@@ -11,6 +11,14 @@
|
||||
# Copyright (C) 1999-2000 Roaring Penguin Software Inc.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
DIR=`dirname $0`
|
||||
cd $DIR
|
||||
if test $? != 0 ; then
|
||||
echo "Unable to cd $DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod 000 include_dir/04cantread.rem
|
||||
TEST_GETENV="foo bar baz" ; export TEST_GETENV
|
||||
echo "Test 1" > ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
@@ -18,7 +26,7 @@ echo "" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
echo "Test 2" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p ../tests/test2.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -p -l ../tests/test2.rem 1 aug 2007 >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
echo "Test 3" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
@@ -29,13 +37,37 @@ echo "" >> ../tests/test.out
|
||||
../src/remind -sa ../tests/test2.rem 1 aug 2007 >> ../tests/test.out
|
||||
echo "Test 5" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -b0 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -p -l -b0 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
|
||||
echo "Test 6" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -b1 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -p -l -b1 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
|
||||
echo "Test 7" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -b2 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -p -l -b2 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
|
||||
|
||||
echo "Test 8" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -df -p -l -b2 ../tests/include_dir 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Test 9" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -df -p -l -b2 ../tests/nonexistent_include_dir 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
../src/remind -df -p -l -b2 ../tests/include_dir_no_rems 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
../src/remind -df -p -l -b2 ../tests/include_test.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
|
||||
chmod 644 include_dir/04cantread.rem
|
||||
|
||||
echo "Color Test" >> ../tests/test.out
|
||||
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out
|
||||
|
||||
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
|
||||
|
||||
../src/remind ../tests/runtest.rem >> ../tests/test.out 2>&1
|
||||
|
||||
cmp -s ../tests/test.out ../tests/test.cmp
|
||||
if [ "$?" = "0" ]; then
|
||||
|
||||
970
tests/test.cmp
970
tests/test.cmp
File diff suppressed because it is too large
Load Diff
@@ -132,7 +132,7 @@ CLEAR-OMIT-CONTEXT
|
||||
REM 1 Mar -1 MSG 1 mar -1
|
||||
REM 1 Mar --1 MSG 1 mar --1
|
||||
REM 28 Feb BEFORE MSG 28 Feb BEFORE
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP
|
||||
REM 28 Feb AFTER MSG 28 Feb AFTER
|
||||
|
||||
POP-OMIT-CONTEXT
|
||||
@@ -144,7 +144,7 @@ REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
|
||||
|
||||
|
||||
REM 13 March 1991 *1 UNTIL 19 March 1991 MSG 13-19 Mar 91
|
||||
|
||||
|
||||
# Test BACK
|
||||
CLEAR-OMIT-CONTEXT
|
||||
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1
|
||||
@@ -163,6 +163,19 @@ REM Fri SCANFROM [trigger(today()-7)] SATISFY 1
|
||||
OMIT [trigger(trigdate())]
|
||||
REM Fri after MSG 16 Feb 1991
|
||||
CLEAR-OMIT-CONTEXT
|
||||
|
||||
# Test omitfunc
|
||||
fset _ofunc(x) (day(x) < 7 || day(x) % 2)
|
||||
REM 1 March OMITFUNC _ofunc AFTER MSG OmitFunc Test
|
||||
REM 8 March OMITFUNC _ofunc -1 MSG OmitFunc Test 2
|
||||
|
||||
# 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
|
||||
REM 1 March OMIT Sun AFTER MSG Should trigger 4 March
|
||||
|
||||
set a000 abs(1)
|
||||
set a001 abs(-1)
|
||||
set a002 asc("foo")
|
||||
|
||||
20
www/rem2html
20
www/rem2html
@@ -9,7 +9,7 @@ my %Options;
|
||||
|
||||
my $rem2html_version = '2.0';
|
||||
|
||||
my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst,
|
||||
my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks,
|
||||
@Daynames, $Nextmon, $Nextlen, $Prevmon, $Prevlen);
|
||||
|
||||
my $TIDY_PROGNAME = $0;
|
||||
@@ -186,6 +186,7 @@ sub parse_input
|
||||
undef $shades;
|
||||
undef $moons;
|
||||
undef $classes;
|
||||
undef $weeks;
|
||||
|
||||
my $found_data = 0;
|
||||
while(<STDIN>) {
|
||||
@@ -232,10 +233,16 @@ sub parse_input
|
||||
next unless m/^(\d*).(\d*).(\d*)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/;
|
||||
my ($y, $m, $d, $special, $tag, $duration, $time, $body) =
|
||||
($1, $2, $3, $4, $5, $6, $7, $8);
|
||||
my $d1 = $d;
|
||||
$d1 =~ s/^0+//;
|
||||
if ($special eq 'HTML') {
|
||||
push(@{$days->[$d]}, $body);
|
||||
} elsif ($special eq 'HTMLCLASS') {
|
||||
$classes->[$d] = $body;
|
||||
} elsif ($special eq 'WEEK') {
|
||||
$body =~ s/^\s+//;
|
||||
$body =~ s/\s+$//;
|
||||
$weeks->{$d1} = $body;
|
||||
} elsif ($special eq 'MOON') {
|
||||
if ($body =~ /(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) {
|
||||
my ($phase, $moonsize, $fontsize, $msg) = ($1, $2, $3, $4);
|
||||
@@ -362,7 +369,6 @@ sub output_calendar
|
||||
# Last column
|
||||
my $last_col = ($first_col + $Numdays - 1) % 7;
|
||||
|
||||
|
||||
# Start the table
|
||||
my $class;
|
||||
if ($Options{'nostyle'}) {
|
||||
@@ -475,6 +481,10 @@ sub draw_day_cell
|
||||
{
|
||||
my($day) = @_;
|
||||
my $shade = $shades->[$day];
|
||||
my $week = '';
|
||||
if (exists($weeks->{$day})) {
|
||||
$week = ' ' . $weeks->{$day};
|
||||
}
|
||||
my $class;
|
||||
if ($Options{'nostyle'}) {
|
||||
$class = $classes->[$day] || '';
|
||||
@@ -524,15 +534,15 @@ sub draw_day_cell
|
||||
if ($Options{'nostyle'}) {
|
||||
print("<div style=\"float: left\"><img border=\"0\" width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
|
||||
} else {
|
||||
print("<div class=\"rem-moon\"><img border=\"0\" width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
|
||||
print("<div class=\"rem-moon\"><img width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
|
||||
}
|
||||
}
|
||||
|
||||
if ($Options{'nostyle'}) {
|
||||
print "<div style=\"float: right\">$day</div>\n";
|
||||
print "<div style=\"float: right\">$day$week</div>\n";
|
||||
print "<p> </p>\n";
|
||||
} else {
|
||||
print "<div class=\"rem-daynumber\">$day</div>\n";
|
||||
print "<div class=\"rem-daynumber\">$day$week</div>\n";
|
||||
}
|
||||
if ($days->[$day]) {
|
||||
print(join("\n", @{$days->[$day]}));
|
||||
|
||||
Reference in New Issue
Block a user