mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 22:38:37 +02:00
Compare commits
44 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 |
2
configure
vendored
2
configure
vendored
@@ -5284,7 +5284,7 @@ _ACEOF
|
||||
fi
|
||||
done
|
||||
|
||||
VERSION=03.01.05
|
||||
VERSION=03.01.06
|
||||
|
||||
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h"
|
||||
|
||||
|
||||
@@ -45,6 +45,6 @@ if test "$GCC" = yes; then
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(setenv unsetenv glob)
|
||||
VERSION=03.01.05
|
||||
VERSION=03.01.06
|
||||
AC_SUBST(VERSION)
|
||||
AC_OUTPUT(src/Makefile www/Makefile src/version.h)
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
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
|
||||
|
||||
247
man/remind.1
247
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
|
||||
@@ -182,13 +182,14 @@ Echo lines when displaying error messages
|
||||
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
|
||||
@@ -337,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]
|
||||
@@ -794,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
|
||||
@@ -1226,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
|
||||
@@ -1888,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
|
||||
@@ -2093,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
|
||||
@@ -2170,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"
|
||||
@@ -2284,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
|
||||
@@ -2310,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()
|
||||
@@ -2449,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.
|
||||
@@ -2596,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
|
||||
@@ -2644,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.
|
||||
@@ -3073,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
|
||||
@@ -3412,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
|
||||
@@ -3823,6 +3931,16 @@ 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
|
||||
@@ -4079,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
|
||||
|
||||
@@ -208,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
|
||||
@@ -747,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
|
||||
@@ -2796,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
|
||||
}
|
||||
|
||||
@@ -748,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;
|
||||
@@ -763,7 +763,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
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;
|
||||
@@ -793,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;
|
||||
}
|
||||
|
||||
@@ -845,7 +845,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DBufInit(&obuf);
|
||||
if ((jul == JulianToday) ||
|
||||
(DoSimpleCalDelta &&
|
||||
ShouldTriggerReminder(&trig, &tim, jul))) {
|
||||
ShouldTriggerReminder(&trig, &tim, jul, &err))) {
|
||||
NumTriggered++;
|
||||
|
||||
if (DoSimpleCalendar || tim.ttime != NO_TIME) {
|
||||
@@ -1265,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) {
|
||||
|
||||
@@ -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 */
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
@@ -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 */
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
93
src/dorem.c
93
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)
|
||||
@@ -786,7 +806,7 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return ShouldTriggerBasedOnWarn(t, jul);
|
||||
return ShouldTriggerBasedOnWarn(t, jul, err);
|
||||
}
|
||||
|
||||
/* Move back by delta days, if any */
|
||||
@@ -795,9 +815,22 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -824,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;
|
||||
}
|
||||
@@ -953,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 */
|
||||
|
||||
@@ -996,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;
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@
|
||||
#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
|
||||
@@ -232,7 +233,8 @@ EXTERN char *ErrMsg[]
|
||||
"Expecting number",
|
||||
"Bad function in WARN clause",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
}
|
||||
#endif /* MK_GLOBALS */
|
||||
;
|
||||
|
||||
10
src/expr.c
10
src/expr.c
@@ -737,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);
|
||||
@@ -791,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;
|
||||
|
||||
@@ -723,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;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ 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);
|
||||
|
||||
@@ -75,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;
|
||||
|
||||
@@ -248,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;
|
||||
@@ -263,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':
|
||||
@@ -576,7 +582,7 @@ void Usage(void)
|
||||
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");
|
||||
|
||||
@@ -308,7 +308,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Numero puuttuu",
|
||||
"Virheellinen funktio WARN-lausekkeessa",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
|
||||
#elif IBMEXTENDED
|
||||
"Ok",
|
||||
@@ -411,7 +412,9 @@ EXTERN char *ErrMsg[] =
|
||||
"Numero puuttuu"
|
||||
"Virheellinen funktio WARN-lausekkeessa",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
|
||||
#else
|
||||
"Ok",
|
||||
"Puuttuva ']'",
|
||||
@@ -513,7 +516,9 @@ EXTERN char *ErrMsg[] =
|
||||
"Numero puuttuu",
|
||||
"Virheellinen funktio WARN-lausekkeessa",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -245,7 +245,9 @@ EXTERN char *ErrMsg[] =
|
||||
"Nombre attendu",
|
||||
"Fonction ill\351gale apr\350s WARN",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
|
||||
#else /* ISOLATIN1 */
|
||||
"Ok",
|
||||
"']' manquant",
|
||||
@@ -347,7 +349,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Nombre attendu",
|
||||
"Fonction illegale apres WARN",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
#endif /* ISOLATIN1 */
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
|
||||
@@ -280,7 +280,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Spodziewana liczba",
|
||||
"Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
#else /* ISOLATIN1 */
|
||||
"OK",
|
||||
"Brakujacy ']'",
|
||||
@@ -382,7 +383,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Spodziewana liczba",
|
||||
"Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
#endif /* ISOLATIN1 */
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
|
||||
@@ -246,7 +246,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Esperando numero",
|
||||
"Funcao ilegal na clausula WARN",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
|
||||
|
||||
@@ -724,7 +724,7 @@ int DoEndif(ParsePtr p)
|
||||
/***************************************************************/
|
||||
int DoIfTrig(ParsePtr p)
|
||||
{
|
||||
int r;
|
||||
int r, err;
|
||||
unsigned syndrome;
|
||||
Trigger trig;
|
||||
TimeTrig tim;
|
||||
@@ -734,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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
10
src/protos.h
10
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);
|
||||
@@ -75,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);
|
||||
@@ -128,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",
|
||||
|
||||
@@ -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;
|
||||
@@ -148,7 +149,8 @@ enum TokTypes
|
||||
T_Warn,
|
||||
T_Tag,
|
||||
T_Duration,
|
||||
T_LongTime
|
||||
T_LongTime,
|
||||
T_OmitFunc
|
||||
};
|
||||
|
||||
/* The structure of a token */
|
||||
|
||||
@@ -223,7 +223,7 @@ int DoSet (Parser *p)
|
||||
r = ParseIdentifier(p, &buf);
|
||||
if (r) return r;
|
||||
|
||||
/* Allow option equals-sign: SET var = value */
|
||||
/* Allow optional equals-sign: SET var = value */
|
||||
if (ParseNonSpaceChar(p, &r, 1) == '=') {
|
||||
ParseNonSpaceChar(p, &r, 0);
|
||||
}
|
||||
@@ -488,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 },
|
||||
@@ -500,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) )
|
||||
|
||||
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
|
||||
@@ -60,6 +60,15 @@ 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
|
||||
echo "Remind: Acceptance test PASSED"
|
||||
|
||||
233
tests/test.cmp
233
tests/test.cmp
@@ -431,7 +431,7 @@ REM 1 Mar --1 MSG 1 mar --1
|
||||
../tests/test.rem(133): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb BEFORE MSG 28 Feb BEFORE
|
||||
../tests/test.rem(134): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP
|
||||
../tests/test.rem(135): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb AFTER MSG 28 Feb AFTER
|
||||
../tests/test.rem(136): Trig = Thursday, 28 February, 1991
|
||||
@@ -451,7 +451,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
|
||||
../tests/test.rem(146): Trig = Wednesday, 13 March, 1991
|
||||
|
||||
|
||||
# Test BACK
|
||||
CLEAR-OMIT-CONTEXT
|
||||
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1
|
||||
@@ -488,6 +488,190 @@ REM Fri after MSG 16 Feb 1991
|
||||
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
|
||||
Entering UserFN _ofunc(1991-02-15)
|
||||
x => 1991-02-15
|
||||
day(1991-02-15) => 15
|
||||
15 < 7 => 0
|
||||
x => 1991-02-15
|
||||
day(1991-02-15) => 15
|
||||
15 % 2 => 1
|
||||
0 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-02-14)
|
||||
x => 1991-02-14
|
||||
day(1991-02-14) => 14
|
||||
14 < 7 => 0
|
||||
x => 1991-02-14
|
||||
day(1991-02-14) => 14
|
||||
14 % 2 => 0
|
||||
0 || 0 => 0
|
||||
Leaving UserFN _ofunc() => 0
|
||||
Entering UserFN _ofunc(1991-03-01)
|
||||
x => 1991-03-01
|
||||
day(1991-03-01) => 1
|
||||
1 < 7 => 1
|
||||
x => 1991-03-01
|
||||
day(1991-03-01) => 1
|
||||
1 % 2 => 1
|
||||
1 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-02)
|
||||
x => 1991-03-02
|
||||
day(1991-03-02) => 2
|
||||
2 < 7 => 1
|
||||
x => 1991-03-02
|
||||
day(1991-03-02) => 2
|
||||
2 % 2 => 0
|
||||
1 || 0 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-03)
|
||||
x => 1991-03-03
|
||||
day(1991-03-03) => 3
|
||||
3 < 7 => 1
|
||||
x => 1991-03-03
|
||||
day(1991-03-03) => 3
|
||||
3 % 2 => 1
|
||||
1 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-04)
|
||||
x => 1991-03-04
|
||||
day(1991-03-04) => 4
|
||||
4 < 7 => 1
|
||||
x => 1991-03-04
|
||||
day(1991-03-04) => 4
|
||||
4 % 2 => 0
|
||||
1 || 0 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-05)
|
||||
x => 1991-03-05
|
||||
day(1991-03-05) => 5
|
||||
5 < 7 => 1
|
||||
x => 1991-03-05
|
||||
day(1991-03-05) => 5
|
||||
5 % 2 => 1
|
||||
1 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-06)
|
||||
x => 1991-03-06
|
||||
day(1991-03-06) => 6
|
||||
6 < 7 => 1
|
||||
x => 1991-03-06
|
||||
day(1991-03-06) => 6
|
||||
6 % 2 => 0
|
||||
1 || 0 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-07)
|
||||
x => 1991-03-07
|
||||
day(1991-03-07) => 7
|
||||
7 < 7 => 0
|
||||
x => 1991-03-07
|
||||
day(1991-03-07) => 7
|
||||
7 % 2 => 1
|
||||
0 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-08)
|
||||
x => 1991-03-08
|
||||
day(1991-03-08) => 8
|
||||
8 < 7 => 0
|
||||
x => 1991-03-08
|
||||
day(1991-03-08) => 8
|
||||
8 % 2 => 0
|
||||
0 || 0 => 0
|
||||
Leaving UserFN _ofunc() => 0
|
||||
../tests/test.rem(169): Trig = Friday, 8 March, 1991
|
||||
REM 8 March OMITFUNC _ofunc -1 MSG OmitFunc Test 2
|
||||
Entering UserFN _ofunc(1991-03-07)
|
||||
x => 1991-03-07
|
||||
day(1991-03-07) => 7
|
||||
7 < 7 => 0
|
||||
x => 1991-03-07
|
||||
day(1991-03-07) => 7
|
||||
7 % 2 => 1
|
||||
0 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-06)
|
||||
x => 1991-03-06
|
||||
day(1991-03-06) => 6
|
||||
6 < 7 => 1
|
||||
x => 1991-03-06
|
||||
day(1991-03-06) => 6
|
||||
6 % 2 => 0
|
||||
1 || 0 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-05)
|
||||
x => 1991-03-05
|
||||
day(1991-03-05) => 5
|
||||
5 < 7 => 1
|
||||
x => 1991-03-05
|
||||
day(1991-03-05) => 5
|
||||
5 % 2 => 1
|
||||
1 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-04)
|
||||
x => 1991-03-04
|
||||
day(1991-03-04) => 4
|
||||
4 < 7 => 1
|
||||
x => 1991-03-04
|
||||
day(1991-03-04) => 4
|
||||
4 % 2 => 0
|
||||
1 || 0 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-03)
|
||||
x => 1991-03-03
|
||||
day(1991-03-03) => 3
|
||||
3 < 7 => 1
|
||||
x => 1991-03-03
|
||||
day(1991-03-03) => 3
|
||||
3 % 2 => 1
|
||||
1 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-02)
|
||||
x => 1991-03-02
|
||||
day(1991-03-02) => 2
|
||||
2 < 7 => 1
|
||||
x => 1991-03-02
|
||||
day(1991-03-02) => 2
|
||||
2 % 2 => 0
|
||||
1 || 0 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-01)
|
||||
x => 1991-03-01
|
||||
day(1991-03-01) => 1
|
||||
1 < 7 => 1
|
||||
x => 1991-03-01
|
||||
day(1991-03-01) => 1
|
||||
1 % 2 => 1
|
||||
1 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-02-28)
|
||||
x => 1991-02-28
|
||||
day(1991-02-28) => 28
|
||||
28 < 7 => 0
|
||||
x => 1991-02-28
|
||||
day(1991-02-28) => 28
|
||||
28 % 2 => 0
|
||||
0 || 0 => 0
|
||||
Leaving UserFN _ofunc() => 0
|
||||
../tests/test.rem(170): Trig = Thursday, 28 February, 1991
|
||||
|
||||
# omitfunc ignores local/global omits
|
||||
fset _ofunc(x) 0
|
||||
OMIT 1 March
|
||||
OMIT 2 March 1991
|
||||
REM 1 March OMIT Sun OMITFUNC _ofunc AFTER MSG Should trigger 1 March
|
||||
../tests/test.rem(176): Warning: OMIT is ignored if you use OMITFUNC
|
||||
Entering UserFN _ofunc(1991-02-15)
|
||||
Leaving UserFN _ofunc() => 0
|
||||
Entering UserFN _ofunc(1991-03-01)
|
||||
Leaving UserFN _ofunc() => 0
|
||||
../tests/test.rem(176): Trig = Friday, 1 March, 1991
|
||||
REM 1 March OMIT Sun AFTER MSG Should trigger 4 March
|
||||
../tests/test.rem(177): Trig = Monday, 4 March, 1991
|
||||
|
||||
set a000 abs(1)
|
||||
abs(1) => 1
|
||||
set a001 abs(-1)
|
||||
@@ -510,7 +694,7 @@ set a008 coerce("string", 11:44)
|
||||
coerce("string", 11:44) => "11:44"
|
||||
set a009 coerce("int", "badnews")
|
||||
coerce("int", "badnews") => Can't coerce
|
||||
../tests/test.rem(175): Can't coerce
|
||||
../tests/test.rem(188): Can't coerce
|
||||
set a010 coerce("int", "12")
|
||||
coerce("int", "12") => 12
|
||||
set a011 coerce("int", 11:44)
|
||||
@@ -522,7 +706,7 @@ set a013 date(1992, 2, 2)
|
||||
date(1992, 2, 2) => 1992-02-02
|
||||
set a014 date(1993, 2, 29)
|
||||
date(1993, 2, 29) => Bad date specification
|
||||
../tests/test.rem(180): Bad date specification
|
||||
../tests/test.rem(193): Bad date specification
|
||||
set a015 day(today())
|
||||
today() => 1991-02-16
|
||||
day(1991-02-16) => 16
|
||||
@@ -617,15 +801,15 @@ strlen("sadjflkhsldkfhsdlfjhk") => 21
|
||||
set a050 substr(a049, 2)
|
||||
a049 => 21
|
||||
substr(21, 2) => Type mismatch
|
||||
../tests/test.rem(218): Type mismatch
|
||||
../tests/test.rem(231): Type mismatch
|
||||
set a051 substr(a050, 2, 6)
|
||||
a050 => ../tests/test.rem(219): Undefined variable: a050
|
||||
a050 => ../tests/test.rem(232): Undefined variable: a050
|
||||
set a052 time(1+2, 3+4)
|
||||
1 + 2 => 3
|
||||
3 + 4 => 7
|
||||
time(3, 7) => 03:07
|
||||
rem 10 jan 1992 AT 11:22 CAL
|
||||
../tests/test.rem(221): Trig = Friday, 10 January, 1992
|
||||
../tests/test.rem(234): Trig = Friday, 10 January, 1992
|
||||
set a053 trigdate()
|
||||
trigdate() => 1992-01-10
|
||||
set a054 trigtime()
|
||||
@@ -638,7 +822,7 @@ set a057 value("a05"+"6")
|
||||
"a05" + "6" => "a056"
|
||||
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
set a058 version()
|
||||
version() => "03.01.05"
|
||||
version() => "03.01.06"
|
||||
set a059 wkday(today())
|
||||
today() => 1991-02-16
|
||||
wkday(1991-02-16) => "Saturday"
|
||||
@@ -717,31 +901,31 @@ y => 11:33
|
||||
x => "foo"
|
||||
y => 11:33
|
||||
"foo" * 11:33 => Type mismatch
|
||||
../tests/test.rem(244): `*': Type mismatch
|
||||
../tests/test.rem(257): `*': Type mismatch
|
||||
Leaving UserFN h() => Type mismatch
|
||||
set a074 dosubst("%a %b %c %d %e %f %g %h", '1992/5/5')
|
||||
dosubst("%a %b %c %d %e %f %g %h", 1992-05-05) => "on Tuesday, 5 May, 1992 in 444 days' tim"...
|
||||
msg [a074]%
|
||||
../tests/test.rem(246): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(259): Trig = Saturday, 16 February, 1991
|
||||
a074 => "on Tuesday, 5 May, 1992 in 444 days' tim"...
|
||||
on Tuesday, 5 May, 1992 in 444 days' time on Tuesday 5 on 05-05-1992 on 05-05-1992 on Tuesday, 5 May on 05-05
|
||||
set a075 dosubst("%i %j %k %l %m %n %o %p", '1992/5/5')
|
||||
dosubst("%i %j %k %l %m %n %o %p", 1992-05-05) => "on 05-05 on Tuesday, May 5th, 1992 on Tu"...
|
||||
msg [a075]%
|
||||
../tests/test.rem(248): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(261): Trig = Saturday, 16 February, 1991
|
||||
a075 => "on 05-05 on Tuesday, May 5th, 1992 on Tu"...
|
||||
on 05-05 on Tuesday, May 5th, 1992 on Tuesday, May 5th on 1992-05-05 May 5 s
|
||||
set a076 dosubst("%q %r %s %t %u %v %w %x", '1992/5/5')
|
||||
dosubst("%q %r %s %t %u %v %w %x", 1992-05-05) => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
|
||||
msg [a076]%
|
||||
../tests/test.rem(250): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(263): Trig = Saturday, 16 February, 1991
|
||||
a076 => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
|
||||
s' 05 th 05 on Tuesday, 5th May, 1992 on Tuesday, 5th May Tuesday 444
|
||||
set a077 dosubst("%y %z", '1992/5/5')
|
||||
dosubst("%y %z", 1992-05-05) => "1992 92
|
||||
"
|
||||
msg [a077]%
|
||||
../tests/test.rem(252): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(265): Trig = Saturday, 16 February, 1991
|
||||
a077 => "1992 92
|
||||
"
|
||||
1992 92
|
||||
@@ -779,7 +963,7 @@ dump
|
||||
a048 "foo"
|
||||
a067 "INT"
|
||||
a039 "February"
|
||||
a058 "03.01.05"
|
||||
a058 "03.01.06"
|
||||
a077 "1992 92
|
||||
"
|
||||
a049 21
|
||||
@@ -1922,4 +2106,23 @@ Color Test
|
||||
(0x(B (0x(B (0x(B[37;1mBright[0m (0x(B (0x(B (0x(B (0x(B (0x(B
|
||||
(0x(B (0x(B (0x(B[37;1mWhite[0m (0x(B (0x(B (0x(B (0x(B (0x(B
|
||||
(0mqqqqqqqqqqvqqqqqqqqqqvqqqqqqqqqqvqqqqqqqqqqvqqqqqqqqqqvqqqqqqqqqqvqqqqqqqqqqj(B
|
||||
|
||||
MON WKDAY DAY across year test
|
||||
-(1): Trig = Monday, 3 January, 2000
|
||||
No reminders.
|
||||
Sort Test
|
||||
Reminders for Saturday, 1st January, 2000:
|
||||
|
||||
Untimed
|
||||
|
||||
Timed
|
||||
|
||||
Reminders for Saturday, 1st January, 2000:
|
||||
|
||||
Timed
|
||||
|
||||
Untimed
|
||||
|
||||
../tests/runtest.rem(2): shell(): RUN disabled
|
||||
../tests/runinc.rem(1): shell(): RUN disabled
|
||||
../tests/runinc.rem(3): shell(): RUN disabled
|
||||
No reminders.
|
||||
|
||||
@@ -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")
|
||||
|
||||
18
www/rem2html
18
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] || '';
|
||||
@@ -529,10 +539,10 @@ sub draw_day_cell
|
||||
}
|
||||
|
||||
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