mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-17 14:59:20 +02:00
Compare commits
180 Commits
05.04.00-B
...
06.00.00-B
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
119e954e9e | ||
|
|
6aa07edffd | ||
|
|
bdb9ad1a5d | ||
|
|
05384fe7cf | ||
|
|
6125001e55 | ||
|
|
78b307e387 | ||
|
|
460d0a8d88 | ||
|
|
add35377ad | ||
|
|
fccd9ed42e | ||
|
|
a49ecccb34 | ||
|
|
ae9fe78817 | ||
|
|
dbc5576312 | ||
|
|
6cbbebceaf | ||
|
|
4dc27ca7f5 | ||
|
|
d8f97ce0f1 | ||
|
|
0e1a80f2bd | ||
|
|
4a7f703ab5 | ||
|
|
101de948b2 | ||
|
|
0e2d382b33 | ||
|
|
a6c5c3cb90 | ||
|
|
da573929ee | ||
|
|
5217d9b675 | ||
|
|
79a87c6f1a | ||
|
|
cde5ffc84a | ||
|
|
6ef323a4f0 | ||
|
|
8331ea2991 | ||
|
|
db28648d9d | ||
|
|
1a5915bba9 | ||
|
|
94a50fa22c | ||
|
|
fad6076568 | ||
|
|
287039ac40 | ||
|
|
8523218ef2 | ||
|
|
fdaaf2b57a | ||
|
|
19eac9b8d5 | ||
|
|
cda4877229 | ||
|
|
0976cd64f3 | ||
|
|
10f7889ef2 | ||
|
|
2391ff4bc7 | ||
|
|
d21ae56deb | ||
|
|
773980afa6 | ||
|
|
46a80da0e1 | ||
|
|
23516aebcb | ||
|
|
b48ce0b245 | ||
|
|
e4c090374d | ||
|
|
39fcbb72fd | ||
|
|
5f2bf48752 | ||
|
|
9e5354fcb8 | ||
|
|
49bdd135f7 | ||
|
|
f9a6aba81d | ||
|
|
175772d959 | ||
|
|
2f03c75826 | ||
|
|
d617000e95 | ||
|
|
04dee13996 | ||
|
|
ebcf6fd534 | ||
|
|
c7c58e20f3 | ||
|
|
a66ca7cce7 | ||
|
|
35cae5f97c | ||
|
|
6d86d88037 | ||
|
|
89f60358c6 | ||
|
|
781e5a6acd | ||
|
|
1b5d34e5e6 | ||
|
|
cb5fa62022 | ||
|
|
9d6ce5b674 | ||
|
|
1cdd9531a5 | ||
|
|
da4633fab3 | ||
|
|
aeff3606d2 | ||
|
|
2af36b7241 | ||
|
|
a7a22d20a2 | ||
|
|
3fdbf8b3bc | ||
|
|
a7696d659c | ||
|
|
865ebae6f8 | ||
|
|
f21f8ee8d0 | ||
|
|
76b7736266 | ||
|
|
0769e3e9cb | ||
|
|
d9ab9e91b5 | ||
|
|
9199ed5cf7 | ||
|
|
68a4b23b6f | ||
|
|
814dd51270 | ||
|
|
59fdf70732 | ||
|
|
24ed30fee0 | ||
|
|
86dcd9ce89 | ||
|
|
4915dc1e8d | ||
|
|
8c4cff22a5 | ||
|
|
50850134f6 | ||
|
|
a5de77cc91 | ||
|
|
87e4ed23bf | ||
|
|
0fe1d1591e | ||
|
|
dfb137085a | ||
|
|
143cdecb9e | ||
|
|
183ccf9d1c | ||
|
|
56ad4efb1a | ||
|
|
f4805a443b | ||
|
|
977aa3d6cf | ||
|
|
fe7ac980e5 | ||
|
|
aebab73dfa | ||
|
|
9bd0055d4d | ||
|
|
d944ceb32d | ||
|
|
3eadb3f767 | ||
|
|
be8a0621d1 | ||
|
|
235f947dd1 | ||
|
|
93dddec24a | ||
|
|
c13b721550 | ||
|
|
1c961dca83 | ||
|
|
700ac85e54 | ||
|
|
e20a14109a | ||
|
|
a3703173e2 | ||
|
|
7325375ccd | ||
|
|
4b898b2ba1 | ||
|
|
aa3760bc04 | ||
|
|
ea5e8c90ff | ||
|
|
609b68ab21 | ||
|
|
c3ab2a15cf | ||
|
|
418b050b1c | ||
|
|
4ab8897577 | ||
|
|
9613417a2e | ||
|
|
f808a2963d | ||
|
|
96a4dc3189 | ||
|
|
3c60285466 | ||
|
|
6fed350e1f | ||
|
|
9f220555af | ||
|
|
005ccef953 | ||
|
|
578c98c865 | ||
|
|
64bf3381c6 | ||
|
|
02ade6fc58 | ||
|
|
2954fca8d8 | ||
|
|
8356dacf2a | ||
|
|
4fd145cf4e | ||
|
|
1af2bdf8f1 | ||
|
|
9b98e65e01 | ||
|
|
0f83b98698 | ||
|
|
4fd62f9894 | ||
|
|
cc06592fe0 | ||
|
|
21d28ebfc3 | ||
|
|
b300422cdb | ||
|
|
37e09f4671 | ||
|
|
b6e53341c8 | ||
|
|
896fcf1d7f | ||
|
|
72155329f2 | ||
|
|
36c7db510a | ||
|
|
d4aa73747d | ||
|
|
3ed657b708 | ||
|
|
0441c0263b | ||
|
|
c40d4ee672 | ||
|
|
96f2d6537a | ||
|
|
dc777c95df | ||
|
|
3090d77346 | ||
|
|
157d2821f3 | ||
|
|
71d2da19a8 | ||
|
|
516b9c81b3 | ||
|
|
58d0e38f1a | ||
|
|
68d487ade9 | ||
|
|
9d42879170 | ||
|
|
db70aabc97 | ||
|
|
c8f55ef60b | ||
|
|
44b50fc6be | ||
|
|
a69a96529b | ||
|
|
f4e5cc63a6 | ||
|
|
136122b1db | ||
|
|
4cc63b1548 | ||
|
|
9390b4335b | ||
|
|
1fcf11a816 | ||
|
|
c4107e6a6f | ||
|
|
ab03232341 | ||
|
|
51a65841cd | ||
|
|
5035deaff1 | ||
|
|
09caa8988a | ||
|
|
9624b1045c | ||
|
|
102748397f | ||
|
|
f852f7e7e5 | ||
|
|
8d88192483 | ||
|
|
a6ca571fe5 | ||
|
|
2af783a58d | ||
|
|
af2daa7a87 | ||
|
|
c5bc459dd9 | ||
|
|
edf26eaa14 | ||
|
|
7e5dc26ee5 | ||
|
|
4c2b6031cd | ||
|
|
af8c1630c3 | ||
|
|
0ec43d570c | ||
|
|
1df8b12e71 |
3
Makefile
3
Makefile
@@ -42,6 +42,9 @@ install-stripped:
|
||||
test:
|
||||
@$(MAKE) -C src -s test
|
||||
|
||||
cppcheck:
|
||||
@$(MAKE) -C src cppcheck
|
||||
|
||||
distclean: clean
|
||||
-rm -f config.cache config.log config.status src/Makefile src/version.h src/config.h tests/test.out www/Makefile rem2pdf/Makefile.top rem2pdf/Makefile.old rem2pdf/Makefile rem2pdf/Makefile.PL rem2pdf/bin/rem2pdf rem2html/rem2html
|
||||
-rm -f man/rem.1 man/rem2ps.1 man/remind.1 man/tkremind.1 scripts/tkremind
|
||||
|
||||
50
README.md
50
README.md
@@ -6,10 +6,14 @@ the GNU General Public License, Vesion 2.
|
||||
|
||||
## Prerequisites:
|
||||
|
||||
remind and rem2ps have no prerequisites beyond the standard C library and
|
||||
the standard math library.
|
||||
### Remind and Rem2PS
|
||||
|
||||
rem2html requires the JSON::MaybeXS Perl module and rem2pdf
|
||||
**remind** and **rem2ps** have no prerequisites beyond the standard C
|
||||
library and the standard math library.
|
||||
|
||||
### Rem2HTML and Rem2PDF
|
||||
|
||||
**rem2html** requires the JSON::MaybeXS Perl module and **rem2pdf**
|
||||
requires the JSON::MaybeXS, Pango and Cairo Perl modules.
|
||||
|
||||
- On Debian-like systems, these prerequisites may be installed with:
|
||||
@@ -24,7 +28,9 @@ requires the JSON::MaybeXS, Pango and Cairo Perl modules.
|
||||
|
||||
- On Arch linux, you need `pango-perl`, `cairo-perl` and `perl-json-maybexs`
|
||||
|
||||
TkRemind requires Tcl/Tk and the tcllib library.
|
||||
### TkRemind
|
||||
|
||||
**tkremind** requires Tcl/Tk and the tcllib library.
|
||||
|
||||
- On Debian-like systems, install with:
|
||||
|
||||
@@ -45,7 +51,8 @@ all of your distribution's Noto Font-related packages.
|
||||
|
||||
## Installation
|
||||
|
||||
Remind can be installed with the usual:
|
||||
Assuming you have a normal C development environment installed, Remind
|
||||
can be installed with the usual:
|
||||
|
||||
`./configure && make && make test && sudo make install`
|
||||
|
||||
@@ -55,6 +62,39 @@ edit custom.h on your behalf:
|
||||
|
||||
`wish ./build.tk`
|
||||
|
||||
## Usage
|
||||
|
||||
Remind is a large and complex program. You can read the full manual page
|
||||
with:
|
||||
|
||||
`man remind`
|
||||
|
||||
after installation. However, the man page is long and detailed and is
|
||||
more of a reference than an introduction. You can get an overview
|
||||
with a [slide deck](https://dianne.skoll.ca/projects/remind/download/remind-oclug.pdf)
|
||||
I made a while back. There's also a (long) [YouTube video](https://www.youtube.com/watch?v=0SNgvsDvx7M) that serves as an
|
||||
introduction to Remind.
|
||||
|
||||
## A Note about AI
|
||||
|
||||
1. No part of Remind was written using AI of any type.<br><br>
|
||||
I certify that all of the C, Perl and Tcl code in Remind was written
|
||||
by a human being. I certify that all code in `.rem` files other than
|
||||
ones under `include/holidays` was written by a human being. The code
|
||||
under `include/holidays` was derived from the Python "holidays" library
|
||||
and I have no direct knowledge of the provenance of that library,
|
||||
though I suspect it's entirely or almost entirely human-written.
|
||||
|
||||
2. No AI-generated patches or other sorts of contributions to Remind
|
||||
will be accepted.
|
||||
|
||||
3. Remind's source code may not be used to train an AI model,
|
||||
including an LLM model, unless all of the output of said model is
|
||||
released under the GNU General Public License, version 2. If you use
|
||||
any of Remind's source code to train your model, then anything that
|
||||
the model produces is a derived product of Remind and must be licensed
|
||||
under the same terms as Remind.
|
||||
|
||||
---
|
||||
|
||||
Contact info: dianne@skoll.ca
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT(remind, 05.04.00, , , https://dianne.skoll.ca/projects/remind/)
|
||||
AC_INIT(remind, 06.00.00, , , https://dianne.skoll.ca/projects/remind/)
|
||||
AC_CONFIG_SRCDIR([src/queue.c])
|
||||
|
||||
cat <<'EOF'
|
||||
|
||||
@@ -110,15 +110,17 @@
|
||||
(defconst remind-keywords
|
||||
(sort
|
||||
(list "ADDOMIT" "AFTER" "AT" "BAN" "BANNER" "BEFORE" "CAL" "CLEAR"
|
||||
"CLEAR-OMIT-CONTEXT" "DEBUG" "DO" "DUMP" "DUMPVARS" "DURATION" "ELSE"
|
||||
"ENDIF" "ERRMSG" "EXIT" "EXPR" "FIRST" "FLUSH" "FOURTH" "FRENAME" "FROM" "FSET"
|
||||
"FUNSET" "IF" "IFTRIG" "IN" "INC" "INCLUDE" "INCLUDECMD" "INFO" "LAST"
|
||||
"LASTDAY" "LASTWORKDAY" "MAYBE" "MAYBE-UNCOMPUTABLE" "MSF" "MSG"
|
||||
"NOQUEUE" "OMIT" "OMITFUNC" "ONCE" "POP" "POP-OMIT-CONTEXT" "PRESERVE"
|
||||
"PRIORITY" "PS" "PSFILE" "PUSH" "PUSH-OMIT-CONTEXT" "REM" "RUN"
|
||||
"SATISFY" "SCAN" "SCANFROM" "SCHED" "SECOND" "SET" "SKIP" "SPECIAL"
|
||||
"SYSINCLUDE" "TAG" "THIRD" "THROUGH" "TRANSLATE" "TRANS" "UNSET"
|
||||
"UNTIL" "WARN")
|
||||
"CLEAR-OMIT-CONTEXT" "COMPLETE-THROUGH" "DEBUG" "DO" "DUMP" "DUMPVARS"
|
||||
"DURATION" "ELSE" "ENDIF" "ERRMSG" "EXIT" "EXPR" "FIRST"
|
||||
"FLUSH" "FOURTH" "FRENAME" "FROM" "FSET" "FUNSET" "IF"
|
||||
"IFTRIG" "IN" "INC" "INCLUDE" "INCLUDECMD" "INFO" "LAST"
|
||||
"LASTDAY" "LASTWORKDAY" "MAYBE" "MAYBE-UNCOMPUTABLE" "MSF"
|
||||
"MSG" "NOQUEUE" "OMIT" "OMITFUNC" "ONCE" "POP"
|
||||
"POP-OMIT-CONTEXT" "POP-FUNCS" "POP-VARS" "PRESERVE" "PRIORITY" "PS"
|
||||
"PSFILE" "PUSH" "PUSH-FUNCS" "PUSH-VARS" "PUSH-OMIT-CONTEXT" "REM" "RETURN"
|
||||
"RUN" "SATISFY" "SCAN" "SCANFROM" "SCHED" "SECOND" "SET"
|
||||
"SKIP" "SPECIAL" "SYSINCLUDE" "TAG" "THIRD" "THROUGH" "TODO"
|
||||
"TRANSLATE" "TRANS" "UNSET" "UNTIL" "WARN")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
|
||||
@@ -164,7 +166,7 @@
|
||||
(defconst remind-builtin-functions
|
||||
(sort
|
||||
(list "_" "abs" "access" "adawn" "adusk" "ampm" "ansicolor" "args" "asc"
|
||||
"baseyr" "catch" "catcherr" "char" "choose" "coerce" "columns" "current" "date"
|
||||
"baseyr" "catch" "catcherr" "char" "choose" "coerce" "columns" "const" "current" "date"
|
||||
"datepart" "datetime" "dawn" "day" "daysinmon" "defined" "dosubst"
|
||||
"dusk" "easterdate" "escape" "eval" "evaltrig" "filedate" "filedatetime"
|
||||
"filedir" "filename" "getenv" "hebdate" "hebday" "hebmon" "hebyear"
|
||||
|
||||
133
docs/WHATSNEW
133
docs/WHATSNEW
@@ -1,6 +1,99 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* VERSION 5.4 Patch 0 - 2025-??-??
|
||||
* VERSION 6.0 Patch 0 - 2025-??-??
|
||||
|
||||
- MAJOR NEW FEATURE: remind: Introduction of TODOs. These are similar
|
||||
to normal reminders, but (in Agenda Mode) you keep getting reminded
|
||||
of them even once they are in the past, unless you specifically mark
|
||||
them as completed.
|
||||
|
||||
- MAJOR NEW FEATURE: remind: The --json long option causes Remind to
|
||||
output JSON in Agenda Mode instead of the normal text output. See
|
||||
tkremind for an example of how a front-end can use this output.
|
||||
|
||||
- MINOR NEW FEATURE: remind: The RETURN statement can be used to skip
|
||||
the rest of the current file. Useful for early exit from an
|
||||
INCLUDEd file.
|
||||
|
||||
- MAJOR IMPROVEMENTS: tkremind: TkRemind has been given an overhaul.
|
||||
The "Show Queue" and "Show Today's Reminders" windows now respect
|
||||
the color scheme. TkRemind lets you create TODO reminders and
|
||||
easily mark them completed. You can right-click on a day number
|
||||
to get a window with Agenda Mode reminders for that day.
|
||||
|
||||
- MINOR IMPROVEMENT: remind: Language packs can define an ordx(n)
|
||||
function that localizes ord(n). If this function is defined, then
|
||||
ord(n) automatically calls it rather than using its built-in English
|
||||
localization. Appropriate ordx(n) definitions have been added to
|
||||
all language packs.
|
||||
|
||||
- MINOR IMPROVEMENT: remind: The %b substitution sequence handles
|
||||
dates in the past (because of TODOs). The %! sequence considers
|
||||
both date and time, and can be used with non-timed reminders. The
|
||||
new %? sequence is similar to %!, but outputs "are" and "were"
|
||||
instead of "is" and "was". The new %*! and %*? sequences are
|
||||
similar to %! and %?, but compare the trigger date to realtoday()
|
||||
instead of to today().
|
||||
|
||||
- MINOR IMPROVEMENT: remind: Downgrade a SPECIAL COLOR... with
|
||||
out-of-range color values to a normal MSG-type reminder.
|
||||
|
||||
- MINOR IMPROVEMENT: include/lang/nl.rem: Use "eergisteren" for "2
|
||||
days ago" and "overmorgen" for "in 2 days' time."
|
||||
|
||||
- MINOR IMPROVEMENT: tkremind: TkRemind now passes all command-line options
|
||||
back to Remind.
|
||||
|
||||
- BUG FIX: remind: SCANFROM and FROM are separated out internally, and
|
||||
in the JSON output, the original FROM or SCANFROM value is
|
||||
preserved, including relative SCANFROMs.
|
||||
|
||||
* VERSION 5.5 Patch 0 - 2025-07-28
|
||||
|
||||
- NEW FEATURE: remind: Add the PUSH-VARS / POP-VARS commands and the
|
||||
analogous PUSH-FUNCS / POP-FUNCS commands. These let you localize
|
||||
changes to variables and functions and help with writing more modular
|
||||
reminder files.
|
||||
|
||||
- INTERNAL CHANGES: Clean up the code following recommendations from
|
||||
an updated "cppcheck" executable.
|
||||
|
||||
* VERSION 5.4 Patch 2 - 2025-07-16
|
||||
|
||||
- MINOR CHANGE: remind: Allow daysinmon() to take a DATE or DATETIME
|
||||
argument.
|
||||
|
||||
- MINOR CHANGE: remind: All functions that want an integer month number
|
||||
will now also accept a string naming the month.
|
||||
|
||||
- UPDATE: include/holidays/chinese-new-year.rem: Add dates for Chinese
|
||||
New Year for 2051 through 2100.
|
||||
|
||||
- BUG FIX: remind: Set trigdate() correctly for a fully-specified
|
||||
date, even if it's in the past, as the manual documented. Bug
|
||||
found by Tim Chase.
|
||||
|
||||
- DOCUMENTATION FIX: rem2html: Document the correct Perl module
|
||||
prerequisites.
|
||||
|
||||
- CODE FIXES: remind: Various minor improvements to the code with
|
||||
no user-visible changes.
|
||||
|
||||
* VERSION 5.4 Patch 1 - 2025-06-15
|
||||
|
||||
- MAJOR BUG FIX: remind: In some circumstances, a REM command could
|
||||
yield a trigger date after its UNTIL date, rather than recognizing it
|
||||
as having expired. This has been fixed. Bug found by Ian! D. Allen.
|
||||
|
||||
- BUG FIX: rem2pdf: Support the COLOUR special (as well as COLOR).
|
||||
|
||||
- MINOR IMPROVEMENT: Add include/utils/add-html-anchors.rem. You can
|
||||
INCLUDE this file to get HTML anchors added to every calendar day
|
||||
by rem2html.
|
||||
|
||||
- DOCUMENTATION: Add NOTE-ABOUT-AI.txt
|
||||
|
||||
* VERSION 5.4 Patch 0 - 2025-06-03
|
||||
|
||||
- MAJOR IMPROVEMENT: remind: Track which expressions and variables
|
||||
Remind can prove to its satisfaction are "constant" - that is, that
|
||||
@@ -11,16 +104,38 @@ CHANGES TO REMIND
|
||||
See the new remind(1) man page section "NON-CONSTANT EXPRESSIONS"
|
||||
|
||||
- MINOR NEW FEATURE: remind: add the "nonconst" built-in function (to
|
||||
force an expression to be interpreted as non-constant) and the
|
||||
"isconst" function to test if an expression is constant.
|
||||
force an expression to be interpreted as non-constant), the "const"
|
||||
function to force an expression to be interpreted as constant, and
|
||||
the "isconst" function to test if an expression is constant.
|
||||
|
||||
- MINOR NEW FEATURE: remind: Add eval() built-in function that takes a
|
||||
string argument and evaluates it as an expression.
|
||||
string argument and evaluates it as an expression. For safety, the
|
||||
"shell" function is disabled inside an eval().
|
||||
|
||||
- MINOR NEW FEATURE: remind: add the "u" debugging flag to warn you if
|
||||
you set a variable that is not subsequently used.
|
||||
|
||||
- MINOR NEW FEATURE: remind: Add the trigbase() function and
|
||||
corresponding $Tb system variable. See the remind(1) man page for
|
||||
details.
|
||||
|
||||
- MINOR IMPROVEMENT: remind: make value("var", default) evaluate the
|
||||
second argument lazily: If "var" is defined, then the second
|
||||
argument is never evaluated.
|
||||
|
||||
- MINOR IMPROVEMENT: remind: Add syntax for redefining a function without
|
||||
issuing a warning. The syntax:
|
||||
|
||||
FSET - func(x) expr
|
||||
|
||||
is equivalent to:
|
||||
|
||||
FUNSET func
|
||||
FSET func(x) expr
|
||||
|
||||
- MINOR IMPROVEMENT: include/holidays: Update a bunch of files to use
|
||||
isany(n, a, b, c) rather than (n == a || n == b || n == c)
|
||||
|
||||
- MINOR IMPROVEMENT: remind: Make $Tu a synonym for triguntil().
|
||||
|
||||
- MINOR IMPROVEMENT: remind: If coerce() fails, issue a more detailed
|
||||
@@ -50,7 +165,7 @@ CHANGES TO REMIND
|
||||
corresponding weekday number returned.
|
||||
|
||||
- MINOR IMPROVEMENT: remind: Make the expression parser optimize away
|
||||
"- INT_CONSTANT" and "! INT_CONSTANT".
|
||||
the unary "-" and "!" operators when followed by an integer constant.
|
||||
|
||||
- BUG FIX: tests: Don't use the obsolete "tail +2" syntax in test-rem.
|
||||
Fix courtesy of Dick Marinus.
|
||||
@@ -1492,10 +1607,10 @@ CHANGES TO REMIND
|
||||
- NEW FEATURE: Add "-u+username" variant to tell Remind to switch users to
|
||||
"username" without disabling RUN directives. Idea courtesy of Ian! D. Allen
|
||||
|
||||
- CHANGE: rem2html: rem2html has been moved out of the www/ directory into
|
||||
its own rem2html/ directory. If your system has the prerequisites
|
||||
(namely Perl, Getopt::Long and JSON::Any) then rem2html will be installed
|
||||
by "make install".
|
||||
- CHANGE: rem2html: rem2html has been moved out of the www/ directory
|
||||
into its own rem2html/ directory. If your system has the
|
||||
prerequisites (namely Perl, Getopt::Long and JSON::MaybeXS) then
|
||||
rem2html will be installed by "make install".
|
||||
|
||||
- CHANGE: Remove "cm2rem". It was about 20 years obsolete.
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ if !defined("ansi_bold")
|
||||
set ansi_underline2 char(27) + "[21m"
|
||||
set ansi_overline char(27) + "[53m"
|
||||
endif
|
||||
preserve ansi_normal ansi_bold ansi_faint ansi_italic ansi_underline2 ansi_reverse ansi_strikeout ansi_underline2 ansi_overline
|
||||
preserve ansi_normal ansi_bold ansi_faint ansi_italic ansi_underline ansi_reverse ansi_strikeout ansi_underline2 ansi_overline
|
||||
endif
|
||||
|
||||
# Example: REM MSG I must [ansi_bold]emphasize[ansi_normal] \
|
||||
|
||||
@@ -38,10 +38,10 @@ You can use the following trick if you would like (for example) 7 days'
|
||||
advance warning of holidays:
|
||||
|
||||
# Save old definition (if any) of msgsuffix
|
||||
FRENAME msgsuffix saved_msgsuffix
|
||||
PUSH-FUNCS msgsuffix
|
||||
|
||||
# Save old value of $DefaultDelta
|
||||
SET old_delta $DefaultDelta
|
||||
PUSH-VARS $DefaultDelta
|
||||
|
||||
# We want 7 days' advance warning
|
||||
SET $DefaultDelta 7
|
||||
@@ -57,6 +57,9 @@ advance warning of holidays:
|
||||
SYSINCLUDE holidays/us.rem
|
||||
SYSINCLUDE holidays/us/ny.rem
|
||||
|
||||
# Restore old version of msgsuffix and $DefaultDelta
|
||||
FRENAME saved_msgsuffix msgsuffix
|
||||
SET $DefaultDelta old_delta
|
||||
# Restore old value $DefaultDelta
|
||||
POP-VARS
|
||||
|
||||
# Restore old version of msgsuffix
|
||||
POP-FUNCS
|
||||
|
||||
|
||||
@@ -6,28 +6,28 @@
|
||||
# See important caveats in the README file in this directory.
|
||||
|
||||
OMIT 1 January MSG Festat e Vitit të Ri
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Festat e Vitit të Ri (ditë pushimi e shtyrë)
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Festat e Vitit të Ri (ditë pushimi e shtyrë)
|
||||
OMIT 2 January MSG Festat e Vitit të Ri
|
||||
REM 2 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 2))==0 || wkdaynum(date($Ty, 1, 2))==6] MSG Festat e Vitit të Ri (ditë pushimi e shtyrë)
|
||||
REM 2 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 2)), 0, 6)] MSG Festat e Vitit të Ri (ditë pushimi e shtyrë)
|
||||
OMIT 14 March MSG Dita e Verës
|
||||
REM 14 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 14))==0 || wkdaynum(date($Ty, 3, 14))==6] MSG Dita e Verës (ditë pushimi e shtyrë)
|
||||
REM 14 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 14)), 0, 6)] MSG Dita e Verës (ditë pushimi e shtyrë)
|
||||
OMIT 22 March MSG Dita e Nevruzit
|
||||
REM 22 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 22))==0 || wkdaynum(date($Ty, 3, 22))==6] MSG Dita e Nevruzit (ditë pushimi e shtyrë)
|
||||
REM 31 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 31))==0 || wkdaynum(date($Ty, 3, 31))==6] MSG E diela e Pashkëve Katolike (ditë pushimi e shtyrë)
|
||||
REM 22 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 22)), 0, 6)] MSG Dita e Nevruzit (ditë pushimi e shtyrë)
|
||||
REM 31 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 31)), 0, 6)] MSG E diela e Pashkëve Katolike (ditë pushimi e shtyrë)
|
||||
OMIT [easterdate($Uy)] MSG E diela e Pashkëve Katolike
|
||||
OMIT [easterdate($Uy)] MSG E diela e Pashkëve Ortodokse
|
||||
OMIT 1 May MSG Dita Ndërkombëtare e Punëtorëve
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 1))==0 || wkdaynum(date($Ty, 5, 1))==6] MSG Dita Ndërkombëtare e Punëtorëve (ditë pushimi e shtyrë)
|
||||
REM 5 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 5))==0 || wkdaynum(date($Ty, 5, 5))==6] MSG E diela e Pashkëve Ortodokse (ditë pushimi e shtyrë)
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 1)), 0, 6)] MSG Dita Ndërkombëtare e Punëtorëve (ditë pushimi e shtyrë)
|
||||
REM 5 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 5)), 0, 6)] MSG E diela e Pashkëve Ortodokse (ditë pushimi e shtyrë)
|
||||
OMIT 5 September MSG Dita e Shenjtërimit të Shenjt Terezës
|
||||
REM 5 September OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 9, 5))==0 || wkdaynum(date($Ty, 9, 5))==6] MSG Dita e Shenjtërimit të Shenjt Terezës (ditë pushimi e shtyrë)
|
||||
REM 5 September OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 9, 5)), 0, 6)] MSG Dita e Shenjtërimit të Shenjt Terezës (ditë pushimi e shtyrë)
|
||||
OMIT 22 November MSG Dita e Alfabetit
|
||||
REM 22 November OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 11, 22))==0 || wkdaynum(date($Ty, 11, 22))==6] MSG Dita e Alfabetit (ditë pushimi e shtyrë)
|
||||
REM 22 November OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 11, 22)), 0, 6)] MSG Dita e Alfabetit (ditë pushimi e shtyrë)
|
||||
OMIT 28 November MSG Dita Flamurit dhe e Pavarësisë
|
||||
REM 28 November OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 11, 28))==0 || wkdaynum(date($Ty, 11, 28))==6] MSG Dita Flamurit dhe e Pavarësisë (ditë pushimi e shtyrë)
|
||||
REM 28 November OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 11, 28)), 0, 6)] MSG Dita Flamurit dhe e Pavarësisë (ditë pushimi e shtyrë)
|
||||
OMIT 29 November MSG Dita e Çlirimit
|
||||
REM 29 November OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 11, 29))==0 || wkdaynum(date($Ty, 11, 29))==6] MSG Dita e Çlirimit (ditë pushimi e shtyrë)
|
||||
REM 29 November OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 11, 29)), 0, 6)] MSG Dita e Çlirimit (ditë pushimi e shtyrë)
|
||||
OMIT 8 December MSG Dita Kombëtare e Rinisë
|
||||
REM 8 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 8))==0 || wkdaynum(date($Ty, 12, 8))==6] MSG Dita Kombëtare e Rinisë (ditë pushimi e shtyrë)
|
||||
REM 8 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 8)), 0, 6)] MSG Dita Kombëtare e Rinisë (ditë pushimi e shtyrë)
|
||||
OMIT 25 December MSG Krishtlindjet
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 25))==0 || wkdaynum(date($Ty, 12, 25))==6] MSG Krishtlindjet (ditë pushimi e shtyrë)
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 25)), 0, 6)] MSG Krishtlindjet (ditë pushimi e shtyrë)
|
||||
|
||||
@@ -6,36 +6,36 @@
|
||||
# See important caveats in the README file in this directory.
|
||||
|
||||
OMIT 1 January MSG Yeni il bayramı
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Yeni il bayramı (müşahidə olunur)
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Yeni il bayramı (müşahidə olunur)
|
||||
OMIT 2 January MSG Yeni il bayramı
|
||||
REM 2 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 2))==0 || wkdaynum(date($Ty, 1, 2))==6] MSG Yeni il bayramı (müşahidə olunur)
|
||||
REM 2 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 2)), 0, 6)] MSG Yeni il bayramı (müşahidə olunur)
|
||||
OMIT 20 January MSG Ümumxalq hüzn günü
|
||||
OMIT 8 March MSG Qadınlar günü
|
||||
REM 8 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 8))==0 || wkdaynum(date($Ty, 3, 8))==6] MSG Qadınlar günü (müşahidə olunur)
|
||||
REM 8 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 8)), 0, 6)] MSG Qadınlar günü (müşahidə olunur)
|
||||
OMIT 20 March MSG Novruz bayramı
|
||||
REM 20 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 20))==0 || wkdaynum(date($Ty, 3, 20))==6] MSG Novruz bayramı (müşahidə olunur)
|
||||
REM 20 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 20)), 0, 6)] MSG Novruz bayramı (müşahidə olunur)
|
||||
OMIT 21 March MSG Novruz bayramı
|
||||
REM 21 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 21))==0 || wkdaynum(date($Ty, 3, 21))==6] MSG Novruz bayramı (müşahidə olunur)
|
||||
REM 21 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 21)), 0, 6)] MSG Novruz bayramı (müşahidə olunur)
|
||||
OMIT 22 March MSG Novruz bayramı
|
||||
REM 22 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 22))==0 || wkdaynum(date($Ty, 3, 22))==6] MSG Novruz bayramı (müşahidə olunur)
|
||||
REM 22 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 22)), 0, 6)] MSG Novruz bayramı (müşahidə olunur)
|
||||
OMIT 23 March MSG Novruz bayramı
|
||||
REM 23 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 23))==0 || wkdaynum(date($Ty, 3, 23))==6] MSG Novruz bayramı (müşahidə olunur)
|
||||
REM 23 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 23)), 0, 6)] MSG Novruz bayramı (müşahidə olunur)
|
||||
OMIT 24 March MSG Novruz bayramı
|
||||
REM 24 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 24))==0 || wkdaynum(date($Ty, 3, 24))==6] MSG Novruz bayramı (müşahidə olunur)
|
||||
REM 24 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 24)), 0, 6)] MSG Novruz bayramı (müşahidə olunur)
|
||||
OMIT 9 May MSG Faşizm üzərində qələbə günü
|
||||
REM 9 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 9))==0 || wkdaynum(date($Ty, 5, 9))==6] MSG Faşizm üzərində qələbə günü (müşahidə olunur)
|
||||
REM 9 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 9)), 0, 6)] MSG Faşizm üzərində qələbə günü (müşahidə olunur)
|
||||
OMIT 28 May MSG Müstəqillik Günü
|
||||
REM 28 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 28))==0 || wkdaynum(date($Ty, 5, 28))==6] MSG Müstəqillik Günü (müşahidə olunur)
|
||||
REM 28 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 28)), 0, 6)] MSG Müstəqillik Günü (müşahidə olunur)
|
||||
OMIT 15 June MSG Azərbaycan xalqının milli qurtuluş günü
|
||||
REM 15 June OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 6, 15))==0 || wkdaynum(date($Ty, 6, 15))==6] MSG Azərbaycan xalqının milli qurtuluş günü (müşahidə olunur)
|
||||
REM 15 June OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 6, 15)), 0, 6)] MSG Azərbaycan xalqının milli qurtuluş günü (müşahidə olunur)
|
||||
OMIT 26 June MSG Azərbaycan Respublikasının Silahlı Qüvvələri günü
|
||||
REM 26 June OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 6, 26))==0 || wkdaynum(date($Ty, 6, 26))==6] MSG Azərbaycan Respublikasının Silahlı Qüvvələri günü (müşahidə olunur)
|
||||
REM 26 June OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 6, 26)), 0, 6)] MSG Azərbaycan Respublikasının Silahlı Qüvvələri günü (müşahidə olunur)
|
||||
OMIT 8 November MSG Zəfər Günü
|
||||
REM 8 November OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 11, 8))==0 || wkdaynum(date($Ty, 11, 8))==6] MSG Zəfər Günü (müşahidə olunur)
|
||||
REM 8 November OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 11, 8)), 0, 6)] MSG Zəfər Günü (müşahidə olunur)
|
||||
OMIT 9 November MSG Azərbaycan Respublikasının Dövlət bayrağı günü
|
||||
REM 9 November OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 11, 9))==0 || wkdaynum(date($Ty, 11, 9))==6] MSG Azərbaycan Respublikasının Dövlət bayrağı günü (müşahidə olunur)
|
||||
REM 9 November OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 11, 9)), 0, 6)] MSG Azərbaycan Respublikasının Dövlət bayrağı günü (müşahidə olunur)
|
||||
OMIT 31 December MSG Dünya azərbaycanlılarının həmrəyliyi günü
|
||||
REM 31 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 31))==0 || wkdaynum(date($Ty, 12, 31))==6] MSG Dünya azərbaycanlılarının həmrəyliyi günü (müşahidə olunur)
|
||||
REM 31 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 31)), 0, 6)] MSG Dünya azərbaycanlılarının həmrəyliyi günü (müşahidə olunur)
|
||||
|
||||
# Optional holidays
|
||||
REM 27 September MSG Anım Günü
|
||||
|
||||
@@ -6,29 +6,29 @@
|
||||
# See important caveats in the README file in this directory.
|
||||
|
||||
OMIT 1 January MSG Нова година
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Нова година (почивен ден)
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Нова година (почивен ден)
|
||||
OMIT 3 March MSG Ден на Освобождението на България от османско иго
|
||||
REM 3 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 3))==0 || wkdaynum(date($Ty, 3, 3))==6] MSG Ден на Освобождението на България от османско иго (почивен ден)
|
||||
REM 3 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 3)), 0, 6)] MSG Ден на Освобождението на България от османско иго (почивен ден)
|
||||
OMIT [orthodoxeaster($Uy)-2] MSG Велики петък
|
||||
OMIT [orthodoxeaster($Uy)-1] MSG Велика събота
|
||||
OMIT [orthodoxeaster($Uy)] MSG Великден
|
||||
OMIT [orthodoxeaster($Uy)+1] MSG Великден
|
||||
OMIT 1 May MSG Ден на труда и на международната работническа солидарност
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 1))==0 || wkdaynum(date($Ty, 5, 1))==6] MSG Ден на труда и на международната работническа солидарност (почивен ден)
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 1)), 0, 6)] MSG Ден на труда и на международната работническа солидарност (почивен ден)
|
||||
OMIT 6 May MSG Гергьовден, Ден на храбростта и Българската армия
|
||||
REM 6 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 6))==0 || wkdaynum(date($Ty, 5, 6))==6] MSG Гергьовден, Ден на храбростта и Българската армия (почивен ден)
|
||||
REM 6 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 6)), 0, 6)] MSG Гергьовден, Ден на храбростта и Българската армия (почивен ден)
|
||||
OMIT 24 May MSG Ден на светите братя Кирил и Методий, на българската азбука, просвета и култура и на славянската книжовност
|
||||
REM 24 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 24))==0 || wkdaynum(date($Ty, 5, 24))==6] MSG Ден на светите братя Кирил и Методий, на българската азбука, просвета и култура и на славянската книжовност (почивен ден)
|
||||
REM 24 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 24)), 0, 6)] MSG Ден на светите братя Кирил и Методий, на българската азбука, просвета и култура и на славянската книжовност (почивен ден)
|
||||
OMIT 6 September MSG Ден на Съединението
|
||||
REM 6 September OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 9, 6))==0 || wkdaynum(date($Ty, 9, 6))==6] MSG Ден на Съединението (почивен ден)
|
||||
REM 6 September OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 9, 6)), 0, 6)] MSG Ден на Съединението (почивен ден)
|
||||
OMIT 22 September MSG Ден на Независимостта на България
|
||||
REM 22 September OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 9, 22))==0 || wkdaynum(date($Ty, 9, 22))==6] MSG Ден на Независимостта на България (почивен ден)
|
||||
REM 22 September OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 9, 22)), 0, 6)] MSG Ден на Независимостта на България (почивен ден)
|
||||
OMIT 24 December MSG Бъдни вечер
|
||||
REM 24 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 24))==0 || wkdaynum(date($Ty, 12, 24))==6] MSG Бъдни вечер (почивен ден)
|
||||
REM 24 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 24)), 0, 6)] MSG Бъдни вечер (почивен ден)
|
||||
OMIT 25 December MSG Рождество Христово
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 25))==0 || wkdaynum(date($Ty, 12, 25))==6] MSG Рождество Христово (почивен ден)
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 25)), 0, 6)] MSG Рождество Христово (почивен ден)
|
||||
OMIT 26 December MSG Рождество Христово
|
||||
REM 26 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 26))==0 || wkdaynum(date($Ty, 12, 26))==6] MSG Рождество Христово (почивен ден)
|
||||
REM 26 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 26)), 0, 6)] MSG Рождество Христово (почивен ден)
|
||||
|
||||
# Optional holidays
|
||||
REM 1 November MSG Ден на народните будители
|
||||
|
||||
@@ -28,3 +28,53 @@ REM 26 Jan 2047 INFO "Url: https://en.wikipedia.org/wiki/Rabbit_(zodiac)" MSG %
|
||||
REM 14 Feb 2048 INFO "Url: https://en.wikipedia.org/wiki/Dragon_(zodiac)" MSG %(Chinese New Year) (%(Dragon))
|
||||
REM 2 Feb 2049 INFO "Url: https://en.wikipedia.org/wiki/Snake_(zodiac)" MSG %(Chinese New Year) (%(Snake))
|
||||
REM 23 Jan 2050 INFO "Url: https://en.wikipedia.org/wiki/Horse_(zodiac)" MSG %(Chinese New Year) (%(Horse))
|
||||
REM 11 Feb 2051 INFO "Url: https://en.wikipedia.org/wiki/Goat_(zodiac)" MSG %(Chinese New Year) (%(Goat))
|
||||
REM 1 Feb 2052 INFO "Url: https://en.wikipedia.org/wiki/Monkey_(zodiac)" MSG %(Chinese New Year) (%(Monkey))
|
||||
REM 19 Feb 2053 INFO "Url: https://en.wikipedia.org/wiki/Rooster_(zodiac)" MSG %(Chinese New Year) (%(Rooster))
|
||||
REM 8 Feb 2054 INFO "Url: https://en.wikipedia.org/wiki/Dog_(zodiac)" MSG %(Chinese New Year) (%(Dog))
|
||||
REM 28 Jan 2055 INFO "Url: https://en.wikipedia.org/wiki/Pig_(zodiac)" MSG %(Chinese New Year) (%(Pig))
|
||||
REM 15 Feb 2056 INFO "Url: https://en.wikipedia.org/wiki/Rat_(zodiac)" MSG %(Chinese New Year) (%(Rat))
|
||||
REM 4 Feb 2057 INFO "Url: https://en.wikipedia.org/wiki/Ox_(zodiac)" MSG %(Chinese New Year) (%(Ox))
|
||||
REM 24 Jan 2058 INFO "Url: https://en.wikipedia.org/wiki/Tiger_(zodiac)" MSG %(Chinese New Year) (%(Tiger))
|
||||
REM 12 Feb 2059 INFO "Url: https://en.wikipedia.org/wiki/Rabbit_(zodiac)" MSG %(Chinese New Year) (%(Rabbit))
|
||||
REM 2 Feb 2060 INFO "Url: https://en.wikipedia.org/wiki/Dragon_(zodiac)" MSG %(Chinese New Year) (%(Dragon))
|
||||
REM 21 Jan 2061 INFO "Url: https://en.wikipedia.org/wiki/Snake_(zodiac)" MSG %(Chinese New Year) (%(Snake))
|
||||
REM 9 Feb 2062 INFO "Url: https://en.wikipedia.org/wiki/Horse_(zodiac)" MSG %(Chinese New Year) (%(Horse))
|
||||
REM 29 Jan 2063 INFO "Url: https://en.wikipedia.org/wiki/Goat_(zodiac)" MSG %(Chinese New Year) (%(Goat))
|
||||
REM 17 Feb 2064 INFO "Url: https://en.wikipedia.org/wiki/Monkey_(zodiac)" MSG %(Chinese New Year) (%(Monkey))
|
||||
REM 5 Feb 2065 INFO "Url: https://en.wikipedia.org/wiki/Rooster_(zodiac)" MSG %(Chinese New Year) (%(Rooster))
|
||||
REM 26 Jan 2066 INFO "Url: https://en.wikipedia.org/wiki/Dog_(zodiac)" MSG %(Chinese New Year) (%(Dog))
|
||||
REM 14 Feb 2067 INFO "Url: https://en.wikipedia.org/wiki/Pig_(zodiac)" MSG %(Chinese New Year) (%(Pig))
|
||||
REM 3 Feb 2068 INFO "Url: https://en.wikipedia.org/wiki/Rat_(zodiac)" MSG %(Chinese New Year) (%(Rat))
|
||||
REM 23 Jan 2069 INFO "Url: https://en.wikipedia.org/wiki/Ox_(zodiac)" MSG %(Chinese New Year) (%(Ox))
|
||||
REM 11 Feb 2070 INFO "Url: https://en.wikipedia.org/wiki/Tiger_(zodiac)" MSG %(Chinese New Year) (%(Tiger))
|
||||
REM 31 Jan 2071 INFO "Url: https://en.wikipedia.org/wiki/Rabbit_(zodiac)" MSG %(Chinese New Year) (%(Rabbit))
|
||||
REM 19 Feb 2072 INFO "Url: https://en.wikipedia.org/wiki/Dragon_(zodiac)" MSG %(Chinese New Year) (%(Dragon))
|
||||
REM 7 Feb 2073 INFO "Url: https://en.wikipedia.org/wiki/Snake_(zodiac)" MSG %(Chinese New Year) (%(Snake))
|
||||
REM 27 Jan 2074 INFO "Url: https://en.wikipedia.org/wiki/Horse_(zodiac)" MSG %(Chinese New Year) (%(Horse))
|
||||
REM 15 Feb 2075 INFO "Url: https://en.wikipedia.org/wiki/Goat_(zodiac)" MSG %(Chinese New Year) (%(Goat))
|
||||
REM 5 Feb 2076 INFO "Url: https://en.wikipedia.org/wiki/Monkey_(zodiac)" MSG %(Chinese New Year) (%(Monkey))
|
||||
REM 24 Jan 2077 INFO "Url: https://en.wikipedia.org/wiki/Rooster_(zodiac)" MSG %(Chinese New Year) (%(Rooster))
|
||||
REM 12 Feb 2078 INFO "Url: https://en.wikipedia.org/wiki/Dog_(zodiac)" MSG %(Chinese New Year) (%(Dog))
|
||||
REM 2 Feb 2079 INFO "Url: https://en.wikipedia.org/wiki/Pig_(zodiac)" MSG %(Chinese New Year) (%(Pig))
|
||||
REM 22 Jan 2080 INFO "Url: https://en.wikipedia.org/wiki/Rat_(zodiac)" MSG %(Chinese New Year) (%(Rat))
|
||||
REM 9 Feb 2081 INFO "Url: https://en.wikipedia.org/wiki/Ox_(zodiac)" MSG %(Chinese New Year) (%(Ox))
|
||||
REM 29 Jan 2082 INFO "Url: https://en.wikipedia.org/wiki/Tiger_(zodiac)" MSG %(Chinese New Year) (%(Tiger))
|
||||
REM 17 Feb 2083 INFO "Url: https://en.wikipedia.org/wiki/Rabbit_(zodiac)" MSG %(Chinese New Year) (%(Rabbit))
|
||||
REM 6 Feb 2084 INFO "Url: https://en.wikipedia.org/wiki/Dragon_(zodiac)" MSG %(Chinese New Year) (%(Dragon))
|
||||
REM 26 Jan 2085 INFO "Url: https://en.wikipedia.org/wiki/Snake_(zodiac)" MSG %(Chinese New Year) (%(Snake))
|
||||
REM 14 Feb 2086 INFO "Url: https://en.wikipedia.org/wiki/Horse_(zodiac)" MSG %(Chinese New Year) (%(Horse))
|
||||
REM 3 Feb 2087 INFO "Url: https://en.wikipedia.org/wiki/Goat_(zodiac)" MSG %(Chinese New Year) (%(Goat))
|
||||
REM 24 Jan 2088 INFO "Url: https://en.wikipedia.org/wiki/Monkey_(zodiac)" MSG %(Chinese New Year) (%(Monkey))
|
||||
REM 10 Feb 2089 INFO "Url: https://en.wikipedia.org/wiki/Rooster_(zodiac)" MSG %(Chinese New Year) (%(Rooster))
|
||||
REM 30 Jan 2090 INFO "Url: https://en.wikipedia.org/wiki/Dog_(zodiac)" MSG %(Chinese New Year) (%(Dog))
|
||||
REM 18 Feb 2091 INFO "Url: https://en.wikipedia.org/wiki/Pig_(zodiac)" MSG %(Chinese New Year) (%(Pig))
|
||||
REM 7 Feb 2092 INFO "Url: https://en.wikipedia.org/wiki/Rat_(zodiac)" MSG %(Chinese New Year) (%(Rat))
|
||||
REM 27 Jan 2093 INFO "Url: https://en.wikipedia.org/wiki/Ox_(zodiac)" MSG %(Chinese New Year) (%(Ox))
|
||||
REM 15 Feb 2094 INFO "Url: https://en.wikipedia.org/wiki/Tiger_(zodiac)" MSG %(Chinese New Year) (%(Tiger))
|
||||
REM 5 Feb 2095 INFO "Url: https://en.wikipedia.org/wiki/Rabbit_(zodiac)" MSG %(Chinese New Year) (%(Rabbit))
|
||||
REM 25 Jan 2096 INFO "Url: https://en.wikipedia.org/wiki/Dragon_(zodiac)" MSG %(Chinese New Year) (%(Dragon))
|
||||
REM 12 Feb 2097 INFO "Url: https://en.wikipedia.org/wiki/Snake_(zodiac)" MSG %(Chinese New Year) (%(Snake))
|
||||
REM 1 Feb 2098 INFO "Url: https://en.wikipedia.org/wiki/Horse_(zodiac)" MSG %(Chinese New Year) (%(Horse))
|
||||
REM 21 Jan 2099 INFO "Url: https://en.wikipedia.org/wiki/Goat_(zodiac)" MSG %(Chinese New Year) (%(Goat))
|
||||
REM 9 Feb 2100 INFO "Url: https://en.wikipedia.org/wiki/Monkey_(zodiac)" MSG %(Chinese New Year) (%(Monkey))
|
||||
|
||||
@@ -26,7 +26,7 @@ REM 29 June ADDOMIT SCANFROM -28 SATISFY [$Tw != 2 && $Tw != 3 && $Tw != 4 && $T
|
||||
REM 2 July ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 6, 29)) == 5] MSG San Pedro y San Pablo
|
||||
OMIT 16 July MSG Virgen del Carmen
|
||||
OMIT 15 August MSG Asunción de la Virgen
|
||||
REM 17 September ADDOMIT SCANFROM -28 SATISFY [$Tw == 1 || $Tw == 5] MSG Fiestas Patrias
|
||||
REM 17 September ADDOMIT SCANFROM -28 SATISFY [isany($Tw, 1, 5)] MSG Fiestas Patrias
|
||||
OMIT 18 September MSG Día de la Independencia
|
||||
OMIT 19 September MSG Día de las Glorias del Ejército
|
||||
REM 20 September ADDOMIT SCANFROM -28 SATISFY [$Tw == 5] MSG Fiestas Patrias
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
# See important caveats in the README file in this directory.
|
||||
|
||||
OMIT 1 January MSG New Year's Day
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG New Year's Day (observed)
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG New Year's Day (observed)
|
||||
OMIT 11 February MSG Youth Day
|
||||
REM 11 February OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 2, 11))==0 || wkdaynum(date($Ty, 2, 11))==6] MSG Youth Day (observed)
|
||||
REM 11 February OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 2, 11)), 0, 6)] MSG Youth Day (observed)
|
||||
OMIT [easterdate($Uy)-2] MSG Good Friday
|
||||
OMIT 1 May MSG Labour Day
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 1))==0 || wkdaynum(date($Ty, 5, 1))==6] MSG Labour Day (observed)
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 1)), 0, 6)] MSG Labour Day (observed)
|
||||
OMIT 20 May MSG National Day
|
||||
REM 20 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 20))==0 || wkdaynum(date($Ty, 5, 20))==6] MSG National Day (observed)
|
||||
REM 20 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 20)), 0, 6)] MSG National Day (observed)
|
||||
OMIT [easterdate($Uy)+39] MSG Ascension Day
|
||||
OMIT 15 August MSG Assumption Day
|
||||
REM 15 August OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 8, 15))==0 || wkdaynum(date($Ty, 8, 15))==6] MSG Assumption Day (observed)
|
||||
REM 15 August OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 8, 15)), 0, 6)] MSG Assumption Day (observed)
|
||||
OMIT 25 December MSG Christmas Day
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 25))==0 || wkdaynum(date($Ty, 12, 25))==6] MSG Christmas Day (observed)
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 25)), 0, 6)] MSG Christmas Day (observed)
|
||||
|
||||
@@ -17,7 +17,7 @@ REM [orthodoxeaster($Uy)+1] MSG ΔΕΥΤΕΡΑ ΤΟΥ ΠΑΣΧΑ
|
||||
# minister decides moving that holiday. Here is a likely assumption of how this day might be moved.
|
||||
# Uncomment following lines to enable.
|
||||
|
||||
set PM date($Uy,5,1)
|
||||
# set PM date($Uy,5,1)
|
||||
# IF PM>=orthodoxeaster($Uy)-7 && PM<=orthodoxeaster($Uy)+1
|
||||
# IF PM<orthodoxeaster($Uy)-3
|
||||
# REM orthodoxeaster($Uy) -8 MSG πιθανόν ΕΡΓΑΤΙΚΗ Πρωτομαγιά
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
# See important caveats in the README file in this directory.
|
||||
|
||||
OMIT 1 January MSG The first day of January
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG The first day of January (observed)
|
||||
REM 4 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 4))==0 || wkdaynum(date($Ty, 4, 4))==6] MSG Ching Ming Festival (observed)
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG The first day of January (observed)
|
||||
REM 4 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 4, 4)), 0, 6)] MSG Ching Ming Festival (observed)
|
||||
OMIT 1 May MSG Labour Day
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 1))==0 || wkdaynum(date($Ty, 5, 1))==6] MSG Labour Day (observed)
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 1)), 0, 6)] MSG Labour Day (observed)
|
||||
OMIT 1 July MSG Hong Kong Special Administrative Region Establishment Day
|
||||
REM 1 July OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 7, 1))==0 || wkdaynum(date($Ty, 7, 1))==6] MSG Hong Kong Special Administrative Region Establishment Day (observed)
|
||||
REM 1 July OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 7, 1)), 0, 6)] MSG Hong Kong Special Administrative Region Establishment Day (observed)
|
||||
OMIT 1 October MSG National Day
|
||||
REM 1 October OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 10, 1))==0 || wkdaynum(date($Ty, 10, 1))==6] MSG National Day (observed)
|
||||
REM 1 October OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 10, 1)), 0, 6)] MSG National Day (observed)
|
||||
OMIT 25 December MSG Christmas Day
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 25))==0 || wkdaynum(date($Ty, 12, 25))==6] MSG Christmas Day (observed)
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 25)), 0, 6)] MSG Christmas Day (observed)
|
||||
OMIT 26 December MSG The first weekday after Christmas Day
|
||||
REM 26 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 26))==0 || wkdaynum(date($Ty, 12, 26))==6] MSG The first weekday after Christmas Day (observed)
|
||||
REM 26 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 26)), 0, 6)] MSG The first weekday after Christmas Day (observed)
|
||||
|
||||
# Optional holidays
|
||||
REM [easterdate($Uy)-2] MSG Good Friday
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# See important caveats in the README file in this directory.
|
||||
|
||||
OMIT 1 January MSG New Year's Day
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG New Year's Day (substitute day)
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG New Year's Day (substitute day)
|
||||
OMIT [easterdate($Uy)-2] MSG Good Friday
|
||||
OMIT [easterdate($Uy)+1] MSG Easter Monday
|
||||
REM First Monday in May ADDOMIT SCANFROM -28 MSG May Bank Holiday
|
||||
@@ -14,6 +14,6 @@ REM 9 May ADDOMIT SCANFROM -28 SATISFY [$Tw != 0] MSG Liberation Day
|
||||
REM Last Monday in May ADDOMIT SCANFROM -28 MSG Spring Bank Holiday
|
||||
REM Last Monday in August ADDOMIT SCANFROM -28 MSG Summer Bank Holiday
|
||||
OMIT 25 December MSG Christmas Day
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 25))==0 || wkdaynum(date($Ty, 12, 25))==6] MSG Christmas Day (substitute day)
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 25)), 0, 6)] MSG Christmas Day (substitute day)
|
||||
OMIT 26 December MSG Boxing Day
|
||||
REM 26 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 26))==0 || wkdaynum(date($Ty, 12, 26))==6] MSG Boxing Day (substitute day)
|
||||
REM 26 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 26)), 0, 6)] MSG Boxing Day (substitute day)
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
# Major Jewish Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
# Save variables and functions that we will mess with
|
||||
PUSH-VARS InIsrael IncludeIsraeliHolidays Reform
|
||||
PUSH-FUNCS _chan _h2 _PastSat _BackTwoFri _BackTwoSat
|
||||
|
||||
# Set the variable InIsrael to 1 if you live in Israel. Otherwise,
|
||||
# you get the Diaspora versions of Jewish holidays
|
||||
SET InIsrael value("InIsrael", 0)
|
||||
|
||||
# Set this if you want to include holidays that are not really
|
||||
# Jewish religious holidays, but simply Israeli holidays
|
||||
SET IncludeIsraeliHolidays value("IncludeIsraeliHolidays", 0)
|
||||
|
||||
# Set the variable Reform to 1 if you want the Reform version of the
|
||||
# Jewish calendar. Otherwise, you get the traditional version
|
||||
SET Reform value("Reform", 0)
|
||||
@@ -14,9 +22,6 @@ FSET _h2(x, y) HEBDATE(x, y, $U-7)
|
||||
FSET _PastSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)+1)
|
||||
FSET _BackTwoFri(x, y) IIF(WKDAYNUM(_h2(x,y))!=5, _h2(x,y), _h2(x,y)-2)
|
||||
FSET _BackTwoSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)-2)
|
||||
# Default values in case InIsrael and Reform are not set
|
||||
SET InIsrael VALUE("InIsrael", 0)
|
||||
SET Reform VALUE("Reform", 0)
|
||||
|
||||
REM [hebdate(1, "Tishrey")] INFO "Url: https://en.wikipedia.org/wiki/Rosh_Hashanah" MSG Rosh Hashana 1
|
||||
|
||||
@@ -83,15 +88,18 @@ IF !InIsrael && !Reform
|
||||
ENDIF
|
||||
|
||||
REM [hebdate(27, "Nisan")] INFO "Url: https://en.wikipedia.org/wiki/Yom_HaShoah" MSG Yom HaShoah
|
||||
REM [_BackTwoFri(4, "Iyar")] INFO "Url: https://en.wikipedia.org/wiki/Yom_HaZikaron" MSG Yom HaZikaron
|
||||
REM [_BackTwoSat(5, "Iyar")] INFO "Url: https://en.wikipedia.org/wiki/Independence_Day_(Israel)" MSG Yom Ha'atzmaut
|
||||
|
||||
IF IncludeIsraeliHolidays
|
||||
REM [_BackTwoFri(4, "Iyar")] INFO "Url: https://en.wikipedia.org/wiki/Yom_HaZikaron" MSG Yom HaZikaron
|
||||
REM [_BackTwoSat(5, "Iyar")] INFO "Url: https://en.wikipedia.org/wiki/Independence_Day_(Israel)" MSG Yom Ha'atzmaut
|
||||
REM [hebdate(28, "Iyar")] INFO "Url: https://en.wikipedia.org/wiki/Jerusalem_Day" MSG Yom Yerushalayim
|
||||
ENDIF
|
||||
|
||||
# Not sure about Reform's position on Lag B'Omer
|
||||
IF !Reform
|
||||
REM [hebdate(18, "Iyar")] INFO "Url: https://en.wikipedia.org/wiki/Lag_BaOmer" MSG Lag B'Omer
|
||||
ENDIF
|
||||
|
||||
REM [hebdate(28, "Iyar")] INFO "Url: https://en.wikipedia.org/wiki/Jerusalem_Day" MSG Yom Yerushalayim
|
||||
REM [hebdate(6, "Sivan")] INFO "Url: https://en.wikipedia.org/wiki/Shavuot" MSG Shavuot
|
||||
|
||||
IF !InIsrael && !Reform
|
||||
@@ -105,3 +113,7 @@ IF !Reform
|
||||
REM [_PastSat(17, "Tamuz")] INFO "Url: https://en.wikipedia.org/wiki/Seventeenth_of_Tammuz" MSG Tzom Tammuz
|
||||
REM [_PastSat(9, "Av")] INFO "Url: https://en.wikipedia.org/wiki/Tisha_B%27Av" MSG Tish'a B'Av
|
||||
ENDIF
|
||||
|
||||
# Tidy up
|
||||
POP-FUNCS
|
||||
POP-VARS
|
||||
|
||||
@@ -6,29 +6,29 @@
|
||||
# See important caveats in the README file in this directory.
|
||||
|
||||
OMIT 1 January MSG Жаңа жыл
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Жаңа жыл (қайта белгіленген демалыс)
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Жаңа жыл (қайта белгіленген демалыс)
|
||||
OMIT 2 January MSG Жаңа жыл
|
||||
REM 2 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 2))==0 || wkdaynum(date($Ty, 1, 2))==6] MSG Жаңа жыл (қайта белгіленген демалыс)
|
||||
REM 2 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 2)), 0, 6)] MSG Жаңа жыл (қайта белгіленген демалыс)
|
||||
OMIT 7 January MSG Православиелік Рождество
|
||||
OMIT 8 March MSG Халықаралық әйелдер күні
|
||||
REM 8 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 8))==0 || wkdaynum(date($Ty, 3, 8))==6] MSG Халықаралық әйелдер күні (қайта белгіленген демалыс)
|
||||
REM 8 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 8)), 0, 6)] MSG Халықаралық әйелдер күні (қайта белгіленген демалыс)
|
||||
OMIT 21 March MSG Наурыз мейрамы
|
||||
REM 21 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 21))==0 || wkdaynum(date($Ty, 3, 21))==6] MSG Наурыз мейрамы (қайта белгіленген демалыс)
|
||||
REM 21 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 21)), 0, 6)] MSG Наурыз мейрамы (қайта белгіленген демалыс)
|
||||
OMIT 22 March MSG Наурыз мейрамы
|
||||
REM 22 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 22))==0 || wkdaynum(date($Ty, 3, 22))==6] MSG Наурыз мейрамы (қайта белгіленген демалыс)
|
||||
REM 22 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 22)), 0, 6)] MSG Наурыз мейрамы (қайта белгіленген демалыс)
|
||||
OMIT 23 March MSG Наурыз мейрамы
|
||||
REM 23 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 23))==0 || wkdaynum(date($Ty, 3, 23))==6] MSG Наурыз мейрамы (қайта белгіленген демалыс)
|
||||
REM 23 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 23)), 0, 6)] MSG Наурыз мейрамы (қайта белгіленген демалыс)
|
||||
OMIT 1 May MSG Қазақстан халқының бірлігі мерекесі
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 1))==0 || wkdaynum(date($Ty, 5, 1))==6] MSG Қазақстан халқының бірлігі мерекесі (қайта белгіленген демалыс)
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 1)), 0, 6)] MSG Қазақстан халқының бірлігі мерекесі (қайта белгіленген демалыс)
|
||||
OMIT 7 May MSG Отан Қорғаушы күні
|
||||
REM 7 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 7))==0 || wkdaynum(date($Ty, 5, 7))==6] MSG Отан Қорғаушы күні (қайта белгіленген демалыс)
|
||||
REM 7 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 7)), 0, 6)] MSG Отан Қорғаушы күні (қайта белгіленген демалыс)
|
||||
OMIT 9 May MSG Жеңіс күні
|
||||
REM 9 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 9))==0 || wkdaynum(date($Ty, 5, 9))==6] MSG Жеңіс күні (қайта белгіленген демалыс)
|
||||
REM 9 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 9)), 0, 6)] MSG Жеңіс күні (қайта белгіленген демалыс)
|
||||
OMIT 6 July MSG Астана күні
|
||||
REM 6 July OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 7, 6))==0 || wkdaynum(date($Ty, 7, 6))==6] MSG Астана күні (қайта белгіленген демалыс)
|
||||
REM 6 July OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 7, 6)), 0, 6)] MSG Астана күні (қайта белгіленген демалыс)
|
||||
OMIT 30 August MSG Қазақстан Республикасының Конституциясы күні
|
||||
REM 30 August OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 8, 30))==0 || wkdaynum(date($Ty, 8, 30))==6] MSG Қазақстан Республикасының Конституциясы күні (қайта белгіленген демалыс)
|
||||
REM 30 August OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 8, 30)), 0, 6)] MSG Қазақстан Республикасының Конституциясы күні (қайта белгіленген демалыс)
|
||||
OMIT 25 October MSG Республика күні
|
||||
REM 25 October OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 10, 25))==0 || wkdaynum(date($Ty, 10, 25))==6] MSG Республика күні (қайта белгіленген демалыс)
|
||||
REM 25 October OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 10, 25)), 0, 6)] MSG Республика күні (қайта белгіленген демалыс)
|
||||
OMIT 16 December MSG Тəуелсіздік күні
|
||||
REM 16 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 16))==0 || wkdaynum(date($Ty, 12, 16))==6] MSG Тəуелсіздік күні (қайта белгіленген демалыс)
|
||||
REM 16 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 16)), 0, 6)] MSG Тəуелсіздік күні (қайта белгіленген демалыс)
|
||||
|
||||
@@ -6,21 +6,21 @@
|
||||
# See important caveats in the README file in this directory.
|
||||
|
||||
OMIT 1 January MSG ວັນປີໃໝ່ສາກົນ
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG ພັກຊົດເຊີຍວັນປີໃໝ່ສາກົນ
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG ພັກຊົດເຊີຍວັນປີໃໝ່ສາກົນ
|
||||
OMIT 8 March MSG ວັນແມ່ຍິງສາກົນ
|
||||
REM 8 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 8))==0 || wkdaynum(date($Ty, 3, 8))==6] MSG ພັກຊົດເຊີຍວັນແມ່ຍິງສາກົນ
|
||||
REM 8 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 8)), 0, 6)] MSG ພັກຊົດເຊີຍວັນແມ່ຍິງສາກົນ
|
||||
OMIT 13 April MSG ບຸນປີໃໝ່ລາວ
|
||||
REM 13 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 13))==0 || wkdaynum(date($Ty, 4, 13))==6] MSG ພັກຊົດເຊີຍບຸນປີໃໝ່ລາວ
|
||||
REM 13 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 4, 13)), 0, 6)] MSG ພັກຊົດເຊີຍບຸນປີໃໝ່ລາວ
|
||||
OMIT 14 April MSG ບຸນປີໃໝ່ລາວ
|
||||
REM 14 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 14))==0 || wkdaynum(date($Ty, 4, 14))==6] MSG ພັກຊົດເຊີຍບຸນປີໃໝ່ລາວ
|
||||
REM 14 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 4, 14)), 0, 6)] MSG ພັກຊົດເຊີຍບຸນປີໃໝ່ລາວ
|
||||
OMIT 15 April MSG ບຸນປີໃໝ່ລາວ
|
||||
REM 15 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 15))==0 || wkdaynum(date($Ty, 4, 15))==6] MSG ພັກຊົດເຊີຍບຸນປີໃໝ່ລາວ
|
||||
REM 15 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 4, 15)), 0, 6)] MSG ພັກຊົດເຊີຍບຸນປີໃໝ່ລາວ
|
||||
OMIT 16 April MSG ບຸນປີໃໝ່ລາວ
|
||||
REM 16 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 16))==0 || wkdaynum(date($Ty, 4, 16))==6] MSG ພັກຊົດເຊີຍບຸນປີໃໝ່ລາວ
|
||||
REM 16 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 4, 16)), 0, 6)] MSG ພັກຊົດເຊີຍບຸນປີໃໝ່ລາວ
|
||||
OMIT 1 May MSG ວັນກຳມະກອນສາກົນ
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 1))==0 || wkdaynum(date($Ty, 5, 1))==6] MSG ພັກຊົດເຊີຍວັນກຳມະກອນສາກົນ
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 1)), 0, 6)] MSG ພັກຊົດເຊີຍວັນກຳມະກອນສາກົນ
|
||||
OMIT 2 December MSG ວັນຊາດ
|
||||
REM 2 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 2))==0 || wkdaynum(date($Ty, 12, 2))==6] MSG ພັກຊົດເຊີຍວັນຊາດ
|
||||
REM 2 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 2)), 0, 6)] MSG ພັກຊົດເຊີຍວັນຊາດ
|
||||
|
||||
# Optional holidays
|
||||
REM 20 January MSG ວັນສ້າງຕັ້ງກອງທັບປະຊາຊົນລາວ
|
||||
@@ -37,7 +37,7 @@ REM 15 August MSG ວັນລັດຖະທໍາມະນູນແຫ່ງ
|
||||
REM 23 August MSG ວັນຍຶດອຳນາດທົ່ວປະເທດ
|
||||
REM 7 October MSG ວັນຄູແຫ່ງຊາດ
|
||||
REM 7 October MSG ວັນສ້າງຕັ້ງທະນາຄານແຫ່ງ ສປປ ລາວ
|
||||
REM 7 October OMIT SAT SUN AFTER SCANFROM -28 SATISFY [wkdaynum(date($Ty, 10, 7))==0 || wkdaynum(date($Ty, 10, 7))==6] MSG ພັກຊົດເຊີຍວັນສ້າງຕັ້ງທະນາຄານແຫ່ງ ສປປ ລາວ
|
||||
REM 7 October OMIT SAT SUN AFTER SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 10, 7)), 0, 6)] MSG ພັກຊົດເຊີຍວັນສ້າງຕັ້ງທະນາຄານແຫ່ງ ສປປ ລາວ
|
||||
REM 12 October MSG ວັນປະກາດເອກະລາດ
|
||||
REM 13 December MSG ວັນຄ້າຍວັນເກີດ ທ່ານ ປະທານ ໄກສອນ ພົມວິຫານ
|
||||
REM 27 December SCANFROM -28 SATISFY [$Tw >= 3 && $Tw <= 5] MSG ສາມວັນລັດຖະການສຸດທ້າຍຂອງທຸກໆປີ
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
# [$SysInclude]/holidays/my/
|
||||
|
||||
OMIT 1 May MSG Hari Pekerja
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 1))==0 || wkdaynum(date($Ty, 5, 1))==6] MSG Cuti Hari Pekerja
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 1)), 0, 6)] MSG Cuti Hari Pekerja
|
||||
REM First Monday in June ADDOMIT SCANFROM -28 MSG Hari Keputeraan Rasmi Seri Paduka Baginda Yang di-Pertuan Agong
|
||||
REM 3 June OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 6, 3))==0 || wkdaynum(date($Ty, 6, 3))==6] MSG Cuti Hari Keputeraan Rasmi Seri Paduka Baginda Yang di-Pertuan Agong
|
||||
REM 3 June OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 6, 3)), 0, 6)] MSG Cuti Hari Keputeraan Rasmi Seri Paduka Baginda Yang di-Pertuan Agong
|
||||
OMIT 31 August MSG Hari Kebangsaan
|
||||
REM 31 August OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 8, 31))==0 || wkdaynum(date($Ty, 8, 31))==6] MSG Cuti Hari Kebangsaan
|
||||
REM 31 August OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 8, 31)), 0, 6)] MSG Cuti Hari Kebangsaan
|
||||
OMIT 16 September MSG Hari Malaysia
|
||||
OMIT 25 December MSG Hari Krismas
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 25))==0 || wkdaynum(date($Ty, 12, 25))==6] MSG Cuti Hari Krismas
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 25)), 0, 6)] MSG Cuti Hari Krismas
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
# also SYSINCLUDE holidays/my.rem
|
||||
|
||||
OMIT 1 January MSG Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Cuti Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Cuti Tahun Baharu
|
||||
OMIT 20 February MSG Hari Pengisytiharan Tarikh Kemerdekaan
|
||||
REM 20 February OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 2, 20))==0 || wkdaynum(date($Ty, 2, 20))==6] MSG Cuti Hari Pengisytiharan Tarikh Kemerdekaan
|
||||
REM 20 February OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 2, 20)), 0, 6)] MSG Cuti Hari Pengisytiharan Tarikh Kemerdekaan
|
||||
OMIT 24 August MSG Hari Jadi Yang di-Pertua Negeri Melaka
|
||||
REM 24 August OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 8, 24))==0 || wkdaynum(date($Ty, 8, 24))==6] MSG Cuti Hari Jadi Yang di-Pertua Negeri Melaka
|
||||
REM 24 August OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 8, 24)), 0, 6)] MSG Cuti Hari Jadi Yang di-Pertua Negeri Melaka
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
# also SYSINCLUDE holidays/my.rem
|
||||
|
||||
OMIT 1 January MSG Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Cuti Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Cuti Tahun Baharu
|
||||
OMIT 14 January MSG Hari Keputeraan Yang di-Pertuan Besar Negeri Sembilan
|
||||
REM 14 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 14))==0 || wkdaynum(date($Ty, 1, 14))==6] MSG Cuti Hari Keputeraan Yang di-Pertuan Besar Negeri Sembilan
|
||||
REM 14 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 14)), 0, 6)] MSG Cuti Hari Keputeraan Yang di-Pertuan Besar Negeri Sembilan
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# also SYSINCLUDE holidays/my.rem
|
||||
|
||||
OMIT 1 January MSG Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Cuti Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Cuti Tahun Baharu
|
||||
OMIT 22 May MSG Hari Hol Sultan Pahang
|
||||
OMIT 30 July MSG Hari Keputeraan Sultan Pahang
|
||||
REM 30 July OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 7, 30))==0 || wkdaynum(date($Ty, 7, 30))==6] MSG Cuti Hari Keputeraan Sultan Pahang
|
||||
REM 30 July OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 7, 30)), 0, 6)] MSG Cuti Hari Keputeraan Sultan Pahang
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# also SYSINCLUDE holidays/my.rem
|
||||
|
||||
OMIT 1 January MSG Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Cuti Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Cuti Tahun Baharu
|
||||
OMIT 7 July MSG Hari Ulang Tahun Perisytiharan Tapak Warisan Dunia
|
||||
REM Second Saturday in July ADDOMIT SCANFROM -28 MSG Hari Jadi Yang di-Pertua Negeri Pulau Pinang
|
||||
REM 13 July OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 7, 13))==0 || wkdaynum(date($Ty, 7, 13))==6] MSG Cuti Hari Jadi Yang di-Pertua Negeri Pulau Pinang
|
||||
REM 13 July OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 7, 13)), 0, 6)] MSG Cuti Hari Jadi Yang di-Pertua Negeri Pulau Pinang
|
||||
|
||||
@@ -11,5 +11,5 @@
|
||||
# also SYSINCLUDE holidays/my.rem
|
||||
|
||||
OMIT 1 January MSG Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Cuti Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Cuti Tahun Baharu
|
||||
REM First Friday in November ADDOMIT SCANFROM -28 MSG Hari Keputeraan Sultan Perak
|
||||
|
||||
@@ -11,4 +11,4 @@
|
||||
# also SYSINCLUDE holidays/my.rem
|
||||
|
||||
OMIT 17 May MSG Hari Ulang Tahun Keputeraan Raja Perlis
|
||||
REM 17 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 17))==0 || wkdaynum(date($Ty, 5, 17))==6] MSG Cuti Hari Ulang Tahun Keputeraan Raja Perlis
|
||||
REM 17 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 17)), 0, 6)] MSG Cuti Hari Ulang Tahun Keputeraan Raja Perlis
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
# also SYSINCLUDE holidays/my.rem
|
||||
|
||||
OMIT 1 January MSG Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Cuti Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Cuti Tahun Baharu
|
||||
OMIT 11 December MSG Hari Keputeraan Sultan Selangor
|
||||
REM 11 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 11))==0 || wkdaynum(date($Ty, 12, 11))==6] MSG Cuti Hari Keputeraan Sultan Selangor
|
||||
REM 11 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 11)), 0, 6)] MSG Cuti Hari Keputeraan Sultan Selangor
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
# also SYSINCLUDE holidays/my.rem
|
||||
|
||||
OMIT 4 March MSG Hari Ulang Tahun Pertabalan Sultan Terengganu
|
||||
REM 4 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 4))==0 || wkdaynum(date($Ty, 3, 4))==6] MSG Cuti Hari Ulang Tahun Pertabalan Sultan Terengganu
|
||||
REM 4 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 4)), 0, 6)] MSG Cuti Hari Ulang Tahun Pertabalan Sultan Terengganu
|
||||
OMIT 26 April MSG Hari Keputeraan Sultan Terengganu
|
||||
REM 26 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 26))==0 || wkdaynum(date($Ty, 4, 26))==6] MSG Cuti Hari Keputeraan Sultan Terengganu
|
||||
REM 26 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 4, 26)), 0, 6)] MSG Cuti Hari Keputeraan Sultan Terengganu
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# also SYSINCLUDE holidays/my.rem
|
||||
|
||||
OMIT 1 January MSG Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Cuti Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Cuti Tahun Baharu
|
||||
OMIT [easterdate($Uy)-2] MSG Good Friday
|
||||
OMIT 30 May MSG Pesta Kaamatan
|
||||
OMIT 31 May MSG Pesta Kaamatan
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
# also SYSINCLUDE holidays/my.rem
|
||||
|
||||
OMIT 1 January MSG Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Cuti Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Cuti Tahun Baharu
|
||||
OMIT [easterdate($Uy)-2] MSG Good Friday
|
||||
OMIT 1 June MSG Perayaan Hari Gawai Dayak
|
||||
REM 1 June OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 6, 1))==0 || wkdaynum(date($Ty, 6, 1))==6] MSG Cuti Perayaan Hari Gawai Dayak
|
||||
REM 1 June OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 6, 1)), 0, 6)] MSG Cuti Perayaan Hari Gawai Dayak
|
||||
OMIT 2 June MSG Perayaan Hari Gawai Dayak
|
||||
REM 2 June OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 6, 2))==0 || wkdaynum(date($Ty, 6, 2))==6] MSG Cuti Perayaan Hari Gawai Dayak
|
||||
REM 2 June OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 6, 2)), 0, 6)] MSG Cuti Perayaan Hari Gawai Dayak
|
||||
OMIT 22 July MSG Hari Kemerdekaan Sarawak
|
||||
REM 22 July OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 7, 22))==0 || wkdaynum(date($Ty, 7, 22))==6] MSG Cuti Hari Kemerdekaan Sarawak
|
||||
REM 22 July OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 7, 22)), 0, 6)] MSG Cuti Hari Kemerdekaan Sarawak
|
||||
REM Second Saturday in October ADDOMIT SCANFROM -28 MSG Hari Jadi Yang di-Pertua Negeri Sarawak
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
# also SYSINCLUDE holidays/my.rem
|
||||
|
||||
OMIT 1 January MSG Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Cuti Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Cuti Tahun Baharu
|
||||
OMIT 1 February MSG Hari Wilayah Persekutuan
|
||||
REM 1 February OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 2, 1))==0 || wkdaynum(date($Ty, 2, 1))==6] MSG Cuti Hari Wilayah Persekutuan
|
||||
REM 1 February OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 2, 1)), 0, 6)] MSG Cuti Hari Wilayah Persekutuan
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
# also SYSINCLUDE holidays/my.rem
|
||||
|
||||
OMIT 1 January MSG Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Cuti Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Cuti Tahun Baharu
|
||||
OMIT 1 February MSG Hari Wilayah Persekutuan
|
||||
REM 1 February OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 2, 1))==0 || wkdaynum(date($Ty, 2, 1))==6] MSG Cuti Hari Wilayah Persekutuan
|
||||
REM 1 February OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 2, 1)), 0, 6)] MSG Cuti Hari Wilayah Persekutuan
|
||||
OMIT 30 May MSG Pesta Kaamatan
|
||||
OMIT 31 May MSG Pesta Kaamatan
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
# also SYSINCLUDE holidays/my.rem
|
||||
|
||||
OMIT 1 January MSG Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Cuti Tahun Baharu
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Cuti Tahun Baharu
|
||||
OMIT 1 February MSG Hari Wilayah Persekutuan
|
||||
REM 1 February OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 2, 1))==0 || wkdaynum(date($Ty, 2, 1))==6] MSG Cuti Hari Wilayah Persekutuan
|
||||
REM 1 February OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 2, 1)), 0, 6)] MSG Cuti Hari Wilayah Persekutuan
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
# See important caveats in the README file in this directory.
|
||||
|
||||
OMIT 1 January MSG New Year's Day
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG New Year's Day (observed)
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG New Year's Day (observed)
|
||||
OMIT [easterdate($Uy)-2] MSG Good Friday
|
||||
OMIT [easterdate($Uy)+1] MSG Easter Monday
|
||||
OMIT 1 May MSG Workers' Day
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 1))==0 || wkdaynum(date($Ty, 5, 1))==6] MSG Workers' Day (observed)
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 1)), 0, 6)] MSG Workers' Day (observed)
|
||||
OMIT 12 June MSG Democracy Day
|
||||
REM 12 June OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 6, 12))==0 || wkdaynum(date($Ty, 6, 12))==6] MSG Democracy Day (observed)
|
||||
REM 12 June OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 6, 12)), 0, 6)] MSG Democracy Day (observed)
|
||||
OMIT 1 October MSG Independence Day
|
||||
REM 1 October OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 10, 1))==0 || wkdaynum(date($Ty, 10, 1))==6] MSG Independence Day (observed)
|
||||
REM 1 October OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 10, 1)), 0, 6)] MSG Independence Day (observed)
|
||||
OMIT 25 December MSG Christmas Day
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 25))==0 || wkdaynum(date($Ty, 12, 25))==6] MSG Christmas Day (observed)
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 25)), 0, 6)] MSG Christmas Day (observed)
|
||||
OMIT 26 December MSG Boxing Day
|
||||
REM 26 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 26))==0 || wkdaynum(date($Ty, 12, 26))==6] MSG Boxing Day (observed)
|
||||
REM 26 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 26)), 0, 6)] MSG Boxing Day (observed)
|
||||
|
||||
@@ -20,7 +20,6 @@ OMIT 26 December MSG Tweede Kerstdag
|
||||
|
||||
# Optional holidays
|
||||
REM [easterdate($Uy)-2] MSG Goede Vrijdag
|
||||
|
||||
# Bevrijdingsdag is a holiday every 5th year.
|
||||
# Hence the two reminders below
|
||||
REM 5 May SATISFY [$Ty % 5 != 0] MSG Bevrijdingsdag
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
# See important caveats in the README file in this directory.
|
||||
|
||||
OMIT 1 January MSG New Year's Day
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG New Year's Day (observed)
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG New Year's Day (observed)
|
||||
OMIT [easterdate($Uy)-2] MSG Good Friday
|
||||
OMIT 1 May MSG Labour Day
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 1))==0 || wkdaynum(date($Ty, 5, 1))==6] MSG Labour Day (observed)
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 1)), 0, 6)] MSG Labour Day (observed)
|
||||
OMIT 9 August MSG National Day
|
||||
REM 9 August OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 8, 9))==0 || wkdaynum(date($Ty, 8, 9))==6] MSG National Day (observed)
|
||||
REM 9 August OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 8, 9)), 0, 6)] MSG National Day (observed)
|
||||
OMIT 25 December MSG Christmas Day
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 25))==0 || wkdaynum(date($Ty, 12, 25))==6] MSG Christmas Day (observed)
|
||||
REM 25 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 25)), 0, 6)] MSG Christmas Day (observed)
|
||||
|
||||
@@ -15,7 +15,7 @@ OMIT 6 April MSG วันจักรี
|
||||
REM 7 April ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 6)) == 0] MSG ชดเชยวันจักรี
|
||||
REM 8 April ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 6)) == 6] MSG ชดเชยวันจักรี
|
||||
OMIT 13 April MSG วันสงกรานต์
|
||||
REM 13 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 13))==0 || wkdaynum(date($Ty, 4, 13))==6] MSG ชดเชยวันสงกรานต์
|
||||
REM 13 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 4, 13)), 0, 6)] MSG ชดเชยวันสงกรานต์
|
||||
OMIT 14 April MSG วันสงกรานต์
|
||||
OMIT 15 April MSG วันสงกรานต์
|
||||
OMIT 1 May MSG วันแรงงานแห่งชาติ
|
||||
|
||||
@@ -6,21 +6,21 @@
|
||||
# See important caveats in the README file in this directory.
|
||||
|
||||
OMIT 1 January MSG 中華民國開國紀念日
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG 中華民國開國紀念日(慶祝)
|
||||
REM 1 January OMIT SAT SUN BEFORE ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG 中華民國開國紀念日(慶祝)
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG 中華民國開國紀念日(慶祝)
|
||||
REM 1 January OMIT SAT SUN BEFORE ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG 中華民國開國紀念日(慶祝)
|
||||
OMIT 28 February MSG 和平紀念日
|
||||
REM 28 February OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 2, 28))==0 || wkdaynum(date($Ty, 2, 28))==6] MSG 和平紀念日(慶祝)
|
||||
REM 28 February OMIT SAT SUN BEFORE ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 2, 28))==0 || wkdaynum(date($Ty, 2, 28))==6] MSG 和平紀念日(慶祝)
|
||||
REM 28 February OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 2, 28)), 0, 6)] MSG 和平紀念日(慶祝)
|
||||
REM 28 February OMIT SAT SUN BEFORE ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 2, 28)), 0, 6)] MSG 和平紀念日(慶祝)
|
||||
REM 2 April ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 4)) == 0] MSG 兒童節(慶祝)
|
||||
REM 3 April ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 4)) == 2] MSG 兒童節(慶祝)
|
||||
REM 3 April ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 4)) == 3] MSG 兒童節(慶祝)
|
||||
REM 3 April ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 4)) == 5] MSG 兒童節(慶祝)
|
||||
REM 3 April ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 4)) == 6] MSG 兒童節(慶祝)
|
||||
OMIT 4 April MSG 兒童節
|
||||
REM 4 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 4))==0 || wkdaynum(date($Ty, 4, 4))==6] MSG 清明節(慶祝)
|
||||
REM 4 April OMIT SAT SUN BEFORE ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 4))==0 || wkdaynum(date($Ty, 4, 4))==6] MSG 清明節(慶祝)
|
||||
REM 4 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 4, 4)), 0, 6)] MSG 清明節(慶祝)
|
||||
REM 4 April OMIT SAT SUN BEFORE ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 4, 4)), 0, 6)] MSG 清明節(慶祝)
|
||||
REM 5 April ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 4)) == 1] MSG 兒童節(慶祝)
|
||||
REM 5 April ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 4)) == 4] MSG 兒童節(慶祝)
|
||||
OMIT 10 October MSG 中華民國國慶日
|
||||
REM 10 October OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 10, 10))==0 || wkdaynum(date($Ty, 10, 10))==6] MSG 中華民國國慶日(慶祝)
|
||||
REM 10 October OMIT SAT SUN BEFORE ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 10, 10))==0 || wkdaynum(date($Ty, 10, 10))==6] MSG 中華民國國慶日(慶祝)
|
||||
REM 10 October OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 10, 10)), 0, 6)] MSG 中華民國國慶日(慶祝)
|
||||
REM 10 October OMIT SAT SUN BEFORE ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 10, 10)), 0, 6)] MSG 中華民國國慶日(慶祝)
|
||||
|
||||
@@ -13,6 +13,6 @@
|
||||
REM Fourth Monday in April ADDOMIT SCANFROM -28 MSG State Holiday
|
||||
REM Second Monday in October ADDOMIT SCANFROM -28 MSG Columbus Day
|
||||
REM Friday 23 November ADDOMIT SCANFROM -28 MSG State Holiday
|
||||
REM 23 December ADDOMIT SCANFROM -28 SATISFY [$TW == 4 || $Tw == 5] MSG Washington's Birthday
|
||||
REM 24 December ADDOMIT SCANFROM -28 SATISFY [$Tw == 1 || $Tw == 2 || $Tw == 4] MSG Washington's Birthday
|
||||
REM 26 December ADDOMIT SCANFROM -28 SATISFY [$Tw == 2 || $Tw == 5] MSG Washington's Birthday
|
||||
REM 23 December ADDOMIT SCANFROM -28 SATISFY [isany($Tw, 5, 4)] MSG Washington's Birthday
|
||||
REM 24 December ADDOMIT SCANFROM -28 SATISFY [isany($Tw, 1, 2, 4)] MSG Washington's Birthday
|
||||
REM 26 December ADDOMIT SCANFROM -28 SATISFY [isany($Tw, 2, 5)] MSG Washington's Birthday
|
||||
|
||||
@@ -14,6 +14,6 @@ OMIT [easterdate($Uy)-2] MSG Good Friday
|
||||
REM Tuesday 2 May ADDOMIT SCANFROM -28 MSG Primary Election Day
|
||||
REM Second Monday in October ADDOMIT SCANFROM -28 MSG Columbus Day
|
||||
REM Friday 23 November ADDOMIT SCANFROM -28 MSG Lincoln's Birthday
|
||||
REM 23 December ADDOMIT SCANFROM -28 SATISFY [$TW == 4 || $Tw == 5] MSG Washington's Birthday
|
||||
REM 24 December ADDOMIT SCANFROM -28 SATISFY [$Tw == 1 || $Tw == 2 || $Tw == 4] MSG Washington's Birthday
|
||||
REM 26 December ADDOMIT SCANFROM -28 SATISFY [$Tw == 2 || $Tw == 5] MSG Washington's Birthday
|
||||
REM 23 December ADDOMIT SCANFROM -28 SATISFY [isany($Tw, 5, 4)] MSG Washington's Birthday
|
||||
REM 24 December ADDOMIT SCANFROM -28 SATISFY [isany($Tw, 1, 2, 4)] MSG Washington's Birthday
|
||||
REM 26 December ADDOMIT SCANFROM -28 SATISFY [isany($Tw, 2, 5)] MSG Washington's Birthday
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
# See important caveats in the README file in this directory.
|
||||
|
||||
OMIT 1 January MSG Yangi yil
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Yangi yil (ko‘chirilgan)
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Yangi yil (ko‘chirilgan)
|
||||
OMIT 8 March MSG Xotin-qizlar kuni
|
||||
REM 8 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 8))==0 || wkdaynum(date($Ty, 3, 8))==6] MSG Xotin-qizlar kuni (ko‘chirilgan)
|
||||
REM 8 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 8)), 0, 6)] MSG Xotin-qizlar kuni (ko‘chirilgan)
|
||||
OMIT 21 March MSG Navro‘z bayrami
|
||||
REM 21 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 3, 21))==0 || wkdaynum(date($Ty, 3, 21))==6] MSG Navro‘z bayrami (ko‘chirilgan)
|
||||
REM 21 March OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 3, 21)), 0, 6)] MSG Navro‘z bayrami (ko‘chirilgan)
|
||||
OMIT 9 May MSG Xotira va qadrlash kuni
|
||||
REM 9 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 9))==0 || wkdaynum(date($Ty, 5, 9))==6] MSG Xotira va qadrlash kuni (ko‘chirilgan)
|
||||
REM 9 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 9)), 0, 6)] MSG Xotira va qadrlash kuni (ko‘chirilgan)
|
||||
OMIT 1 September MSG Mustaqillik kuni
|
||||
REM 1 September OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 9, 1))==0 || wkdaynum(date($Ty, 9, 1))==6] MSG Mustaqillik kuni (ko‘chirilgan)
|
||||
REM 1 September OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 9, 1)), 0, 6)] MSG Mustaqillik kuni (ko‘chirilgan)
|
||||
OMIT 1 October MSG O‘qituvchi va murabbiylar kuni
|
||||
REM 1 October OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 10, 1))==0 || wkdaynum(date($Ty, 10, 1))==6] MSG O‘qituvchi va murabbiylar kuni (ko‘chirilgan)
|
||||
REM 1 October OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 10, 1)), 0, 6)] MSG O‘qituvchi va murabbiylar kuni (ko‘chirilgan)
|
||||
OMIT 8 December MSG O‘zbekiston Respublikasi Konstitutsiyasi kuni
|
||||
REM 8 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 12, 8))==0 || wkdaynum(date($Ty, 12, 8))==6] MSG O‘zbekiston Respublikasi Konstitutsiyasi kuni (ko‘chirilgan)
|
||||
REM 8 December OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 12, 8)), 0, 6)] MSG O‘zbekiston Respublikasi Konstitutsiyasi kuni (ko‘chirilgan)
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
# See important caveats in the README file in this directory.
|
||||
|
||||
OMIT 1 January MSG Tết Dương lịch
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 1, 1))==0 || wkdaynum(date($Ty, 1, 1))==6] MSG Tết Dương lịch (nghỉ bù)
|
||||
REM 1 January OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 1, 1)), 0, 6)] MSG Tết Dương lịch (nghỉ bù)
|
||||
OMIT 30 April MSG Ngày Chiến thắng
|
||||
REM 30 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 4, 30))==0 || wkdaynum(date($Ty, 4, 30))==6] MSG Ngày Chiến thắng (nghỉ bù)
|
||||
REM 30 April OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 4, 30)), 0, 6)] MSG Ngày Chiến thắng (nghỉ bù)
|
||||
OMIT 1 May MSG Ngày Quốc tế Lao động
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 5, 1))==0 || wkdaynum(date($Ty, 5, 1))==6] MSG Ngày Quốc tế Lao động (nghỉ bù)
|
||||
REM 1 September ADDOMIT SCANFROM -28 SATISFY [$Tw == 1 || $Tw == 2 || $Tw == 4 || $Tw == 5] MSG Quốc khánh
|
||||
REM 1 May OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 5, 1)), 0, 6)] MSG Ngày Quốc tế Lao động (nghỉ bù)
|
||||
REM 1 September ADDOMIT SCANFROM -28 SATISFY [isany($Tw, 1, 2, 4, 5)] MSG Quốc khánh
|
||||
OMIT 2 September MSG Quốc khánh
|
||||
REM 2 September OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [wkdaynum(date($Ty, 9, 2))==0 || wkdaynum(date($Ty, 9, 2))==6] MSG Quốc khánh (nghỉ bù)
|
||||
REM 3 September ADDOMIT SCANFROM -28 SATISFY [$Tw == 2 || $Tw == 5 || $Tw == 1] MSG Quốc khánh
|
||||
REM 2 September OMIT SAT SUN AFTER ADDOMIT SCANFROM -28 SATISFY [isany(wkdaynum(date($Ty, 9, 2)), 0, 6)] MSG Quốc khánh (nghỉ bù)
|
||||
REM 3 September ADDOMIT SCANFROM -28 SATISFY [isany($Tw, 2, 5, 1)] MSG Quốc khánh
|
||||
|
||||
@@ -1,28 +1,32 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
if !defined("__autolang__")
|
||||
SET __autolang__ 1
|
||||
PRESERVE __autolang__
|
||||
SET autolang getenv("REMIND_LANG")
|
||||
if defined("__autolang__")
|
||||
RETURN
|
||||
endif
|
||||
|
||||
IF autolang == ""
|
||||
SET autolang getenv("LC_ALL")
|
||||
ENDIF
|
||||
IF autolang == ""
|
||||
SET autolang getenv("LANGUAGE")
|
||||
ENDIF
|
||||
IF autolang == ""
|
||||
SET autolang getenv("LANG")
|
||||
ENDIF
|
||||
SET __autolang__ 1
|
||||
PRESERVE __autolang__
|
||||
|
||||
IF autolang != ""
|
||||
IF access($SysInclude + "/lang/" + lower(substr(autolang, 1, 5)) + ".rem", "r") == 0
|
||||
SYSINCLUDE lang/[lower(substr(autolang, 1, 5))].rem
|
||||
ELSE
|
||||
IF access($SysInclude + "/lang/" + lower(substr(autolang, 1, 2)) + ".rem", "r") == 0
|
||||
SYSINCLUDE lang/[lower(substr(autolang, 1, 2))].rem
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
UNSET autolang
|
||||
PUSH-VARS autolang
|
||||
SET autolang getenv("REMIND_LANG")
|
||||
|
||||
IF autolang == ""
|
||||
SET autolang getenv("LC_ALL")
|
||||
ENDIF
|
||||
IF autolang == ""
|
||||
SET autolang getenv("LANGUAGE")
|
||||
ENDIF
|
||||
IF autolang == ""
|
||||
SET autolang getenv("LANG")
|
||||
ENDIF
|
||||
|
||||
IF autolang != ""
|
||||
IF access($SysInclude + "/lang/" + lower(substr(autolang, 1, 5)) + ".rem", "r") == 0
|
||||
SYSINCLUDE lang/[lower(substr(autolang, 1, 5))].rem
|
||||
ELSE
|
||||
IF access($SysInclude + "/lang/" + lower(substr(autolang, 1, 2)) + ".rem", "r") == 0
|
||||
SYSINCLUDE lang/[lower(substr(autolang, 1, 2))].rem
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
POP-VARS
|
||||
|
||||
|
||||
@@ -28,7 +28,11 @@ SET $December "desembre"
|
||||
|
||||
SET $Today "avui"
|
||||
SET $Tomorrow "demà"
|
||||
FSET subst_bx(a,d,t) iif(d==today()+2, "demà passat", "d'aquí " + (d-today()) + " dies")
|
||||
TRANSLATE "yesterday" "ahir"
|
||||
TRANSLATE "are" "són"
|
||||
TRANSLATE "were" "eren"
|
||||
|
||||
FSET subst_bx(a,d,t) iif(d==today()+2, "demà passat", d >= today(), "d'aquí " + (d-today()) + " dies", "fa " + (today()-d) + " dies")
|
||||
|
||||
# 1 d'abril vs 1 de maig.
|
||||
FSET subst_sx(a,d,t) iif(isany(substr(mon(d), 1, 1), "a", "o") , "d'", "de")
|
||||
|
||||
@@ -29,6 +29,10 @@ SET $December "December"
|
||||
SET $Today "i dag"
|
||||
SET $Tomorrow "i morgen"
|
||||
|
||||
TRANSLATE "yesterday" "i går"
|
||||
TRANSLATE "are" "er"
|
||||
TRANSLATE "were" "var"
|
||||
|
||||
BANNER Påmindelse for %w, %d. %m, %y%o:
|
||||
|
||||
SET $Am "am"
|
||||
@@ -51,13 +55,14 @@ SET $Mplu "ter"
|
||||
|
||||
FSET subst_ampm(h) iif(h<5, " om natten", h < 12, " om formiddagen", h < 18, " om eftermiddagen", " om aftenen")
|
||||
FSET subst_ordinal(d) "."
|
||||
FSET ordx(n) n + "."
|
||||
|
||||
FSET subst_p(alt, d, t) iif(d==today()+1, "", "e")
|
||||
FSET zeropad(s, len) pad(s, "0", len)
|
||||
FSET subst_a_alt(d) wkday(d) + ", den " + day(d) + ". " + mon(d) + " " + year(d)
|
||||
FSET subst_ax(alt, d, t) iif(alt, subst_a_alt(d), $On + " " + subst_a_alt(d))
|
||||
|
||||
FSET subst_bx(a, d, t) "om " + (d-today()) + " dage"
|
||||
FSET subst_bx(a, d, t) iif(d >= today(), "om " + (d-today()) + " dage", "for " + (today()-d) + " dage siden")
|
||||
|
||||
FSET subst_ex(alt, d, t) "den " + zeropad(day(d), 2) + $DateSep + zeropad(monnum(d), 2) + $DateSep + zeropad(year(d), 4)
|
||||
FSET subst_fx(alt, d, t) "den " + zeropad(monnum(d), 2) + $DateSep + zeropad(day(d), 2) + $DateSep + zeropad(year(d), 4)
|
||||
|
||||
@@ -31,6 +31,10 @@ SET $December "Dezember"
|
||||
SET $Today "heute"
|
||||
SET $Tomorrow "morgen"
|
||||
|
||||
TRANSLATE "yesterday" "gestern"
|
||||
TRANSLATE "are" "sind"
|
||||
TRANSLATE "were" "waren"
|
||||
|
||||
# Banner
|
||||
BANNER Termine für %w, den %d. %m %y%o:
|
||||
|
||||
@@ -51,11 +55,12 @@ SET $Fromnow "von heute"
|
||||
|
||||
FSET subst_ampm(h) iif(h<5, " nachts", h<12, " vormittags", h<=17, " nachmittags", " abends")
|
||||
FSET subst_ordinal(d) "."
|
||||
FSET ordx(n) n + "."
|
||||
|
||||
FSET subst_a_alt(d) wkday(d) + ", den " + day(d) + ". " + mon(d) + " " + year(d)
|
||||
FSET subst_ax(alt, d, t) iif(alt, subst_a_alt(d), $On + " " + subst_a_alt(d))
|
||||
|
||||
FSET subst_bx(a, d, t) "in " + (d-today()) + " Tagen"
|
||||
FSET subst_bx(a, d, t) iif(d >= today(), "in " + (d-today()) + " Tagen", "vor " + (today()-d) + " Tagen")
|
||||
|
||||
FSET subst_g_alt(d) wkday(d) + ", den " + day(d) + ". " + mon(d)
|
||||
FSET subst_gx(alt, d, t) iif(alt, subst_g_alt(d), $On + " " + subst_g_alt(d))
|
||||
|
||||
@@ -29,6 +29,10 @@ SET $December "Diciembre"
|
||||
SET $Today "hoy"
|
||||
SET $Tomorrow "mañana"
|
||||
|
||||
TRANSLATE "yesterday" "ayer"
|
||||
TRANSLATE "are" "son"
|
||||
TRANSLATE "were" "eran"
|
||||
|
||||
BANNER Agenda para el %w, %d%s %m, %y%o:
|
||||
|
||||
SET $Am "am"
|
||||
@@ -47,4 +51,4 @@ SET $And "y"
|
||||
SET $Hplu "s"
|
||||
SET $Mplu "s"
|
||||
|
||||
FSET subst_bx(a, d, t) "dentro de " + (d-today()) + " días"
|
||||
FSET subst_bx(a, d, t) iif(d >= today(), "dentro de " + (d-today()) + " días", "hace " + (today()-d) + " dias")
|
||||
|
||||
@@ -29,6 +29,10 @@ SET $December "joulukuu"
|
||||
SET $Today "tänään"
|
||||
SET $Tomorrow "huomenna"
|
||||
|
||||
TRANSLATE "yesterday" "eilen"
|
||||
TRANSLATE "are" "ovat"
|
||||
TRANSLATE "were" "olivat"
|
||||
|
||||
BANNER Viestit %wna %d. %mta %y%o:
|
||||
|
||||
SET $Am " ap."
|
||||
@@ -52,11 +56,12 @@ SET $Mplu "a"
|
||||
FSET zeropad(s, len) pad(s, "0", len)
|
||||
|
||||
FSET subst_ordinal(d) iif(d==1, ":senä", d==2, ":sena", (d%10)==2||(d%10)==3||(d%10)==6||(d%10)==8, ":ntena", ":ntenä")
|
||||
FSET ordx(d) d + subst_ordinal(d)
|
||||
|
||||
FSET subst_a_alt(d, o, p) wkday(d) + o + " " + day(d) + ". " + mon(d) + p + " " + year(d)
|
||||
FSET subst_ax(a, d, t) iif(a, subst_a_alt(d, "", ""), subst_a_alt(d, $On, "ta"))
|
||||
|
||||
FSET subst_bx(a, d, t) (d-today()) + " päivän kuluttua"
|
||||
FSET subst_bx(a, d, t) iif(d >= today(), (d-today()) + " päivän kuluttua", (today()-d) + " päivää sitten")
|
||||
FSET subst_cx(a, d, t) iif(a, wkday(d), wkday(d) + $On)
|
||||
|
||||
FSET subst_ex(a, d, t) zeropad(day(d), 2) + $DateSep + zeropad(monnum(d), 2) + $DateSep + zeropad(year(d), 4)
|
||||
|
||||
@@ -28,6 +28,11 @@ SET $December "décembre"
|
||||
|
||||
SET $Today "aujourd'hui"
|
||||
SET $Tomorrow "demain"
|
||||
|
||||
TRANSLATE "yesterday" "hier"
|
||||
TRANSLATE "are" "sont"
|
||||
TRANSLATE "were" "étaient"
|
||||
|
||||
SET $On "le"
|
||||
SET $At "à"
|
||||
SET $Now "maintenant"
|
||||
@@ -46,6 +51,7 @@ BANNER Rappels pour %w, %d%s %m, %y%o:
|
||||
|
||||
# Ordinal for a day (English would be "st", "nd", "rd", "th")
|
||||
FSET subst_ordinal(d) iif(d == 1, "er", "")
|
||||
FSET ordx(n) n + iif(n == 1, "er", "e")
|
||||
|
||||
# "%d hours", "%d minutes", or "%d hours and %d minutes"
|
||||
FSET subst_tdiff(hdiff, mdiff) iif(hdiff==0&&mdiff==0, $Now, \
|
||||
@@ -56,13 +62,14 @@ FSET subst_1(alt, date, time) iif(time == now(), "maintenant", \
|
||||
time > now(), "dans " + subst_tdiff((time-now())/60, (time-now())%60), \
|
||||
"il y a " + subst_tdiff ((now()-time)/60, (now()-time)%60))
|
||||
|
||||
FSET subst_bx(alt, date, time) "dans " + (date-today()) + " jours"
|
||||
FSET subst_bx(alt, date, time) iif(date >= today(), "dans " + (date-today()) + " jours", "il y a " + (today()-date) + " jours")
|
||||
FSET subst_j_alt(date) wkday(date) + ", " + day(date) + subst_ordinal(day(date)) + " " + mon(date) + ", " + year(date)
|
||||
FSET subst_jx(alt, date, time) iif(alt, subst_j_alt(date), $On + " " + subst_j_alt(date))
|
||||
|
||||
FSET subst_k_alt(date) wkday(date) + ", " + day(date) + subst_ordinal(day(date)) + " " + mon(date)
|
||||
FSET subst_kx(alt, date, time) iif(alt, subst_k_alt(date), $On + " " + subst_k_alt(date))
|
||||
|
||||
|
||||
TRANSLATE "Missing ']'" "']' manquant"
|
||||
TRANSLATE "Missing quote" "Apostrophe manquant"
|
||||
TRANSLATE "Expression too complex" "Expression trop complexe"
|
||||
|
||||
@@ -29,6 +29,10 @@ SET $December "Δεκέμβρ."
|
||||
SET $Today "σήμερα"
|
||||
SET $Tomorrow "αύριο"
|
||||
|
||||
TRANSLATE "yesterday" "εχθές"
|
||||
TRANSLATE "are" "είναι"
|
||||
TRANSLATE "were" "ήταν"
|
||||
|
||||
BANNER Υπενθυμίσεις: %w, %d %m, %y%o:
|
||||
|
||||
SET $Am "πμ"
|
||||
@@ -49,8 +53,9 @@ SET $And "και"
|
||||
SET $Hplu ""
|
||||
SET $Mplu ""
|
||||
|
||||
FSET subst_bx(a, d, t) "σε " + (d - today()) + " ημέρες"
|
||||
FSET subst_bx(a, d, t) iif(d >= today(), "σε " + (d - today()) + " ημέρες", "πριν από " + (today()-d) + " ημέρες")
|
||||
FSET subst_ordinal(d) "."
|
||||
FSET ordx(d) d + "."
|
||||
FSET subst_a_alt(d) wkday(d) + ", " + day(d) + ". " + mon(d) + " " + year(d)
|
||||
FSET subst_ax(alt, d, t) iif(alt, subst_a_alt(d), $On + " " + subst_a_alt(d))
|
||||
FSET subst_g_alt(d) wkday(d) + ", " + day(d) + ". " + mon(d)
|
||||
|
||||
@@ -29,6 +29,10 @@ SET $December "desember"
|
||||
SET $Today "í dag"
|
||||
SET $Tomorrow "á morgun"
|
||||
|
||||
TRANSLATE "yesterday" "í gær"
|
||||
TRANSLATE "are" "eru"
|
||||
TRANSLATE "were" "voru"
|
||||
|
||||
BANNER Minnisatriði: %w, %d%s %m, %y%o:
|
||||
|
||||
SET $Am "fh"
|
||||
@@ -49,5 +53,5 @@ SET $And "og"
|
||||
SET $Hplu "ir"
|
||||
SET $Mplu "r"
|
||||
|
||||
FSET subst_bx(a, d, t) "eftir " + (d - today()) + " daga"
|
||||
FSET subst_bx(a, d, t) iif(d >= today(), "eftir " + (d - today()) + " daga", "fyrir " + (today()-d) + " dögum")
|
||||
fset subst_p(a, d, t) iif(d == today()+1, "", "a")
|
||||
|
||||
@@ -29,6 +29,10 @@ SET $December "Dicembre"
|
||||
SET $Today "oggi"
|
||||
SET $Tomorrow "domani"
|
||||
|
||||
TRANSLATE "yesterday" "Ieri"
|
||||
TRANSLATE "are" "sono"
|
||||
TRANSLATE "were" "erano"
|
||||
|
||||
BANNER Promemoria per %w, %d %m %y%o:
|
||||
|
||||
SET $Am "am"
|
||||
@@ -48,7 +52,7 @@ SET $And "e"
|
||||
SET $Hplu "a"
|
||||
SET $Mplu "i"
|
||||
|
||||
FSET subst_bx(a, d, t) "fra " + (d-today()) + " giorni"
|
||||
FSET subst_bx(a, d, t) iif(d >= today(), "fra " + (d-today()) + " giorni", (today()-d) + " giorni fa")
|
||||
FSET subst_p(a, d, t) iif(d==today()+1, "o", "i")
|
||||
FSET subst_q(a, d, t) iif(d==today()+1, "a", "e")
|
||||
|
||||
|
||||
@@ -28,6 +28,9 @@ SET $December "december"
|
||||
|
||||
SET $Today "vandaag"
|
||||
SET $Tomorrow "morgen"
|
||||
TRANSLATE "yesterday" "gisteren"
|
||||
TRANSLATE "are" "zijn"
|
||||
TRANSLATE "were" "waren"
|
||||
|
||||
BANNER Herinneringen voor %w, %d %m, %y%o:
|
||||
|
||||
@@ -55,9 +58,12 @@ FSET subst_1b(hdiff, mdiff) iif(hdiff==0, subst_minutes(mdiff), mdiff==0, subst_
|
||||
FSET subst_minutes(m) iif(m==1, "1 minuut", m + " minuten")
|
||||
FSET subst_hours(h) iif(h==1, "1 uur", h + " uren")
|
||||
|
||||
FSET subst_bx(a, d, t) "over " + (d-today()) + " dagen"
|
||||
FSET subst_bx(a, d, t) iif (d == today()+2, "overmorgen", d+2 == today(), "eergisteren", d >= today(), "over " + (d-today()) + " dagen", (today()-d) + " dagen geleden")
|
||||
|
||||
FSET subst_s(a, d, t) iif(day(d) == 1 || day(d) == 8, "e", day(d) < 20, "de", "te")
|
||||
|
||||
FSET ordx(n) n + "e"
|
||||
|
||||
TRANSLATE "New Moon" "Nieuwe maan"
|
||||
TRANSLATE "First Quarter" "Eerste kwartier"
|
||||
TRANSLATE "Full Moon" "Volle maan"
|
||||
|
||||
@@ -29,6 +29,10 @@ SET $December "Desember"
|
||||
SET $Today "i dag"
|
||||
SET $Tomorrow "i morgen"
|
||||
|
||||
TRANSLATE "yesterday" "i går"
|
||||
TRANSLATE "are" "er"
|
||||
TRANSLATE "were" "var"
|
||||
|
||||
BANNER Påminnelse for %w, %d. %m, %y%o:
|
||||
|
||||
SET $Am "am"
|
||||
@@ -48,8 +52,9 @@ SET $And "og"
|
||||
SET $Hplu "r"
|
||||
SET $Mplu "er"
|
||||
|
||||
FSET subst_bx(a, d, t) "om " + (d-today()) + " dager"
|
||||
FSET subst_bx(a, d, t) iif(d >= today(), "om " + (d-today()) + " dager", "for " + (today()-d) + " dager siden")
|
||||
FSET subst_ordinal(d) "."
|
||||
FSET ordx(n) n + "."
|
||||
|
||||
FSET subst_ax(a, d, t) iif(a, subst_a_alt(d), $On + " " + subst_a_alt(d))
|
||||
FSET subst_a_alt(d) wkday(d) + ", den " + day(d) + ". " + mon(d) + " " + year(d)
|
||||
|
||||
@@ -29,6 +29,10 @@ SET $December "Grudzień"
|
||||
SET $Today "dzisiaj"
|
||||
SET $Tomorrow "jutro"
|
||||
|
||||
TRANSLATE "yesterday" "wczoraj"
|
||||
TRANSLATE "are" "są"
|
||||
TRANSLATE "were" "byli"
|
||||
|
||||
BANNER Terminarz na %w, %d. %m %y%o:
|
||||
|
||||
SET $Am "am"
|
||||
@@ -53,7 +57,7 @@ FSET subst_ordinal(d) ""
|
||||
|
||||
FSET subst_a_alt(d) wkday(d) + ", " + day(d) + ". " + mon(d) + " " + year(d)
|
||||
FSET subst_ax(a, d, t) iif(a, subst_a_alt(d), $On + " " + subst_a_alt(d))
|
||||
FSET subst_bx(a, d, t) "za " + (d-today()) + " dni"
|
||||
FSET subst_bx(a, d, t) iif(d >= today(), "za " + (d-today()) + " dni", (today()-d) + " dni temu")
|
||||
FSET subst_g_alt(d) wkday(d) + ", " + day(d) + ". " + mon(d)
|
||||
FSET subst_gx(a, d, t) iif(a, subst_g_alt(d), $On + " " + subst_g_alt(d))
|
||||
FSET subst_ux(a, d, t) subst_ax(a, d, t)
|
||||
|
||||
@@ -29,6 +29,10 @@ SET $December "dezembro"
|
||||
SET $Today "hoje"
|
||||
SET $Tomorrow "amanhã"
|
||||
|
||||
TRANSLATE "yesterday" "ontem"
|
||||
TRANSLATE "are" "são"
|
||||
TRANSLATE "were" "eram"
|
||||
|
||||
BANNER Avisos para %w, %d de %m de %y%o:
|
||||
|
||||
SET $Am "am"
|
||||
@@ -53,7 +57,7 @@ FSET subst_ordinal(d) ""
|
||||
FSET subst_on_wd(d) iif(wkdaynum(d) == 1 || wkdaynum(d) == 2, "no", "na")
|
||||
|
||||
FSET subst_a_alt(d) wkday(d) + ", " + day(d) + " de " + mon(d) + " de " + year(d)
|
||||
FSET subst_bx(a, d, t) "em " + (d-today()) + " dias"
|
||||
FSET subst_bx(a, d, t) iif(d >= today(), "em " + (d-today()) + " dias", "há " + (today()-d) + " dias")
|
||||
FSET subst_c_alt(d) wkday(d)
|
||||
FSET subst_g_alt(d) wkday(d) + ", " + day(d) + " " + mon(d)
|
||||
FSET subst_ax(a, d, t) iif(a, subst_a_alt(d), subst_on_wd(d) + " " + subst_a_alt(d))
|
||||
|
||||
@@ -28,6 +28,9 @@ SET $December "Decembrie"
|
||||
|
||||
SET $Today "astăzi"
|
||||
SET $Tomorrow "mâine"
|
||||
TRANSLATE "yesterday" "ieri"
|
||||
TRANSLATE "are" "sunt"
|
||||
TRANSLATE "were" "au fost"
|
||||
|
||||
BANNER Reamintiri pentru %w, %d %m %y%o:
|
||||
|
||||
@@ -49,7 +52,7 @@ SET $Mplu "e"
|
||||
SET $Hplu "e"
|
||||
SET $And "şi"
|
||||
|
||||
FSET subst_bx(a, d, t) "peste " + (d-today()) + " zile"
|
||||
FSET subst_bx(a, d, t) iif(d >= today(), "peste " + (d-today()) + " zile", "acume " + (today()-d) + " zile")
|
||||
|
||||
FSET subst_ampm(h) iif(h<4, " noaptea", h<12, " dimineaţa", h<18, " după-amiaza", " seara")
|
||||
FSET subst_ordinal(d) ""
|
||||
|
||||
5
include/utils/add-html-anchors.rem
Normal file
5
include/utils/add-html-anchors.rem
Normal file
@@ -0,0 +1,5 @@
|
||||
# Add HTML anchors to each day box.
|
||||
# This adds anchors: <a id="YYYY-MM-DD" name="YYYY-MM-DD"></a>
|
||||
# to each calendar box in an HTML calendar.
|
||||
|
||||
REM SPECIAL HTML <a id="[$T]" name="[$T]"></a>
|
||||
@@ -622,14 +622,23 @@ will be present. Its value will be a string of the form YYYY-MM-DD.
|
||||
If the reminder contains a ONCE keyword, this key will be present
|
||||
with a value of 1.
|
||||
.TP
|
||||
.B scanfrom \fIYYYY-MM-DD\fR
|
||||
.B scanfrom \fIYYYY-MM-DD\fR or \fBscanfrom\fR \fI-n\fR
|
||||
If the reminder contains a SCANFROM keyword, this key will be present
|
||||
and its value will be a string of the form YYYY-MM-DD.
|
||||
and its value will be a string of the form YYYY-MM-DD for an absolute
|
||||
SCANFROM, or a negative integer of the form -n for a relative scanfrom
|
||||
.TP
|
||||
.B from \fIYYYY-MM-DD\fR
|
||||
If the reminder contains a FROM keyword, this key will be present
|
||||
and its value will be a string of the form YYYY-MM-DD.
|
||||
.TP
|
||||
.B is_todo \fIflag\fR
|
||||
If the reminder is a TODO reminder, then \fIflag\fR will be the integer
|
||||
1. Otherwise, it will be the integer zero.
|
||||
.TP
|
||||
.B complete_through \fIYYYY-MM-DD\fR
|
||||
If the reminder has a COMPLETE-THROUGH date, then this key will be present
|
||||
and its value will be a string of the form YYYY-MM-DD.
|
||||
.TP
|
||||
.B priority \fIn\fR
|
||||
The priority of the reminder. Always present; if no PRIORITY keyword
|
||||
is specified, then a reminder has a default priority of 5000.
|
||||
|
||||
474
man/remind.1.in
474
man/remind.1.in
@@ -25,6 +25,29 @@ match the sort order used by the shell to expand "*.rem".
|
||||
until it encounters a line whose sole content is "__EOF__" (without the quotes.)
|
||||
Anything after the __EOF__ marker is completely ignored.
|
||||
|
||||
.SH MODES OF OPERATION
|
||||
\fBRemind\fR has four major modes of operation:
|
||||
.TP
|
||||
.B Agenda Mode
|
||||
Agenda mode is the default mode. In this mode, \fBRemind\fR prints
|
||||
today's reminders on standard output and exits. It may fork a background
|
||||
process to pop up queued reminders for later in the day.
|
||||
.TP
|
||||
.B Calendar Mode
|
||||
In this mode, \fBRemind\fR generates a calendar either by drawing it
|
||||
in the terminal or by sending data in computer-readable format to a back-end
|
||||
program that actually draws the calendar.
|
||||
.TP
|
||||
.B Daemon Mode
|
||||
This is a special mode of operation in which \fBRemind\fR is invoked
|
||||
by a front-end and runs as a daemon, accepting requests from
|
||||
the front-end and sending messages back to the front-end.
|
||||
\fBTkRemind\fR uses \fBRemind\fR in daemon mode.
|
||||
.TP
|
||||
.B Purge Mode
|
||||
In this mode, \fBRemind\fR produces no output, but creates new versions of
|
||||
its input files with all expired reminders commented out.
|
||||
|
||||
.SH OPTIONS
|
||||
\fBRemind\fR has a slew of options. If you're new to the program,
|
||||
ignore them for now and skip to the section "REMINDER FILES".
|
||||
@@ -209,7 +232,7 @@ format rather than the "simple calendar" format. This format is
|
||||
also documented in the \fBrem2ps(1)\fR man page. Finally, if you use
|
||||
three p's, as in \fB\-ppp\fR, then \fBRemind\fR uses a pure JSON
|
||||
format, again documented in \fBrem2ps(1)\fR. If you include a \fBq\fR
|
||||
letter with this option, then the normal calendar-mode substitution filter
|
||||
letter with this option, then the usual calendar-mode substitution filter
|
||||
is disabled and the %"...%" sequences are preserved in the output.
|
||||
.PP
|
||||
Note that to pass INFO strings to a back-end, you must use \fB\-pp\fR
|
||||
@@ -300,7 +323,7 @@ standard error stream) to the standard output stream.
|
||||
.B \-d\fR\fIchars\fR
|
||||
The \fB-d\fR option enables certain debugging modes. The \fIchars\fR
|
||||
specify which modes to enable:
|
||||
.RS 2
|
||||
.RS
|
||||
.TP
|
||||
.B e
|
||||
Echo all input lines
|
||||
@@ -328,6 +351,26 @@ tree. This is unlikely to be useful unless you are working on
|
||||
.B h
|
||||
Dump hash-table statistics on exit.
|
||||
.TP
|
||||
.B u
|
||||
When \fBRemind\fR exits, print a list of variables that were SET, but
|
||||
not subsequently used.
|
||||
.RS
|
||||
.PP
|
||||
Note that the \fBu\fR debugging flag may produce spurious warnings. For
|
||||
example, this sequence of commands:
|
||||
.PP
|
||||
.nf
|
||||
DEBUG +u
|
||||
SET a 1
|
||||
IFTRIG Wed
|
||||
MSG a = [a]
|
||||
ENDIF
|
||||
.fi
|
||||
.PP
|
||||
will issue a warning about \fBa\fR being unused unless it is run on a
|
||||
Wednesday.
|
||||
.RE
|
||||
.TP
|
||||
.B n
|
||||
Print debugging information about why \fBRemind\fR considers an expression
|
||||
to be "non-constant"
|
||||
@@ -489,11 +532,29 @@ information.
|
||||
\fBRemind\fR supports the following long options, which \fIare\fR
|
||||
case-sensitive:
|
||||
|
||||
.PP
|
||||
.TP
|
||||
.B \-\-version
|
||||
The \fB\-\-version\fR option causes \fBRemind\fR to print its version number
|
||||
to standard output and then exit.
|
||||
.TP
|
||||
.B \-\-hide-completed-todos
|
||||
In Calendar Mode, \fBRemind\fR normally shows all TODOs. If you supply
|
||||
this option, the it will not show TODOs that have been marked as
|
||||
completed.
|
||||
.TP
|
||||
.B \-\-only-todos
|
||||
Only issue TODO-type reminders.
|
||||
.TP
|
||||
.B \-\-only-events
|
||||
Do not issue TODO-type reminders.
|
||||
.TP
|
||||
.B \-\-json
|
||||
In Agenda Mode, output JSON instead of the normal text-mode output.
|
||||
\fB\-\-json\fR also disables sorting (the \fB-g\fR option) and
|
||||
disables queueing (the \fB-q\fR option). See the section
|
||||
"AGENDA MODE JSON OUTPUT" for more details. The \fB\-\-json\fR option
|
||||
is ignored in Calendar Mode.
|
||||
.TP
|
||||
.B \-\-print-errs
|
||||
The \fB\-\-print-errs\fR option causes \fBRemind\fR to print all
|
||||
possible error messages to standard output and then exit. The
|
||||
@@ -606,6 +667,8 @@ Its syntax is:
|
||||
[\fIback\fR]
|
||||
[\fIdelta\fR]
|
||||
[\fIrepeat\fR]
|
||||
[\fBTODO\fR]
|
||||
[\fBCOMPLETE-THROUGH\fR \fIcomplete_date\fR]
|
||||
[\fBPRIORITY\fR \fIprio\fR]
|
||||
[\fBSKIP\fR | \fBBEFORE\fR | \fBAFTER\fR]
|
||||
[\fBOMIT\fR \fIomit_list\fR]
|
||||
@@ -1757,8 +1820,16 @@ is replaced with "s" if the value produced by \fB%8\fR is not 1.
|
||||
is replaced with "s" if the value produced by \fB%7\fR is not 1.
|
||||
.TP
|
||||
.B %!
|
||||
is replaced with "is" if the current time is before the \fBAT\fR time,
|
||||
or "was" if it is after.
|
||||
is replaced with "is" if the current date and time is before the
|
||||
trigger date and the \fBAT\fR time, or "was" if it is after. The %!
|
||||
sequence may be used in a non-timed reminder, in which case only dates
|
||||
are compared.
|
||||
.TP
|
||||
.B %?
|
||||
is replaced with "are" if the current date and time is before the
|
||||
trigger date and the \fBAT\fR time, or "were" if it is after. The %!
|
||||
sequence may be used in a non-timed reminder, in which case only dates
|
||||
are compared.
|
||||
.TP
|
||||
.B %@
|
||||
is similar to \fB%2\fR but displays the current time.
|
||||
@@ -1797,15 +1868,20 @@ be preceded by an asterisk (for example, %*c) which causes the word
|
||||
omitted.
|
||||
.TP
|
||||
o
|
||||
Any of the substitutions dealing with time (0 through 9 and '!')
|
||||
produce undefined results if used in a reminder that does not have
|
||||
an \fBAT\fR keyword. Also, if a reminder has a \fIdelta\fR and may
|
||||
be triggered on several days, the time substitutions ignore the date. Thus,
|
||||
the \fB%1\fR substitution may report that a meeting is in 15 minutes, for
|
||||
example, even though it may only be in 2 days time, because a \fIdelta\fR has
|
||||
triggered the reminder. It is recommended that you use the time substitutions
|
||||
only in timed reminders with no \fIdelta\fR that are designed to be
|
||||
queued for timed activation.
|
||||
The ! and ? substitutions may be preceded by an asterisk (%*! or %*?),
|
||||
in which case the comparison is made between the trigger date and
|
||||
realtoday() instead of today().
|
||||
.TP
|
||||
o
|
||||
Any of the substitutions dealing with time (0 through 9) produce
|
||||
undefined results if used in a reminder that does not have an \fBAT\fR
|
||||
keyword. Also, if a reminder has a \fIdelta\fR and may be triggered
|
||||
on several days, the time substitutions ignore the date. Thus, the
|
||||
\fB%1\fR substitution may report that a meeting is in 15 minutes, for
|
||||
example, even though it may only be in 2 days time, because a
|
||||
\fIdelta\fR has triggered the reminder. It is recommended that you
|
||||
use the time substitutions only in timed reminders with no \fIdelta\fR
|
||||
that are designed to be queued for timed activation.
|
||||
.TP
|
||||
o
|
||||
Capital letters can be used in the substitution sequence, in which case
|
||||
@@ -1823,6 +1899,110 @@ normally scans for the first non-space character after a
|
||||
or
|
||||
.B RUN
|
||||
token.
|
||||
.PP
|
||||
.SH EVENTS AND TODOS
|
||||
.PP
|
||||
The \fBREM\fR command is normally used to create an \fIEVENT\fR. This
|
||||
is something that happens at a certain time, possibly recurring, and
|
||||
happens no matter what action you take. Events include things like
|
||||
birthdays, holidays, meetings, etc... pretty much everything that occurs
|
||||
on a particular schedule. Once the date of an event has passed,
|
||||
\fBRemind\fR will no longer remind you about the event.
|
||||
.PP
|
||||
A \fITODO\fR is different; it is a task that you have to complete by a
|
||||
specific date or date and time. If you don't explicitly mark a TODO
|
||||
as done, \fBRemind\fR will keep reminding you about it \fIeven past
|
||||
the due date.\fR.
|
||||
.PP
|
||||
To mark a \fBREM\fR as a TODO, simply include the TODO keyword. For example:
|
||||
.PP
|
||||
.nf
|
||||
REM TODO 15 August 2025 ++5 MSG Buy cat food %b.
|
||||
.fi
|
||||
.PP
|
||||
In Agenda Mode, \fBRemind\fR will start warning you on 10 Aug 2025 that
|
||||
you have to but cat food in 5 days' time, 4 days' time, etc...
|
||||
.PP
|
||||
However, on 16 Aug 2025, \fBRemind\fR will say "Buy cat food yesterday."
|
||||
and it will keep reminding you of your need to buy cat food until the end
|
||||
of time, or until you mark the TODO as done.
|
||||
.PP
|
||||
.SH MARKING TODOS AS DONE
|
||||
.PP
|
||||
There are two ways to mark a TODO as done. If the TODO is not recurring,
|
||||
the simplest way is simply to remove the TODO designator from the REM
|
||||
command (or indeed, to completely delete it.) The former keeps the
|
||||
reminder on the calendar while the latter completely removes it.
|
||||
.PP
|
||||
If a TODO is recurring, use the \fBCOMPLETE-THROUGH\fR clause to mark
|
||||
which recurrences have been completed. For example:
|
||||
.PP
|
||||
.nf
|
||||
REM TODO 30 April ++15 COMPLETE-THROUGH 2025-04-30 MSG File taxes
|
||||
.fi
|
||||
.PP
|
||||
Canadian income taxes must be filed every 30 April. The above command
|
||||
will remind you to pay taxes in 2026. If you don't update the
|
||||
COMPLETE-THROUGH date, then after 30 April 2026, \fBRemind\fR will
|
||||
keep reminding you until the end of time that my taxes were due on 30
|
||||
April 2026. To indicate that you've paid them, simply update the
|
||||
COMPLETE-THROUGH date to 2026-04-30 and then \fBRemind\fR will start
|
||||
reminding you of your 2027 taxes (starting 15 days before the due
|
||||
date.)
|
||||
.PP
|
||||
It is an error to specify COMPLETE-THROUGH without also specifying TODO.
|
||||
.PP
|
||||
.SH MORE DETAILS ABOUT TODOS
|
||||
.PP
|
||||
TODOs are treated specially only in Agenda Mode. In Calendar Mode,
|
||||
they appear in the calendar exactly as a normal event would.
|
||||
.PP
|
||||
TODOs are implemented internally by using the COMPLETE-THROUGH date
|
||||
plus one day as the starting point for \fBRemind\fR's date-scanning
|
||||
algorithm. If you have a recurring TODO without a COMPLETE-THROUGH
|
||||
clause, then \fBRemind\fR starts scanning from the beginning of time,
|
||||
which we all know is 1 January 1990. Consider this command:
|
||||
.PP
|
||||
.nf
|
||||
REM TODO Wed +7 MSG Take out the trash %a (%b)
|
||||
.fi
|
||||
.PP
|
||||
Running that command in Agenda Mode on 2025-08-13 yields the following output:
|
||||
.PP
|
||||
.nf
|
||||
Take out the trash on Wednesday, 3 January, 1990 (13006 days ago)
|
||||
.fi
|
||||
.PP
|
||||
\fBRemind\fR is very persistent about reminding you of tasks! If you take
|
||||
out the trash and mark it done:
|
||||
.PP
|
||||
.nf
|
||||
REM TODO Wed +7 COMPLETE-THROUGH 2025-08-13 MSG Take out the trash %a (%b)
|
||||
.fi
|
||||
.PP
|
||||
then you get this:
|
||||
.PP
|
||||
.nf
|
||||
Take out the trash on Wednesday, 20 August, 2025 (in 7 days' time)
|
||||
.fi
|
||||
.PP
|
||||
You can use \fBFROM\fR and \fBUNTIL\fR to limit the recurrence interval of
|
||||
tasks just as you can with events. For example, if you are house-sitting
|
||||
for the month of August and need to water plants every Wednesday:
|
||||
.PP
|
||||
.nf
|
||||
REM TODO Wed +7 FROM 2025-08-06 UNTIL 2025-08-27 MSG Plants %b.
|
||||
.fi
|
||||
.PP
|
||||
Running that command on 13 Aug yields: "Plants 7 days ago." because you
|
||||
have not told \fBRemind\fR that you completed the first watering. If you finish
|
||||
your duties and add a COMMPLETE-THROUGH date of 2025-08-27, then \fBRemind\fR
|
||||
never reminds you of that task in the future.
|
||||
.PP
|
||||
In Purge Mode, \fBRemind\fR will not purge TODOs unless they have been marked
|
||||
as complete. In the case of a recurring TODO, \fBRemind\fR will not purge
|
||||
it until the last occurrence is marked as complete.
|
||||
.PP
|
||||
.SH THE OMIT COMMAND
|
||||
.PP
|
||||
In addition to being a keyword in the \fBREM\fR command,
|
||||
@@ -2048,6 +2228,24 @@ relative pathnames under the system directory containing standard reminder
|
||||
scripts. For this version of \fBRemind\fR, the system directory is
|
||||
"@prefix@/share/remind".
|
||||
.PP
|
||||
.SH THE RETURN COMMAND
|
||||
.PP
|
||||
The \fBRETURN\fR command causes \fBRemind\fR to ignore the remaining
|
||||
contents of the file currently being processed. It can be used as a
|
||||
quick way to "exit" from an included file (though it also works at
|
||||
the top-level.)
|
||||
.PP
|
||||
Here is an example of how \fBRETURN\fR might be used:
|
||||
.PP
|
||||
.nf
|
||||
IF already_done
|
||||
RETURN
|
||||
ENDIF
|
||||
set already_done 1
|
||||
preserve already_done
|
||||
# Do expensive processing here
|
||||
.fi
|
||||
.PP
|
||||
.SH THE RUN COMMAND
|
||||
.PP
|
||||
If you include other files in your reminder script, you may not always
|
||||
@@ -2559,7 +2757,7 @@ For example, to delete all the variables declared above, use:
|
||||
UNSET a b mydir time date
|
||||
.fi
|
||||
.PP
|
||||
.B SYSTEM VARIABLES
|
||||
.SH SYSTEM VARIABLES
|
||||
.PP
|
||||
In addition to the regular user variables, \fBRemind\fR has several
|
||||
"system variables" that are used to query or control the operating
|
||||
@@ -3038,7 +3236,7 @@ Equivalent to \fBday(trigdate())\fR.
|
||||
.B $Tm (read-only)
|
||||
Equivalent to \fBmonnum(trigdate())\fR.
|
||||
.TP
|
||||
.B $Tu (read-only)
|
||||
.B $Tu (read-only, DATE type)
|
||||
Equivalent to \fBtriguntil()\fR.
|
||||
.TP
|
||||
.B $Tw (read-only)
|
||||
@@ -3105,7 +3303,43 @@ Note: If any of the calendar modes are in effect, then the
|
||||
values of $Daemon, $DontFork, $DontTrigAts, $DontQueue, $HushMode,
|
||||
$IgnoreOnce, $InfDelta, and $NextMode are not meaningful.
|
||||
.PP
|
||||
.B BUILT-IN FUNCTIONS
|
||||
.SH SAVING AND RESTORING VARIABLES
|
||||
.PP
|
||||
Just as with the OMIT context, you can save and restore the values of
|
||||
global variables and all (modifiable) system variables. For example:
|
||||
.PP
|
||||
.nf
|
||||
SET a 1
|
||||
UNSET b
|
||||
|
||||
# Save variables
|
||||
PUSH-VARS $DefaultColor $AddBlankLines a b
|
||||
|
||||
SET $DefaultColor "255 0 0"
|
||||
SET $AddBlankLines 0
|
||||
SET a 3
|
||||
SET b 4
|
||||
REM MSG Hello
|
||||
|
||||
# Restore all the variables we pushed earlier
|
||||
POP-VARS
|
||||
|
||||
# Now the changes to $DefaultColor and $AddBlankLines
|
||||
# have been undone. Additionally, a is restored to 1
|
||||
# and b is unset
|
||||
.fi
|
||||
.PP
|
||||
As you see from the example, PUSH-VARS takes a list of global variable
|
||||
names and/or system variable names. You can save the values of any
|
||||
\fImodifiable\fR system variables and any global variable. You can
|
||||
even push global variables that are not set.
|
||||
.PP
|
||||
The POP-VARS command restores the values of all system variables and
|
||||
global variables that were pushed by the most recent PUSH-VARS
|
||||
command. If you push an undefined global variable, then that variable
|
||||
is unset by the POP-VARS command.
|
||||
.PP
|
||||
.SH BUILT-IN FUNCTIONS
|
||||
.PP
|
||||
\fBRemind\fR has a plethora of built-in functions. The syntax for a function
|
||||
call is the same as in C - the function name, followed a comma-separated list
|
||||
@@ -3249,8 +3483,8 @@ calendar mode:
|
||||
FSET fg(r,g,b) ansicolor(r,g,b)
|
||||
FSET bg(r,g,b) ansicolor(r,g,b,1)
|
||||
ENDIF
|
||||
REM [fg(255,0,0)][bg(64,64,64)]Red on Gray[fg(-1,-1,-1)] in normal mode
|
||||
REM SPECIAL COLOR 0 255 0 Green in normal and calendar mode
|
||||
REM [fg(255,0,0)][bg(64,64,64)]Red on Gray[fg(-1,-1,-1)] in agenda mode
|
||||
REM SPECIAL COLOR 0 255 0 Green in agenda and calendar mode
|
||||
.fi
|
||||
.PP
|
||||
If you use the \fBansicolor\fR function, don't forget to reset the color
|
||||
@@ -3400,15 +3634,22 @@ characters occupy two columns. \fBcolumns(str)\fR takes all of that
|
||||
into account. Note that if \fBRemind\fR was compiled without Unicode support,
|
||||
\fBcolumns(str)\fR returns a type mismatch error.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B const(x_arg)
|
||||
Evaluates \fIarg\fR and returns it, but also ensures that the result
|
||||
is marked "constant". Use with caution; incorrect use could result
|
||||
in unwanted reminders being purged in Purge Mode. See also the section
|
||||
"NON-CONSTANT EXPRESSIONS"
|
||||
.TP
|
||||
.B current()
|
||||
Returns the current date and time as a DATETIME object. This may be the
|
||||
actual date and time, or may be the date and time supplied on the command line.
|
||||
.TP
|
||||
.B date(i_y, i_m, i_d)
|
||||
.B date(i_y, si_m, i_d)
|
||||
The \fBdate()\fR function returns a \fBDATE\fR object with the year,
|
||||
month and day components specified by \fIy\fR, \fIm\fR and \fId\fR.
|
||||
The month can be specified as an integer from 1 to 12, or a string
|
||||
that is the name of a month.
|
||||
.TP
|
||||
.B datepart(dq_datetime)
|
||||
Returns a \fBDATE\fR object representing the date portion of
|
||||
@@ -3425,11 +3666,13 @@ If you supply three arguments, the first
|
||||
must be a DATE and the second and third must be INTs. The second and
|
||||
third arguments are interpreted as hours and minutes and converted to a TIME.
|
||||
.PP
|
||||
If you supply four arguments, the first three must be INTs, interpreted
|
||||
as the year, month and day. The fourth argument must be a TIME.
|
||||
If you supply four arguments, they are interpreted as year, month, day
|
||||
and time. Year and day must be INTs. Month may be an INT from 0 to 12
|
||||
or a string naming a month. Time must be a TIME.
|
||||
.PP
|
||||
Finally, if you supply five arguments, they must all be INTs and are
|
||||
interpreted as year, month, day, hour and minute.
|
||||
interpreted as year, month, day, hour and minute. (Actually, month
|
||||
can also be a string that is the name of a month.)
|
||||
.RE
|
||||
.TP
|
||||
.B dawn([dq_date])
|
||||
@@ -3442,8 +3685,12 @@ This function takes a \fBDATE\fR or \fBDATETIME\fR as an argument, and
|
||||
returns an \fBINT\fR that is the day-of-month component of
|
||||
\fIdate\fR.
|
||||
.TP
|
||||
.B daysinmon(i_m, i_y)
|
||||
Returns the number of days in month \fIm\fR (1-12) of the year \fIy\fR.
|
||||
.B daysinmon(si_m, i_y)\fR or \fB daysinmon(dq_date)\fR
|
||||
Returns the number of days in month \fIm\fR (1-12) of the year
|
||||
\fIy\fR. The first argument can either be an integer from 1 to 12, or
|
||||
a string that is the name of a month. If given a single DATE or
|
||||
DATETIME argument, returns the number of days in the month containing
|
||||
the argument.
|
||||
.TP
|
||||
.B defined(s_var)
|
||||
Returns 1 if the variable named by \fIvar\fR is defined, or 0 if it is not.
|
||||
@@ -3534,6 +3781,10 @@ The result will be "F is 12" because the reference to \fIx\fR inside the
|
||||
\fBeval()\fR argument refers to the \fIglobal\fR variable \fIx\fR and
|
||||
not the function argument.
|
||||
.PP
|
||||
Note that for safety, \fBRUN\fR is disabled during the evaluation of
|
||||
\fBeval()\fR, which means you can't use the \fBshell()\fR function from
|
||||
within an \fBeval()\fR.
|
||||
.PP
|
||||
.RE
|
||||
.TP
|
||||
.B evaltrig(s_trigger [,dq_start])
|
||||
@@ -3745,10 +3996,20 @@ functions. It is available starting with version 03.00.07 of \fBRemind\fR.
|
||||
.B minute(tq_time)
|
||||
Returns the minute component of \fItime\fR.
|
||||
.TP
|
||||
.B mon(dqi_arg)
|
||||
.B mon(dqis_arg)
|
||||
If \fIarg\fR is of \fBDATE\fR or \fBDATETIME\fR type, returns a string
|
||||
that names the month component of the date. If \fIarg\fR is an
|
||||
\fBINT\fR from 1 to 12, returns a string that names the month.
|
||||
\fBINT\fR from 1 to 12, returns a string that names the month. If \fIarg\fR
|
||||
is a \fBSTRING\fR, returns the name of the month. This last case might
|
||||
sound silly, but for example:
|
||||
.RS
|
||||
.PP
|
||||
.nf
|
||||
mon("Mar")
|
||||
.fi
|
||||
.PP
|
||||
will return "March", the full name of the month.
|
||||
.RE
|
||||
.TP
|
||||
.B monnum(dq_date)\fR or \fBmonnum(s_str)\fR
|
||||
Returns an \fBINT\fR from 1 to 12, representing the month component of
|
||||
@@ -3995,6 +4256,13 @@ the actual time, or a time supplied on the command line.
|
||||
.B ord(i_num)
|
||||
Returns a string that is the ordinal number \fInum\fR. For example,
|
||||
\fBord(2)\fR returns "2nd", and \fBord(213)\fR returns "213th".
|
||||
.RS
|
||||
.PP
|
||||
In order to help with localization, if you define a function called
|
||||
\fBordx\fR that takes a single parameter, then calling
|
||||
\fBord\fR(\fIn\fR) invokes \fBordx\fR(\fIn\fR) and returns whatever
|
||||
it does.
|
||||
.RE
|
||||
.TP
|
||||
.B orthodoxeaster([dqi_arg])
|
||||
If \fIarg\fR is an \fBINT\fR, then returns the date of Orthodox Easter Sunday
|
||||
@@ -4566,7 +4834,9 @@ an error results.
|
||||
.PP
|
||||
However, if you supply a second argument, it is returned if the \fIvarname\fR
|
||||
is not defined. The expression value("XY", 0) will return 0 if XY is not
|
||||
defined, and the value of XY if it is defined.
|
||||
defined, and the value of XY if it is defined. Note that \fBvalue\fR
|
||||
evaluates the second argument lazily; it is \fInot\fR evaluated if
|
||||
\fIvarname\fR is defined.
|
||||
.RE
|
||||
.TP
|
||||
.B version()
|
||||
@@ -4615,7 +4885,7 @@ midnight, 1 January 1970 UTC. If the \fBtime_t\fR type is only
|
||||
19 January 2038 at 03:14:07 UTC.
|
||||
.PP
|
||||
To work around this limitation, \fBRemind\fR will "fold" years greater than 2037
|
||||
to a smaller year that begins on the same day and has the same numebr of
|
||||
to a smaller year that begins on the same day and has the same number of
|
||||
days. This results in a year that's very likely to have the same
|
||||
daylight saving rules as the original year, unless the rules have changed
|
||||
in the interim (in which case the rule change could not even be represented
|
||||
@@ -5023,29 +5293,69 @@ it is defined. However, if \fIfunc_a\fR exists, then it is renamed to
|
||||
was defined prior to the \fBFRENAME\fR command, then that old
|
||||
definition is lost.
|
||||
.PP
|
||||
\fBFRENAME\fR is useful if you want to save and restore the definition
|
||||
of a user-defined function. For example, you might want to define
|
||||
a \fBmsgprefix\fR function for a block of reminders, but not permanently
|
||||
overwrite any existing definition. You could do something like this:
|
||||
.PP
|
||||
.nf
|
||||
FRENAME msgprefix saved_msgprefix
|
||||
FSET msgprefix(x) "My new prefix: "
|
||||
INCLUDE block_of_reminders.rem
|
||||
FRENAME saved_msgprefix msgprefix
|
||||
.PP
|
||||
The file \fBblock_of_reminders.rem\fR would be executed with the
|
||||
\fBmsgprefix\fR function defined above. After the second FRENAME,
|
||||
\fBmsgprefix\fR would be restored to its previous definition if
|
||||
it had one, or simply unset if it was not previously defined.
|
||||
.PP
|
||||
If either argument to the \fBFRENAME\fR command is the name of a built-in
|
||||
function, the command fails with an error message and does nothing.
|
||||
.PP
|
||||
If you define a user-defined function and then later on redefine it,
|
||||
\fBRemind\fR will issue a warning. If you do not want this warning,
|
||||
then use \fBFUNSET\fR to remove the existing definition before you
|
||||
redefine the function.
|
||||
redefine the function. Alternatively, you can use a "-" token before
|
||||
the function name to suppress "redefined function" warnings, as in the
|
||||
following example:
|
||||
.PP
|
||||
.nf
|
||||
FSET - f(x) 2*x
|
||||
# You must have space before and after the "-"
|
||||
# This will NOT work:
|
||||
# FSET -f(x) 2*x
|
||||
.fi
|
||||
.PP
|
||||
to define a function and suppress any "redefined function" warning.
|
||||
.PP
|
||||
.SH SAVING AND RESTORING FUNCTIONS
|
||||
.PP
|
||||
Occasionally, it is useful to redefine a function for a specific block of
|
||||
reminders, but to restore its original definition at the end of that
|
||||
block. Just as with variables, functions can be pushed onto and popped
|
||||
off an internal stack. Here is an example:
|
||||
.PP
|
||||
.nf
|
||||
PUSH-FUNCS msgprefix
|
||||
FSET msgprefix(x) "My new prefix: "
|
||||
INCLUDE block_of_reminders.rem
|
||||
POP-FUNCS
|
||||
.fi
|
||||
.PP
|
||||
The file \fBblock_of_reminders.rem\fR would be executed with the
|
||||
\fBmsgprefix\fR function defined above. After the POP-FUNCS
|
||||
\fBmsgprefix\fR would be restored to its previous definition if
|
||||
it had one, or simply unset if it was not previously defined.
|
||||
.PP
|
||||
The command PUSH-FUNCS takes a space-separated list of function names.
|
||||
All of the named user-defined functions will be saved to an internal
|
||||
stack. You can even push names that are not defined as any function.
|
||||
.PP
|
||||
After a function name has been pushed, \fBRemind\fR will not issue a
|
||||
warning if you redefine it, because presumably the purpose of pushing
|
||||
it in the first place is to redefine it.
|
||||
.PP
|
||||
The command POP-FUNCS restores the definitions of all the user-defined
|
||||
functions in the corresponding PUSH-FUNCS command. If undefined functions
|
||||
were pushed onto the stack, then POP-FUNCS makes those functions undefined
|
||||
again. Here's one more example:
|
||||
.PP
|
||||
.nf
|
||||
FUNSET a
|
||||
FSET b(x) 2*x
|
||||
REM MSG [b(3)] # Outputs 6
|
||||
PUSH-FUNCS a b
|
||||
FSET a(x) 22*x
|
||||
FSET b(x) 3*x
|
||||
REM MSG [a(3)] [b(3)] # Outputs 66 9
|
||||
POP-FUNCS
|
||||
REM MSG [a(3)] # Undefined function "a"
|
||||
REM MSG [b(3)] # Outputs 6
|
||||
.fi
|
||||
.PP
|
||||
.SH PRECISE SCHEDULING
|
||||
.PP
|
||||
@@ -5335,7 +5645,7 @@ under program control. The format is:
|
||||
.PP
|
||||
\fBDEBUG\fR [+\fIflagson\fR] [\-\fIflagsoff\fR]
|
||||
.PP
|
||||
\fIFlagson\fR and \fIflagsoff\fR consist of strings of the characters "shextvlfqn"
|
||||
\fIFlagson\fR and \fIflagsoff\fR consist of strings of the characters "shextvlfqnu"
|
||||
that correspond to the debugging options discussed in the command-line
|
||||
options section. If preceded with a "+", the corresponding group of
|
||||
debugging options is switched on. Otherwise, they are switched off.
|
||||
@@ -5400,6 +5710,35 @@ streams used by \fBRemind\fR. This is not terribly useful to most
|
||||
people, but may be useful if you run \fBRemind\fR as a subprocess of
|
||||
another program, and want to use pipes for communication.
|
||||
.PP
|
||||
.SH AGENDA MODE JSON OUTPUT
|
||||
.PP
|
||||
If you supply the \fB\-\-json\fR argument, then Remind outputs JSON
|
||||
instead of the normal text output. The JSON output consists of
|
||||
a single JSON array of zero or more objects. There are three
|
||||
possible types of objects in the array:
|
||||
.TP
|
||||
.B banner
|
||||
The \fBbanner\fR object, if present, will be the first object in the array.
|
||||
There will be at most one \fBbanner\fR object. It contains a single
|
||||
key, \fBbanner\fR, whose value is the banner that \fBRemind\fR would normally
|
||||
print in Agenda Mode.
|
||||
.TP
|
||||
.B noreminders
|
||||
The \fBnoreminders\fR object, if present, will be the final object in the
|
||||
array. There will be at most one \fBnoreminders\fR object. It contains
|
||||
a single keym, \fBnoreminders\fR, whose value is the phrase "No reminders.",
|
||||
possibly localized into a different language.
|
||||
.TP
|
||||
.B event
|
||||
All other objects in the array are \fBevent\fR objects. They are JSON
|
||||
objects that contain all of the keys described in the \fBrem2ps\fR(1)
|
||||
man page section "CALENDAR ENTRIES". However, the \fBcalendar_body\fR,
|
||||
\fBplain_body\fR and \fBraw_body\fR keys will not be present.
|
||||
.PP
|
||||
JSON output can be used by a front-end to display an attractive list of
|
||||
reminders in Agenda Mode. The "show today's reminders" feature of
|
||||
\fBtkremind\fR uses the JSON output.
|
||||
.PP
|
||||
.SH CALENDAR MODE
|
||||
.PP
|
||||
If you supply the \fB\-c\fR, \fB\-s\fR or \fB\-p\fR
|
||||
@@ -5444,7 +5783,7 @@ example, consider the following:
|
||||
REM 6 Jan MSG %"Dianne's birthday%" is %b
|
||||
.fi
|
||||
.PP
|
||||
In the normal mode, \fBRemind\fR would print "Dianne's birthday is today"
|
||||
In agenda mode, \fBRemind\fR would print "Dianne's birthday is today"
|
||||
on 6 January. However, in the calendar mode, only the text "Dianne's birthday"
|
||||
is inserted into the box for 6 January.
|
||||
.PP
|
||||
@@ -5810,7 +6149,13 @@ Here are some examples that should make things clear:
|
||||
.PP
|
||||
Note that within the \fBIF\fR...\fBENDIF\fR scope, any assignments
|
||||
are non-constant because the code flow depends on today's date, which
|
||||
could change in subsequent \fBRemind\fR runs.
|
||||
could change in subsequent \fBRemind\fR runs. If you want to force
|
||||
a variable to be treated as constant, no matter what, then use the following
|
||||
just before you use the variable:
|
||||
.PP
|
||||
.nf
|
||||
SET var const(var)
|
||||
.fi
|
||||
.PP
|
||||
Variables initialized on the command-line with the \fB\-i\fR flag are
|
||||
\fIalways\fR considered to be non-constant.
|
||||
@@ -5918,7 +6263,7 @@ You can define two functions in your script called \fBmsgprefix()\fR
|
||||
and \fBmsgsuffix()\fR. They should each accept one argument, a number
|
||||
from 0 to 9999.
|
||||
.PP
|
||||
In normal mode, for \fBMSG\fR- and \fBMSF\fR-type reminders,
|
||||
In agenda mode, for \fBMSG\fR- and \fBMSF\fR-type reminders,
|
||||
the following sequence occurs when
|
||||
\fBRemind\fR triggers a reminder:
|
||||
.TP
|
||||
@@ -6443,8 +6788,8 @@ Calculations" by E. M. Reingold and Nachum Dershowitz.
|
||||
The \fBSPECIAL\fR keyword is used to transmit "out-of-band" information
|
||||
to \fBRemind\fR backends, such as \fBtkremind\fR or \fBRem2PS\fR.
|
||||
They are used only when piping data from a \fBremind \-p\fR line.
|
||||
(Note that the COLOR special is an exception; it downgrades to the
|
||||
equivalent of MSG in \fBRemind's\fR normal mode of operation.)
|
||||
(Note that the COLOR special is an exception; it works similarly
|
||||
to MSG when the \fB\-p\fR option is not supplied.)
|
||||
.PP
|
||||
The various \fBSPECIAL\fRs recognized are particular for each
|
||||
backend; however, there are four \fBSPECIAL\fRs that all backends
|
||||
@@ -6513,10 +6858,10 @@ Immediately following COLOR should be three decimal numbers ranging
|
||||
from 0 to 255 specifying red, green and blue intensities, respectively.
|
||||
The rest of the line is the text to put in the calendar.
|
||||
.PP
|
||||
The COLOR special is "doubly special", because in its normal operating
|
||||
mode, \fBremind\fR treats a COLOR special just like a MSG-type reminder.
|
||||
Also, if you invoke \fBRemind\fR with \fB\-@\fR[\fIn\fR], then it approximates
|
||||
SPECIAL COLOR reminders on your terminal.
|
||||
The COLOR special is "doubly special", because in agenda mode,
|
||||
\fBremind\fR treats a COLOR special just like a MSG-type reminder.
|
||||
Also, if you invoke \fBRemind\fR with \fB\-@\fR[\fIn\fR], then it
|
||||
approximates SPECIAL COLOR reminders on your terminal.
|
||||
.PP
|
||||
See also the documentation of the \fB$DefaultColor\fR system variable
|
||||
in the section "SYSTEM VARIABLES".
|
||||
@@ -6679,6 +7024,10 @@ the previous example could also be written like this:
|
||||
REM Mon AFTER MSG Hello
|
||||
.fi
|
||||
.PP
|
||||
A SCANFROM that specifies a full date is called an \fIabsolute SCANFROM\fR
|
||||
and a SCANFROM that specifies a negative number is called a
|
||||
\fIrelative SCANFROM\fR.
|
||||
.PP
|
||||
In general, use \fBSCANFROM\fR as shown for safe movable \fBOMITs\fR. The
|
||||
amount you should scan back by (7 days in the example above) depends on
|
||||
the number of possible consecutive \fBOMITted\fR days that may occur, and
|
||||
@@ -6725,12 +7074,13 @@ date of the scanning\fR that
|
||||
satisfies the trigger. In addition, there is one special case in which
|
||||
\fBtrigvalid()\fR returns 1 and \fBtrigdate()\fR returns a meaningful result:
|
||||
.PP
|
||||
If the \fBREM\fR or \fBIFTRIG\fR command did not contain an \fBUNTIL\fR
|
||||
clause, and contained all of the \fIday\fR, \fImonth\fR and \fIyear\fR
|
||||
components, then \fBRemind\fR will correctly compute a trigger date, even
|
||||
if it happens to be before the start of scanning.
|
||||
Note that this behaviour is not true for
|
||||
If the \fBREM\fR or \fBIFTRIG\fR command did not contain an
|
||||
\fBUNTIL\fR or \fBSATISFY\fR clause, and contained all of the
|
||||
\fIday\fR, \fImonth\fR and \fIyear\fR components, then \fBRemind\fR
|
||||
will correctly compute a trigger date, even if it happens to be before
|
||||
the start of scanning. Note that this behaviour is not true for
|
||||
versions of \fBRemind\fR prior to 03.00.01.
|
||||
|
||||
.SH FILES
|
||||
.PP
|
||||
The traditional location of your reminders file or directory is:
|
||||
|
||||
@@ -20,18 +20,16 @@ or the tkpng extension to handle PNG images.
|
||||
|
||||
.SH COMMAND-LINE OPTIONS
|
||||
\fBTkRemind\fR itself has no command-line options. However, it passes
|
||||
certain options on to \fBRemind\fR. The options it passes are
|
||||
\fB\-b\fR, \fB\-g\fR, \fB\-x\fR, \fB\-i\fR and \fB\-m\fR. See the
|
||||
\fBRemind\fR man page for details about the options. Note that
|
||||
\fBTkRemind\fR will respect the \fB\-m\fR and \fB\-b1\fR options and
|
||||
adjust its appearance accordingly.
|
||||
|
||||
any command-line argument starting with \fB\-\fR to \fBRemind\fR as an
|
||||
option. In addition, \fBTkRemind\fR will respect the \fB\-m\fR and
|
||||
\fB\-b1\fR options and adjust its appearance accordingly.
|
||||
.PP
|
||||
\fIRead_file\fR is the file from which \fBTkRemind\fR reads reminders.
|
||||
It is in standard \fBRemind\fR format. \fIWrite_file\fR is the file
|
||||
to which \fBTkRemind\fR writes reminders which you add using the GUI.
|
||||
If \fIRead_file\fR is omitted, it defaults to \fB$HOME/.reminders\fR.
|
||||
If \fIWrite_file\fR is omitted, it defaults to \fIRead_file\fR.
|
||||
|
||||
.PP
|
||||
You may wish to have a different \fIWrite_file\fR from \fIRead_file\fR if
|
||||
you want to collect all of \fBTkRemind\fR's reminders in one place. Suppose
|
||||
your main file is \fI$HOME/.reminders\fR and you want \fBTkRemind\fR to put
|
||||
@@ -96,10 +94,16 @@ The fourth control specifies which days \fBRemind\fR considers
|
||||
as part of the weekend. This can affect the interpretation of "weekday"
|
||||
in the second and third types of reminders.
|
||||
|
||||
The fifth control associates a time with the reminder.
|
||||
You can also specify advance notice, possibly repeating.
|
||||
The fifth group of controls associates a time and possible duration
|
||||
with the reminder. You can also specify advance notice, possibly
|
||||
repeating.
|
||||
|
||||
The sixth control specifies what \fBRemind\fR should do if a reminder
|
||||
The sixth control allows you to specify whether the reminder is a TODO,
|
||||
and if so, its completion date. Double-clicking in the "Complete through"
|
||||
field automatically fills in the date of the calendar entry. Otherwise,
|
||||
enter a possible completion date in the form YYYY-MM-DD.
|
||||
|
||||
The seventh control specifies what \fBRemind\fR should do if a reminder
|
||||
falls on a holiday or weekend.
|
||||
|
||||
Enter the body of the reminder into the \fBSummary:\fR text entry. If
|
||||
@@ -121,6 +125,16 @@ edit the reminder, thereby gaining access to advanced features of
|
||||
\fBRemind\fR. You can also use it simply to play around and discover
|
||||
\fBRemind\fR's idioms for expressing different types of reminders.
|
||||
|
||||
.SH SEEING A SINGLE DAY'S REMINDERS
|
||||
Right-click on any day number in the calendar to pop up a window with
|
||||
that day's reminders in Agenda Mode. You can left- or right-click the
|
||||
current date and time indicator at the bottom of the window to see today's
|
||||
reminders in Agenda Mode.
|
||||
|
||||
In the Agenda Mode display, hovering over a reminder will show ancillary
|
||||
information such as a Location, URL or Description. Clicking on a reminder
|
||||
will open an editor on the REM command that created the reminder.
|
||||
|
||||
.SH PRINTING
|
||||
To print the current month's calendar, click \fBPrint...\fR on the
|
||||
main calendar window. This brings up the print dialog. Printing
|
||||
|
||||
@@ -4,7 +4,7 @@ REM2HTML
|
||||
rem2html is a Perl script that transforms the output of `remind -pp
|
||||
...' to HTML. Type `perl rem2html --help' for usage information.
|
||||
|
||||
rem2html requires the Perl modules `JSON::Any' and `Getopt::Long'. It
|
||||
rem2html requires the Perl modules `JSON::MaybeXS' and `Getopt::Long'. It
|
||||
will not be installed unless you have those modules as well as Perl
|
||||
itself.
|
||||
|
||||
|
||||
@@ -265,6 +265,7 @@ while(1) {
|
||||
}
|
||||
my ($obj, $err) = Remind::PDF->create_from_stream(*STDIN,
|
||||
{color => 1,
|
||||
colour => 1,
|
||||
shade => 1,
|
||||
moon => 1,
|
||||
pango => 1,
|
||||
|
||||
@@ -517,7 +517,7 @@ sub render
|
||||
}
|
||||
}
|
||||
|
||||
if ($so_far > $settings->{height} - $settings->{margin_bottom}) {
|
||||
if ($so_far > $settings->{height} - $settings->{margin_bottom} + 1) {
|
||||
print STDERR "WARNING: overfull calendar box\n";
|
||||
}
|
||||
# The vertical lines
|
||||
@@ -583,7 +583,7 @@ sub draw_row
|
||||
$self->draw_day($cr, $settings, $so_far, $day, $col, $height);
|
||||
}
|
||||
|
||||
return $so_far + $height + $settings->{border_size};
|
||||
return $so_far + $height + $settings->{border_size} * 2;
|
||||
}
|
||||
|
||||
=head2 col_box_coordinates($so_far, $col, $height, $settings)
|
||||
|
||||
@@ -158,11 +158,6 @@ if {[catch {package require json}]} {
|
||||
missing_tcllib json
|
||||
}
|
||||
|
||||
if {$tcl_platform(platform) == "windows"} {
|
||||
tk_messageBox -message "Please do not port Remind to Windows" -icon error -type ok
|
||||
exit 1
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# GetRemindVersion
|
||||
# Arguments:
|
||||
@@ -317,6 +312,8 @@ set TodayDay [string trim [clock format $now -format %e]]
|
||||
set CurMonth $TodayMonth
|
||||
set CurYear $TodayYear
|
||||
|
||||
set DateOfEventBeingEdited ""
|
||||
|
||||
# Reminder option types and skip types
|
||||
set OptionType 1
|
||||
set SkipType 1
|
||||
@@ -364,8 +361,8 @@ set HighestTagSoFar 0
|
||||
# Check Remind version
|
||||
set ver [GetRemindVersion]
|
||||
|
||||
if {"$ver" < "04.03.03"} {
|
||||
tk_messageBox -message "This version of TkRemind requires Remind version 04.03.03 or newer; you have version $ver" -icon error -type ok
|
||||
if {"$ver" < "06.00.00"} {
|
||||
tk_messageBox -message "This version of TkRemind requires Remind version 06.00.00 or newer; you have version $ver" -icon error -type ok
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -447,7 +444,10 @@ proc Initialize {} {
|
||||
if {"[lindex $argv $i]" == "-b1"} {
|
||||
set TwentyFourHourMode 1
|
||||
}
|
||||
} else {
|
||||
} elseif { [regexp -- {-.*} [lindex $argv $i]]} {
|
||||
append CommandLine " [lindex $argv $i]"
|
||||
append PSCmd " [lindex $argv $i]"
|
||||
} else {
|
||||
break
|
||||
}
|
||||
incr i
|
||||
@@ -583,7 +583,7 @@ proc CreateCalFrame { w dayNames } {
|
||||
text $w.t$f -width 12 -height $h -bd 0 -spacing3 3 -wrap word -relief flat \
|
||||
-state disabled -takefocus 0 -cursor {} -font CalboxFont -foreground $Option(TextColor) -background $Option(BackgroundColor) \
|
||||
-highlightthickness 0
|
||||
frame $w.f$f -padx 0 -pady 0 -highlightthickness 0 -relief flat -bd 0
|
||||
frame $w.f$f -padx 0 -pady 0 -highlightthickness 0 -relief flat -bd 0 -background $Option(BackgroundColor)
|
||||
$w.t$f tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$f"
|
||||
$w.t$f tag bind REM <ButtonPress-2> "OpenUrl $w.t$f"
|
||||
$w.t$f tag bind REM <ButtonPress-3> "FireEditor $w.t$f"
|
||||
@@ -650,7 +650,8 @@ proc ConfigureCalFrame { w firstDay numDays } {
|
||||
raise $w.t$i
|
||||
set d [expr $i-$first+1]
|
||||
$w.l$i configure -text $d -state normal -relief flat \
|
||||
-command "ModifyDay $d $firstDay" -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
|
||||
-command "ModifyDay $d $firstDay" -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
|
||||
bind $w.l$i <ButtonPress-3> [list ShowSpecificDayReminders $d]
|
||||
balloon_add_help $w.l$i "Add a reminder..."
|
||||
$w.t$i configure -relief sunken -takefocus 1 -state normal -foreground $Option(TextColor) -background $Option(BackgroundColor)
|
||||
$w.t$i delete 1.0 end
|
||||
@@ -753,7 +754,13 @@ proc CreateCalWindow { dayNames } {
|
||||
button .b.quit -text {Quit} -command {Quit} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
|
||||
balloon_add_help .b.quit "Quit TkRemind"
|
||||
label .b.status -text "" -width 25 -relief flat -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 0
|
||||
bind .b.status <ButtonPress-1> [list ShowTodaysReminders 1 ""]
|
||||
bind .b.status <ButtonPress-3> [list ShowTodaysReminders 1 ""]
|
||||
balloon_add_help .b.status "Show Today's Reminders"
|
||||
label .b.nqueued -text "" -width 20 -relief flat -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 0
|
||||
balloon_add_help .b.nqueued "See the queue of pending reminders (debugging purposes only)"
|
||||
bind .b.nqueued <ButtonPress-1> [list DoQueue]
|
||||
bind .b.nqueued <ButtonPress-3> [list DoQueue]
|
||||
pack .b.prev .b.this .b.next .b.goto .b.print .b.options .b.queue .b.quit -side left -fill both -padx 1
|
||||
pack .b.status -side left -fill both -expand 1 -padx 1
|
||||
pack .b.nqueued -side left -fill both -padx 1
|
||||
@@ -968,6 +975,7 @@ proc CancelOptions { } {
|
||||
global Option
|
||||
font configure CalboxFont {*}$Option(CalboxFont)
|
||||
font configure HeadingFont {*}$Option(HeadingFont)
|
||||
font configure BoldFont {*}$Option(HeadingFont) -weight bold
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
@@ -1105,6 +1113,7 @@ proc LoadOptions {} {
|
||||
}
|
||||
font configure CalboxFont {*}$Option(CalboxFont)
|
||||
font configure HeadingFont {*}$Option(HeadingFont)
|
||||
font configure BoldFont {*}$Option(HeadingFont) -weight bold
|
||||
}
|
||||
|
||||
|
||||
@@ -1694,6 +1703,36 @@ proc Quit {} {
|
||||
}
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# ShowSpecificDayReminders - show reminders for a specific day
|
||||
# Arguments:
|
||||
# d - day whose reminders should be shown
|
||||
#---------------------------------------------------------------------------
|
||||
proc ShowSpecificDayReminders { d } {
|
||||
global CurYear CurMonth
|
||||
set date [format "%04d-%02d-%02d" $CurYear [expr 1 + $CurMonth] $d]
|
||||
ShowTodaysReminders 1 $date
|
||||
}
|
||||
|
||||
proc toggle_complete_through { w } {
|
||||
global todobut
|
||||
if {$todobut} {
|
||||
$w.complete_through configure -state normal
|
||||
} else {
|
||||
$w.complete_through configure -state disabled
|
||||
}
|
||||
}
|
||||
|
||||
proc complete_through_today { w } {
|
||||
global DateOfEventBeingEdited
|
||||
$w.complete_through delete 0 end
|
||||
if {"$DateOfEventBeingEdited" != ""} {
|
||||
$w.complete_through insert end $DateOfEventBeingEdited
|
||||
} else {
|
||||
$w.complete_through insert end [clock format [clock seconds] -format %Y-%m-%d]
|
||||
}
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# CreateModifyDialog -- create dialog for adding a reminder
|
||||
# Arguments:
|
||||
@@ -1707,7 +1746,9 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
|
||||
# Set up: Year, Month, Day, WeekdayName
|
||||
global CurYear CurMonth EnglishDayNames MonthNames OptionType SkipType
|
||||
global ModifyDialogResult TwentyFourHourMode
|
||||
global ModifyDialogResult TwentyFourHourMode DateOfEventBeingEdited
|
||||
|
||||
set DateOfEventBeingEdited ""
|
||||
|
||||
set OptionType 1
|
||||
set SkipType 1
|
||||
@@ -1724,12 +1765,13 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
frame $w.adv -bd 4
|
||||
frame $w.weekend -bd 4
|
||||
frame $w.durationbox -bd 4
|
||||
frame $w.todobox
|
||||
frame $w.time -bd 4
|
||||
frame $w.hol -bd 4
|
||||
frame $w.msg
|
||||
frame $w.buttons
|
||||
pack $w.o1 $w.o2 $w.o3 -side top -anchor w -in $w.o
|
||||
pack $w.o $w.exp $w.adv $w.weekend $w.time $w.durationbox $w.hol $w.msg -side top -anchor w -pady 4 -expand 0 -fill both
|
||||
pack $w.o $w.exp $w.adv $w.weekend $w.time $w.durationbox $w.todobox $w.hol $w.msg -side top -anchor w -pady 4 -expand 0 -fill both
|
||||
pack $w.msg -side top -anchor w -pady 4 -padx 4 -expand true -fill both
|
||||
pack $w.buttons -side top -anchor w -pady 4 -expand 0 -fill x
|
||||
|
||||
@@ -1919,6 +1961,17 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
}
|
||||
pack $w.durationbut $w.durationh $w.durationcolon $w.durationm -side left -anchor w -in $w.durationbox
|
||||
|
||||
# TODO?
|
||||
checkbutton $w.todobut -text "This is a TODO " -command [list toggle_complete_through $w]
|
||||
|
||||
balloon_add_help $w.todobut "Select if this is a TODO-type reminder"
|
||||
$w.todobut deselect
|
||||
label $w.lcomplete -text "Complete through: "
|
||||
entry $w.complete_through -width 20
|
||||
bind $w.complete_through <Double-Button-1> [list complete_through_today $w]
|
||||
balloon_add_help $w.complete_through "Enter the date of completed TODO in the form YYYY-MM-DD"
|
||||
pack $w.todobut $w.lcomplete $w.complete_through -side left -anchor w -in $w.todobox
|
||||
|
||||
# SKIP TYPE
|
||||
label $w.labhol -text "On holidays or weekends:"
|
||||
radiobutton $w.issue -variable SkipType -value 1 -text "Issue reminder as usual"
|
||||
@@ -1930,7 +1983,7 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
# TEXT ENTRY
|
||||
label $w.msglab -text "Summary: "
|
||||
entry $w.entry
|
||||
balloon_add_help $w.entry "Enter the text of the reminder"
|
||||
balloon_add_help $w.entry "Enter the text of the reminder (required)"
|
||||
grid $w.msglab -row 0 -column 0 -in $w.msg -sticky e
|
||||
grid $w.entry -row 0 -column 1 -in $w.msg -sticky nsew
|
||||
|
||||
@@ -1987,7 +2040,7 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
#***********************************************************************
|
||||
proc RemindDialogToOptions { w } {
|
||||
global OptionType SkipType repbut expbut advbut advcount
|
||||
global timebut timeadvbut timerepbut durationbut
|
||||
global timebut timeadvbut timerepbut durationbut todobut
|
||||
global dSaturday dSunday dMonday dTuesday dWednesday dThursday dFriday
|
||||
set ans {}
|
||||
lappend ans "-global-OptionType" $OptionType
|
||||
@@ -2021,10 +2074,11 @@ proc RemindDialogToOptions { w } {
|
||||
#***********************************************************************
|
||||
proc OptionsToRemindDialog { w opts } {
|
||||
global OptionType SkipType repbut expbut advbut advcount
|
||||
global timebut timeadvbut timerepbut TwentyFourHourMode durationbut
|
||||
global dSaturday dSunday dMonday dTuesday dWednesday dThursday dFriday
|
||||
global timebut timeadvbut timerepbut TwentyFourHourMode durationbut todobut
|
||||
global dSaturday dSunday dMonday dTuesday dWednesday dThursday dFriday DateOfEventBeingEdited
|
||||
set hour ""
|
||||
set ampm ""
|
||||
$w.complete_through configure -state normal
|
||||
foreach {flag value} $opts {
|
||||
switch -glob -- $flag {
|
||||
"-text-*" {
|
||||
@@ -2072,6 +2126,7 @@ proc OptionsToRemindDialog { w opts } {
|
||||
}
|
||||
}
|
||||
}
|
||||
toggle_complete_through $w
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -2163,6 +2218,7 @@ proc ModifyDay {d firstDay} {
|
||||
wm iconname .mod "Add Reminder"
|
||||
tkwait visibility .mod
|
||||
set oldFocus [focus]
|
||||
toggle_complete_through .mod
|
||||
while {1} {
|
||||
grab .mod
|
||||
raise .mod
|
||||
@@ -2243,7 +2299,7 @@ proc CreateReminder {w} {
|
||||
set body [string trim [$w.entry get]]
|
||||
|
||||
if {"$body" == ""} {
|
||||
error "Blank body in reminder"
|
||||
error "Summary is required"
|
||||
}
|
||||
|
||||
set DidOmit 0
|
||||
@@ -2251,7 +2307,7 @@ proc CreateReminder {w} {
|
||||
# Delegate the first part to CreateReminder1, CreateReminder2, or
|
||||
# CreateReminder3
|
||||
global OptionType SkipType repbut expbut advbut advcount
|
||||
global timebut timeadvbut timerepbut durationbut
|
||||
global timebut timeadvbut timerepbut durationbut todobut
|
||||
|
||||
set rem [CreateReminder$OptionType $w]
|
||||
|
||||
@@ -2299,6 +2355,13 @@ proc CreateReminder {w} {
|
||||
}
|
||||
}
|
||||
|
||||
if {$todobut} {
|
||||
append rem " TODO"
|
||||
set ct [string trim [$w.complete_through get]]
|
||||
if {"$ct" != ""} {
|
||||
append rem " COMPLETE-THROUGH $ct"
|
||||
}
|
||||
}
|
||||
global SkipType
|
||||
if {$SkipType == 2} {
|
||||
append rem " SKIP"
|
||||
@@ -2845,14 +2908,15 @@ proc RestartBackgroundRemindDaemon {} {
|
||||
# Dumps the debugging queue listing
|
||||
#---------------------------------------------------------------------------
|
||||
proc ShowQueue { queue } {
|
||||
global Option
|
||||
set w .queuedbg
|
||||
catch { destroy $w }
|
||||
toplevel $w
|
||||
toplevel $w -background $Option(WinBackground)
|
||||
wm title $w "Queue (Debugging Output)"
|
||||
wm iconname $w "Queue Dbg"
|
||||
text $w.t -fg black -bg white -width 80 -height 30 -wrap word -yscrollcommand "$w.sb set"
|
||||
text $w.t -fg black -bg white -width 80 -height 30 -wrap word -yscrollcommand "$w.sb set" -foreground $Option(TextColor) -background $Option(BackgroundColor) -font CalBoxFont
|
||||
scrollbar $w.sb -orient vertical -command "$w.text yview"
|
||||
button $w.ok -text "OK" -command "destroy $w"
|
||||
button $w.ok -text "OK" -command "destroy $w" -foreground $Option(TextColor) -background $Option(BackgroundColor) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
|
||||
grid $w.t -row 0 -column 0 -sticky nsew
|
||||
grid $w.sb -row 0 -column 1 -sticky ns
|
||||
grid $w.ok -row 1 -column 0 -sticky w
|
||||
@@ -2864,7 +2928,6 @@ proc ShowQueue { queue } {
|
||||
set obj [lsort -command sort_q $queue]
|
||||
set did 0
|
||||
$w.t tag configure grey -background "#DDDDDD" -selectbackground "#999999"
|
||||
set toggle 0
|
||||
foreach q $obj {
|
||||
if { $did > 0 } {
|
||||
$w.t insert end "\n"
|
||||
@@ -2887,24 +2950,17 @@ proc ShowQueue { queue } {
|
||||
}
|
||||
foreach key [list time nexttime body] {
|
||||
set r [dict get $q $key]
|
||||
if { $toggle != 0 } {
|
||||
$w.t insert end "$key=$r" [list grey $fntag]
|
||||
if {"$key" != "body"} {
|
||||
$w.t insert end "; " [list grey $fntag]
|
||||
}
|
||||
} else {
|
||||
$w.t insert end "$key=$r" [list $fntag]
|
||||
if {"$key" != "body"} {
|
||||
$w.t insert end "; " [list $fntag]
|
||||
}
|
||||
$w.t insert end "$key=$r" [list $fntag]
|
||||
if {"$key" != "body"} {
|
||||
$w.t insert end "; " [list $fntag]
|
||||
}
|
||||
}
|
||||
$w.t insert end "\n"
|
||||
set toggle [expr 1 - $toggle]
|
||||
set did 1
|
||||
}
|
||||
if { $did == 0 } {
|
||||
$w.t insert end "(Queue is empty)\n"
|
||||
$w.t tag configure bold -font BoldFont
|
||||
$w.t insert end "(Queue is empty)\n" bold
|
||||
} else {
|
||||
$w.t insert end "\n\nClick on a queue item to open an editor on the corresponding REM command.\n"
|
||||
}
|
||||
@@ -3014,7 +3070,7 @@ proc DaemonReadable { file } {
|
||||
catch { unset Ignore }
|
||||
Initialize
|
||||
FillCalWindow
|
||||
ShowTodaysReminders
|
||||
ShowTodaysReminders 0 ""
|
||||
}
|
||||
"reread" {
|
||||
if {[dict exists $obj command]} {
|
||||
@@ -3195,6 +3251,7 @@ proc main {} {
|
||||
|
||||
font create CalboxFont {*}[font actual TkFixedFont]
|
||||
font create HeadingFont {*}[font actual TkDefaultFont]
|
||||
font create BoldFont {*}[font actual TkDefaultFont] -weight bold
|
||||
|
||||
global AppendFile HighestTagSoFar DayNames
|
||||
catch {
|
||||
@@ -3212,7 +3269,7 @@ proc main {} {
|
||||
}
|
||||
FindConfigFile
|
||||
LoadOptions
|
||||
ShowTodaysReminders
|
||||
ShowTodaysReminders 0 ""
|
||||
ScanForTags $AppendFile
|
||||
CreateCalWindow $DayNames
|
||||
FillCalWindow
|
||||
@@ -3284,6 +3341,9 @@ proc ReadTaggedOptions { tag date } {
|
||||
}
|
||||
}
|
||||
|
||||
if {[dict exists $obj date]} {
|
||||
lappend ans -global-DateOfEventBeingEdited $date
|
||||
}
|
||||
if {[dict exists $obj d]} {
|
||||
lappend ans -text-day1 [dict get $obj d]
|
||||
lappend ans -text-day2 [dict get $obj d]
|
||||
@@ -3509,6 +3569,18 @@ proc ReadTaggedOptions { tag date } {
|
||||
lappend ans -entry-entry [dict get $obj body]
|
||||
}
|
||||
|
||||
# Is this a TODO?
|
||||
if {[dict exists $obj is_todo]} {
|
||||
lappend ans -global-todobut [dict get $obj is_todo]
|
||||
} else {
|
||||
lappend ans -global-todobut 0
|
||||
}
|
||||
if {[dict exists $obj complete_through]} {
|
||||
lappend ans -entry-complete_through [dict get $obj complete_through]
|
||||
} else {
|
||||
lappend ans -entry-complete_through ""
|
||||
}
|
||||
|
||||
# Figure out the reminder type
|
||||
if {[dict exists $obj rep]} {
|
||||
# Repeat must be type 1
|
||||
@@ -3818,7 +3890,7 @@ proc EditTaggedReminder { w } {
|
||||
wm title .mod "TkRemind Edit Reminder..."
|
||||
wm iconname .mod "Edit Reminder"
|
||||
OptionsToRemindDialog .mod $opts
|
||||
|
||||
toggle_complete_through .mod
|
||||
tkwait visibility .mod
|
||||
set oldFocus [focus]
|
||||
while {1} {
|
||||
@@ -4240,47 +4312,67 @@ proc DisplayTimeContinuously {} {
|
||||
}
|
||||
|
||||
|
||||
proc daily_rem_enter { lines } {
|
||||
global Balloon
|
||||
balloon_cancel_timer
|
||||
set Balloon(HelpId) [after $Balloon(HelpTime) [list details_popup $lines]]
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: ShowTodaysReminders
|
||||
# %ARGUMENTS:
|
||||
# None
|
||||
# force -- if true, show today's reminders even if option is disabled.
|
||||
# date -- if non-blank, show reminders for specified date rather than today.
|
||||
# %RETURNS:
|
||||
# Nothing
|
||||
# %DESCRIPTION:
|
||||
# Shows all of today's non-timed reminders in a window
|
||||
#***********************************************************************
|
||||
proc ShowTodaysReminders {} {
|
||||
proc ShowTodaysReminders { force date } {
|
||||
global Option
|
||||
global Remind
|
||||
global ReminderFile
|
||||
global TwentyFourHourMode
|
||||
if {!$Option(ShowTodaysReminders)} {
|
||||
if {!$force && !$Option(ShowTodaysReminders)} {
|
||||
return
|
||||
}
|
||||
|
||||
set w .today
|
||||
catch { destroy $w }
|
||||
toplevel $w
|
||||
wm title $w "Today's Reminders"
|
||||
toplevel $w -background $Option(WinBackground)
|
||||
if {"$date" == ""} {
|
||||
set wtitle "Today's Reminders"
|
||||
} else {
|
||||
set wtitle "Reminders for $date"
|
||||
}
|
||||
wm iconname $w "Reminders"
|
||||
text $w.text -width 80 -height 20 -wrap word -yscrollcommand "$w.sb set"
|
||||
text $w.text -width 80 -height 20 -wrap word -yscrollcommand "$w.sb set" -foreground $Option(TextColor) -background $Option(BackgroundColor) -font CalboxFont -spacing1 3
|
||||
scrollbar $w.sb -orient vertical -command "$w.text yview"
|
||||
button $w.ok -text "OK" -command "destroy $w"
|
||||
button $w.ok -text "OK" -command "destroy $w" -foreground $Option(TextColor) -background $Option(BackgroundColor) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
|
||||
|
||||
grid $w.text -row 0 -column 0 -sticky nsew
|
||||
grid $w.sb -row 0 -column 1 -sticky ns
|
||||
grid $w.ok -row 1 -column 0 -sticky w
|
||||
|
||||
grid rowconfigure $w 0 -weight 1
|
||||
grid rowconfigure $w 1 -weight 0
|
||||
grid columnconfigure $w 0 -weight 1
|
||||
grid columnconfigure $w 1 -weight 0
|
||||
CenterWindow $w .
|
||||
|
||||
# Grab the reminders
|
||||
set stuff ""
|
||||
set cmdline "|$Remind -itkremind=1 -g -q -r "
|
||||
set cmdline "|$Remind -itkremind=1 --json -q -r "
|
||||
if {$TwentyFourHourMode} {
|
||||
append cmdline "-b1 "
|
||||
}
|
||||
append cmdline $Option(ExtraRemindArgs);
|
||||
append cmdline " $ReminderFile 2>@1"
|
||||
append cmdline " $ReminderFile"
|
||||
if {"$date" != ""} {
|
||||
append cmdline " $date"
|
||||
} else {
|
||||
set date [clock format [clock seconds] -format "%Y-%m-%d" -locale C]
|
||||
}
|
||||
append cmdline " 2>@1"
|
||||
set f [open $cmdline r]
|
||||
while {[gets $f line] >= 0} {
|
||||
append stuff "$line\n"
|
||||
@@ -4290,12 +4382,163 @@ proc ShowTodaysReminders {} {
|
||||
$w.text insert end $stuff
|
||||
$w.text insert end "\n"
|
||||
$w.text insert end $err
|
||||
} else {
|
||||
$w.text insert end $stuff
|
||||
$w.text configure -state disabled
|
||||
return
|
||||
}
|
||||
|
||||
if {[catch {set arr [::json::json2dict $stuff]} err]} {
|
||||
$w.text insert end "Error converting JSON\n\n"
|
||||
$w.text insert end $err
|
||||
$w.text configure -state disabled
|
||||
return
|
||||
}
|
||||
|
||||
# If first element is banner, set window title
|
||||
set first [lindex $arr 0]
|
||||
$w.text tag configure bold -font BoldFont
|
||||
if {"[lindex $first 0]" == "banner"} {
|
||||
set banner [lindex $first 1]
|
||||
# Trim trailing colon
|
||||
set wtitle [string trimright $banner ":"]
|
||||
set arr [lreplace $arr 0 0]
|
||||
$w.text insert end "$banner" bold
|
||||
$w.text insert end "\n\n"
|
||||
}
|
||||
|
||||
# At this point, we can set the window title
|
||||
wm title $w $wtitle
|
||||
|
||||
# If first element is no reminders, FINE.
|
||||
set first [lindex $arr 0]
|
||||
if {"[lindex $first 0]" == "noreminders"} {
|
||||
$w.text insert end [lindex $first 1] bold
|
||||
$w.text insert end "\n"
|
||||
$w.text configure -state disabled
|
||||
return
|
||||
}
|
||||
|
||||
set arr [lsort -command compare_reminders $arr]
|
||||
set old_date {}
|
||||
set did_a_date 0
|
||||
set t_index 0
|
||||
foreach thing $arr {
|
||||
incr t_index
|
||||
set mydate [dict get $thing date]
|
||||
if {"$mydate" != "$old_date"} {
|
||||
if {"$old_date" != ""} {
|
||||
$w.text insert end "\n"
|
||||
}
|
||||
if {$did_a_date || "$mydate" != "$date"} {
|
||||
$w.text insert end "> $mydate\n" bold
|
||||
set did_a_date 1
|
||||
}
|
||||
}
|
||||
set old_date $mydate
|
||||
set tags [list "l_$t_index"]
|
||||
if {[dict exists $thing r] && [dict exists $thing g] && [dict exists $thing g]} {
|
||||
set r [dict get $thing r]
|
||||
set g [dict get $thing g]
|
||||
set b [dict get $thing b]
|
||||
if {$r > 255} {
|
||||
set r 255
|
||||
} elseif {$r < 0} {
|
||||
set r 0
|
||||
}
|
||||
if {$g > 255} {
|
||||
set g 255
|
||||
} elseif {$g < 0} {
|
||||
set g 0
|
||||
}
|
||||
if {$b > 255} {
|
||||
set b 255
|
||||
} elseif {$b < 0} {
|
||||
set b 0
|
||||
}
|
||||
set color [format "%02X%02X%02X" $r $g $b]
|
||||
lappend tags "clr$color"
|
||||
$w.text tag configure "clr$color" -foreground "#$color"
|
||||
}
|
||||
|
||||
set help_lines {}
|
||||
if {[dict exists $thing info]} {
|
||||
set info [dict get $thing info]
|
||||
if {[dict exists $info location]} {
|
||||
lappend help_lines [list "Location:" [dict get $info location]]
|
||||
}
|
||||
if {[dict exists $info description]} {
|
||||
lappend help_lines [list "Description:" [dict get $info description]]
|
||||
}
|
||||
if {[dict exists $info url]} {
|
||||
lappend help_lines [list "URL:" "Middle-click to open [dict get $info url]"]
|
||||
$w.text tag bind "l_$t_index" <ButtonPress-2> [list exec xdg-open [dict get $info url]]
|
||||
}
|
||||
}
|
||||
if {[llength $help_lines] >= 1} {
|
||||
$w.text tag bind "l_$t_index" <Enter> +[list daily_rem_enter $help_lines]
|
||||
$w.text tag bind "l_$t_index" <Leave> +[list details_leave $w]
|
||||
}
|
||||
if {[dict exists $thing filename]} {
|
||||
set fname [dict get $thing filename]
|
||||
# Don't make INCLUDECMD output editable
|
||||
if {![string match "*|" $fname]} {
|
||||
if {[dict exists $thing lineno_start]} {
|
||||
set l [dict get $thing lineno_start]
|
||||
} else {
|
||||
set l [dict get $thing lineno]
|
||||
}
|
||||
set fntag [string cat "FILE_" $l "_" $fname]
|
||||
$w.text tag bind "l_$t_index" <Enter> +[list $w.text tag configure "l_$t_index" -underline 1]
|
||||
$w.text tag bind "l_$t_index" <Leave> +[list $w.text tag configure "l_$t_index" -underline 0]
|
||||
$w.text tag bind "l_$t_index" <ButtonPress-1> [list FireEditor $w.text $fntag]
|
||||
$w.text tag bind "l_$t_index" <ButtonPress-3> [list FireEditor $w.text $fntag]
|
||||
}
|
||||
}
|
||||
$w.text insert end [dict get $thing body] $tags
|
||||
$w.text insert end "\n"
|
||||
}
|
||||
|
||||
#$w.text insert end "\n\n$stuff\n"
|
||||
$w.text configure -state disabled
|
||||
}
|
||||
|
||||
proc compare_reminders { a b } {
|
||||
set a_date [dict get $a date]
|
||||
set b_date [dict get $b date]
|
||||
#puts "Comparing $a_date $b_date"
|
||||
if {"$a_date" < "$b_date"} {
|
||||
return -1
|
||||
}
|
||||
if {"$a_date" > "$b_date"} {
|
||||
return 1
|
||||
}
|
||||
|
||||
if {[dict exists $a time]} {
|
||||
set a_time [dict get $a time]
|
||||
} else {
|
||||
set a_time 1441
|
||||
}
|
||||
if {[dict exists $b time]} {
|
||||
set b_time [dict get $b time]
|
||||
} else {
|
||||
set b_time 1441
|
||||
}
|
||||
if {$a_time < $b_time} {
|
||||
return -1
|
||||
}
|
||||
if {$a_time > $b_time} {
|
||||
return 1
|
||||
}
|
||||
set a_prio [dict get $a priority]
|
||||
set b_prio [dict get $b priority]
|
||||
if {$a_prio < $b_prio} {
|
||||
return -1;
|
||||
}
|
||||
if {$a_prio > $b_prio} {
|
||||
return 1;
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: InteractiveDeleteReminder
|
||||
# %ARGUMENTS:
|
||||
@@ -4516,6 +4759,7 @@ proc ChooseHeadingFont {} {
|
||||
proc SetHeadingFont {font} {
|
||||
global tmpOpt
|
||||
font configure HeadingFont {*}[font actual $font]
|
||||
font configure BoldFont {*}$Option(HeadingFont) -weight bold
|
||||
set tmpOpt(HeadingFont) [font actual $font]
|
||||
raise .opt
|
||||
}
|
||||
@@ -4616,13 +4860,13 @@ proc set_button_to_errors {} {
|
||||
}
|
||||
|
||||
proc ShowErrors {} {
|
||||
global RemindErrors
|
||||
global RemindErrors Option
|
||||
set w ".errors"
|
||||
catch { destroy $w }
|
||||
toplevel $w
|
||||
text $w.t -width 80 -height 30 -wrap word -yscrollcommand "$w.sb set"
|
||||
toplevel $w -background $Option(WinBackground)
|
||||
text $w.t -width 80 -height 30 -wrap word -yscrollcommand "$w.sb set" -foreground $Option(TextColor) -background $Option(BackgroundColor) -font CalBoxFont
|
||||
scrollbar $w.sb -orient vertical -command "$w.t yview"
|
||||
button $w.ok -text OK -command DoneShowingErrors
|
||||
button $w.ok -text OK -command DoneShowingErrors -foreground $Option(TextColor) -background $Option(BackgroundColor) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
|
||||
grid $w.t -row 0 -column 0 -sticky nsew
|
||||
grid $w.sb -row 0 -column 1 -sticky ns
|
||||
grid $w.ok -row 1 -column 0 -stick w
|
||||
|
||||
@@ -46,10 +46,12 @@ test: all
|
||||
.c.o:
|
||||
@CC@ -c @CPPFLAGS@ @CFLAGS@ @DEFS@ $(CEXTRA) -DSYSDIR=$(datarootdir)/remind -I. -I$(srcdir) $<
|
||||
|
||||
# Extract all tr() strings into a file. NOTE: SOURCE CODE MUST NOT HAVE
|
||||
# MORE THAN ONE tr() PER LINE!!!
|
||||
xlat.c: $(REMINDSRCS)
|
||||
@echo "#include <stddef.h>" > xlat.c
|
||||
@echo "char const *translatables[] = {" >> xlat.c
|
||||
@cat $(REMINDSRCS) | grep 'tr(".*")' | sed -e 's/.*tr."/"/' -e 's/").*/"/' | LANG=C LC_ALL=C sort | uniq | grep -E -v '^"(am|at|from now|hour|minute|now|on|pm|today|tomorrow|was)"$$' | sed -e 's/^/ /' -e 's/$$/,/' >> xlat.c
|
||||
@cat $(REMINDSRCS) | grep 'tr(".*")' | sed -e 's/.*tr."/"/' -e 's/").*/"/' | LANG=C LC_ALL=C sort | uniq | grep -E -v '^"(ago|am|and|at|from now|is|hour|minute|now|on|pm|today|tomorrow|was)"$$' | sed -e 's/^/ /' -e 's/$$/,/' >> xlat.c
|
||||
@echo " NULL" >> xlat.c
|
||||
@echo "};" >> xlat.c
|
||||
|
||||
@@ -102,7 +104,7 @@ depend:
|
||||
# distributions, etc.
|
||||
|
||||
cppcheck:
|
||||
cppcheck -j`nproc` -v --force --enable=all --suppress=ConfigurationNotChecked --suppress=unmatchedSuppression --suppress=variableScope --inline-suppr .
|
||||
cppcheck -j`nproc` -v --force --enable=all --suppress=missingIncludeSystem --suppress=ConfigurationNotChecked --suppress=unmatchedSuppression --suppress=variableScope --inline-suppr --check-level=exhaustive .
|
||||
|
||||
# Build a tar file based on all files checked into git.
|
||||
distro:
|
||||
|
||||
113
src/calendar.c
113
src/calendar.c
@@ -55,7 +55,7 @@ typedef struct cal_entry {
|
||||
DynamicBuffer tags;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
int duration;
|
||||
char *filename;
|
||||
char const *filename;
|
||||
int lineno;
|
||||
int lineno_start;
|
||||
Trigger trig;
|
||||
@@ -279,6 +279,7 @@ static int DidAMonth;
|
||||
static int DidAWeek;
|
||||
static int DidADay;
|
||||
|
||||
static char const *CalendarTime(int tim, int duration);
|
||||
static void ColorizeEntry(CalEntry const *e, int clamp);
|
||||
static void SortCol (CalEntry **col);
|
||||
static void DoCalendarOneWeek (int nleft);
|
||||
@@ -288,7 +289,7 @@ static int WriteCalendarRow (void);
|
||||
static void WriteWeekHeaderLine (void);
|
||||
static void WritePostHeaderLine (void);
|
||||
static void PrintLeft (char const *s, int width, char pad);
|
||||
static void PrintCentered (char const *s, int width, char *pad);
|
||||
static void PrintCentered (char const *s, int width, char const *pad);
|
||||
static int WriteOneCalLine (int dse, int wd);
|
||||
static int WriteOneColLine (int col);
|
||||
static void GenerateCalEntries (int col);
|
||||
@@ -380,7 +381,7 @@ despace(char const *s)
|
||||
return buf;
|
||||
}
|
||||
|
||||
void PrintJSONChar(char c) {
|
||||
static void PrintJSONChar(char c) {
|
||||
switch(c) {
|
||||
case '\b': printf("\\b"); break;
|
||||
case '\f': printf("\\f"); break;
|
||||
@@ -422,7 +423,7 @@ void PrintJSONString(char const *s)
|
||||
}
|
||||
}
|
||||
|
||||
void PrintJSONStringLC(char const *s)
|
||||
static void PrintJSONStringLC(char const *s)
|
||||
{
|
||||
while (*s) {
|
||||
switch(*s) {
|
||||
@@ -466,7 +467,7 @@ void PrintJSONKeyPairString(char const *name, char const *val)
|
||||
printf("\",");
|
||||
}
|
||||
|
||||
void PrintJSONKeyPairDate(char const *name, int dse)
|
||||
static void PrintJSONKeyPairDate(char const *name, int dse)
|
||||
{
|
||||
int y, m, d;
|
||||
if (dse == NO_DATE) {
|
||||
@@ -480,7 +481,7 @@ void PrintJSONKeyPairDate(char const *name, int dse)
|
||||
|
||||
}
|
||||
|
||||
void PrintJSONKeyPairDateTime(char const *name, int dt)
|
||||
static void PrintJSONKeyPairDateTime(char const *name, int dt)
|
||||
{
|
||||
int y, m, d, h, i, k;
|
||||
if (dt == NO_TIME) {
|
||||
@@ -498,7 +499,7 @@ void PrintJSONKeyPairDateTime(char const *name, int dt)
|
||||
|
||||
}
|
||||
|
||||
void PrintJSONKeyPairTime(char const *name, int t)
|
||||
static void PrintJSONKeyPairTime(char const *name, int t)
|
||||
{
|
||||
int h, i;
|
||||
if (t == NO_TIME) {
|
||||
@@ -646,7 +647,7 @@ Colorize256(int r, int g, int b, int bg, int clamp)
|
||||
int best = -1;
|
||||
int best_dist = 0;
|
||||
int dist;
|
||||
struct xterm256_colors *cur;
|
||||
struct xterm256_colors const *cur;
|
||||
size_t i;
|
||||
|
||||
if (clamp) {
|
||||
@@ -757,7 +758,7 @@ InitMoonsAndShades(void)
|
||||
static void
|
||||
SetShadeEntry(int dse, char const *shade)
|
||||
{
|
||||
int y, m, d;
|
||||
int d;
|
||||
int r, g, b;
|
||||
/* Don't bother if we're not doing SHADE specials */
|
||||
if (!UseBGVTColors) {
|
||||
@@ -774,7 +775,7 @@ SetShadeEntry(int dse, char const *shade)
|
||||
if (r < 0 || g < 0 || b < 0 || r > 255 || g > 255 || b > 255) {
|
||||
return;
|
||||
}
|
||||
FromDSE(dse, &y, &m, &d);
|
||||
FromDSE(dse, NULL, NULL, &d);
|
||||
bgcolor[d][0] = r;
|
||||
bgcolor[d][1] = g;
|
||||
bgcolor[d][2] = b;
|
||||
@@ -784,7 +785,7 @@ static void
|
||||
SetMoonEntry(int dse, char const *moon)
|
||||
{
|
||||
int phase;
|
||||
int y, m, d;
|
||||
int d;
|
||||
char msg[28];
|
||||
|
||||
/* Don't bother unless it's utf-8 */
|
||||
@@ -803,7 +804,7 @@ SetMoonEntry(int dse, char const *moon)
|
||||
/* Bad phase */
|
||||
return;
|
||||
}
|
||||
FromDSE(dse, &y, &m, &d);
|
||||
FromDSE(dse, NULL, NULL, &d);
|
||||
if (msg[0]) {
|
||||
snprintf(moons[d], sizeof(moons[d]), "%s %s", moonphase_emojis[phase], msg);
|
||||
} else {
|
||||
@@ -1387,7 +1388,7 @@ static void PrintLeft(char const *s, int width, char pad)
|
||||
/* Center a piece of text */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void PrintCentered(char const *s, int width, char *pad)
|
||||
static void PrintCentered(char const *s, int width, char const *pad)
|
||||
{
|
||||
#ifndef REM_USE_WCHAR
|
||||
int len = strlen(s);
|
||||
@@ -1476,13 +1477,13 @@ static void PrintCentered(char const *s, int width, char *pad)
|
||||
static int WriteOneCalLine(int start_dse, int wd)
|
||||
{
|
||||
int done = 1, i;
|
||||
int y, m, d;
|
||||
int d;
|
||||
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
for (i=0; i<7; i++) {
|
||||
FromDSE(start_dse+i, &y, &m, &d);
|
||||
FromDSE(start_dse+i, NULL, NULL, &d);
|
||||
d -= wd;
|
||||
if (CalColumn[i]) {
|
||||
Backgroundize(ColToDay[i]);
|
||||
@@ -1539,7 +1540,6 @@ static int WriteOneColLine(int col)
|
||||
CalColumn[col] = e->next;
|
||||
free(e->text);
|
||||
free(e->raw_text);
|
||||
free(e->filename);
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
FreeTrigInfoChain(e->infos);
|
||||
free(e);
|
||||
@@ -1626,7 +1626,6 @@ static int WriteOneColLine(int col)
|
||||
CalColumn[col] = e->next;
|
||||
free(e->text);
|
||||
free(e->raw_text);
|
||||
free(e->filename);
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
FreeTrigInfoChain(e->infos);
|
||||
free(e);
|
||||
@@ -1645,7 +1644,6 @@ static int WriteOneColLine(int col)
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
CalColumn[col] = e->next;
|
||||
free(e->text);
|
||||
free(e->filename);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
#endif
|
||||
@@ -1708,7 +1706,6 @@ static int WriteOneColLine(int col)
|
||||
if (!*s && !e->next) {
|
||||
CalColumn[col] = e->next;
|
||||
free(e->text);
|
||||
free(e->filename);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
#endif
|
||||
@@ -1780,6 +1777,7 @@ static void GenerateCalEntries(int col)
|
||||
case T_ErrMsg: r=DoErrMsg(&p); break;
|
||||
case T_Rem: r=DoCalRem(&p, col); break;
|
||||
case T_If: r=DoIf(&p); break;
|
||||
case T_Return: r=DoReturn(&p); break;
|
||||
case T_IfTrig: r=DoIfTrig(&p); break;
|
||||
case T_Else: r=DoElse(&p); break;
|
||||
case T_EndIf: r=DoEndif(&p); break;
|
||||
@@ -1809,6 +1807,18 @@ static void GenerateCalEntries(int col)
|
||||
break;
|
||||
case T_Pop: r=PopOmitContext(&p); break;
|
||||
case T_Push: r=PushOmitContext(&p); break;
|
||||
case T_PushVars:
|
||||
r=PushVars(&p);
|
||||
break;
|
||||
case T_PopVars:
|
||||
r=PopVars(&p);
|
||||
break;
|
||||
case T_PushFuncs:
|
||||
r=PushUserFuncs(&p);
|
||||
break;
|
||||
case T_PopFuncs:
|
||||
r=PopUserFuncs(&p);
|
||||
break;
|
||||
case T_Preserve: r=DoPreserve(&p); break;
|
||||
case T_Expr: r = DoExpr(&p); break;
|
||||
case T_Translate: r = DoTranslate(&p); break;
|
||||
@@ -2009,7 +2019,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
}
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
dse = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
||||
dse = ComputeTrigger(get_scanfrom(&trig), &trig, &tim, &r, 1);
|
||||
if (r) {
|
||||
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
|
||||
r = OK;
|
||||
@@ -2040,6 +2050,13 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Filter unwanted events/todos */
|
||||
if ((TodoFilter == ONLY_TODOS && !trig.is_todo) ||
|
||||
(TodoFilter == ONLY_EVENTS && trig.is_todo)) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Save nonconst_expr flag */
|
||||
nonconst_expr = p->nonconst_expr;
|
||||
/* Convert PS and PSF to PASSTHRU */
|
||||
@@ -2139,14 +2156,18 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
}
|
||||
(void) sscanf(DBufValue(&pre_buf), "%d %d %d",
|
||||
&col_r, &col_g, &col_b);
|
||||
if (col_r < 0) col_r = 0;
|
||||
else if (col_r > 255) col_r = 255;
|
||||
if (col_g < 0) col_g = 0;
|
||||
else if (col_g > 255) col_g = 255;
|
||||
if (col_b < 0) col_b = 0;
|
||||
else if (col_b > 255) col_b = 255;
|
||||
if (!PsCal && !DoSimpleCalendar) {
|
||||
if (col_r < 0 || col_g < 0 || col_b < 0 ||
|
||||
col_r > 255 || col_g > 255 || col_b > 255) {
|
||||
is_color = 0;
|
||||
col_r = -1;
|
||||
col_g = -1;
|
||||
col_b = -1;
|
||||
trig.passthru[0] = 0;
|
||||
DBufFree(&pre_buf);
|
||||
} else {
|
||||
if (!PsCal && !DoSimpleCalendar) {
|
||||
DBufFree(&pre_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2317,17 +2338,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
FreeTrig(&trig);
|
||||
e->duration = tim.duration;
|
||||
e->priority = trig.priority;
|
||||
e->filename = StrDup(FileName);
|
||||
if(!e->filename) {
|
||||
FreeTrigInfoChain(e->infos);
|
||||
if (e->text) free(e->text);
|
||||
if (e->raw_text) free(e->raw_text);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
#endif
|
||||
free(e);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
e->filename = GetCurrentFilename();
|
||||
e->lineno = LineNo;
|
||||
e->lineno_start = LineNoStart;
|
||||
|
||||
@@ -2356,7 +2367,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
return OK;
|
||||
}
|
||||
|
||||
static void WriteSimpleEntryProtocol1(CalEntry *e)
|
||||
static void WriteSimpleEntryProtocol1(CalEntry const *e)
|
||||
{
|
||||
if (e->passthru[0]) {
|
||||
printf(" %s", e->passthru);
|
||||
@@ -2427,7 +2438,7 @@ WriteJSONInfoChain(TrigInfo *ti)
|
||||
}
|
||||
printf("},");
|
||||
}
|
||||
void WriteJSONTrigger(Trigger const *t, int include_tags, int today)
|
||||
void WriteJSONTrigger(Trigger const *t, int include_tags)
|
||||
{
|
||||
/* wd is an array of days from 0=monday to 6=sunday.
|
||||
We convert to array of strings */
|
||||
@@ -2455,6 +2466,8 @@ void WriteJSONTrigger(Trigger const *t, int include_tags, int today)
|
||||
if (t->y != NO_YR) {
|
||||
PrintJSONKeyPairInt("y", t->y);
|
||||
}
|
||||
PrintJSONKeyPairInt("is_todo", t->is_todo);
|
||||
PrintJSONKeyPairDate("complete_through", t->complete_through);
|
||||
if (t->back) {
|
||||
PrintJSONKeyPairInt("back", t->back);
|
||||
}
|
||||
@@ -2500,8 +2513,12 @@ void WriteJSONTrigger(Trigger const *t, int include_tags, int today)
|
||||
if (t->once != NO_ONCE) {
|
||||
PrintJSONKeyPairInt("once", t->once);
|
||||
}
|
||||
if (t->scanfrom != today) {
|
||||
PrintJSONKeyPairDate("scanfrom", t->scanfrom);
|
||||
if (t->scanfrom != NO_SCANFROM) {
|
||||
if (t->scanfrom >= 0) {
|
||||
PrintJSONKeyPairDate("scanfrom", t->scanfrom);
|
||||
} else {
|
||||
PrintJSONKeyPairInt("scanfrom", t->scanfrom);
|
||||
}
|
||||
}
|
||||
PrintJSONKeyPairDate("from", t->from);
|
||||
PrintJSONKeyPairInt("priority", t->priority);
|
||||
@@ -2529,7 +2546,7 @@ void WriteJSONTrigger(Trigger const *t, int include_tags, int today)
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
||||
static void WriteSimpleEntryProtocol2(CalEntry *e)
|
||||
{
|
||||
char const *s;
|
||||
if (DoPrefixLineNo) {
|
||||
@@ -2556,7 +2573,7 @@ static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
||||
PrintJSONKeyPairInt("trep", e->tt.rep);
|
||||
}
|
||||
}
|
||||
WriteJSONTrigger(&e->trig, 0, today);
|
||||
WriteJSONTrigger(&e->trig, 0);
|
||||
if (e->nonconst_expr) {
|
||||
PrintJSONKeyPairInt("nonconst_expr", e->nonconst_expr);
|
||||
}
|
||||
@@ -2661,7 +2678,7 @@ static void WriteSimpleEntries(int col, int dse)
|
||||
}
|
||||
DidADay = 1;
|
||||
printf("{\"date\":\"%04d-%02d-%02d\",", y, m+1, d);
|
||||
WriteSimpleEntryProtocol2(e, dse);
|
||||
WriteSimpleEntryProtocol2(e);
|
||||
printf("}");
|
||||
if (PsCal != PSCAL_LEVEL3) {
|
||||
printf("\n");
|
||||
@@ -2673,7 +2690,6 @@ static void WriteSimpleEntries(int col, int dse)
|
||||
|
||||
free(e->text);
|
||||
free(e->raw_text);
|
||||
free(e->filename);
|
||||
FreeTrigInfoChain(e->infos);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
@@ -2797,7 +2813,7 @@ static void WriteCalDays(void)
|
||||
/* This takes into account duration */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
char const *
|
||||
static char const *
|
||||
CalendarTime(int tim, int duration)
|
||||
{
|
||||
static char buf[128];
|
||||
@@ -2895,7 +2911,8 @@ char const *SimpleTime(int tim)
|
||||
if (h == 0) hh=12;
|
||||
else if (h > 12) hh=h-12;
|
||||
else hh=h;
|
||||
snprintf(buf, sizeof(buf), "%d%c%02d%.64s ", hh, TimeSep, min, (h>=12) ? tr("pm") : tr("am"));
|
||||
snprintf(buf, sizeof(buf), "%d%c%02d%.64s ", hh, TimeSep, min, (h>=12) ? tr("pm") :
|
||||
tr("am"));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
12
src/dedupe.c
12
src/dedupe.c
@@ -28,9 +28,9 @@ typedef struct dedupe_entry {
|
||||
|
||||
static hash_table DedupeTable;
|
||||
|
||||
static unsigned int DedupeHashFunc(void *x)
|
||||
static unsigned int DedupeHashFunc(void const *x)
|
||||
{
|
||||
DedupeEntry *e = (DedupeEntry *) x;
|
||||
DedupeEntry const *e = (DedupeEntry const *) x;
|
||||
unsigned int hashval = (unsigned int) e->trigger_date;
|
||||
if (e->trigger_time != NO_TIME) {
|
||||
hashval += (unsigned int) e->trigger_time;
|
||||
@@ -39,10 +39,10 @@ static unsigned int DedupeHashFunc(void *x)
|
||||
return hashval;
|
||||
}
|
||||
|
||||
static int CompareDedupes(void *x, void *y)
|
||||
static int CompareDedupes(void const *x, void const *y)
|
||||
{
|
||||
DedupeEntry *a = (DedupeEntry *) x;
|
||||
DedupeEntry *b = (DedupeEntry *) y;
|
||||
DedupeEntry const *a = (DedupeEntry const *) x;
|
||||
DedupeEntry const *b = (DedupeEntry const *) y;
|
||||
if (a->trigger_date != b->trigger_date) return a->trigger_date - b->trigger_date;
|
||||
if (a->trigger_time != b->trigger_time) return a->trigger_time - b->trigger_time;
|
||||
return strcmp(a->body, b->body);
|
||||
@@ -122,7 +122,7 @@ InsertDedupeEntry(int trigger_date, int trigger_time, char const *body)
|
||||
int
|
||||
ShouldDedupe(int trigger_date, int trigger_time, char const *body)
|
||||
{
|
||||
DedupeEntry *e = FindDedupeEntry(trigger_date, trigger_time, body);
|
||||
DedupeEntry const *e = FindDedupeEntry(trigger_date, trigger_time, body);
|
||||
|
||||
if (e) {
|
||||
return 1;
|
||||
|
||||
507
src/dorem.c
507
src/dorem.c
@@ -29,8 +29,82 @@ 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, int type);
|
||||
static int ShouldTriggerBasedOnWarn (Trigger *t, int dse, int *err);
|
||||
static int ComputeTrigDuration(TimeTrig *t);
|
||||
static int ShouldTriggerBasedOnWarn (Trigger const *t, int dse, int *err);
|
||||
static int ComputeTrigDuration(TimeTrig const *t);
|
||||
|
||||
void remove_trailing_newlines(DynamicBuffer *buf)
|
||||
{
|
||||
char *s = (char *) DBufValue(buf) + DBufLen(buf) - 1;
|
||||
while (s >= DBufValue(buf)) {
|
||||
if (*s == '\n') {
|
||||
*s = 0;
|
||||
s--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
static int todo_filtered(Trigger const *t)
|
||||
{
|
||||
if (t->is_todo && TodoFilter == ONLY_EVENTS) return 1;
|
||||
if (!t->is_todo && TodoFilter == ONLY_TODOS) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_raw_scanfrom(Trigger const *t)
|
||||
{
|
||||
if (t->from != NO_DATE) {
|
||||
if (t->from > DSEToday) return t->from;
|
||||
return DSEToday;
|
||||
}
|
||||
if (t->scanfrom == NO_SCANFROM) return NO_SCANFROM;
|
||||
if (t->scanfrom > 0) return t->scanfrom;
|
||||
|
||||
/* Relative SCANFROM is negative, so subtract from today() */
|
||||
return DSEToday + t->scanfrom;
|
||||
}
|
||||
|
||||
int
|
||||
get_scanfrom(Trigger const *t)
|
||||
{
|
||||
int calmode = (DoSimpleCalendar || DoCalendar) ? 1 : 0;
|
||||
|
||||
/* TODOs are treated just like events in calendar mode */
|
||||
if (!calmode && t->is_todo && t->from != NO_DATE) {
|
||||
if (t->complete_through != NO_DATE) {
|
||||
if (t->complete_through+1 > t->from) {
|
||||
return t->complete_through+1;
|
||||
} else {
|
||||
return t->from;
|
||||
}
|
||||
} else {
|
||||
return t->from;
|
||||
}
|
||||
}
|
||||
if (get_raw_scanfrom(t) != NO_SCANFROM) {
|
||||
if (!calmode && t->complete_through != NO_DATE) {
|
||||
if (t->complete_through+1 > get_raw_scanfrom(t)) {
|
||||
return t->complete_through+1;
|
||||
} else {
|
||||
return get_raw_scanfrom(t);
|
||||
}
|
||||
} else {
|
||||
return get_raw_scanfrom(t);
|
||||
}
|
||||
}
|
||||
if (!calmode) {
|
||||
if (t->complete_through != NO_DATE) {
|
||||
return t->complete_through+1;
|
||||
}
|
||||
if (t->is_todo) {
|
||||
/* TODO with no COMPLETE-THROUGH.
|
||||
Scan from the beginning of time */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return DSEToday;
|
||||
}
|
||||
|
||||
static int
|
||||
ensure_expr_references_first_local_arg(expr_node *node)
|
||||
@@ -179,7 +253,7 @@ static void ensure_satnode_mentions_trigdate(expr_node *node)
|
||||
|
||||
|
||||
static int
|
||||
ComputeTrigDuration(TimeTrig *t)
|
||||
ComputeTrigDuration(TimeTrig const *t)
|
||||
{
|
||||
if (t->ttime == NO_TIME ||
|
||||
t->duration == NO_TIME) {
|
||||
@@ -213,6 +287,12 @@ int DoRem(ParsePtr p)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (trig.complete_through != NO_DATE && !trig.is_todo) {
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
FreeTrig(&trig);
|
||||
return E_COMPLETE_WITHOUT_TODO;
|
||||
}
|
||||
|
||||
if (trig.typ == NO_TYPE) {
|
||||
if (!Hush) {
|
||||
PurgeEchoLine("%s\n", "#!P! Cannot parse next line");
|
||||
@@ -286,7 +366,7 @@ int DoRem(ParsePtr p)
|
||||
}
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
dse = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
||||
dse = ComputeTrigger(get_scanfrom(&trig), &trig, &tim, &r, 1);
|
||||
if (r) {
|
||||
if (PurgeMode) {
|
||||
if (!Hush) {
|
||||
@@ -311,7 +391,7 @@ int DoRem(ParsePtr p)
|
||||
}
|
||||
}
|
||||
if (PurgeMode) {
|
||||
if (trig.expired || dse < DSEToday) {
|
||||
if (trig.expired || (!trig.is_todo && dse < DSEToday)) {
|
||||
if (p->expr_happened) {
|
||||
if (p->nonconst_expr) {
|
||||
if (!Hush) {
|
||||
@@ -339,8 +419,11 @@ int DoRem(ParsePtr p)
|
||||
if (dse == DSEToday &&
|
||||
!(!IgnoreOnce &&
|
||||
trig.once != NO_ONCE &&
|
||||
GetOnceDate() == DSEToday))
|
||||
QueueReminder(p, &trig, &tim, trig.sched);
|
||||
GetOnceDate() == DSEToday)) {
|
||||
if (!todo_filtered(&trig)) {
|
||||
QueueReminder(p, &trig, &tim, trig.sched);
|
||||
}
|
||||
}
|
||||
/* If we're in daemon mode, do nothing over here */
|
||||
if (Daemon) {
|
||||
FreeTrig(&trig);
|
||||
@@ -349,7 +432,72 @@ int DoRem(ParsePtr p)
|
||||
|
||||
r = OK;
|
||||
if (ShouldTriggerReminder(&trig, &tim, dse, &err)) {
|
||||
if ( (r=TriggerReminder(p, &trig, &tim, dse, 0, NULL)) ) {
|
||||
/* Filter unwanted events/todos */
|
||||
if (todo_filtered(&trig)) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (JSONMode) {
|
||||
DynamicBuffer body;
|
||||
int y, m, d;
|
||||
int if_depth = get_if_pointer() - get_base_if_pointer();
|
||||
DBufInit(&body);
|
||||
int red=-1, green=-1, blue=-1;
|
||||
r=TriggerReminder(p, &trig, &tim, dse, 0, &body, &red, &green, &blue);
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
/* Remove trailing newlines from body */
|
||||
remove_trailing_newlines(&body);
|
||||
|
||||
if (!*DBufValue(&body)) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
if (JSONLinesEmitted) {
|
||||
printf("},\n");
|
||||
}
|
||||
JSONLinesEmitted++;
|
||||
FromDSE(dse, &y, &m, &d);
|
||||
printf("{\"date\":\"%04d-%02d-%02d\",", y, m+1, d);
|
||||
PrintJSONKeyPairString("filename", GetCurrentFilename());
|
||||
PrintJSONKeyPairInt("lineno", LineNo);
|
||||
if (LineNoStart != LineNo) {
|
||||
PrintJSONKeyPairInt("lineno_start", LineNoStart);
|
||||
}
|
||||
PrintJSONKeyPairString("passthru", trig.passthru);
|
||||
if (trig.duration_days) {
|
||||
PrintJSONKeyPairInt("duration", trig.duration_days);
|
||||
}
|
||||
if (tim.ttime != NO_TIME) {
|
||||
PrintJSONKeyPairInt("time", tim.ttime);
|
||||
}
|
||||
if (p->nonconst_expr) {
|
||||
PrintJSONKeyPairInt("nonconst_expr", 1);
|
||||
}
|
||||
if (if_depth) {
|
||||
PrintJSONKeyPairInt("if_depth", if_depth);
|
||||
}
|
||||
if (tim.delta) {
|
||||
PrintJSONKeyPairInt("tdelta", tim.delta);
|
||||
}
|
||||
if (tim.rep) {
|
||||
PrintJSONKeyPairInt("trep", tim.rep);
|
||||
}
|
||||
if (red >= 0 && red <= 255 && green >= 0 && green <= 255 && blue >=0 && blue <= 255) {
|
||||
PrintJSONKeyPairInt("r", red);
|
||||
PrintJSONKeyPairInt("g", green);
|
||||
PrintJSONKeyPairInt("b", blue);
|
||||
}
|
||||
|
||||
WriteJSONTrigger(&trig, 1);
|
||||
printf("\"body\":\"");
|
||||
PrintJSONString(DBufValue(&body));
|
||||
printf("\"");
|
||||
} else {
|
||||
r=TriggerReminder(p, &trig, &tim, dse, 0, NULL, NULL, NULL, NULL);
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
@@ -369,6 +517,106 @@ int DoRem(ParsePtr p)
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* GetFullDate - get a full date, either YYYY-MM-DD or */
|
||||
/* YEAR MON DAY */
|
||||
/* */
|
||||
/* Returns OK on success or an error code on failure. Sets */
|
||||
/* *dse on success. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int GetFullDate(ParsePtr s, char const *prefix, int *dse)
|
||||
{
|
||||
Token tok;
|
||||
DynamicBuffer buf;
|
||||
int y = NO_YR, m = NO_MON, d = NO_DAY;
|
||||
int r;
|
||||
*dse = NO_DATE;
|
||||
|
||||
DBufInit(&buf);
|
||||
|
||||
while(1) {
|
||||
r = ParseToken(s, &buf);
|
||||
if (r) return r;
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
switch(tok.type) {
|
||||
case T_Year:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) {
|
||||
Eprint("%s: %s", prefix, GetErr(E_YR_TWICE));
|
||||
return E_YR_TWICE;
|
||||
}
|
||||
y = tok.val;
|
||||
break;
|
||||
|
||||
case T_Month:
|
||||
DBufFree(&buf);
|
||||
if (m != NO_MON) {
|
||||
Eprint("%s: %s", prefix, GetErr(E_MON_TWICE));
|
||||
return E_MON_TWICE;
|
||||
}
|
||||
m = tok.val;
|
||||
break;
|
||||
|
||||
case T_Day:
|
||||
DBufFree(&buf);
|
||||
if (d != NO_DAY) {
|
||||
Eprint("%s: %s", prefix, GetErr(E_DAY_TWICE));
|
||||
return E_DAY_TWICE;
|
||||
}
|
||||
d = tok.val;
|
||||
break;
|
||||
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) {
|
||||
Eprint("%s: %s", prefix, GetErr(E_YR_TWICE));
|
||||
return E_YR_TWICE;
|
||||
}
|
||||
if (m != NO_MON) {
|
||||
Eprint("%s: %s", prefix, GetErr(E_MON_TWICE));
|
||||
return E_MON_TWICE;
|
||||
}
|
||||
if (d != NO_DAY) {
|
||||
Eprint("%s: %s", prefix, GetErr(E_DAY_TWICE));
|
||||
return E_DAY_TWICE;
|
||||
}
|
||||
if (*dse != NO_DATE) {
|
||||
return E_DAY_TWICE;
|
||||
}
|
||||
*dse = tok.val;
|
||||
/* We're done here! */
|
||||
return OK;
|
||||
|
||||
default:
|
||||
if (tok.type == T_Illegal && tok.val < 0) {
|
||||
Eprint("%s: `%s'", GetErr(-tok.val), DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return -tok.val;
|
||||
}
|
||||
if (*dse == NO_DATE && (y == NO_YR || m == NO_MON || d == NO_DAY)) {
|
||||
Eprint("%s: %s", prefix, GetErr(E_INCOMPLETE));
|
||||
DBufFree(&buf);
|
||||
return E_INCOMPLETE;
|
||||
}
|
||||
if (*dse != NO_DATE) {
|
||||
PushToken(DBufValue(&buf), s);
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
}
|
||||
if (!DateOK(y, m, d)) {
|
||||
DBufFree(&buf);
|
||||
return E_BAD_DATE;
|
||||
}
|
||||
*dse = DSE(y, m, d);
|
||||
PushToken(DBufValue(&buf), s);
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* ParseRem */
|
||||
@@ -383,6 +631,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
DynamicBuffer buf;
|
||||
Token tok;
|
||||
int y, m, d;
|
||||
int dse;
|
||||
int seen_delta = 0;
|
||||
|
||||
DBufInit(&buf);
|
||||
@@ -401,7 +650,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
trig->addomit = 0;
|
||||
trig->noqueue = 0;
|
||||
trig->typ = NO_TYPE;
|
||||
trig->scanfrom = NO_DATE;
|
||||
trig->scanfrom = NO_SCANFROM;
|
||||
trig->from = NO_DATE;
|
||||
trig->priority = DefaultPrio;
|
||||
trig->sched[0] = 0;
|
||||
@@ -418,6 +667,8 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
tim->rep = NO_REP;
|
||||
tim->duration = NO_TIME;
|
||||
trig->need_wkday = 0;
|
||||
trig->is_todo = 0;
|
||||
trig->complete_through = NO_DATE;
|
||||
trig->adj_for_last = 0;
|
||||
trig->infos = NULL;
|
||||
|
||||
@@ -430,6 +681,11 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
/* Figure out what we've got */
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
switch(tok.type) {
|
||||
case T_Todo:
|
||||
if (trig->is_todo) return E_TODO_TWICE;
|
||||
trig->is_todo = 1;
|
||||
break;
|
||||
|
||||
case T_In:
|
||||
/* Completely ignored */
|
||||
DBufFree(&buf);
|
||||
@@ -556,6 +812,13 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case T_CompleteThrough:
|
||||
if (trig->complete_through != NO_DATE) return E_COMPLETE_THROUGH_TWICE;
|
||||
r = GetFullDate(s, "COMPLETE-THROUGH", &dse);
|
||||
if (r != OK) return r;
|
||||
trig->complete_through = dse;
|
||||
break;
|
||||
|
||||
case T_Until:
|
||||
DBufFree(&buf);
|
||||
r=ParseUntil(s, trig, tok.type);
|
||||
@@ -767,8 +1030,8 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
if (trig->until != NO_UNTIL && trig->until < trig->from) {
|
||||
Wprint(tr("Warning: UNTIL/THROUGH date earlier than FROM date"));
|
||||
}
|
||||
} else if (trig->scanfrom != NO_DATE) {
|
||||
if (trig->until != NO_UNTIL && trig->until < trig->scanfrom) {
|
||||
} else if (get_raw_scanfrom(trig) != NO_SCANFROM) {
|
||||
if (trig->until != NO_UNTIL && trig->until < get_raw_scanfrom(trig)) {
|
||||
Wprint(tr("Warning: UNTIL/THROUGH date earlier than SCANFROM date"));
|
||||
}
|
||||
}
|
||||
@@ -778,11 +1041,6 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
Wprint(tr("Warning: Useless use of UNTIL with fully-specified date and no *rep"));
|
||||
}
|
||||
|
||||
/* Set scanfrom to default if not set explicitly */
|
||||
if (trig->scanfrom == NO_DATE) {
|
||||
trig->scanfrom = DSEToday;
|
||||
}
|
||||
|
||||
/* Check that any SCHED / WARN / OMITFUNC functions refer to
|
||||
their arguments */
|
||||
check_trigger_function(trig->sched, "SCHED");
|
||||
@@ -884,93 +1142,25 @@ static int ParseLocalOmit(ParsePtr s, Trigger *t)
|
||||
/***************************************************************/
|
||||
static int ParseUntil(ParsePtr s, Trigger *t, int type)
|
||||
{
|
||||
int y = NO_YR,
|
||||
m = NO_MON,
|
||||
d = NO_DAY;
|
||||
|
||||
char const *which;
|
||||
int dse;
|
||||
|
||||
if (type == T_Until) {
|
||||
which = "UNTIL";
|
||||
} else {
|
||||
which = "THROUGH";
|
||||
}
|
||||
Token tok;
|
||||
int r;
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
|
||||
if (t->until != NO_UNTIL) return E_UNTIL_TWICE;
|
||||
|
||||
while(1) {
|
||||
r = ParseToken(s, &buf);
|
||||
if (r) return r;
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
switch(tok.type) {
|
||||
case T_Year:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) {
|
||||
Eprint("%s: %s", which, GetErr(E_YR_TWICE));
|
||||
return E_YR_TWICE;
|
||||
}
|
||||
y = tok.val;
|
||||
break;
|
||||
|
||||
case T_Month:
|
||||
DBufFree(&buf);
|
||||
if (m != NO_MON) {
|
||||
Eprint("%s: %s", which, GetErr(E_MON_TWICE));
|
||||
return E_MON_TWICE;
|
||||
}
|
||||
m = tok.val;
|
||||
break;
|
||||
|
||||
case T_Day:
|
||||
DBufFree(&buf);
|
||||
if (d != NO_DAY) {
|
||||
Eprint("%s: %s", which, GetErr(E_DAY_TWICE));
|
||||
return E_DAY_TWICE;
|
||||
}
|
||||
d = tok.val;
|
||||
break;
|
||||
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) {
|
||||
Eprint("%s: %s", which, GetErr(E_YR_TWICE));
|
||||
return E_YR_TWICE;
|
||||
}
|
||||
if (m != NO_MON) {
|
||||
Eprint("%s: %s", which, GetErr(E_MON_TWICE));
|
||||
return E_MON_TWICE;
|
||||
}
|
||||
if (d != NO_DAY) {
|
||||
Eprint("%s: %s", which, GetErr(E_DAY_TWICE));
|
||||
return E_DAY_TWICE;
|
||||
}
|
||||
FromDSE(tok.val, &y, &m, &d);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (tok.type == T_Illegal && tok.val < 0) {
|
||||
Eprint("%s: `%s'", GetErr(-tok.val), DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return -tok.val;
|
||||
}
|
||||
if (y == NO_YR || m == NO_MON || d == NO_DAY) {
|
||||
Eprint("%s: %s", which, GetErr(E_INCOMPLETE));
|
||||
DBufFree(&buf);
|
||||
return E_INCOMPLETE;
|
||||
}
|
||||
if (!DateOK(y, m, d)) {
|
||||
DBufFree(&buf);
|
||||
return E_BAD_DATE;
|
||||
}
|
||||
t->until = DSE(y, m, d);
|
||||
PushToken(DBufValue(&buf), s);
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
}
|
||||
int r = GetFullDate(s, which, &dse);
|
||||
if (r != OK) {
|
||||
return r;
|
||||
}
|
||||
|
||||
t->until = dse;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -980,12 +1170,9 @@ static int ParseUntil(ParsePtr s, Trigger *t, int type)
|
||||
/***************************************************************/
|
||||
static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
{
|
||||
int y = NO_YR,
|
||||
m = NO_MON,
|
||||
d = NO_DAY;
|
||||
|
||||
Token tok;
|
||||
int r;
|
||||
int y = NO_YR, m = NO_MON, d = NO_DAY;
|
||||
Token tok;
|
||||
DynamicBuffer buf;
|
||||
char const *word;
|
||||
|
||||
@@ -996,8 +1183,8 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
word = "FROM";
|
||||
}
|
||||
|
||||
if (t->scanfrom != NO_DATE) return E_SCAN_TWICE;
|
||||
|
||||
if (t->scanfrom != NO_SCANFROM) return E_SCAN_TWICE;
|
||||
if (t->from != NO_DATE) return E_SCAN_TWICE;
|
||||
while(1) {
|
||||
r = ParseToken(s, &buf);
|
||||
if (r) return r;
|
||||
@@ -1044,8 +1231,12 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
Eprint("%s: %s", word, GetErr(E_DAY_TWICE));
|
||||
return E_DAY_TWICE;
|
||||
}
|
||||
FromDSE(tok.val, &y, &m, &d);
|
||||
break;
|
||||
if (type == FROM_TYPE) {
|
||||
t->from = tok.val;
|
||||
} else {
|
||||
t->scanfrom = tok.val;
|
||||
}
|
||||
return OK;
|
||||
|
||||
case T_Back:
|
||||
DBufFree(&buf);
|
||||
@@ -1065,15 +1256,14 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
Eprint("%s: %s", word, GetErr(E_DAY_TWICE));
|
||||
return E_DAY_TWICE;
|
||||
}
|
||||
if (tok.val < 0) {
|
||||
if (tok.val > 0) {
|
||||
tok.val = -tok.val;
|
||||
}
|
||||
FromDSE(DSEToday - tok.val, &y, &m, &d);
|
||||
/* Don't purge reminders with a relative scanfrom */
|
||||
t->scanfrom = tok.val;
|
||||
s->expr_happened = 1;
|
||||
nonconst_debug(s->nonconst_expr, tr("Relative SCANFROM counts as a non-constant expression"));
|
||||
s->nonconst_expr = 1;
|
||||
break;
|
||||
return OK;
|
||||
|
||||
default:
|
||||
if (tok.type == T_Illegal && tok.val < 0) {
|
||||
@@ -1090,14 +1280,10 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
DBufFree(&buf);
|
||||
return E_BAD_DATE;
|
||||
}
|
||||
t->scanfrom = DSE(y, m, d);
|
||||
if (type == FROM_TYPE) {
|
||||
t->from = t->scanfrom;
|
||||
if (t->scanfrom < DSEToday) {
|
||||
t->scanfrom = DSEToday;
|
||||
}
|
||||
t->from = DSE(y, m, d);
|
||||
} else {
|
||||
t->from = NO_DATE;
|
||||
t->scanfrom = DSE(y, m, d);
|
||||
}
|
||||
|
||||
PushToken(DBufValue(&buf), s);
|
||||
@@ -1115,7 +1301,7 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
/* Trigger the reminder if it's a RUN or MSG type. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queued, DynamicBuffer *output)
|
||||
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is_queued, DynamicBuffer *output, int *rr, int *gg, int *bb)
|
||||
{
|
||||
int r, y, m, d;
|
||||
int adjusted_for_newline = 0;
|
||||
@@ -1180,17 +1366,37 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
t->typ = MSG_TYPE;
|
||||
|
||||
if (red < 0 || green < 0 || blue < 0 || red > 255 || green > 255 || blue > 255) {
|
||||
red = -1;
|
||||
green = -1;
|
||||
blue = -1;
|
||||
t->passthru[0] = 0;
|
||||
}
|
||||
}
|
||||
/* If it's a MSG-type reminder, and no -k option was used, issue the banner. */
|
||||
if ((t->typ == MSG_TYPE || t->typ == MSF_TYPE)
|
||||
&& !DidMsgReminder && !NextMode && !msg_command && !is_queued) {
|
||||
DynamicBuffer buf2;
|
||||
DBufInit(&buf2);
|
||||
DidMsgReminder = 1;
|
||||
if (!DoSubstFromString(DBufValue(&Banner), &buf,
|
||||
if (!DoSubstFromString(DBufValue(&Banner), &buf2,
|
||||
DSEToday, NO_TIME) &&
|
||||
DBufLen(&buf)) {
|
||||
printf("%s\n", DBufValue(&buf));
|
||||
DBufLen(&buf2)) {
|
||||
if (!JSONMode) {
|
||||
printf("%s\n", DBufValue(&buf2));
|
||||
} else {
|
||||
if (JSONLinesEmitted) {
|
||||
printf("},\n");
|
||||
}
|
||||
JSONLinesEmitted++;
|
||||
printf("{\"banner\":\"");
|
||||
remove_trailing_newlines(&buf2);
|
||||
PrintJSONString(DBufValue(&buf2));
|
||||
printf("\"");
|
||||
}
|
||||
}
|
||||
DBufFree(&buf);
|
||||
DBufFree(&buf2);
|
||||
}
|
||||
|
||||
/* If it's NextMode, process as a ADVANCE_MODE-type entry, and issue
|
||||
@@ -1265,7 +1471,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
||||
}
|
||||
|
||||
/* Correct colors */
|
||||
if (UseVTColors) {
|
||||
if (JSONMode || UseVTColors) {
|
||||
if (red == -1 && green == -1 && blue == -1) {
|
||||
if (DefaultColorR != -1 && DefaultColorG != -1 && DefaultColorB != -1) {
|
||||
red = DefaultColorR;
|
||||
@@ -1279,6 +1485,17 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
||||
if (green > 255) green = 255;
|
||||
if (blue > 255) blue = 255;
|
||||
}
|
||||
if (rr) *rr = red;
|
||||
if (gg) *gg = green;
|
||||
if (bb) *bb = blue;
|
||||
|
||||
/* Don't ANSI-colorize JSON output! */
|
||||
if (JSONMode) {
|
||||
is_color = 0;
|
||||
red = -1;
|
||||
green = -1;
|
||||
blue = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Put the substituted string into the substitution buffer */
|
||||
@@ -1427,16 +1644,38 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
||||
/* triggered. Sets *err non-zero in event of an error. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int dse, int *err)
|
||||
int ShouldTriggerReminder(Trigger const *t, TimeTrig const *tim, int dse, int *err)
|
||||
{
|
||||
int r, omit;
|
||||
int calmode = (DoSimpleCalendar || DoCalendar) ? 1 : 0;
|
||||
if (HideCompletedTodos) calmode = 0;
|
||||
|
||||
*err = 0;
|
||||
|
||||
/* Handle the ONCE modifier in the reminder. */
|
||||
if (!IgnoreOnce && t->once !=NO_ONCE && GetOnceDate() == DSEToday)
|
||||
return 0;
|
||||
|
||||
if (dse < DSEToday) return 0;
|
||||
/* TODOs are handled differently */
|
||||
if (t->is_todo && !calmode) {
|
||||
/* Do NOT trigger if TODO has been completed through today (or later) */
|
||||
if (t->complete_through != NO_DATE && t->complete_through >= DSEToday && dse <= t->complete_through) {
|
||||
return 0;
|
||||
}
|
||||
/* DO trigger if has not been completed through trigger date */
|
||||
if (t->complete_through == NO_DATE || t->complete_through < dse) {
|
||||
/* Trigger date is in the past - overdue */
|
||||
if (dse < DSEToday) {
|
||||
return 1;
|
||||
}
|
||||
/* Trigger date in future - use normal Remind rules */
|
||||
} else {
|
||||
/* We're complete as of trigger date */
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (dse < DSEToday) return 0;
|
||||
}
|
||||
|
||||
/* Don't trigger timed reminders if DontIssueAts is true, and if the
|
||||
reminder is for today */
|
||||
@@ -1530,7 +1769,7 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
||||
ensure_satnode_mentions_trigdate(sat_node);
|
||||
|
||||
iter = 0;
|
||||
start = trig->scanfrom;
|
||||
start = get_scanfrom(trig);
|
||||
while (iter++ < MaxSatIter) {
|
||||
dse = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, 0);
|
||||
if (r) {
|
||||
@@ -1554,6 +1793,8 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
||||
}
|
||||
if (dse == -1) {
|
||||
free_expr_tree(sat_node);
|
||||
LastTrigValid = 0;
|
||||
LastTriggerDate = -1;
|
||||
return E_EXPIRED;
|
||||
}
|
||||
r = evaluate_expression(sat_node, NULL, &v, &nonconst);
|
||||
@@ -1567,12 +1808,12 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
||||
}
|
||||
if ((v.type == INT_TYPE && v.v.val) ||
|
||||
(v.type == STR_TYPE && *v.v.str)) {
|
||||
AdjustTriggerForDuration(trig->scanfrom, dse, trig, tt, 1);
|
||||
AdjustTriggerForDuration(get_scanfrom(trig), dse, trig, tt, 1);
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
int y, m, d;
|
||||
FromDSE(LastTriggerDate, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%s): Trig(satisfied) = %s, %d %s, %d",
|
||||
FileName, line_range(LineNoStart, LineNo),
|
||||
GetCurrentFilename(), line_range(LineNoStart, LineNo),
|
||||
get_day_name(LastTriggerDate % 7),
|
||||
d,
|
||||
get_month_name(m),
|
||||
@@ -1702,7 +1943,7 @@ finished:
|
||||
/* function. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int ShouldTriggerBasedOnWarn(Trigger *t, int dse, int *err)
|
||||
static int ShouldTriggerBasedOnWarn(Trigger const *t, int dse, int *err)
|
||||
{
|
||||
char buffer[VAR_NAME_LEN+32];
|
||||
int i;
|
||||
@@ -1710,6 +1951,26 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int dse, int *err)
|
||||
int r, omit;
|
||||
Value v;
|
||||
int lastReturnVal = 0; /* Silence compiler warning */
|
||||
int calmode = (DoSimpleCalendar || DoCalendar) ? 1 : 0;
|
||||
|
||||
/* TODOs are handled differently */
|
||||
if (t->is_todo && !calmode) {
|
||||
/* Do NOT trigger if TODO has been completed through today (or later) */
|
||||
if (t->complete_through != NO_DATE && t->complete_through >= DSEToday) {
|
||||
return 0;
|
||||
}
|
||||
/* DO trigger if has not been completed through trigger date */
|
||||
if (t->complete_through == NO_DATE || t->complete_through < dse) {
|
||||
/* Trigger date is in the past - overdue */
|
||||
if (dse < DSEToday) {
|
||||
return 1;
|
||||
}
|
||||
/* Trigger date in future - use normal Remind rules */
|
||||
} else {
|
||||
/* We're complete as of trigger date */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If no proper function exists, barf... */
|
||||
if (UserFuncExists(t->warn) != 1) {
|
||||
|
||||
@@ -54,9 +54,11 @@ check_subst_args(UserFunc *f, int n)
|
||||
/* If mode==ADVANCE_MODE, ignore %" but don't add newline */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse, int mode)
|
||||
int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig const *tt, int dse, int mode)
|
||||
{
|
||||
int diff = dse - DSEToday;
|
||||
int rdiff = dse - RealToday;
|
||||
int bangdiff = diff;
|
||||
int curtime = MinutesPastMidnight(0);
|
||||
int err, done;
|
||||
int c;
|
||||
@@ -67,6 +69,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
char const *pm, *cpm;
|
||||
int tdiff, adiff, mdiff, hdiff;
|
||||
char const *mplu, *hplu, *when, *plu;
|
||||
char const *is, *was;
|
||||
int has_quote = 0;
|
||||
char *ss;
|
||||
char const *expr;
|
||||
@@ -98,7 +101,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
mplu = (mdiff == 1 ? "" : DynamicMplu);
|
||||
hplu = (hdiff == 1 ? "" : DynamicHplu);
|
||||
|
||||
when = (tdiff < 0) ? tr("ago") : tr("from now");
|
||||
when = (tdiff < 0) ? tr("ago") :
|
||||
tr("from now");
|
||||
|
||||
h = tim / 60;
|
||||
min = tim % 60;
|
||||
@@ -122,7 +126,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
}
|
||||
}
|
||||
if (r != OK) {
|
||||
pm = (h < 12) ? tr("am") : tr("pm");
|
||||
pm = (h < 12) ? tr("am") :
|
||||
tr("pm");
|
||||
}
|
||||
|
||||
hh = (h == 12 || h == 0) ? 12 : h % 12;
|
||||
@@ -149,7 +154,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
}
|
||||
}
|
||||
if (r != OK) {
|
||||
cpm = (h < 12) ? tr("am") : tr("pm");
|
||||
cpm = (h < 12) ? tr("am") :
|
||||
tr("pm");
|
||||
}
|
||||
chh = (ch == 0 || ch == 12) ? 12 : ch % 12;
|
||||
|
||||
@@ -358,7 +364,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
}
|
||||
}
|
||||
|
||||
if (diff <= 1) {
|
||||
if (abs(diff) <= 1) {
|
||||
switch(UPPER(c)) {
|
||||
case 'A':
|
||||
case 'B':
|
||||
@@ -373,7 +379,9 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
case 'L':
|
||||
case 'U':
|
||||
case 'V':
|
||||
snprintf(s, sizeof(s), "%s", (diff ? tr("tomorrow") : tr("today")));
|
||||
snprintf(s, sizeof(s), "%s", (diff == 1 ? tr("tomorrow") :
|
||||
diff == -1 ? tr("yesterday") :
|
||||
tr("today")));
|
||||
SHIP_OUT(s);
|
||||
done = 1;
|
||||
break;
|
||||
@@ -408,7 +416,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
}
|
||||
}
|
||||
if (origtime == NO_TIME) {
|
||||
if ((c >= '0' && c <= '9') || (c == '!')) {
|
||||
if ((c >= '0' && c <= '9')) {
|
||||
Wprint(tr("`%%%c' substitution sequence should not be used without an AT clause"), c);
|
||||
}
|
||||
}
|
||||
@@ -426,7 +434,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
snprintf(s, sizeof(s), "in %d days' time", diff);
|
||||
if (diff > 0) {
|
||||
snprintf(s, sizeof(s), "in %d days' time", diff);
|
||||
} else {
|
||||
snprintf(s, sizeof(s), "%d days ago", -diff);
|
||||
}
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
|
||||
@@ -614,7 +626,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
snprintf(s, sizeof(s), "%d %s%s %s", hdiff, tr("hour"), hplu, when);
|
||||
else
|
||||
snprintf(s, sizeof(s), "%d %s%s %s %d %s%s %s", hdiff, tr("hour"), hplu,
|
||||
tr("and"), mdiff, tr("minute"), mplu, when);
|
||||
tr("and"), mdiff,
|
||||
tr("minute"), mplu, when);
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
|
||||
@@ -672,7 +685,26 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
break;
|
||||
|
||||
case '!':
|
||||
snprintf(s, sizeof(s), "%s", (tdiff >= 0 ? tr("is") : tr("was")));
|
||||
case '?':
|
||||
if (c == '!') {
|
||||
is = tr("is");
|
||||
was = tr("was");
|
||||
} else {
|
||||
is = tr("are");
|
||||
was = tr("were");
|
||||
}
|
||||
if (altmode) {
|
||||
bangdiff = rdiff;
|
||||
} else {
|
||||
bangdiff = diff;
|
||||
}
|
||||
if (bangdiff > 0) {
|
||||
snprintf(s, sizeof(s), "%s", is);
|
||||
} else if (bangdiff < 0) {
|
||||
snprintf(s, sizeof(s), "%s", was);
|
||||
} else {
|
||||
snprintf(s, sizeof(s), "%s", (tdiff >= 0 ? is : was));
|
||||
}
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
|
||||
|
||||
34
src/err.h
34
src/err.h
@@ -23,25 +23,25 @@
|
||||
#define E_MISS_END 1
|
||||
#define E_MISS_QUOTE 2
|
||||
#define E_OP_STK_OVER 3
|
||||
/* #define E_VA_STK_OVER 4 */
|
||||
#define E_CANT_PARSE_MONTH 4
|
||||
#define E_MISS_RIGHT_PAREN 5
|
||||
#define E_UNDEF_FUNC 6
|
||||
#define E_ILLEGAL_CHAR 7
|
||||
/* #define E_EXPECTING_BINOP 8 */
|
||||
#define E_CANT_PARSE_WKDAY 8
|
||||
#define E_NO_MEM 9
|
||||
#define E_BAD_NUMBER 10
|
||||
/* #define E_OP_STK_UNDER 11 */
|
||||
/* #define E_VA_STK_UNDER 12 */
|
||||
#define E_PUSHV_NO_POP 11
|
||||
#define E_POPV_NO_PUSH 12
|
||||
#define E_CANT_COERCE 13
|
||||
#define E_BAD_TYPE 14
|
||||
#define E_DATE_OVER 15
|
||||
/* #define E_STACK_ERR 16 */
|
||||
#define E_POPF_NO_PUSH 16
|
||||
#define E_DIV_ZERO 17
|
||||
#define E_NOSUCH_VAR 18
|
||||
#define E_EOLN 19
|
||||
#define E_EOF 20
|
||||
#define E_IO_ERR 21
|
||||
/* #define E_LINE_2_LONG 22 */
|
||||
#define E_PUSHF_NO_POP 22
|
||||
#define E_SWERR 23
|
||||
#define E_BAD_DATE 24
|
||||
#define E_2FEW_ARGS 25
|
||||
@@ -76,7 +76,7 @@
|
||||
#define E_DAY_TWICE 52
|
||||
#define E_UNKNOWN_TOKEN 53
|
||||
#define E_SPEC_MON 54
|
||||
/* #define E_2MANY_PART 55 */
|
||||
#define E_TODO_TWICE 55
|
||||
#define E_2MANY_FULL 56
|
||||
#define E_PUSH_NOPOP 57
|
||||
#define E_ERR_READING 58
|
||||
@@ -114,7 +114,7 @@
|
||||
#define E_MISS_EQ 90
|
||||
#define E_MISS_VAR 91
|
||||
#define E_MISS_EXPR 92
|
||||
/* #define M_CANTSET_ACCESS 93 */
|
||||
#define E_COMPLETE_THROUGH_TWICE 93
|
||||
#define M_I_OPTION 94
|
||||
#define E_NOREMINDERS 95
|
||||
#define M_QUEUED 96
|
||||
@@ -129,6 +129,7 @@
|
||||
#define E_REPEATED_ARG 105
|
||||
#define E_EXPR_DISABLED 106
|
||||
#define E_TIME_EXCEEDED 107
|
||||
#define E_COMPLETE_WITHOUT_TODO 108
|
||||
|
||||
#ifdef MK_GLOBALS
|
||||
#undef EXTERN
|
||||
@@ -151,25 +152,25 @@ EXTERN char *ErrMsg[]
|
||||
/* E_MISS_END */ "Missing ']'",
|
||||
/* E_MISS_QUOTE */ "Missing quote",
|
||||
/* E_OP_STK_OVER */ "Expression too complex",
|
||||
/* E_VA_STK_OVER */ "",
|
||||
/* E_CANT_PARSE_MONTH */ "Invalid month name",
|
||||
/* E_MISS_RIGHT_PAREN */ "Missing ')'",
|
||||
/* E_UNDEF_FUNC */ "Undefined function",
|
||||
/* E_ILLEGAL_CHAR */ "Illegal character",
|
||||
/* E_EXPECTING_BINOP */ "Expecting binary operator",
|
||||
/* E_CANT_PARSE_WKDAY*/ "Invalid weekday name",
|
||||
/* E_NO_MEM */ "Out of memory",
|
||||
/* E_BAD_NUMBER */ "Ill-formed number",
|
||||
/* E_OP_STK_UNDER */ "",
|
||||
/* E_VA_STK_UNDER */ "",
|
||||
/* E_PUSHV_NO_POP */ "Warning: PUSH-VARS without matching POP-VARS",
|
||||
/* E_POPV_NO_PUSH */ "POP-VARS without matching PUSH-VARS",
|
||||
/* E_CANT_COERCE */ "Can't coerce",
|
||||
/* E_BAD_TYPE */ "Type mismatch",
|
||||
/* E_DATE_OVER */ "Date overflow",
|
||||
/* E_STACK_ERR */ "",
|
||||
/* E_POPF_NO_PUSH */ "POP-FUNCS without matching PUSH-FUNCS",
|
||||
/* E_DIV_ZERO */ "Division by zero",
|
||||
/* E_NOSUCH_VAR */ "Undefined variable",
|
||||
/* E_EOLN */ "Unexpected end of line",
|
||||
/* E_EOF */ "Unexpected end of file",
|
||||
/* E_IO_ERR */ "I/O error",
|
||||
/* E_LINE_2_LONG */ "",
|
||||
/* E_PUSHF_NO_POP */ "Warning: PUSH-FUNCS without matching POP-FUNCS",
|
||||
/* E_SWERR */ "Internal error",
|
||||
/* E_BAD_DATE */ "Bad date specification",
|
||||
/* E_2FEW_ARGS */ "Not enough arguments",
|
||||
@@ -202,7 +203,7 @@ EXTERN char *ErrMsg[]
|
||||
/* E_DAY_TWICE */ "Day specified twice",
|
||||
/* E_UNKNOWN_TOKEN */ "Unknown token",
|
||||
/* E_SPEC_MON */ "Must specify month in OMIT command",
|
||||
/* E_2MANY_PART */ "",
|
||||
/* E_TODO_TWICE */ "TODO specified twice",
|
||||
/* E_2MANY_FULL */ "Too many full OMITs (max. " STR(MAX_FULL_OMITS) ")",
|
||||
/* E_PUSH_NOPOP */ "Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT",
|
||||
/* E_ERR_READING */ "Error reading",
|
||||
@@ -240,7 +241,7 @@ EXTERN char *ErrMsg[]
|
||||
/* E_MISS_EQ */ "Missing '=' sign",
|
||||
/* E_MISS_VAR */ "Missing variable name",
|
||||
/* E_MISS_EXPR */ "Missing expression",
|
||||
/* M_CANTSET_ACCESS */ "",
|
||||
/* E_COMPLETE_THROUGH_TWICE */ "COMPLETE-THROUGH specified twice",
|
||||
/* M_I_OPTION */ "Remind: '-i' option: %s",
|
||||
/* E_NOREMINDERS */ "No reminders.",
|
||||
/* M_QUEUED */ "%d reminder(s) queued for later today.",
|
||||
@@ -255,6 +256,7 @@ EXTERN char *ErrMsg[]
|
||||
/* E_REPEATED_ARG */ "Duplicate argument name",
|
||||
/* E_EXPR_DISABLED */ "Expression evaluation is disabled",
|
||||
/* E_TIME_EXCEEDED */ "Time limit for expression evaluation exceeded",
|
||||
/* E_COMPLETE_WITHOUT_TODO */ "COMPLETE-THROUGH specified without TODO",
|
||||
}
|
||||
#endif /* MK_GLOBALS */
|
||||
;
|
||||
|
||||
91
src/expr.c
91
src/expr.c
@@ -191,6 +191,7 @@ static int ExprNodesUsed = 0;
|
||||
/* Forward references */
|
||||
static expr_node * parse_expression_aux(char const **e, int *r, Var *locals, int level);
|
||||
static char const *get_operator_name(expr_node *node);
|
||||
static void print_expr_tree(expr_node *node, FILE *fp);
|
||||
|
||||
/* This is super-skanky... we keep track of the currently-executing
|
||||
user-defined function in a global var */
|
||||
@@ -425,7 +426,8 @@ get_var(expr_node *node, Value *ans, int *nonconst)
|
||||
Eprint("%s: `%s'", GetErr(E_NOSUCH_VAR), str);
|
||||
return E_NOSUCH_VAR;
|
||||
}
|
||||
if (v->nonconstant) {
|
||||
v->used_since_set = 1;
|
||||
if (!v->is_constant) {
|
||||
nonconst_debug(*nonconst, tr("Global variable `%s' makes expression non-constant"), str);
|
||||
*nonconst = 1;
|
||||
}
|
||||
@@ -442,7 +444,7 @@ get_var(expr_node *node, Value *ans, int *nonconst)
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int
|
||||
get_sysvar(expr_node *node, Value *ans)
|
||||
get_sysvar(expr_node const *node, Value *ans)
|
||||
{
|
||||
if (node->type == N_SHORT_SYSVAR) {
|
||||
return GetSysVar(node->u.name, ans);
|
||||
@@ -568,6 +570,13 @@ eval_builtin(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
/* All went well; copy the result destructively */
|
||||
(*ans) = info.retval;
|
||||
|
||||
/* Special case of const cunction */
|
||||
if (!strcmp(f->name, "const")) {
|
||||
if (*nonconst) {
|
||||
nonconst_debug(0, tr("Non-constant expression converted to constant by `const' built-in function"));
|
||||
}
|
||||
*nonconst = 0;
|
||||
}
|
||||
/* Don't allow retval to be destroyed! */
|
||||
info.retval.type = ERR_TYPE;
|
||||
}
|
||||
@@ -825,7 +834,7 @@ evaluate_expression(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int CopyShortStr(Value *ans, expr_node *node)
|
||||
static int CopyShortStr(Value *ans, expr_node const *node)
|
||||
{
|
||||
size_t len = strlen(node->u.name);
|
||||
ans->v.str = malloc(len+1);
|
||||
@@ -1827,6 +1836,78 @@ expr_node * free_expr_tree(expr_node *node)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* clone_expr_tree */
|
||||
/* */
|
||||
/* Clone an entire expr_tree. The clone shares no memory */
|
||||
/* with the original. Returns NULL and sets *r on failure. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
expr_node * clone_expr_tree(expr_node const *src, int *r)
|
||||
{
|
||||
int rc;
|
||||
expr_node *dest = alloc_expr_node(r);
|
||||
if (!dest) return NULL;
|
||||
|
||||
dest->type = src->type;
|
||||
dest->num_kids = src->num_kids;
|
||||
switch(dest->type) {
|
||||
case N_FREE:
|
||||
case N_ERROR:
|
||||
*r = E_SWERR;
|
||||
free_expr_tree(dest);
|
||||
return NULL;
|
||||
|
||||
case N_CONSTANT:
|
||||
case N_VARIABLE:
|
||||
case N_SYSVAR:
|
||||
case N_USER_FUNC:
|
||||
rc = CopyValue(&(dest->u.value), &(src->u.value));
|
||||
if (rc != OK) {
|
||||
*r = rc;
|
||||
free_expr_tree(dest);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case N_SHORT_STR:
|
||||
case N_SHORT_VAR:
|
||||
case N_SHORT_SYSVAR:
|
||||
case N_SHORT_USER_FUNC:
|
||||
strcpy(dest->u.name, src->u.name);
|
||||
break;
|
||||
|
||||
case N_LOCAL_VAR:
|
||||
dest->u.arg = src->u.arg;
|
||||
break;
|
||||
|
||||
case N_BUILTIN_FUNC:
|
||||
dest->u.builtin_func = src->u.builtin_func;
|
||||
break;
|
||||
|
||||
case N_OPERATOR:
|
||||
dest->u.operator_func = src->u.operator_func;
|
||||
break;
|
||||
}
|
||||
|
||||
if (src->child) {
|
||||
dest->child = clone_expr_tree(src->child, r);
|
||||
if (!dest->child) {
|
||||
free_expr_tree(dest);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (src->sibling) {
|
||||
dest->sibling = clone_expr_tree(src->sibling, r);
|
||||
if (!dest->sibling) {
|
||||
free_expr_tree(dest);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* set_long_name - set a long name in an expr_node */
|
||||
@@ -2704,7 +2785,7 @@ static void print_kids(expr_node *node, FILE *fp)
|
||||
/* file. Used for debugging (the "-ds" flag.) */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void print_expr_tree(expr_node *node, FILE *fp)
|
||||
static void print_expr_tree(expr_node *node, FILE *fp)
|
||||
{
|
||||
if (!node) {
|
||||
return;
|
||||
@@ -2953,7 +3034,7 @@ int CopyValue(Value *dest, const Value *src)
|
||||
/* 4:00PM */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ParseLiteralTime(char const **s, int *tim)
|
||||
static int ParseLiteralTime(char const **s, int *tim)
|
||||
{
|
||||
int h=0;
|
||||
int m=0;
|
||||
|
||||
104
src/files.c
104
src/files.c
@@ -20,6 +20,7 @@
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef TM_IN_SYS_TIME
|
||||
#include <sys/time.h>
|
||||
@@ -85,10 +86,21 @@ typedef struct {
|
||||
int ownedByMe;
|
||||
} IncludeStruct;
|
||||
|
||||
typedef struct fn_entry {
|
||||
struct hash_link link;
|
||||
char const *fname;
|
||||
} FilenameHashEntry;
|
||||
|
||||
/* A hash table to hold unique copies of all the filenames we process */
|
||||
static hash_table FilenameHashTable;
|
||||
|
||||
static CachedFile *CachedFiles = (CachedFile *) NULL;
|
||||
static CachedLine *CLine = (CachedLine *) NULL;
|
||||
static DirectoryFilenameChain *CachedDirectoryChains = NULL;
|
||||
|
||||
/* Current filename */
|
||||
static char const *FileName = NULL;
|
||||
|
||||
static FILE *fp;
|
||||
|
||||
static IncludeStruct IStack[INCLUDE_NEST];
|
||||
@@ -102,6 +114,64 @@ static int CheckSafetyAux (struct stat *statbuf);
|
||||
static int PopFile (void);
|
||||
static int IncludeCmd(char const *);
|
||||
|
||||
static unsigned int FnHashFunc(void const *x)
|
||||
{
|
||||
FilenameHashEntry const *e = (FilenameHashEntry const *) x;
|
||||
return HashVal_preservecase(e->fname);
|
||||
}
|
||||
|
||||
static int FnCompareFunc(void const *a, void const *b)
|
||||
{
|
||||
FilenameHashEntry const *e1 = (FilenameHashEntry const *) a;
|
||||
FilenameHashEntry const *e2 = (FilenameHashEntry const *) b;
|
||||
return strcmp(e1->fname, e2->fname);
|
||||
}
|
||||
|
||||
void InitFiles(void)
|
||||
{
|
||||
if (hash_table_init(&FilenameHashTable, offsetof(FilenameHashEntry, link),
|
||||
FnHashFunc, FnCompareFunc) < 0) {
|
||||
fprintf(ErrFp, "Unable to initialize filename hash table: Out of memory. Exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void SetCurrentFilename(char const *fname)
|
||||
{
|
||||
FilenameHashEntry *e;
|
||||
FilenameHashEntry candidate;
|
||||
candidate.fname = fname;
|
||||
|
||||
e = (FilenameHashEntry *) hash_table_find(&FilenameHashTable, &candidate);
|
||||
if (!e) {
|
||||
e = NEW(FilenameHashEntry);
|
||||
if (!e) {
|
||||
fprintf(ErrFp, "Out of Memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
e->fname = strdup(fname);
|
||||
if (!e->fname) {
|
||||
fprintf(ErrFp, "Out of Memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
hash_table_insert(&FilenameHashTable, e);
|
||||
}
|
||||
FileName = e->fname;
|
||||
}
|
||||
|
||||
char const *GetCurrentFilename(void)
|
||||
{
|
||||
if (FileName) {
|
||||
if (!strcmp(FileName, "-")) {
|
||||
return "-stdin-";
|
||||
} else {
|
||||
return FileName;
|
||||
}
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
got_a_fresh_line(void)
|
||||
{
|
||||
@@ -109,7 +179,7 @@ got_a_fresh_line(void)
|
||||
WarnedAboutImplicit = 0;
|
||||
}
|
||||
|
||||
void set_cloexec(FILE *fp)
|
||||
static void set_cloexec(FILE *fp)
|
||||
{
|
||||
int flags;
|
||||
int fd;
|
||||
@@ -311,7 +381,7 @@ static int ReadLineFromFile(int use_pclose)
|
||||
/* ShouldCache is 1, cache the file */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int OpenFile(char const *fname)
|
||||
static int OpenFile(char const *fname)
|
||||
{
|
||||
CachedFile *h = CachedFiles;
|
||||
int r;
|
||||
@@ -332,7 +402,7 @@ int OpenFile(char const *fname)
|
||||
fprintf(ErrFp, "\n");
|
||||
}
|
||||
CLine = h->cache;
|
||||
STRSET(FileName, fname);
|
||||
SetCurrentFilename(fname);
|
||||
LineNo = 0;
|
||||
LineNoStart = 0;
|
||||
if (!h->ownedByMe) {
|
||||
@@ -387,7 +457,7 @@ int OpenFile(char const *fname)
|
||||
}
|
||||
}
|
||||
}
|
||||
STRSET(FileName, fname);
|
||||
SetCurrentFilename(fname);
|
||||
LineNo = 0;
|
||||
LineNoStart = 0;
|
||||
if (FileName) return OK; else return E_NO_MEM;
|
||||
@@ -569,7 +639,7 @@ static int PopFile(void)
|
||||
set_base_if_pointer(i->base_if_pointer);
|
||||
CLine = i->CLine;
|
||||
fp = NULL;
|
||||
STRSET(FileName, i->filename);
|
||||
SetCurrentFilename(i->filename);
|
||||
if (!i->ownedByMe) {
|
||||
RunDisabled |= RUN_NOTOWNER;
|
||||
} else {
|
||||
@@ -589,7 +659,6 @@ static int PopFile(void)
|
||||
if (fp != stdin)
|
||||
(void) fseek(fp, i->offset, 0); /* Trust that it works... */
|
||||
}
|
||||
free((char *) i->filename);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -894,15 +963,7 @@ static int IncludeCmd(char const *cmd)
|
||||
}
|
||||
fname = DBufValue(&buf);
|
||||
|
||||
if (FileName) {
|
||||
i->filename = StrDup(FileName);
|
||||
if (!i->filename) {
|
||||
DBufFree(&buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
} else {
|
||||
i->filename = NULL;
|
||||
}
|
||||
i->filename = FileName;
|
||||
i->ownedByMe = 1;
|
||||
i->LineNo = LineNo;
|
||||
i->LineNoStart = LineNo;
|
||||
@@ -927,7 +988,7 @@ static int IncludeCmd(char const *cmd)
|
||||
fprintf(ErrFp, "\n");
|
||||
}
|
||||
CLine = h->cache;
|
||||
STRSET(FileName, fname);
|
||||
SetCurrentFilename(fname);
|
||||
DBufFree(&buf);
|
||||
LineNo = 0;
|
||||
LineNoStart = 0;
|
||||
@@ -979,7 +1040,7 @@ static int IncludeCmd(char const *cmd)
|
||||
CLine = CachedFiles->cache;
|
||||
LineNo = 0;
|
||||
LineNoStart = 0;
|
||||
STRSET(FileName, fname);
|
||||
SetCurrentFilename(fname);
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
}
|
||||
@@ -1008,12 +1069,7 @@ int IncludeFile(char const *fname)
|
||||
if (IStackPtr >= INCLUDE_NEST) return E_NESTED_INCLUDE;
|
||||
i = &IStack[IStackPtr];
|
||||
|
||||
if (FileName) {
|
||||
i->filename = StrDup(FileName);
|
||||
if (!i->filename) return E_NO_MEM;
|
||||
} else {
|
||||
i->filename = NULL;
|
||||
}
|
||||
i->filename = FileName;
|
||||
i->LineNo = LineNo;
|
||||
i->LineNoStart = LineNoStart;
|
||||
i->base_if_pointer = get_base_if_pointer();
|
||||
@@ -1095,7 +1151,7 @@ int IncludeFile(char const *fname)
|
||||
int GetAccessDate(char const *file)
|
||||
{
|
||||
struct stat statbuf;
|
||||
struct tm *t1;
|
||||
struct tm const *t1;
|
||||
|
||||
if (stat(file, &statbuf)) return -1;
|
||||
t1 = localtime(&(statbuf.st_atime));
|
||||
|
||||
305
src/funcs.c
305
src/funcs.c
@@ -59,7 +59,9 @@
|
||||
#define Nargs (info->nargs)
|
||||
#define RetVal (info->retval)
|
||||
|
||||
#define DBG(x) do { if (DebugFlag & DB_PRTEXPR) { x; } } while(0)
|
||||
#define DBGX (DebugFlag & DB_PRTEXPR)
|
||||
|
||||
#define DBG(x) do { if (DBGX) { x; } } while(0)
|
||||
/* Debugging helpers for "choose()", "iif(), etc. */
|
||||
#define PUT(x) DBufPuts(&DebugBuf, x)
|
||||
#define OUT() do { fprintf(ErrFp, "%s\n", DBufValue(&DebugBuf)); DBufFree(&DebugBuf); } while(0)
|
||||
@@ -193,7 +195,7 @@ static int FTypeof (func_info *);
|
||||
static int FTzconvert (func_info *);
|
||||
static int FUTCToLocal (func_info *);
|
||||
static int FUpper (func_info *);
|
||||
static int FValue (func_info *);
|
||||
static int FValue (expr_node *, Value *, Value *, int *);
|
||||
static int FVersion (func_info *);
|
||||
static int FWeekno (func_info *);
|
||||
static int FWkday (func_info *);
|
||||
@@ -229,8 +231,10 @@ static int CacheHebYear, CacheHebMon, CacheHebDay;
|
||||
#define HASDATE(x) ((x).type & DATE_TYPE)
|
||||
#define HASTIME(x) ((x).type & TIME_TYPE)
|
||||
|
||||
#define GETMON(x) get_month(&(ARG(x)))
|
||||
|
||||
/* Macro for copying a value while destroying original copy */
|
||||
#define DCOPYVAL(x, y) ( (x) = (y), (y).type = ERR_TYPE )
|
||||
#define DCOPYVAL(x, y) ( (x) = (y), (y).type = ERR_TYPE, (y).v.val = 0 )
|
||||
|
||||
/* Get at RetVal.v.val easily */
|
||||
#define RETVAL info->retval.v.val
|
||||
@@ -258,13 +262,14 @@ BuiltinFunc Func[] = {
|
||||
{ "choose", 2, NO_MAX, 1, NULL, FChoose }, /*NEW-STYLE*/
|
||||
{ "coerce", 2, 2, 1, FCoerce, NULL },
|
||||
{ "columns", 0, 1, 0, FColumns, NULL },
|
||||
{ "const", 1, 1, 1, FNonconst, NULL },
|
||||
{ "current", 0, 0, 0, FCurrent, NULL },
|
||||
{ "date", 3, 3, 1, FDate, NULL },
|
||||
{ "datepart", 1, 1, 1, FDatepart, NULL },
|
||||
{ "datetime", 2, 5, 1, FDateTime, NULL },
|
||||
{ "dawn", 0, 1, 0, FDawn, NULL },
|
||||
{ "day", 1, 1, 1, FDay, NULL },
|
||||
{ "daysinmon", 2, 2, 1, FDaysinmon, NULL },
|
||||
{ "daysinmon", 1, 2, 1, FDaysinmon, NULL },
|
||||
{ "defined", 1, 1, 0, FDefined, NULL },
|
||||
{ "dosubst", 1, 3, 0, FDosubst, NULL },
|
||||
{ "dusk", 0, 1, 0, FDusk, NULL },
|
||||
@@ -364,7 +369,7 @@ BuiltinFunc Func[] = {
|
||||
{ "tzconvert", 2, 3, 0, FTzconvert, NULL },
|
||||
{ "upper", 1, 1, 1, FUpper, NULL },
|
||||
{ "utctolocal", 1, 1, 1, FUTCToLocal, NULL },
|
||||
{ "value", 1, 2, 0, FValue, NULL },
|
||||
{ "value", 1, 2, 1, NULL, FValue }, /* NEW-STYLE */
|
||||
{ "version", 0, 0, 1, FVersion, NULL },
|
||||
{ "weekno", 0, 3, 0, FWeekno, NULL },
|
||||
{ "wkday", 1, 1, 1, FWkday, NULL },
|
||||
@@ -375,6 +380,26 @@ BuiltinFunc Func[] = {
|
||||
/* Need a variable here - Func[] array not really visible to outside. */
|
||||
int NumFuncs = sizeof(Func) / sizeof(BuiltinFunc) ;
|
||||
|
||||
static int get_month(Value *v)
|
||||
{
|
||||
Token tok;
|
||||
|
||||
if (v->type == INT_TYPE) {
|
||||
if (v->v.val < 1) return -E_2LOW;
|
||||
if (v->v.val > 12) return -E_2HIGH;
|
||||
return v->v.val - 1;
|
||||
}
|
||||
if (v->type == STR_TYPE) {
|
||||
FindToken(v->v.str, &tok);
|
||||
if (tok.type != T_Month) {
|
||||
return -E_CANT_PARSE_MONTH;
|
||||
}
|
||||
return tok.val;
|
||||
}
|
||||
return -E_BAD_TYPE;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* RetStrVal */
|
||||
@@ -460,29 +485,27 @@ static int FBaseyr(func_info *info)
|
||||
static int FDate(func_info *info)
|
||||
{
|
||||
int y, m, d;
|
||||
int ytemp, mtemp, dtemp;
|
||||
|
||||
/* Any arg can be a date (in which case we use the corresponding
|
||||
component) or an integer */
|
||||
if (HASDATE(ARG(0))) {
|
||||
FromDSE(DATEPART(ARG(0)), &ytemp, &mtemp, &dtemp);
|
||||
y = ytemp;
|
||||
FromDSE(DATEPART(ARG(0)), &y, NULL, NULL);
|
||||
} else {
|
||||
ASSERT_TYPE(0, INT_TYPE);
|
||||
y = ARGV(0);
|
||||
}
|
||||
|
||||
if (HASDATE(ARG(1))) {
|
||||
FromDSE(DATEPART(ARG(1)), &ytemp, &mtemp, &dtemp);
|
||||
m = mtemp;
|
||||
FromDSE(DATEPART(ARG(1)), NULL, &m, NULL);
|
||||
} else {
|
||||
ASSERT_TYPE(1, INT_TYPE);
|
||||
m = ARGV(1) - 1;
|
||||
m = GETMON(1);
|
||||
if (m < 0) {
|
||||
return -m;
|
||||
}
|
||||
}
|
||||
|
||||
if (HASDATE(ARG(2))) {
|
||||
FromDSE(DATEPART(ARG(2)), &ytemp, &mtemp, &dtemp);
|
||||
d = dtemp;
|
||||
FromDSE(DATEPART(ARG(2)), NULL, NULL, &d);
|
||||
} else {
|
||||
ASSERT_TYPE(2, INT_TYPE);
|
||||
d = ARGV(2);
|
||||
@@ -527,11 +550,11 @@ static int FDateTime(func_info *info)
|
||||
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 = ARGV(0);
|
||||
m = ARGV(1) - 1;
|
||||
m = GETMON(1);
|
||||
if (m < 0) return -m;
|
||||
d = ARGV(2);
|
||||
|
||||
if (!DateOK(y, m, d)) return E_BAD_DATE;
|
||||
@@ -539,13 +562,13 @@ static int FDateTime(func_info *info)
|
||||
return OK;
|
||||
case 5:
|
||||
if (ARG(0).type != INT_TYPE ||
|
||||
ARG(1).type != INT_TYPE ||
|
||||
ARG(2).type != INT_TYPE ||
|
||||
ARG(3).type != INT_TYPE ||
|
||||
ARG(4).type != INT_TYPE) return E_BAD_TYPE;
|
||||
|
||||
y = ARGV(0);
|
||||
m = ARGV(1) - 1;
|
||||
m = GETMON(1);
|
||||
if (m < 0) return -m;
|
||||
d = ARGV(2);
|
||||
if (!DateOK(y, m, d)) return E_BAD_DATE;
|
||||
|
||||
@@ -756,7 +779,7 @@ static int FMonnum(func_info *info)
|
||||
/* Convert a month name to a month number */
|
||||
FindToken(ARG(0).v.str, &tok);
|
||||
if (tok.type != T_Month) {
|
||||
return E_BAD_TYPE;
|
||||
return E_CANT_PARSE_MONTH;
|
||||
}
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = tok.val + 1;
|
||||
@@ -808,7 +831,7 @@ static int FWkdaynum(func_info *info)
|
||||
/* Convert a day name to a day number */
|
||||
FindToken(ARG(0).v.str, &tok);
|
||||
if (tok.type != T_WkDay) {
|
||||
return E_BAD_TYPE;
|
||||
return E_CANT_PARSE_WKDAY;
|
||||
}
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = (tok.val + 1) % 7;
|
||||
@@ -845,12 +868,11 @@ static int FMon(func_info *info)
|
||||
char const *s;
|
||||
int y, m, d, v;
|
||||
|
||||
if (!HASDATE(ARG(0)) && ARG(0).type != INT_TYPE) return E_BAD_TYPE;
|
||||
if (!HASDATE(ARG(0)) && ARG(0).type != INT_TYPE && ARG(0).type != STR_TYPE) return E_BAD_TYPE;
|
||||
|
||||
if (ARG(0).type == INT_TYPE) {
|
||||
m = ARGV(0) - 1;
|
||||
if (m < 0) return E_2LOW;
|
||||
if (m > 11) return E_2HIGH;
|
||||
if (ARG(0).type == INT_TYPE || ARG(0).type == STR_TYPE) {
|
||||
m = GETMON(0);
|
||||
if (m < 0) return -m;
|
||||
} else {
|
||||
v = DATEPART(ARG(0));
|
||||
if (v == CacheDse)
|
||||
@@ -1128,6 +1150,7 @@ static int FAmpm(func_info *info)
|
||||
/***************************************************************/
|
||||
static int FOrd(func_info *info)
|
||||
{
|
||||
static int in_ford = 0;
|
||||
int t, u, v;
|
||||
char const *s;
|
||||
|
||||
@@ -1135,6 +1158,36 @@ static int FOrd(func_info *info)
|
||||
|
||||
ASSERT_TYPE(0, INT_TYPE);
|
||||
|
||||
if (!in_ford && UserFuncExists("ordx") == 1) {
|
||||
expr_node *n;
|
||||
int r;
|
||||
char const *e = buf;
|
||||
Value val;
|
||||
int nonconst;
|
||||
|
||||
val.type = ERR_TYPE;
|
||||
snprintf(buf, sizeof(buf), "ordx(%d)", ARGV(0));
|
||||
n = parse_expression(&e, &r, NULL);
|
||||
if (r != OK) {
|
||||
return r;
|
||||
}
|
||||
in_ford = 1;
|
||||
r = evaluate_expr_node(n, NULL, &val, &nonconst);
|
||||
in_ford = 0;
|
||||
free_expr_tree(n);
|
||||
if (r != OK) {
|
||||
return r;
|
||||
}
|
||||
if (nonconst) info->nonconst = nonconst;
|
||||
r = DoCoerce(STR_TYPE, &val);
|
||||
if (r != OK) {
|
||||
DestroyValue(val);
|
||||
return r;
|
||||
}
|
||||
DCOPYVAL(RetVal, val);
|
||||
return OK;
|
||||
}
|
||||
|
||||
v = ARGV(0);
|
||||
if (v < 0) {
|
||||
t = (-v) % 100;
|
||||
@@ -1162,7 +1215,7 @@ static int FOrd(func_info *info)
|
||||
static int FPad(func_info *info)
|
||||
{
|
||||
int r;
|
||||
char *s;
|
||||
char const *s;
|
||||
DynamicBuffer dbuf;
|
||||
size_t len;
|
||||
size_t wantlen;
|
||||
@@ -1298,7 +1351,7 @@ static int FIsconst(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
ans->type = INT_TYPE;
|
||||
ans->v.val = (my_nonconst ? 0 : 1);
|
||||
DBG(PUT(PrintValue(&junk, NULL)));
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
PUT(") => ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
OUT();
|
||||
@@ -1365,7 +1418,7 @@ static int FIsAny(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
break;
|
||||
}
|
||||
DestroyValue(v);
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
while(cur->sibling) {
|
||||
cur = cur->sibling;
|
||||
PUT(", ?");
|
||||
@@ -1402,7 +1455,7 @@ static int FCatch(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
SuppressErrorOutputInCatch = old_suppress;
|
||||
|
||||
if (r == OK) {
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
PUT(PrintValue(ans, NULL));
|
||||
PUT(", ?) => ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
@@ -1413,14 +1466,14 @@ static int FCatch(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
|
||||
/* Save the catch error */
|
||||
LastCatchError = r;
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
PUT("*");
|
||||
PUT(GetErr(r));
|
||||
PUT("*, ");
|
||||
}
|
||||
r = evaluate_expr_node(cur->sibling, locals, ans, nonconst);
|
||||
if (r == OK) {
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
PUT(PrintValue(ans, NULL));
|
||||
PUT(") => ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
@@ -1428,7 +1481,7 @@ static int FCatch(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
}
|
||||
return r;
|
||||
}
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
PUT("*");
|
||||
PUT(GetErr(r));
|
||||
PUT("*) => ");
|
||||
@@ -1477,7 +1530,7 @@ static int FChoose(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
}
|
||||
DBG(PUT(PrintValue(&v, NULL)));
|
||||
if (v.type != INT_TYPE) {
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
cur = cur->sibling;
|
||||
while(cur) {
|
||||
PUT(", ?");
|
||||
@@ -1487,6 +1540,7 @@ static int FChoose(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
PUT(GetErr(E_BAD_TYPE));
|
||||
OUT();
|
||||
}
|
||||
DestroyValue(v);
|
||||
Eprint("choose(): %s", GetErr(E_BAD_TYPE));
|
||||
return E_BAD_TYPE;
|
||||
}
|
||||
@@ -1504,7 +1558,7 @@ static int FChoose(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
DBG(DBufFree(&DebugBuf));
|
||||
return r;
|
||||
}
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
PUT(", ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
cur = cur->sibling;
|
||||
@@ -1694,25 +1748,92 @@ static int FGetenv(func_info *info)
|
||||
/* it is returned if variable is undefined. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int FValue(func_info *info)
|
||||
static int FValue(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
{
|
||||
DynamicBuffer DebugBuf;
|
||||
expr_node *cur;
|
||||
int r;
|
||||
Value varname;
|
||||
Var *v;
|
||||
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
switch(Nargs) {
|
||||
case 1:
|
||||
return GetVarValue(ARGSTR(0), &RetVal);
|
||||
DBG(DBufInit(&DebugBuf));
|
||||
|
||||
case 2:
|
||||
v = FindVar(ARGSTR(0), 0);
|
||||
if (!v) {
|
||||
DCOPYVAL(RetVal, ARG(1));
|
||||
return OK;
|
||||
} else {
|
||||
return CopyValue(&RetVal, &v->v);
|
||||
cur = node->child;
|
||||
r = evaluate_expr_node(cur, locals, &varname, nonconst);
|
||||
if (r != OK) {
|
||||
DBG(DBufFree(&DebugBuf));
|
||||
return r;
|
||||
}
|
||||
|
||||
DBG(PUT("value("));
|
||||
DBG(PUT(PrintValue(&varname, NULL)));
|
||||
if (node->num_kids == 1) {
|
||||
DBG(PUT(") => "));
|
||||
} else {
|
||||
DBG(PUT(", "));
|
||||
}
|
||||
if (varname.type != STR_TYPE) {
|
||||
if (DBGX) {
|
||||
if (node->num_kids == 2) {
|
||||
PUT("?) => ");
|
||||
}
|
||||
PUT(GetErr(E_BAD_TYPE));
|
||||
OUT();
|
||||
}
|
||||
DestroyValue(varname);
|
||||
return E_BAD_TYPE;
|
||||
}
|
||||
|
||||
v = FindVar(varname.v.str, 0);
|
||||
if (!v) {
|
||||
r = E_NOSUCH_VAR;
|
||||
} else {
|
||||
r = OK;
|
||||
v->used_since_set = 1;
|
||||
CopyValue(ans, &v->v);
|
||||
if (!v->is_constant) {
|
||||
nonconst_debug(*nonconst, tr("Global variable `%s' makes expression non-constant"), varname.v.str);
|
||||
*nonconst = 1;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
if (r == OK || node->num_kids == 1) {
|
||||
DestroyValue(varname);
|
||||
if (DBGX) {
|
||||
if (node->num_kids == 2) {
|
||||
PUT("?) => ");
|
||||
}
|
||||
if (r != OK) {
|
||||
PUT(GetErr(r));
|
||||
} else {
|
||||
PUT(PrintValue(ans, NULL));
|
||||
}
|
||||
OUT();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Variable does not exist. We have to mark the result of value()
|
||||
as non-constant because the nonexistence of a variable may depend
|
||||
on today's date (for example) */
|
||||
nonconst_debug(*nonconst, tr("Nonexistence of global variable `%s' makes value() non-constant"), varname.v.str);
|
||||
DestroyValue(varname);
|
||||
*nonconst = 1;
|
||||
r = evaluate_expr_node(cur->sibling, locals, ans, nonconst);
|
||||
if (DBGX) {
|
||||
if (node->num_kids == 2) {
|
||||
if (r != OK) {
|
||||
PUT(GetErr(r));
|
||||
PUT(") => ");
|
||||
PUT(GetErr(r));
|
||||
} else {
|
||||
PUT(PrintValue(ans, NULL));
|
||||
PUT(") => ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
}
|
||||
OUT();
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -1877,12 +1998,12 @@ static int FTriguntil(func_info *info)
|
||||
|
||||
static int FTrigscanfrom(func_info *info)
|
||||
{
|
||||
if (LastTrigger.scanfrom == NO_DATE) {
|
||||
if (get_scanfrom(&LastTrigger) == NO_DATE) {
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = -1;
|
||||
} else {
|
||||
RetVal.type = DATE_TYPE;
|
||||
RETVAL = LastTrigger.scanfrom;
|
||||
RETVAL = get_scanfrom(&LastTrigger);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
@@ -1937,19 +2058,29 @@ static int FTrigdatetime(func_info *info)
|
||||
/* */
|
||||
/* FDaysinmon */
|
||||
/* */
|
||||
/* Returns the number of days in mon,yr */
|
||||
/* Returns the number of days in mon,yr OR month containing */
|
||||
/* given date. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int FDaysinmon(func_info *info)
|
||||
{
|
||||
if (ARG(0).type != INT_TYPE || ARG(1).type != INT_TYPE) return E_BAD_TYPE;
|
||||
int y, m;
|
||||
|
||||
if (ARGV(0) > 12 || ARGV(0) < 1 ||
|
||||
ARGV(1) < BASE || ARGV(1) > BASE+YR_RANGE)
|
||||
return E_DOMAIN_ERR;
|
||||
if (Nargs == 1) {
|
||||
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||
FromDSE(DATEPART(ARG(0)), &y, &m, NULL);
|
||||
} else {
|
||||
if (ARG(1).type != INT_TYPE) return E_BAD_TYPE;
|
||||
|
||||
m = GETMON(0);
|
||||
if (m < 0) return -m;
|
||||
y = ARGV(1);
|
||||
if (y < BASE) return E_2LOW;
|
||||
if (y > BASE + YR_RANGE) return E_2HIGH;
|
||||
}
|
||||
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = DaysInMonth(ARGV(0)-1, ARGV(1));
|
||||
RETVAL = DaysInMonth(m, y);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -1962,13 +2093,13 @@ static int FDaysinmon(func_info *info)
|
||||
/***************************************************************/
|
||||
static int FIsleap(func_info *info)
|
||||
{
|
||||
int y, m, d;
|
||||
int y;
|
||||
|
||||
if (ARG(0).type != INT_TYPE && !HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||
|
||||
/* If it's a date, extract the year */
|
||||
if (HASDATE(ARG(0)))
|
||||
FromDSE(DATEPART(ARG(0)), &y, &m, &d);
|
||||
FromDSE(DATEPART(ARG(0)), &y, NULL, NULL);
|
||||
else
|
||||
y = ARGV(0);
|
||||
|
||||
@@ -2214,7 +2345,7 @@ static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
cur = node->child;
|
||||
|
||||
if (!(node->num_kids % 2)) {
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
r = 0;
|
||||
while(cur) {
|
||||
if (r) PUT(", ");
|
||||
@@ -2237,7 +2368,7 @@ static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
DBG(DBufFree(&DebugBuf));
|
||||
return r;
|
||||
}
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
if (done) PUT(", ");
|
||||
done = 1;
|
||||
PUT(PrintValue(&v, NULL));
|
||||
@@ -2245,7 +2376,7 @@ static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
|
||||
if (truthy(&v)) {
|
||||
r = evaluate_expr_node(cur->sibling, locals, ans, nonconst);
|
||||
if (r == OK && (DebugFlag & DB_PRTEXPR)) {
|
||||
if (r == OK && DBGX) {
|
||||
PUT(", ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
cur = cur->sibling->sibling;
|
||||
@@ -2266,7 +2397,7 @@ static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
|
||||
/* Return the last arg */
|
||||
r = evaluate_expr_node(cur, locals, ans, nonconst);
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
if (DBGX) {
|
||||
if (done) PUT(", ");
|
||||
PUT(PrintValue(ans, NULL));
|
||||
PUT(") => ");
|
||||
@@ -2285,7 +2416,7 @@ static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
/***************************************************************/
|
||||
static int FFilename(func_info *info)
|
||||
{
|
||||
return RetStrVal(FileName, info);
|
||||
return RetStrVal(GetCurrentFilename(), info);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -2303,7 +2434,7 @@ static int FFiledir(func_info *info)
|
||||
|
||||
DBufInit(&buf);
|
||||
|
||||
if (DBufPuts(&buf, FileName) != OK) return E_NO_MEM;
|
||||
if (DBufPuts(&buf, GetCurrentFilename()) != OK) return E_NO_MEM;
|
||||
if (DBufLen(&buf) == 0) {
|
||||
DBufFree(&buf);
|
||||
return RetStrVal(".", info);
|
||||
@@ -2363,12 +2494,12 @@ static int FAccess(func_info *info)
|
||||
static int FTypeof(func_info *info)
|
||||
{
|
||||
switch(ARG(0).type) {
|
||||
case INT_TYPE: return RetStrVal("INT", info);
|
||||
case DATE_TYPE: return RetStrVal("DATE", info);
|
||||
case TIME_TYPE: return RetStrVal("TIME", info);
|
||||
case STR_TYPE: return RetStrVal("STRING", info);
|
||||
case INT_TYPE: return RetStrVal("INT", info);
|
||||
case DATE_TYPE: return RetStrVal("DATE", info);
|
||||
case TIME_TYPE: return RetStrVal("TIME", info);
|
||||
case STR_TYPE: return RetStrVal("STRING", info);
|
||||
case DATETIME_TYPE: return RetStrVal("DATETIME", info);
|
||||
default: return RetStrVal("ERR", info);
|
||||
default: return RetStrVal("ERR", info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2754,7 +2885,7 @@ static int FEasterdate(func_info *info)
|
||||
int base;
|
||||
if (Nargs == 0) {
|
||||
base = DSEToday;
|
||||
FromDSE(DSEToday, &y, &m, &d);
|
||||
FromDSE(DSEToday, &y, NULL, NULL);
|
||||
} else {
|
||||
if (ARG(0).type == INT_TYPE) {
|
||||
base = -1;
|
||||
@@ -2763,7 +2894,7 @@ static int FEasterdate(func_info *info)
|
||||
else if (y > BASE+YR_RANGE) return E_2HIGH;
|
||||
} else if (HASDATE(ARG(0))) {
|
||||
base = DATEPART(ARG(0));
|
||||
FromDSE(DATEPART(ARG(0)), &y, &m, &d); /* We just want the year */
|
||||
FromDSE(DATEPART(ARG(0)), &y, NULL, NULL); /* We just want the year */
|
||||
} else return E_BAD_TYPE;
|
||||
}
|
||||
|
||||
@@ -2807,7 +2938,7 @@ static int FOrthodoxeaster(func_info *info)
|
||||
int base = -1;
|
||||
if (Nargs == 0) {
|
||||
base = DSEToday;
|
||||
FromDSE(DSEToday, &y, &m, &d);
|
||||
FromDSE(DSEToday, &y, NULL, NULL);
|
||||
} else {
|
||||
if (ARG(0).type == INT_TYPE) {
|
||||
y = ARGV(0);
|
||||
@@ -2815,7 +2946,7 @@ static int FOrthodoxeaster(func_info *info)
|
||||
else if (y > BASE+YR_RANGE) return E_2HIGH;
|
||||
} else if (HASDATE(ARG(0))) {
|
||||
base = DATEPART(ARG(0));
|
||||
FromDSE(DATEPART(ARG(0)), &y, &m, &d); /* We just want the year */
|
||||
FromDSE(DATEPART(ARG(0)), &y, NULL, NULL); /* We just want the year */
|
||||
} else return E_BAD_TYPE;
|
||||
}
|
||||
|
||||
@@ -2890,7 +3021,8 @@ static int FTimeStuff(int wantmins, func_info *info)
|
||||
static int FTimezone(func_info *info)
|
||||
{
|
||||
int yr, mon, day, hr, min, dse, now;
|
||||
struct tm local, *withzone;
|
||||
struct tm local;
|
||||
struct tm const * withzone;
|
||||
time_t t;
|
||||
char buf[64];
|
||||
|
||||
@@ -3279,7 +3411,7 @@ static int FADusk(func_info *info)
|
||||
static int FFiledate(func_info *info)
|
||||
{
|
||||
struct stat statbuf;
|
||||
struct tm *t1;
|
||||
struct tm const *t1;
|
||||
|
||||
RetVal.type = DATE_TYPE;
|
||||
|
||||
@@ -3310,7 +3442,7 @@ static int FFiledate(func_info *info)
|
||||
static int FFiledatetime(func_info *info)
|
||||
{
|
||||
struct stat statbuf;
|
||||
struct tm *t1;
|
||||
struct tm const *t1;
|
||||
|
||||
RetVal.type = DATETIME_TYPE;
|
||||
|
||||
@@ -3721,7 +3853,7 @@ static int tz_convert(int year, int month, int day,
|
||||
{
|
||||
int r;
|
||||
time_t t;
|
||||
struct tm *res;
|
||||
struct tm const *res;
|
||||
char const *old_tz;
|
||||
|
||||
/* init tm struct */
|
||||
@@ -3843,7 +3975,7 @@ FSlide(func_info *info)
|
||||
for (i=localargs; i<Nargs; i++) {
|
||||
if (ARG(i).type != STR_TYPE) return E_BAD_TYPE;
|
||||
FindToken(ARG(i).v.str, &tok);
|
||||
if (tok.type != T_WkDay) return E_UNKNOWN_TOKEN;
|
||||
if (tok.type != T_WkDay) return E_CANT_PARSE_WKDAY;
|
||||
localomit |= (1 << tok.val);
|
||||
}
|
||||
|
||||
@@ -3901,7 +4033,7 @@ FNonomitted(func_info *info)
|
||||
for (i=localargs; i<Nargs; i++) {
|
||||
if (ARG(i).type != STR_TYPE) return E_BAD_TYPE;
|
||||
FindToken(ARG(i).v.str, &tok);
|
||||
if (tok.type != T_WkDay) return E_UNKNOWN_TOKEN;
|
||||
if (tok.type != T_WkDay) return E_CANT_PARSE_WKDAY;
|
||||
localomit |= (1 << tok.val);
|
||||
}
|
||||
|
||||
@@ -3992,6 +4124,7 @@ FEval(func_info *info)
|
||||
{
|
||||
expr_node *n;
|
||||
int r;
|
||||
int run_was_enabled = 0;
|
||||
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
char const *e = ARGSTR(0);
|
||||
@@ -4002,7 +4135,15 @@ FEval(func_info *info)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Disable shell() command in eval */
|
||||
if (! (RunDisabled & RUN_IN_EVAL)) {
|
||||
run_was_enabled = 1;
|
||||
RunDisabled |= RUN_IN_EVAL;
|
||||
}
|
||||
r = evaluate_expr_node(n, NULL, &(info->retval), &(info->nonconst));
|
||||
if (run_was_enabled) {
|
||||
RunDisabled &= ~RUN_IN_EVAL;
|
||||
}
|
||||
free_expr_tree(n);
|
||||
return r;
|
||||
}
|
||||
@@ -4037,10 +4178,10 @@ FEvalTrig(func_info *info)
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
if (scanfrom == NO_DATE) {
|
||||
dse = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 0);
|
||||
dse = ComputeTrigger(get_scanfrom(&trig), &trig, &tim, &r, 0);
|
||||
} else {
|
||||
/* Hokey... */
|
||||
if (trig.scanfrom != DSEToday) {
|
||||
if (get_scanfrom(&trig) != DSEToday) {
|
||||
Wprint(tr("Warning: SCANFROM is ignored in two-argument form of evaltrig()"));
|
||||
}
|
||||
dse = ComputeTrigger(scanfrom, &trig, &tim, &r, 0);
|
||||
@@ -4099,7 +4240,7 @@ FMultiTrig(func_info *info)
|
||||
Eprint(tr("Cannot use AT clause in multitrig() function"));
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
dse = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 0);
|
||||
dse = ComputeTrigger(get_scanfrom(&trig), &trig, &tim, &r, 0);
|
||||
DestroyParser(&p);
|
||||
|
||||
if (r != E_CANT_TRIG) {
|
||||
@@ -4152,7 +4293,7 @@ FTrig(func_info *info)
|
||||
FreeTrig(&trig);
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
dse = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 0);
|
||||
dse = ComputeTrigger(get_scanfrom(&trig), &trig, &tim, &r, 0);
|
||||
DestroyParser(&p);
|
||||
|
||||
if (r == E_CANT_TRIG) {
|
||||
|
||||
@@ -35,6 +35,10 @@ EXTERN FILE *ErrFp;
|
||||
|
||||
#define MINUTES_PER_DAY 1440
|
||||
|
||||
#define TODOS_AND_EVENTS 0
|
||||
#define ONLY_TODOS 1
|
||||
#define ONLY_EVENTS 2
|
||||
|
||||
#define DaysInYear(y) (((y) % 4) ? 365 : ((!((y) % 100) && ((y) % 400)) ? 365 : 366 ))
|
||||
#define IsLeapYear(y) (((y) % 4) ? 0 : ((!((y) % 100) && ((y) % 400)) ? 0 : 1 ))
|
||||
#define DaysInMonth(m, y) ((m) != 1 ? MonthDays[m] : 28 + IsLeapYear(y))
|
||||
@@ -52,6 +56,8 @@ EXTERN int FreshLine;
|
||||
EXTERN int WarnedAboutImplicit;
|
||||
EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS];
|
||||
|
||||
EXTERN INIT( int JSONMode, 0);
|
||||
EXTERN INIT( int JSONLinesEmitted, 0);
|
||||
EXTERN INIT( int MaxLateMinutes, 0);
|
||||
EXTERN INIT( int NumTrustedUsers, 0);
|
||||
EXTERN INIT( char const *MsgCommand, NULL);
|
||||
@@ -61,6 +67,7 @@ EXTERN INIT( int DebugFlag, 0);
|
||||
EXTERN INIT( int DoCalendar, 0);
|
||||
EXTERN INIT( int DoSimpleCalendar, 0);
|
||||
EXTERN INIT( int DoSimpleCalDelta, 0);
|
||||
EXTERN INIT( int HideCompletedTodos, 0);
|
||||
EXTERN INIT( int DoPrefixLineNo, 0);
|
||||
EXTERN INIT( int MondayFirst, 0);
|
||||
EXTERN INIT( int AddBlankLines, 1);
|
||||
@@ -72,6 +79,7 @@ EXTERN INIT( int CalMonths, 0);
|
||||
EXTERN INIT( char const *CalType, "none");
|
||||
EXTERN INIT( int Hush, 0);
|
||||
EXTERN INIT( int NextMode, 0);
|
||||
EXTERN INIT( int TodoFilter, TODOS_AND_EVENTS);
|
||||
EXTERN INIT( int InfiniteDelta, 0);
|
||||
EXTERN INIT( int DefaultTDelta, 0);
|
||||
EXTERN INIT( int DefaultDelta, NO_DELTA);
|
||||
@@ -113,7 +121,6 @@ EXTERN INIT( int SynthesizeTags, 0);
|
||||
EXTERN INIT( int ScFormat, SC_AMPM);
|
||||
EXTERN INIT( int MaxSatIter, 1000);
|
||||
EXTERN INIT( int MaxStringLen, MAX_STR_LEN);
|
||||
EXTERN INIT( char *FileName, NULL);
|
||||
EXTERN INIT( int UseStdin, 0);
|
||||
EXTERN INIT( int PurgeMode, 0);
|
||||
EXTERN INIT( int PurgeIncludeDepth, 0);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* HASHTAB_STATS.C */
|
||||
/* HASHTAB.C */
|
||||
/* */
|
||||
/* Implementation of hash table. */
|
||||
/* */
|
||||
@@ -99,8 +99,8 @@ static size_t bucket_choices[] = {
|
||||
int
|
||||
hash_table_init(hash_table *t,
|
||||
size_t link_offset,
|
||||
unsigned int (*hashfunc)(void *x),
|
||||
int (*compare)(void *a, void *b))
|
||||
unsigned int (*hashfunc)(void const *x),
|
||||
int (*compare)(void const *a, void const *b))
|
||||
{
|
||||
t->bucket_choice_index = 0;
|
||||
t->num_entries = 0;
|
||||
@@ -141,7 +141,7 @@ hash_table_free(hash_table *t)
|
||||
* \return The number of items in the hash table
|
||||
*/
|
||||
size_t
|
||||
hash_table_num_entries(hash_table *t)
|
||||
hash_table_num_entries(hash_table const *t)
|
||||
{
|
||||
return t->num_entries;
|
||||
}
|
||||
@@ -154,7 +154,7 @@ hash_table_num_entries(hash_table *t)
|
||||
* \return The number of buckets in the hash table
|
||||
*/
|
||||
size_t
|
||||
hash_table_num_buckets(hash_table *t)
|
||||
hash_table_num_buckets(hash_table const *t)
|
||||
{
|
||||
if (t->bucket_choice_index >= NUM_BUCKET_CHOICES) {
|
||||
return 0;
|
||||
@@ -321,7 +321,7 @@ hash_table_find(hash_table *t, void *candidate)
|
||||
*
|
||||
* \return 0 on success, -1 on failure
|
||||
*/
|
||||
int
|
||||
static int
|
||||
hash_table_delete_helper(hash_table *t, void *item, int resize_ok)
|
||||
{
|
||||
if (!item) {
|
||||
|
||||
@@ -34,8 +34,8 @@ typedef struct {
|
||||
size_t num_entries; /**< Number of entries in the hash table */
|
||||
size_t hash_link_offset; /**< Offset of the struct hash_link in the container */
|
||||
void **buckets; /**< Array of buckets */
|
||||
unsigned int (*hashfunc)(void *x); /**< Pointer to the hashing function */
|
||||
int (*compare)(void *a, void *b); /**< Pointer to the comparison function */
|
||||
unsigned int (*hashfunc)(void const *x); /**< Pointer to the hashing function */
|
||||
int (*compare)(void const *a, void const *b); /**< Pointer to the comparison function */
|
||||
} hash_table;
|
||||
|
||||
/**
|
||||
@@ -56,11 +56,11 @@ struct hash_table_stats {
|
||||
|
||||
int hash_table_init(hash_table *t,
|
||||
size_t link_offset,
|
||||
unsigned int (*hashfunc)(void *x),
|
||||
int (*compare)(void *a, void *b));
|
||||
unsigned int (*hashfunc)(void const *x),
|
||||
int (*compare)(void const *a, void const *b));
|
||||
void hash_table_free(hash_table *t);
|
||||
size_t hash_table_num_entries(hash_table *t);
|
||||
size_t hash_table_num_buckets(hash_table *t);
|
||||
size_t hash_table_num_entries(hash_table const *t);
|
||||
size_t hash_table_num_buckets(hash_table const *t);
|
||||
size_t hash_table_chain_len(hash_table *t, size_t i);
|
||||
int hash_table_insert(hash_table *t, void *item);
|
||||
void *hash_table_find(hash_table *t, void *candidate);
|
||||
@@ -68,7 +68,6 @@ int hash_table_delete(hash_table *t, void *item);
|
||||
int hash_table_delete_no_resize(hash_table *t, void *item);
|
||||
void *hash_table_next(hash_table *t, void *cur);
|
||||
void hash_table_dump_stats(hash_table *t, FILE *fp);
|
||||
void hash_table_get_stats(hash_table *t, struct hash_table_stats *stat);
|
||||
|
||||
/**
|
||||
* \brief Iterate over all items in a hash table
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
static void hash_table_get_stats(hash_table *t, struct hash_table_stats *stat);
|
||||
|
||||
/**
|
||||
* \brief Dump hash table statistics to a stdio FILE
|
||||
*
|
||||
@@ -53,7 +55,7 @@ hash_table_dump_stats(hash_table *t, FILE *fp)
|
||||
* \param t A pointer to a hash_table object
|
||||
* \param stat A pointer to a hash_table_stats object that will be filled in
|
||||
*/
|
||||
void
|
||||
static void
|
||||
hash_table_get_stats(hash_table *t, struct hash_table_stats *stat)
|
||||
{
|
||||
size_t n = hash_table_num_buckets(t);
|
||||
|
||||
10
src/hbcal.c
10
src/hbcal.c
@@ -70,6 +70,8 @@ static char MaxMonLen[] = {
|
||||
|
||||
static char HebIsLeap[] = {0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,1};
|
||||
|
||||
static long DaysToHebYear(int y);
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* RoshHashana */
|
||||
@@ -78,7 +80,7 @@ static char HebIsLeap[] = {0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,1};
|
||||
/* Hebrew year. (ie, 5751, not 1990) */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int RoshHashana(int i)
|
||||
static int RoshHashana(int i)
|
||||
{
|
||||
long j;
|
||||
j = DaysToHebYear(i-3744) - CORRECTION;
|
||||
@@ -93,7 +95,7 @@ int RoshHashana(int i)
|
||||
/* from new moon before Tishrey 1 5701. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
long DaysToHebYear(int y)
|
||||
static long DaysToHebYear(int y)
|
||||
{
|
||||
long m, nm, dw, s, l;
|
||||
|
||||
@@ -126,7 +128,7 @@ long DaysToHebYear(int y)
|
||||
/* */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DaysInHebYear(int y)
|
||||
static int DaysInHebYear(int y)
|
||||
{
|
||||
long thisyear, nextyear;
|
||||
|
||||
@@ -143,7 +145,7 @@ int DaysInHebYear(int y)
|
||||
/* given the LENGTH of the Hebrew year. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
char const *DaysInHebMonths(int ylen)
|
||||
static char const *DaysInHebMonths(int ylen)
|
||||
{
|
||||
static char monlen[14] =
|
||||
{30, 29, 30, 29, 30, 0, 29, 30, 29, 30, 29, 30, 29, 29};
|
||||
|
||||
22
src/ifelse.c
22
src/ifelse.c
@@ -24,6 +24,9 @@ static int if_pointer = 0;
|
||||
/* The base pointer for the current file */
|
||||
static int base_pointer = 0;
|
||||
|
||||
/* True if a "RETURN" statement was encountered in current file */
|
||||
static int return_encountered = 0;
|
||||
|
||||
/*
|
||||
* The current state of the IF...ELSE...ENDIF context is stored in
|
||||
* an array of "ifentry" objects, from the outermost to the
|
||||
@@ -103,6 +106,19 @@ encounter_else(void)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoReturn - handle the RETURN command */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int
|
||||
DoReturn(ParsePtr p)
|
||||
{
|
||||
int r = VerifyEoln(p);
|
||||
return_encountered = 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* encounter_endif - note that the most-recently-pushed IF */
|
||||
@@ -162,6 +178,10 @@ int
|
||||
should_ignore_line(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (return_encountered) {
|
||||
return 1;
|
||||
}
|
||||
for (i=base_pointer; i<if_pointer; i++) {
|
||||
if (( IfArray[i].if_true && !IfArray[i].before_else) ||
|
||||
(!IfArray[i].if_true && IfArray[i].before_else)) {
|
||||
@@ -193,11 +213,13 @@ in_constant_context(void)
|
||||
/* */
|
||||
/* pop_excess_ifs - pop excess IFs from the stack, printing */
|
||||
/* error messages as needed. */
|
||||
/* Also resets return_encountered */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void
|
||||
pop_excess_ifs(char const *fname)
|
||||
{
|
||||
return_encountered = 0;
|
||||
if (if_pointer <= base_pointer) {
|
||||
return;
|
||||
}
|
||||
|
||||
47
src/init.c
47
src/init.c
@@ -186,6 +186,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
InitUserFunctions();
|
||||
|
||||
InitTranslationTable();
|
||||
InitFiles();
|
||||
|
||||
/* If stdout is a terminal, initialize $FormWidth to terminal width-8,
|
||||
but clamp to [20, 500] */
|
||||
@@ -644,6 +645,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
case 'f': case 'F': DebugFlag |= DB_TRACE_FILES; break;
|
||||
case 'q': case 'Q': DebugFlag |= DB_TRANSLATE; break;
|
||||
case 'n': case 'N': DebugFlag |= DB_NONCONST; break;
|
||||
case 'u': case 'U': DebugFlag |= DB_UNUSED_VARS; break;
|
||||
default:
|
||||
fprintf(ErrFp, GetErr(M_BAD_DB_FLAG), *(arg-1));
|
||||
fprintf(ErrFp, "\n");
|
||||
@@ -796,6 +798,13 @@ void InitRemind(int argc, char const *argv[])
|
||||
|
||||
}
|
||||
|
||||
/* JSON mode turns off sorting */
|
||||
if (JSONMode) {
|
||||
SortByTime = SORT_NONE;
|
||||
SortByDate = SORT_NONE;
|
||||
SortByPrio = SORT_NONE;
|
||||
}
|
||||
|
||||
/* Figure out the offset from UTC */
|
||||
if (CalculateUTC) {
|
||||
(void) CalcMinsFromUTC(DSEToday, MinutesPastMidnight(0),
|
||||
@@ -836,7 +845,7 @@ void Usage(void)
|
||||
fprintf(ErrFp, " -q Don't queue timed reminders\n");
|
||||
fprintf(ErrFp, " -f Trigger timed reminders by staying in foreground\n");
|
||||
fprintf(ErrFp, " -z[n] Enter daemon mode, waking every n (1) minutes.\n");
|
||||
fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline f=tracefiles\n");
|
||||
fprintf(ErrFp, " -d... Debug: See man page for details\n");
|
||||
fprintf(ErrFp, " -e Divert messages normally sent to stderr to stdout\n");
|
||||
fprintf(ErrFp, " -b[n] Time format for cal: 0=am/pm, 1=24hr, 2=none\n");
|
||||
fprintf(ErrFp, " -x[n] Iteration limit for SATISFY clause (def=1000)\n");
|
||||
@@ -846,6 +855,16 @@ void Usage(void)
|
||||
fprintf(ErrFp, " -m Start calendar with Monday rather than Sunday\n");
|
||||
fprintf(ErrFp, " -y Synthesize tags for tagless reminders\n");
|
||||
fprintf(ErrFp, " -j[n] Run in 'purge' mode. [n = INCLUDE depth]\n");
|
||||
fprintf(ErrFp, "\nLong Options:\n");
|
||||
fprintf(ErrFp, " --version Print Remind version\n");
|
||||
fprintf(ErrFp, " --hide-completed-todos Don't show completed todos on calendar\n");
|
||||
fprintf(ErrFp, " --only-todos Only issue TODO reminders\n");
|
||||
fprintf(ErrFp, " --only-events Do not issue TODO reminders\n");
|
||||
fprintf(ErrFp, " --json Use JSON output instead of plain-text\n");
|
||||
fprintf(ErrFp, " --max-execution-time=n Limit execution time to n seconds\n");
|
||||
fprintf(ErrFp, " --print-config-cmd Print ./configure cmd used to build Remind\n");
|
||||
fprintf(ErrFp, " --print-errs Print all possible error messages\n");
|
||||
fprintf(ErrFp, " --print-tokens Print all possible Remind tokens\n");
|
||||
fprintf(ErrFp, "\nRemind home page: %s\n", PACKAGE_URL);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -1015,11 +1034,6 @@ static void InitializeVar(char const *str)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!*varname) {
|
||||
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(E_MISS_VAR));
|
||||
fprintf(ErrFp, "\n");
|
||||
return;
|
||||
}
|
||||
expr = str+1;
|
||||
if (!*expr) {
|
||||
fprintf(ErrFp, GetErr(M_I_OPTION), GetErr(E_MISS_EXPR));
|
||||
@@ -1061,7 +1075,7 @@ static void InitializeVar(char const *str)
|
||||
static void
|
||||
AddTrustedUser(char const *username)
|
||||
{
|
||||
struct passwd *pwent;
|
||||
struct passwd const *pwent;
|
||||
if (NumTrustedUsers >= MAX_TRUSTED_USERS) {
|
||||
fprintf(ErrFp, "Too many trusted users (%d max)\n",
|
||||
MAX_TRUSTED_USERS);
|
||||
@@ -1134,6 +1148,20 @@ ProcessLongOption(char const *arg)
|
||||
|
||||
return;
|
||||
}
|
||||
if (!strcmp(arg, "only-todos")) {
|
||||
TodoFilter = ONLY_TODOS;
|
||||
return;
|
||||
}
|
||||
if (!strcmp(arg, "only-events")) {
|
||||
TodoFilter = ONLY_EVENTS;
|
||||
return;
|
||||
}
|
||||
if (!strcmp(arg, "json")) {
|
||||
JSONMode = 1;
|
||||
DontQueue = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(arg, "version")) {
|
||||
printf("%s\n", VERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
@@ -1152,6 +1180,11 @@ ProcessLongOption(char const *arg)
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (!strcmp(arg, "hide-completed-todos")) {
|
||||
HideCompletedTodos = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(arg, "print-tokens")) {
|
||||
print_remind_tokens();
|
||||
print_builtinfunc_tokens();
|
||||
|
||||
27
src/json.c
27
src/json.c
@@ -47,19 +47,8 @@
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifndef JSON_INT_T_OVERRIDDEN
|
||||
#if defined(_MSC_VER)
|
||||
/* https://docs.microsoft.com/en-us/cpp/cpp/data-type-ranges */
|
||||
#define JSON_INT_MAX 9223372036854775807LL
|
||||
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
/* C99 */
|
||||
#define JSON_INT_MAX INT_FAST64_MAX
|
||||
#else
|
||||
/* C89 */
|
||||
#include <limits.h>
|
||||
#define JSON_INT_MAX LONG_MAX
|
||||
#endif
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#define JSON_INT_MAX LONG_MAX
|
||||
|
||||
#ifndef JSON_INT_MAX
|
||||
#define JSON_INT_MAX (json_int_t)(((unsigned json_int_t)(-1)) / (unsigned json_int_t)2);
|
||||
@@ -69,6 +58,8 @@ typedef unsigned int json_uchar;
|
||||
|
||||
const struct _json_value json_value_none;
|
||||
|
||||
static void json_value_free_ex (json_settings * settings, json_value * value);
|
||||
|
||||
static unsigned char hex_value (json_char c)
|
||||
{
|
||||
if (isdigit((unsigned char)c))
|
||||
@@ -252,10 +243,10 @@ static const long
|
||||
flag_block_comment = 1 << 14,
|
||||
flag_num_got_decimal = 1 << 15;
|
||||
|
||||
json_value * json_parse_ex (json_settings * settings,
|
||||
const json_char * json,
|
||||
size_t length,
|
||||
char * error_buf)
|
||||
static json_value * json_parse_ex (json_settings const * settings,
|
||||
const json_char * json,
|
||||
size_t length,
|
||||
char * error_buf)
|
||||
{
|
||||
char error [json_error_max];
|
||||
const json_char * end;
|
||||
@@ -999,7 +990,7 @@ json_value * json_parse (const json_char * json, size_t length)
|
||||
return json_parse_ex (&settings, json, length, 0);
|
||||
}
|
||||
|
||||
void json_value_free_ex (json_settings * settings, json_value * value)
|
||||
static void json_value_free_ex (json_settings * settings, json_value * value)
|
||||
{
|
||||
json_value * cur_value;
|
||||
|
||||
|
||||
12
src/json.h
12
src/json.h
@@ -266,21 +266,9 @@ json_value * json_parse (const json_char * json,
|
||||
size_t length);
|
||||
|
||||
#define json_error_max 128
|
||||
json_value * json_parse_ex (json_settings * settings,
|
||||
const json_char * json,
|
||||
size_t length,
|
||||
char * error);
|
||||
|
||||
void json_value_free (json_value *);
|
||||
|
||||
|
||||
/* Not usually necessary, unless you used a custom mem_alloc and now want to
|
||||
* use a custom mem_free.
|
||||
*/
|
||||
void json_value_free_ex (json_settings * settings,
|
||||
json_value *);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
154
src/main.c
154
src/main.c
@@ -50,16 +50,23 @@
|
||||
#include "err.h"
|
||||
|
||||
static void DoReminders(void);
|
||||
static int DoDebug(ParsePtr p);
|
||||
static void ClearLastTriggers(void);
|
||||
static int DoBanner(ParsePtr p);
|
||||
static void SaveLastTimeTrig(TimeTrig const *t);
|
||||
|
||||
/* Macro for simplifying common block so as not to litter code */
|
||||
#define OUTPUT(c) do { if (output) { DBufPutc(output, c); } else { putchar(c); } } while(0)
|
||||
|
||||
void
|
||||
static void
|
||||
exitfunc(void)
|
||||
{
|
||||
/* Kill any execution-time-limiter process */
|
||||
unlimit_execution_time();
|
||||
|
||||
if (DebugFlag & DB_UNUSED_VARS) {
|
||||
DumpUnusedVars();
|
||||
}
|
||||
if (DebugFlag & DB_HASHSTATS) {
|
||||
fflush(stdout);
|
||||
fflush(ErrFp);
|
||||
@@ -165,6 +172,9 @@ int main(int argc, char *argv[])
|
||||
ShouldCache = (Iterations > 1);
|
||||
|
||||
while (Iterations--) {
|
||||
if (JSONMode) {
|
||||
printf("[\n");
|
||||
}
|
||||
PerIterationInit();
|
||||
DoReminders();
|
||||
|
||||
@@ -174,10 +184,48 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (!Hush) {
|
||||
if (DestroyOmitContexts(1))
|
||||
if (DestroyOmitContexts(1)) {
|
||||
FreshLine = 1;
|
||||
Eprint("%s", GetErr(E_PUSH_NOPOP));
|
||||
}
|
||||
if (EmptyVarStack(1)) {
|
||||
FreshLine = 1;
|
||||
Eprint("%s", GetErr(E_PUSHV_NO_POP));
|
||||
}
|
||||
if (EmptyUserFuncStack(1)) {
|
||||
FreshLine = 1;
|
||||
Eprint("%s", GetErr(E_PUSHF_NO_POP));
|
||||
}
|
||||
if (!Daemon && !NextMode && !NumTriggered && !NumQueued) {
|
||||
printf("%s\n", GetErr(E_NOREMINDERS));
|
||||
if (!JSONMode) {
|
||||
printf("%s\n", GetErr(E_NOREMINDERS));
|
||||
} else {
|
||||
if (!DidMsgReminder) {
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
/* Do a banner in JSON mode*/
|
||||
if (!DoSubstFromString(DBufValue(&Banner), &buf,
|
||||
DSEToday, NO_TIME) &&
|
||||
DBufLen(&buf)) {
|
||||
if (JSONLinesEmitted) {
|
||||
printf("},\n");
|
||||
}
|
||||
JSONLinesEmitted++;
|
||||
printf("{\"banner\":\"");
|
||||
remove_trailing_newlines(&buf);
|
||||
PrintJSONString(DBufValue(&buf));
|
||||
printf("\"");
|
||||
}
|
||||
DBufFree(&buf);
|
||||
}
|
||||
if (JSONLinesEmitted) {
|
||||
printf("},\n");
|
||||
}
|
||||
printf("{\"noreminders\":\"");
|
||||
PrintJSONString(GetErr(E_NOREMINDERS));
|
||||
printf("\"");
|
||||
JSONLinesEmitted++;
|
||||
}
|
||||
} else if (!Daemon && !NextMode && !NumTriggered) {
|
||||
printf(GetErr(M_QUEUED), NumQueued);
|
||||
printf("\n");
|
||||
@@ -187,6 +235,12 @@ int main(int argc, char *argv[])
|
||||
/* If there are sorted reminders, handle them */
|
||||
if (SortByDate) IssueSortedReminders();
|
||||
|
||||
if (JSONMode) {
|
||||
if (JSONLinesEmitted) {
|
||||
printf("}\n");
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
/* If there are any background reminders queued up, handle them */
|
||||
if (NumQueued || Daemon) {
|
||||
|
||||
@@ -228,11 +282,14 @@ PerIterationInit(void)
|
||||
{
|
||||
ClearGlobalOmits();
|
||||
DestroyOmitContexts(1);
|
||||
EmptyVarStack(1);
|
||||
EmptyUserFuncStack(1);
|
||||
DestroyVars(0);
|
||||
DefaultColorR = -1;
|
||||
DefaultColorG = -1;
|
||||
DefaultColorB = -1;
|
||||
NumTriggered = 0;
|
||||
JSONLinesEmitted = 0;
|
||||
ClearLastTriggers();
|
||||
ClearDedupeTable();
|
||||
}
|
||||
@@ -314,6 +371,7 @@ static void DoReminders(void)
|
||||
case T_Rem: r=DoRem(&p); purge_handled = 1; break;
|
||||
case T_ErrMsg: r=DoErrMsg(&p); break;
|
||||
case T_If: r=DoIf(&p); break;
|
||||
case T_Return: r=DoReturn(&p); break;
|
||||
case T_IfTrig: r=DoIfTrig(&p); break;
|
||||
case T_Else: r=DoElse(&p); break;
|
||||
case T_EndIf: r=DoEndif(&p); break;
|
||||
@@ -359,6 +417,18 @@ static void DoReminders(void)
|
||||
case T_Pop: r=PopOmitContext(&p); break;
|
||||
case T_Preserve: r=DoPreserve(&p); break;
|
||||
case T_Push: r=PushOmitContext(&p); break;
|
||||
case T_PushVars:
|
||||
r=PushVars(&p);
|
||||
break;
|
||||
case T_PopVars:
|
||||
r=PopVars(&p);
|
||||
break;
|
||||
case T_PushFuncs:
|
||||
r=PushUserFuncs(&p);
|
||||
break;
|
||||
case T_PopFuncs:
|
||||
r=PopUserFuncs(&p);
|
||||
break;
|
||||
case T_Expr: r = DoExpr(&p); break;
|
||||
case T_Translate: r = DoTranslate(&p); break;
|
||||
case T_RemType: if (tok.val == RUN_TYPE) {
|
||||
@@ -456,6 +526,15 @@ void FromDSE(int dse, int *y, int *m, int *d)
|
||||
try_yr--;
|
||||
try_dse -= DaysInYear(try_yr);
|
||||
}
|
||||
if (y) {
|
||||
*y = try_yr;
|
||||
}
|
||||
|
||||
/* If all we want is the year, we can quit here */
|
||||
if (!d && !m) {
|
||||
return;
|
||||
}
|
||||
|
||||
dse -= try_dse;
|
||||
|
||||
t = DaysInMonth(try_mon, try_yr);
|
||||
@@ -464,9 +543,6 @@ void FromDSE(int dse, int *y, int *m, int *d)
|
||||
try_mon++;
|
||||
t = DaysInMonth(try_mon, try_yr);
|
||||
}
|
||||
if (y) {
|
||||
*y = try_yr;
|
||||
}
|
||||
if (m) {
|
||||
*m = try_mon;
|
||||
}
|
||||
@@ -899,24 +975,17 @@ void Wprint(char const *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
|
||||
char const *fname = GetCurrentFilename();
|
||||
if (SuppressErrorOutputInCatch) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* We can't use line_range because caller might have used it */
|
||||
if (FileName) {
|
||||
if (strcmp(FileName, "-")) {
|
||||
if (LineNoStart == LineNo) {
|
||||
(void) fprintf(ErrFp, "%s(%d): ", FileName, LineNo);
|
||||
} else {
|
||||
(void) fprintf(ErrFp, "%s(%d:%d): ", FileName, LineNoStart, LineNo);
|
||||
}
|
||||
if (fname) {
|
||||
if (LineNoStart == LineNo) {
|
||||
(void) fprintf(ErrFp, "%s(%d): ", fname, LineNo);
|
||||
} else {
|
||||
if (LineNoStart == LineNo) {
|
||||
(void) fprintf(ErrFp, "-stdin-(%d): ", LineNo);
|
||||
} else {
|
||||
(void) fprintf(ErrFp, "-stdin-(%d:%d): ", LineNoStart, LineNo);
|
||||
}
|
||||
(void) fprintf(ErrFp, "%s(%d:%d): ", fname, LineNoStart, LineNo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -934,24 +1003,27 @@ void Wprint(char const *fmt, ...)
|
||||
void Eprint(char const *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char const *fname;
|
||||
|
||||
if (SuppressErrorOutputInCatch) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if more than one error msg. from this line */
|
||||
if (!FreshLine && !ShowAllErrors) return;
|
||||
|
||||
if (!FileName) {
|
||||
if (should_ignore_line()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(FileName, "-")) {
|
||||
fname = FileName;
|
||||
} else {
|
||||
fname = "-stdin-";
|
||||
char const *fname = GetCurrentFilename();
|
||||
if (!fname) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (LineNo < 1) {
|
||||
/* Not yet processing a file */
|
||||
return;
|
||||
}
|
||||
/* Check if more than one error msg. from this line */
|
||||
if (!FreshLine && !ShowAllErrors) return;
|
||||
|
||||
if (FreshLine) {
|
||||
/* We can't use line_range because caller might have used it */
|
||||
if (LineNo == LineNoStart) {
|
||||
@@ -1062,7 +1134,7 @@ int PushToken(char const *tok, ParsePtr p)
|
||||
int SystemTime(int realtime)
|
||||
{
|
||||
time_t now;
|
||||
struct tm *t;
|
||||
struct tm const *t;
|
||||
|
||||
if (!realtime && (SysTime != -1)) return SysTime;
|
||||
|
||||
@@ -1102,7 +1174,7 @@ int MinutesPastMidnight(int realtime)
|
||||
int SystemDate(int *y, int *m, int *d)
|
||||
{
|
||||
time_t now;
|
||||
struct tm *t;
|
||||
struct tm const *t;
|
||||
|
||||
/* In test mode, always return 6 January 2025 */
|
||||
if (TestMode) {
|
||||
@@ -1218,7 +1290,7 @@ int DoIfTrig(ParsePtr p)
|
||||
} else {
|
||||
if ( (r=ParseRem(p, &trig, &tim)) ) return r;
|
||||
if (trig.typ != NO_TYPE) return E_PARSE_ERR;
|
||||
dse = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
||||
dse = ComputeTrigger(get_scanfrom(&trig), &trig, &tim, &r, 1);
|
||||
if (r) {
|
||||
if (r != E_CANT_TRIG || !trig.maybe_uncomputable) {
|
||||
if (!Hush || r != E_RUN_DISABLED) {
|
||||
@@ -1276,7 +1348,7 @@ int VerifyEoln(ParsePtr p)
|
||||
/* Set the debug options under program control. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DoDebug(ParsePtr p)
|
||||
static int DoDebug(ParsePtr p)
|
||||
{
|
||||
int err;
|
||||
int ch;
|
||||
@@ -1362,6 +1434,11 @@ int DoDebug(ParsePtr p)
|
||||
if (val) DebugFlag |= DB_NONCONST;
|
||||
else DebugFlag &= ~DB_NONCONST;
|
||||
break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
if (val) DebugFlag |= DB_UNUSED_VARS;
|
||||
else DebugFlag &= ~DB_UNUSED_VARS;
|
||||
break;
|
||||
default:
|
||||
Wprint(GetErr(M_BAD_DB_FLAG), ch);
|
||||
break;
|
||||
@@ -1377,7 +1454,7 @@ int DoDebug(ParsePtr p)
|
||||
/* reminder is issued. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DoBanner(ParsePtr p)
|
||||
static int DoBanner(ParsePtr p)
|
||||
{
|
||||
int err;
|
||||
int c;
|
||||
@@ -1561,7 +1638,8 @@ int CalcMinsFromUTC(int dse, int tim, int *mins, int *isdst)
|
||||
/* Convert dse and tim to an Unix tm struct */
|
||||
int yr, mon, day;
|
||||
int tdiff;
|
||||
struct tm local, utc, *temp;
|
||||
struct tm local, utc;
|
||||
struct tm const * temp;
|
||||
time_t loc_t, utc_t;
|
||||
int isdst_tmp;
|
||||
|
||||
@@ -1955,7 +2033,7 @@ FreeTrig(Trigger *t)
|
||||
t->infos = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
ClearLastTriggers(void)
|
||||
{
|
||||
LastTrigger.expired = 0;
|
||||
@@ -1990,9 +2068,11 @@ SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigt
|
||||
{
|
||||
SaveLastTrigger(t);
|
||||
SaveLastTimeTrig(tt);
|
||||
LastTriggerDate = trigdate;
|
||||
if (trigdate != -1) {
|
||||
LastTriggerDate = trigdate;
|
||||
LastTrigValid = valid;
|
||||
}
|
||||
LastTriggerTime = trigtime;
|
||||
LastTrigValid = valid;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2013,7 +2093,7 @@ SaveLastTrigger(Trigger const *t)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
SaveLastTimeTrig(TimeTrig const *t)
|
||||
{
|
||||
memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "md5.h"
|
||||
|
||||
static void byteReverse(unsigned char *buf, unsigned longs);
|
||||
static void MD5Transform(uint32 buf[4], uint32 const in[16]);
|
||||
|
||||
/*
|
||||
* Note: this code is harmless on little-endian machines.
|
||||
@@ -163,7 +164,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
void MD5Transform(uint32 buf[4], uint32 const in[16])
|
||||
static void MD5Transform(uint32 buf[4], uint32 const in[16])
|
||||
{
|
||||
register uint32 a, b, c, d;
|
||||
|
||||
|
||||
@@ -29,6 +29,5 @@ void MD5Init(struct MD5Context *context);
|
||||
void MD5Update(struct MD5Context *context, unsigned char const *buf,
|
||||
unsigned len);
|
||||
void MD5Final(unsigned char digest[16], struct MD5Context *context);
|
||||
void MD5Transform(uint32 buf[4], uint32 const in[16]);
|
||||
|
||||
#endif /* !MD5_H */
|
||||
|
||||
@@ -636,7 +636,7 @@ static time_t time_t_from_dse(int dse)
|
||||
|
||||
static int datetime_from_time_t(time_t t)
|
||||
{
|
||||
struct tm *local;
|
||||
struct tm const *local;
|
||||
int ans;
|
||||
|
||||
/* Round to nearest minute */
|
||||
@@ -665,7 +665,7 @@ static double interpolate(double f0, double f1, double f2, double p)
|
||||
|
||||
/* Moon position using fundamental arguments
|
||||
Van Flandern & Pulkkinen, 1979) */
|
||||
void moon_position(double dayOffset, double *ra, double *declination, double *distance)
|
||||
static void moon_position(double dayOffset, double *ra, double *declination, double *distance)
|
||||
{
|
||||
double l = 0.606434 + 0.03660110129 * dayOffset;
|
||||
double m = 0.374897 + 0.03629164709 * dayOffset;
|
||||
|
||||
24
src/omit.c
24
src/omit.c
@@ -36,7 +36,7 @@ int NumFullOmits, NumPartialOmits;
|
||||
/* The structure for saving and restoring OMIT contexts */
|
||||
typedef struct omitcontext {
|
||||
struct omitcontext *next;
|
||||
char *filename;
|
||||
char const *filename;
|
||||
int lineno;
|
||||
int numfull, numpart;
|
||||
int *fullsave;
|
||||
@@ -98,7 +98,6 @@ int DestroyOmitContexts(int print_unmatched)
|
||||
num++;
|
||||
if (c->fullsave) free(c->fullsave);
|
||||
if (c->partsave) free(c->partsave);
|
||||
if (c->filename) free(c->filename);
|
||||
d = c->next;
|
||||
free(c);
|
||||
c = d;
|
||||
@@ -122,28 +121,19 @@ int PushOmitContext(ParsePtr p)
|
||||
context = NEW(OmitContext);
|
||||
if (!context) return E_NO_MEM;
|
||||
|
||||
if (FileName) {
|
||||
context->filename = StrDup(FileName);
|
||||
} else {
|
||||
context->filename = StrDup("");
|
||||
}
|
||||
if (!context->filename) {
|
||||
free(context);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
context->filename = GetCurrentFilename();
|
||||
context->lineno = LineNo;
|
||||
|
||||
context->numfull = NumFullOmits;
|
||||
context->numpart = NumPartialOmits;
|
||||
context->weekdaysave = WeekdayOmits;
|
||||
context->fullsave = malloc(NumFullOmits * sizeof(int));
|
||||
if (NumFullOmits && !context->fullsave) {
|
||||
free(context->filename);
|
||||
free(context);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
context->partsave = malloc(NumPartialOmits * sizeof(int));
|
||||
if (NumPartialOmits && !context->partsave) {
|
||||
free(context->filename);
|
||||
if (context->fullsave) {
|
||||
free(context->fullsave);
|
||||
}
|
||||
@@ -172,6 +162,7 @@ int PopOmitContext(ParsePtr p)
|
||||
{
|
||||
|
||||
OmitContext *c = SavedOmitContexts;
|
||||
char const *fname = GetCurrentFilename();
|
||||
|
||||
if (!c) return E_POP_NO_PUSH;
|
||||
NumFullOmits = c->numfull;
|
||||
@@ -185,13 +176,12 @@ int PopOmitContext(ParsePtr p)
|
||||
/* Remove the context from the stack */
|
||||
SavedOmitContexts = c->next;
|
||||
|
||||
if (c->filename && FileName && strcmp(c->filename, FileName)) {
|
||||
Wprint(tr("POP-OMIT-CONTEXT at %s:%d matches PUSH-OMIT-CONTEXT in different file: %s:%d"), FileName, LineNo, c->filename, c->lineno);
|
||||
if (c->filename && fname && strcmp(c->filename, fname)) {
|
||||
Wprint(tr("POP-OMIT-CONTEXT at %s:%d matches PUSH-OMIT-CONTEXT in different file: %s:%d"), fname, LineNo, c->filename, c->lineno);
|
||||
}
|
||||
/* Free memory used by the saved context */
|
||||
if (c->partsave) free(c->partsave);
|
||||
if (c->fullsave) free(c->fullsave);
|
||||
if (c->filename) free(c->filename);
|
||||
free(c);
|
||||
|
||||
return VerifyEoln(p);
|
||||
@@ -249,7 +239,7 @@ int IsOmitted(int dse, int localomit, char const *omitfunc, int *omit)
|
||||
return OK;
|
||||
}
|
||||
|
||||
FromDSE(dse, &y, &m, &d);
|
||||
FromDSE(dse, NULL, &m, &d);
|
||||
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d)) {
|
||||
*omit = 1;
|
||||
return OK;
|
||||
|
||||
57
src/protos.h
57
src/protos.h
@@ -47,32 +47,29 @@ int DoFrename (ParsePtr p);
|
||||
void UnsetAllUserFuncs(void);
|
||||
void ProduceCalendar (void);
|
||||
char const *SimpleTime (int tim);
|
||||
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 TriggerReminder (ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queued, DynamicBuffer *output);
|
||||
int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int dse, int *err);
|
||||
int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse, int mode);
|
||||
int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is_queued, DynamicBuffer *output, int *r, int *g, int *b);
|
||||
int ShouldTriggerReminder (Trigger const *t, TimeTrig const *tim, int dse, int *err);
|
||||
int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig const *tt, int dse, int mode);
|
||||
int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int dse, int tim);
|
||||
int ParseLiteralDateOrTime (char const **s, int *dse, int *tim);
|
||||
int ParseLiteralTime (char const **s, int *tim);
|
||||
expr_node *parse_expression(char const **e, int *r, Var *locals);
|
||||
|
||||
int evaluate_expression(expr_node *node, Value *locals, Value *ans, int *nonconst);
|
||||
int evaluate_expr_node(expr_node *node, Value *locals, Value *ans, int *nonconst);
|
||||
int truthy(Value const *v);
|
||||
|
||||
void print_expr_tree(expr_node *node, FILE *fp);
|
||||
void unlimit_execution_time(void);
|
||||
expr_node *free_expr_tree(expr_node *node);
|
||||
expr_node *clone_expr_tree(expr_node const *node, int *r);
|
||||
int EvalExpr (char const **e, Value *v, ParsePtr p);
|
||||
int DoCoerce (char type, Value *v);
|
||||
char const *PrintValue (Value *v, FILE *fp);
|
||||
int CopyValue (Value *dest, const Value *src);
|
||||
int ReadLine (void);
|
||||
int OpenFile (char const *fname);
|
||||
int DoInclude (ParsePtr p, enum TokTypes tok);
|
||||
int DoIncludeCmd (ParsePtr p);
|
||||
int IncludeFile (char const *fname);
|
||||
@@ -106,11 +103,9 @@ int SystemDate (int *y, int *m, int *d);
|
||||
int DoIf (ParsePtr p);
|
||||
int DoElse (ParsePtr p);
|
||||
int DoEndif (ParsePtr p);
|
||||
int DoReturn (ParsePtr p);
|
||||
int DoIfTrig (ParsePtr p);
|
||||
int ShouldIgnoreLine (void);
|
||||
int VerifyEoln (ParsePtr p);
|
||||
int DoDebug (ParsePtr p);
|
||||
int DoBanner (ParsePtr p);
|
||||
int DoRun (ParsePtr p);
|
||||
int DoExpr (ParsePtr p);
|
||||
int DoTranslate (ParsePtr p);
|
||||
@@ -124,13 +119,12 @@ int PushOmitContext (ParsePtr p);
|
||||
int PopOmitContext (ParsePtr p);
|
||||
int IsOmitted (int dse, int localomit, char const *omitfunc, int *omit);
|
||||
int DoOmit (ParsePtr p);
|
||||
int QueueReminder (ParsePtr p, Trigger *trig, TimeTrig *tim, char const *sched);
|
||||
int QueueReminder (ParsePtr p, Trigger *trig, TimeTrig const *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, TimeTrig *tim, int *err, int save_in_globals);
|
||||
int ComputeTriggerNoAdjustDuration (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals, int duration_days);
|
||||
int ComputeTriggerNoAdjustDuration (int today, Trigger *trig, TimeTrig const *tim, int *err, int save_in_globals, int duration_days);
|
||||
int AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int save_in_globals);
|
||||
char *StrnCpy (char *dest, char const *source, int n);
|
||||
|
||||
@@ -150,20 +144,24 @@ void strtolower(char *s);
|
||||
|
||||
Var *FindVar (char const *str, int create);
|
||||
SysVar *FindSysVar (char const *name);
|
||||
int DeleteVar (char const *str);
|
||||
int SetVar (char const *str, Value const *val, int nonconst_expr);
|
||||
int GetVarValue (char const *str, Value *val);
|
||||
int DoSet (Parser *p);
|
||||
int DoUnset (Parser *p);
|
||||
int DoDump (ParsePtr p);
|
||||
int PushVars(ParsePtr p);
|
||||
int EmptyVarStack(int print_unmatched);
|
||||
int PopVars(ParsePtr p);
|
||||
int PushUserFuncs(ParsePtr p);
|
||||
int EmptyUserFuncStack(int print_unmatched);
|
||||
int PopUserFuncs(ParsePtr p);
|
||||
void DumpVarTable (int dump_constness);
|
||||
void DumpUnusedVars(void);
|
||||
void DestroyVars (int all);
|
||||
int PreserveVar (char const *name);
|
||||
int DoPreserve (Parser *p);
|
||||
int DoSatRemind (Trigger *trig, TimeTrig *tt, ParsePtr p);
|
||||
int DoMsgCommand (char const *cmd, char const *msg, int is_queued);
|
||||
int ParseNonSpaceChar (ParsePtr p, int *err, int peek);
|
||||
unsigned int HashVal_ignorecase(char const *str);
|
||||
unsigned int HashVal_preservecase(char const *str);
|
||||
int DateOK (int y, int m, int d);
|
||||
BuiltinFunc *FindBuiltinFunc (char const *name);
|
||||
@@ -174,10 +172,6 @@ int UserFuncExists (char const *fn);
|
||||
void DSEToHeb (int dse, int *hy, int *hm, int *hd);
|
||||
int HebNameToNum (char const *mname);
|
||||
char const *HebMonthName (int m, int y);
|
||||
int RoshHashana (int i);
|
||||
long DaysToHebYear (int y);
|
||||
int DaysInHebYear (int y);
|
||||
char const *DaysInHebMonths (int ylen);
|
||||
int HebToDSE (int hy, int hm, int hd);
|
||||
int GetValidHebDate (int yin, int min, int din, int adarbehave, int *mout, int *dout, int yahr);
|
||||
int GetNextHebrewDate (int dsestart, int hm, int hd, int yahr, int adarbehave, int *ans);
|
||||
@@ -198,9 +192,7 @@ void PurgeEchoLine(char const *fmt, ...);
|
||||
void FreeTrig(Trigger *t);
|
||||
void AppendTag(DynamicBuffer *buf, char const *s);
|
||||
char const *SynthesizeTag(void);
|
||||
void ClearLastTriggers(void);
|
||||
void SaveLastTrigger(Trigger const *t);
|
||||
void SaveLastTimeTrig(TimeTrig const *t);
|
||||
void SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigtime, int valid);
|
||||
|
||||
void PerIterationInit(void);
|
||||
@@ -209,13 +201,9 @@ char const *Colorize(int r, int g, int b, int bg, int clamp);
|
||||
void PrintJSONString(char const *s);
|
||||
void PrintJSONKeyPairInt(char const *name, int val);
|
||||
void PrintJSONKeyPairString(char const *name, char const *val);
|
||||
void PrintJSONKeyPairDate(char const *name, int dse);
|
||||
void PrintJSONKeyPairDateTime(char const *name, int dt);
|
||||
void PrintJSONKeyPairTime(char const *name, int t);
|
||||
void System(char const *cmd, int queued);
|
||||
int ShellEscape(char const *in, DynamicBuffer *out);
|
||||
int AddGlobalOmit(int dse);
|
||||
void set_lat_and_long_from_components(void);
|
||||
void set_components_from_lat_and_long(void);
|
||||
|
||||
void DebugExitFunc(void);
|
||||
@@ -225,13 +213,12 @@ int GetTerminalBackground(void);
|
||||
char const *get_day_name(int wkday);
|
||||
char const *get_month_name(int mon);
|
||||
|
||||
void set_cloexec(FILE *fp);
|
||||
int push_call(char const *filename, char const *func, int lineno, int lineno_start);
|
||||
void clear_callstack(void);
|
||||
int print_callstack(FILE *fp);
|
||||
void pop_call(void);
|
||||
void FixSpecialType(Trigger *trig);
|
||||
void WriteJSONTrigger(Trigger const *t, int include_tags, int today);
|
||||
void WriteJSONTrigger(Trigger const *t, int include_tags);
|
||||
void WriteJSONTimeTrigger(TimeTrig const *tt);
|
||||
int GetOnceDate(void);
|
||||
#ifdef REM_USE_WCHAR
|
||||
@@ -268,6 +255,7 @@ void InitDedupeTable(void);
|
||||
void InitVars(void);
|
||||
void InitUserFunctions(void);
|
||||
void InitTranslationTable(void);
|
||||
void InitFiles(void);
|
||||
char const *GetTranslatedString(char const *orig);
|
||||
int GetTranslatedStringTryingVariants(char const *orig, DynamicBuffer *out);
|
||||
char const *GetErr(int r);
|
||||
@@ -277,12 +265,8 @@ void print_escaped_string(FILE *fp, char const *s);
|
||||
void print_escaped_string_helper(FILE *fp, char const *s, int esc_for_remind, int json);
|
||||
void GenerateSysvarTranslationTemplates(void);
|
||||
void TranslationTemplate(char const *msg);
|
||||
TrigInfo *NewTrigInfo(char const *i);
|
||||
void FreeTrigInfo(TrigInfo *ti);
|
||||
void FreeTrigInfoChain(TrigInfo *ti);
|
||||
int AppendTrigInfo(Trigger *t, char const *info);
|
||||
int TrigInfoHeadersAreTheSame(char const *i1, char const *i2);
|
||||
int TrigInfoIsValid(char const *info);
|
||||
char const *FindTrigInfo(Trigger *t, char const *header);
|
||||
void WriteJSONInfoChain(TrigInfo *ti);
|
||||
char const *line_range(int lineno_start, int lineno);
|
||||
@@ -304,8 +288,7 @@ int should_ignore_line(void);
|
||||
int in_constant_context(void);
|
||||
void pop_excess_ifs(char const *fname);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void SetCurrentFilename(char const *fname);
|
||||
char const *GetCurrentFilename(void);
|
||||
int get_scanfrom(Trigger const *t);
|
||||
void remove_trailing_newlines(DynamicBuffer *buf);
|
||||
|
||||
88
src/queue.c
88
src/queue.c
@@ -12,12 +12,6 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* Solaris needs this to get select() prototype */
|
||||
#ifdef __sun__
|
||||
#define __EXTENSIONS__ 1
|
||||
#endif
|
||||
|
||||
/* We only want object code generated if we have queued reminders */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
@@ -45,13 +39,6 @@ static void consume_inotify_events(int fd);
|
||||
static int setup_inotify_watch(void);
|
||||
#endif
|
||||
|
||||
/* A list of filenames associated with queued reminders */
|
||||
typedef struct queuedfname {
|
||||
struct queuedfname *next;
|
||||
char const *fname;
|
||||
} QueuedFilename;
|
||||
|
||||
|
||||
/* List structure for holding queued reminders */
|
||||
typedef struct queuedrem {
|
||||
struct queuedrem *next;
|
||||
@@ -72,7 +59,6 @@ typedef struct queuedrem {
|
||||
/* Global variables */
|
||||
|
||||
static QueuedRem *QueueHead = NULL;
|
||||
static QueuedFilename *Files = NULL;
|
||||
static time_t FileModTime;
|
||||
static struct stat StatBuf;
|
||||
|
||||
@@ -83,7 +69,6 @@ static int CalculateNextTimeUsingSched (QueuedRem *q);
|
||||
static void ServerWait (struct timeval *sleep_tv);
|
||||
static void reread (void);
|
||||
static void PrintQueue(void);
|
||||
static char const *QueueFilename(char const *fname);
|
||||
|
||||
static void chomp(DynamicBuffer *buf)
|
||||
{
|
||||
@@ -100,7 +85,7 @@ static void chomp(DynamicBuffer *buf)
|
||||
}
|
||||
}
|
||||
|
||||
char const *SimpleTimeNoSpace(int tim)
|
||||
static char const *SimpleTimeNoSpace(int tim)
|
||||
{
|
||||
char *s = (char *) SimpleTime(tim);
|
||||
if (s && *s) {
|
||||
@@ -112,49 +97,7 @@ char const *SimpleTimeNoSpace(int tim)
|
||||
return s;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* QueueFilename */
|
||||
/* */
|
||||
/* Add fname to the list of queued filenames if it's not */
|
||||
/* already present. Either way, return a pointer to the */
|
||||
/* filename. Returns NULL if out of memory */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static QueuedFilename *last_file_found = NULL;
|
||||
static char const *QueueFilename(char const *fname)
|
||||
{
|
||||
QueuedFilename *elem = Files;
|
||||
|
||||
/* Optimization: We are very likely in the same file as
|
||||
before... */
|
||||
if (last_file_found && !strcmp(fname, last_file_found->fname)) {
|
||||
return last_file_found->fname;
|
||||
}
|
||||
|
||||
/* No such luck; search the list */
|
||||
while(elem) {
|
||||
if (!strcmp(elem->fname, fname)) {
|
||||
last_file_found = elem;
|
||||
return elem->fname;
|
||||
}
|
||||
elem = elem->next;
|
||||
}
|
||||
/* Not found... queue it */
|
||||
elem = NEW(QueuedFilename);
|
||||
if (!elem) return NULL;
|
||||
elem->fname = StrDup(fname);
|
||||
if (!elem->fname) {
|
||||
free(elem);
|
||||
return NULL;
|
||||
}
|
||||
elem->next = Files;
|
||||
Files = elem;
|
||||
last_file_found = elem;
|
||||
return elem->fname;
|
||||
}
|
||||
|
||||
static void del_reminder(QueuedRem *qid)
|
||||
static void del_reminder(QueuedRem const *qid)
|
||||
{
|
||||
QueuedRem *q = QueueHead;
|
||||
QueuedRem *next;
|
||||
@@ -194,7 +137,7 @@ static void del_reminder_ul(unsigned long qid) {
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int QueueReminder(ParsePtr p, Trigger *trig,
|
||||
TimeTrig *tim, char const *sched)
|
||||
TimeTrig const *tim, char const *sched)
|
||||
{
|
||||
QueuedRem *qelem;
|
||||
|
||||
@@ -217,13 +160,7 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
||||
free(qelem);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
qelem->fname = QueueFilename(FileName);
|
||||
if (!qelem->fname) {
|
||||
free((void *) qelem->text);
|
||||
free(qelem);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
|
||||
qelem->fname = GetCurrentFilename();
|
||||
qelem->lineno = LineNo;
|
||||
qelem->lineno_start = LineNoStart;
|
||||
NumQueued++;
|
||||
@@ -272,7 +209,7 @@ maybe_close(int fd)
|
||||
(void) close(new_fd);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
SigContHandler(int d)
|
||||
{
|
||||
UNUSED(d);
|
||||
@@ -327,12 +264,6 @@ void HandleQueuedReminders(void)
|
||||
/* Turn off sorting -- otherwise, TriggerReminder has no effect! */
|
||||
SortByDate = 0;
|
||||
|
||||
/* Free FileName if necessary */
|
||||
if (FileName) {
|
||||
free(FileName);
|
||||
FileName = NULL;
|
||||
}
|
||||
|
||||
/* We don't need to keep the dedupe table around */
|
||||
ClearDedupeTable();
|
||||
|
||||
@@ -495,7 +426,7 @@ void HandleQueuedReminders(void)
|
||||
/* Set up global variables so some functions like trigdate()
|
||||
and trigtime() work correctly */
|
||||
SaveAllTriggerInfo(&(q->t), &(q->tt), DSEToday, q->tt.ttime, 1);
|
||||
FileName = (char *) q->fname;
|
||||
SetCurrentFilename(q->fname);
|
||||
DefaultColorR = q->red;
|
||||
DefaultColorG = q->green;
|
||||
DefaultColorB = q->blue;
|
||||
@@ -505,7 +436,7 @@ void HandleQueuedReminders(void)
|
||||
if (DaemonJSON) {
|
||||
DynamicBuffer out;
|
||||
DBufInit(&out);
|
||||
(void) TriggerReminder(&p, &tcopy, &q->tt, DSEToday, 1, &out);
|
||||
(void) TriggerReminder(&p, &tcopy, &q->tt, DSEToday, 1, &out, NULL, NULL, NULL);
|
||||
if (q->typ != RUN_TYPE) {
|
||||
printf("\"body\":\"");
|
||||
chomp(&out);
|
||||
@@ -514,9 +445,8 @@ void HandleQueuedReminders(void)
|
||||
}
|
||||
DBufFree(&out);
|
||||
} else {
|
||||
(void) TriggerReminder(&p, &tcopy, &q->tt, DSEToday, 1, NULL);
|
||||
(void) TriggerReminder(&p, &tcopy, &q->tt, DSEToday, 1, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
FileName = NULL;
|
||||
if (IsServerMode() && !DaemonJSON && q->typ != RUN_TYPE) {
|
||||
printf("NOTE endreminder\n");
|
||||
}
|
||||
@@ -774,7 +704,7 @@ json_queue(QueuedRem const *q)
|
||||
}
|
||||
done = 1;
|
||||
printf("{");
|
||||
WriteJSONTrigger(&(q->t), 1, DSEToday);
|
||||
WriteJSONTrigger(&(q->t), 1);
|
||||
WriteJSONTimeTrigger(&(q->tt));
|
||||
if (TestMode) {
|
||||
snprintf(idbuf, sizeof(idbuf), "42424242");
|
||||
|
||||
44
src/rem2ps.c
44
src/rem2ps.c
@@ -131,16 +131,16 @@ int LeftMarg, RightMarg, TopMarg, BotMarg;
|
||||
int FillPage;
|
||||
int Verbose = 0;
|
||||
|
||||
void Init (int argc, char *argv[]);
|
||||
void Usage (char const *s);
|
||||
void DoPsCal (void);
|
||||
int DoQueuedPs (void);
|
||||
void DoSmallCal (char const *m, int days, int first, int col, int which);
|
||||
void WriteProlog (void);
|
||||
void WriteCalEntry (void);
|
||||
void WriteOneEntry (CalEntry *c);
|
||||
void GetSmallLocations (void);
|
||||
char const *EatToken(char const *in, char *out, int maxlen);
|
||||
static void Init (int argc, char const *argv[]);
|
||||
static void Usage (char const *s);
|
||||
static void DoPsCal (void);
|
||||
static int DoQueuedPs (void);
|
||||
static void DoSmallCal (char const *m, int days, int first, int col, int which);
|
||||
static void WriteProlog (void);
|
||||
static void WriteCalEntry (void);
|
||||
static void WriteOneEntry (CalEntry const *c);
|
||||
static void GetSmallLocations (void);
|
||||
static char const *EatToken(char const *in, char *out, int maxlen);
|
||||
|
||||
static void
|
||||
put_escaped_string(char const *s)
|
||||
@@ -161,7 +161,7 @@ put_escaped_string(char const *s)
|
||||
/* Compare strings, case insensitive. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int StrCmpi(char const *s1, char const *s2)
|
||||
static int StrCmpi(char const *s1, char const *s2)
|
||||
{
|
||||
int r;
|
||||
while (*s1 && *s2) {
|
||||
@@ -178,7 +178,7 @@ int StrCmpi(char const *s1, char const *s2)
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static CalEntry *
|
||||
JSONToCalEntry(DynamicBuffer *buf)
|
||||
JSONToCalEntry(DynamicBuffer const *buf)
|
||||
{
|
||||
CalEntry *c;
|
||||
json_value *val;
|
||||
@@ -325,7 +325,7 @@ TextToCalEntry(DynamicBuffer *buf)
|
||||
/* MAIN PROGRAM */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int main(int argc, char *argv[])
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
/* If stdin is a tty - probably wrong. */
|
||||
|
||||
@@ -375,7 +375,7 @@ int main(int argc, char *argv[])
|
||||
/* DoPsCal - emit PostScript for the calendar. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void DoPsCal(void)
|
||||
static void DoPsCal(void)
|
||||
{
|
||||
char month[40], year[40];
|
||||
char prevm[40], nextm[40];
|
||||
@@ -595,7 +595,7 @@ void DoPsCal(void)
|
||||
/* WriteProlog - write the PostScript prologue */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void WriteProlog(void)
|
||||
static void WriteProlog(void)
|
||||
{
|
||||
int i;
|
||||
int x = CurPage->xsize;
|
||||
@@ -702,7 +702,7 @@ void WriteProlog(void)
|
||||
/* WriteCalEntry - write all entries for one day */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void WriteCalEntry(void)
|
||||
static void WriteCalEntry(void)
|
||||
{
|
||||
CalEntry *c = CurEntries;
|
||||
CalEntry *d;
|
||||
@@ -789,7 +789,7 @@ void WriteCalEntry(void)
|
||||
/* WriteOneEntry - write an entry for one day */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void WriteOneEntry(CalEntry *c)
|
||||
static void WriteOneEntry(CalEntry const *c)
|
||||
{
|
||||
int ch, i;
|
||||
char const *s = c->entry;
|
||||
@@ -851,7 +851,7 @@ void WriteOneEntry(CalEntry *c)
|
||||
/* Init - set up parameters */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void Init(int argc, char *argv[])
|
||||
static void Init(int argc, char const *argv[])
|
||||
{
|
||||
char const *s;
|
||||
char const *t;
|
||||
@@ -1043,7 +1043,7 @@ void Usage(char const *s)
|
||||
/* month. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void DoSmallCal(char const *m, int days, int first, int col, int which)
|
||||
static void DoSmallCal(char const *m, int days, int first, int col, int which)
|
||||
{
|
||||
/* Do the small calendar */
|
||||
int i, j;
|
||||
@@ -1097,7 +1097,7 @@ void DoSmallCal(char const *m, int days, int first, int col, int which)
|
||||
/* DoQueuedPs - do the queued PS and PSFILE reminders. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DoQueuedPs(void)
|
||||
static int DoQueuedPs(void)
|
||||
{
|
||||
int i;
|
||||
int HadPS = 0;
|
||||
@@ -1305,7 +1305,7 @@ int DoQueuedPs(void)
|
||||
/* Set up the locations for the small calendars. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void GetSmallLocations(void)
|
||||
static void GetSmallLocations(void)
|
||||
{
|
||||
char c;
|
||||
char const *s = SmallLocation;
|
||||
@@ -1370,7 +1370,7 @@ void GetSmallLocations(void)
|
||||
/* Read a space-delimited token into an output buffer. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
char const *EatToken(char const *in, char *out, int maxlen)
|
||||
static char const *EatToken(char const *in, char *out, int maxlen)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
|
||||
26
src/token.c
26
src/token.c
@@ -27,11 +27,11 @@
|
||||
executes 'return' if an initial non-numeric char is found. */
|
||||
#define PARSENUM(var, string) \
|
||||
if (!isdigit(*(string))) return; \
|
||||
var = 0; \
|
||||
(var) = 0; \
|
||||
while (isdigit(*(string))) { \
|
||||
var *= 10; \
|
||||
var += *(string) - '0'; \
|
||||
string++; \
|
||||
(var) *= 10; \
|
||||
(var) += *(string) - '0'; \
|
||||
(string)++; \
|
||||
}
|
||||
|
||||
/* The big array holding all recognized (literal) tokens in reminder file.
|
||||
@@ -46,7 +46,8 @@ Token TokArray[] = {
|
||||
{ "banner", 3, T_Banner, 0 },
|
||||
{ "before", 6, T_Skip, BEFORE_SKIP },
|
||||
{ "cal", 3, T_RemType, CAL_TYPE },
|
||||
{ "clear-omit-context", 5, T_Clr, 0 },
|
||||
{ "clear-omit-context", 5, T_Clr, 0 },
|
||||
{ "complete-through", 16, T_CompleteThrough, 0 },
|
||||
{ "debug", 5, T_Debug, 0 },
|
||||
{ "december", 3, T_Month, 11 },
|
||||
{ "do", 2, T_IncludeR, 0 },
|
||||
@@ -90,13 +91,18 @@ Token TokArray[] = {
|
||||
{ "omit", 4, T_Omit, 0 },
|
||||
{ "omitfunc", 8, T_OmitFunc, 0 },
|
||||
{ "once", 4, T_Once, 0 },
|
||||
{ "pop-funcs", 9, T_PopFuncs, 0 },
|
||||
{ "pop-omit-context", 3, T_Pop, 0 },
|
||||
{ "pop-vars", 8, T_PopVars, 0 },
|
||||
{ "preserve", 8, T_Preserve, 0 },
|
||||
{ "priority", 8, T_Priority, 0 },
|
||||
{ "ps", 2, T_RemType, PS_TYPE },
|
||||
{ "psfile", 6, T_RemType, PSF_TYPE },
|
||||
{ "psfile", 6, T_RemType, PSF_TYPE },
|
||||
{ "push-funcs", 10, T_PushFuncs, 0 },
|
||||
{ "push-omit-context", 4, T_Push, 0 },
|
||||
{ "push-vars", 9, T_PushVars, 0 },
|
||||
{ "rem", 3, T_Rem, 0 },
|
||||
{ "return", 6, T_Return, 0 },
|
||||
{ "run", 3, T_RemType, RUN_TYPE },
|
||||
{ "satisfy", 7, T_RemType, SAT_TYPE },
|
||||
{ "saturday", 3, T_WkDay, 5 },
|
||||
@@ -113,6 +119,7 @@ Token TokArray[] = {
|
||||
{ "third", 5, T_Ordinal, 2 },
|
||||
{ "through", 7, T_Through, 0 },
|
||||
{ "thursday", 3, T_WkDay, 3 },
|
||||
{ "todo", 4, T_Todo, 0 },
|
||||
{ "translate", 5, T_Translate, 0 },
|
||||
{ "tuesday", 3, T_WkDay, 1 },
|
||||
{ "unset", 5, T_UnSet, 0 },
|
||||
@@ -122,6 +129,7 @@ Token TokArray[] = {
|
||||
};
|
||||
|
||||
static int TokStrCmp (Token const *t, char const *s);
|
||||
static void FindNumericToken(char const *s, Token *t);
|
||||
|
||||
static void
|
||||
init_token(Token *t)
|
||||
@@ -247,7 +255,7 @@ void FindToken(char const *s, Token *tok)
|
||||
/* Rep - *n */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void FindNumericToken(char const *s, Token *t)
|
||||
static void FindNumericToken(char const *s, Token *t)
|
||||
{
|
||||
int mult = 1, hour, min;
|
||||
char const *s_orig = s;
|
||||
@@ -443,7 +451,7 @@ static int TokStrCmp(Token const *t, char const *s)
|
||||
}
|
||||
|
||||
static void
|
||||
print_token(Token *tok)
|
||||
print_token(Token const *tok)
|
||||
{
|
||||
if (tok->MinLen < (int) strlen(tok->name)) {
|
||||
printf("%.*s\n", tok->MinLen, tok->name);
|
||||
@@ -455,7 +463,7 @@ void
|
||||
print_remind_tokens(void)
|
||||
{
|
||||
int i;
|
||||
Token *tok;
|
||||
Token const *tok;
|
||||
int num = (int) (sizeof(TokArray) / sizeof(TokArray[0]));
|
||||
printf("# Remind Tokens\n\n");
|
||||
for (i=0; i<num; i++) {
|
||||
|
||||
12
src/trans.c
12
src/trans.c
@@ -272,17 +272,17 @@ DumpTranslationTable(FILE *fp, int json)
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
HashXlateItem(void *x)
|
||||
HashXlateItem(void const *x)
|
||||
{
|
||||
XlateItem *item = (XlateItem *) x;
|
||||
XlateItem const *item = (XlateItem const *) x;
|
||||
return HashVal_preservecase(item->orig);
|
||||
}
|
||||
|
||||
static int
|
||||
CompareXlateItems(void *a, void *b)
|
||||
CompareXlateItems(void const *a, void const *b)
|
||||
{
|
||||
XlateItem *i = (XlateItem *) a;
|
||||
XlateItem *j = (XlateItem *) b;
|
||||
XlateItem const *i = (XlateItem const *) a;
|
||||
XlateItem const *j = (XlateItem const *) b;
|
||||
return strcmp(i->orig, j->orig);
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ InsertTranslation(char const *orig, char const *translated)
|
||||
char const *
|
||||
GetTranslatedString(char const *orig)
|
||||
{
|
||||
XlateItem *item = FindTranslation(orig);
|
||||
XlateItem const *item = FindTranslation(orig);
|
||||
if (!item) return NULL;
|
||||
return item->translated;
|
||||
}
|
||||
|
||||
@@ -29,8 +29,10 @@
|
||||
|
||||
static int DSEYear(int dse);
|
||||
static int DSEMonth(int dse);
|
||||
static int NextSimpleTrig(int startdate, Trigger *trig, int *err);
|
||||
static int NextSimpleTrig(int startdate, Trigger const *trig, int *err);
|
||||
static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart);
|
||||
static int TrigInfoIsValid(char const *info);
|
||||
static int TrigInfoHeadersAreTheSame(char const *i1, char const *i2);
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -44,7 +46,7 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
/* so that dates with a REP can be handled properly. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
static int NextSimpleTrig(int startdate, Trigger const *trig, int *err)
|
||||
{
|
||||
int typ = 0;
|
||||
int d, m, y, j, d2, m2, y2;
|
||||
@@ -309,16 +311,28 @@ static int DSEYear(int dse)
|
||||
static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart)
|
||||
{
|
||||
int simple, mod, omit;
|
||||
int calmode = (DoSimpleCalendar || DoCalendar) ? 1 : 0;
|
||||
if (HideCompletedTodos) calmode = 0;
|
||||
|
||||
/* First: Have we passed the UNTIL date? */
|
||||
if (trig->until != NO_UNTIL &&
|
||||
/* First: Have we passed the UNTIL date? */
|
||||
if (!trig->is_todo &&
|
||||
trig->until != NO_UNTIL &&
|
||||
trig->until < start) {
|
||||
trig->expired = 1;
|
||||
return -1; /* expired */
|
||||
}
|
||||
|
||||
/* Next: If it's an "AFTER"-type skip, back up
|
||||
until we're at the start of a block of holidays */
|
||||
/* If it's a TODO and complete_through is past today, we're good */
|
||||
if (!calmode &&
|
||||
trig->is_todo &&
|
||||
trig->complete_through != NO_DATE &&
|
||||
trig->complete_through >= start) {
|
||||
trig->expired = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
int iter = 0;
|
||||
while (iter++ <= MaxSatIter) {
|
||||
@@ -339,16 +353,16 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the next simple trigger */
|
||||
/* Find the next simple trigger */
|
||||
simple = NextSimpleTrig(start, trig, err);
|
||||
|
||||
/* Problems? */
|
||||
/* Problems? */
|
||||
if (*err || (simple == -1)) return -1;
|
||||
|
||||
/* Suggested starting point for next attempt */
|
||||
/* Suggested starting point for next attempt */
|
||||
*nextstart = simple+1;
|
||||
|
||||
/* If there's a BACK, back up... */
|
||||
/* If there's a BACK, back up... */
|
||||
if (trig->back != NO_BACK) {
|
||||
mod = trig->back;
|
||||
if (mod < 0) {
|
||||
@@ -376,7 +390,7 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
}
|
||||
}
|
||||
|
||||
/* If there's a REP, calculate the next occurrence */
|
||||
/* If there's a REP, calculate the next occurrence */
|
||||
if (trig->rep != NO_REP) {
|
||||
if (simple < start) {
|
||||
mod = (start - simple) / trig->rep;
|
||||
@@ -385,7 +399,7 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
}
|
||||
}
|
||||
|
||||
/* If it's a "BEFORE"-type skip, back up */
|
||||
/* If it's a "BEFORE"-type skip, back up */
|
||||
if (trig->skip == BEFORE_SKIP) {
|
||||
int iter = 0;
|
||||
while(iter++ <= MaxSatIter) {
|
||||
@@ -406,7 +420,7 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
}
|
||||
}
|
||||
|
||||
/* If it's an "AFTER"-type skip, jump ahead */
|
||||
/* If it's an "AFTER"-type skip, jump ahead */
|
||||
if (trig->skip == AFTER_SKIP) {
|
||||
int iter = 0;
|
||||
while (iter++ <= MaxSatIter) {
|
||||
@@ -423,7 +437,12 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the date */
|
||||
/* If we've passed the UNTIL, then it's expired */
|
||||
if (trig->until != NO_UNTIL && simple > trig->until) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return the date */
|
||||
return simple;
|
||||
}
|
||||
|
||||
@@ -453,7 +472,7 @@ AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int sav
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
FromDSE(r, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%s): Trig(adj) = %s, %d %s, %d",
|
||||
FileName, line_range(LineNoStart, LineNo),
|
||||
GetCurrentFilename(), line_range(LineNoStart, LineNo),
|
||||
get_day_name(r % 7),
|
||||
d,
|
||||
get_month_name(m),
|
||||
@@ -524,7 +543,7 @@ int ComputeTrigger(int today, Trigger *trig, TimeTrig *tim,
|
||||
/* duration. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig const *tim,
|
||||
int *err, int save_in_globals, int duration_days)
|
||||
{
|
||||
int nattempts = 0,
|
||||
@@ -536,6 +555,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
trig->expired = 0;
|
||||
if (save_in_globals) {
|
||||
LastTrigValid = 0;
|
||||
LastTriggerDate = -1;
|
||||
}
|
||||
|
||||
/* Assume everything works */
|
||||
@@ -574,14 +594,13 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
|
||||
while (nattempts++ < TRIG_ATTEMPTS) {
|
||||
result = GetNextTriggerDate(trig, start, err, &nextstart);
|
||||
|
||||
/* If there's an error, die immediately */
|
||||
if (*err) return -1;
|
||||
if (result == -1) {
|
||||
trig->expired = 1;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%s): %s\n",
|
||||
FileName, line_range(LineNoStart, LineNo), GetErr(E_EXPIRED));
|
||||
GetCurrentFilename(), line_range(LineNoStart, LineNo), GetErr(E_EXPIRED));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -604,7 +623,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
FromDSE(result, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%s): Trig = %s, %d %s, %d",
|
||||
FileName, line_range(LineNoStart, LineNo),
|
||||
GetCurrentFilename(), line_range(LineNoStart, LineNo),
|
||||
get_day_name(result % 7),
|
||||
d,
|
||||
get_month_name(m),
|
||||
@@ -630,8 +649,9 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
trig->rep == NO_REP) {
|
||||
trig->expired = 1;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%s): %s\n",
|
||||
FileName, line_range(LineNoStart, LineNo), GetErr(E_EXPIRED));
|
||||
FromDSE(result, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%s): %s: %04d-%02d-%02d\n",
|
||||
GetCurrentFilename(), line_range(LineNoStart, LineNo), GetErr(E_EXPIRED), y, m+1, d);
|
||||
}
|
||||
if (save_in_globals) {
|
||||
LastTriggerDate = result;
|
||||
@@ -656,7 +676,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
trig->expired = 1;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%s): %s\n",
|
||||
FileName, line_range(LineNoStart, LineNo), GetErr(E_EXPIRED));
|
||||
GetCurrentFilename(), line_range(LineNoStart, LineNo), GetErr(E_EXPIRED));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -677,7 +697,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
/* Returns NULL if memory allocation fails. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
TrigInfo *
|
||||
static TrigInfo *
|
||||
NewTrigInfo(char const *i)
|
||||
{
|
||||
TrigInfo *ti = malloc(sizeof(TrigInfo));
|
||||
@@ -701,7 +721,7 @@ NewTrigInfo(char const *i)
|
||||
/* Free a TrigInfo objects. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void
|
||||
static void
|
||||
FreeTrigInfo(TrigInfo *ti)
|
||||
{
|
||||
if (ti->info) {
|
||||
@@ -768,7 +788,7 @@ AppendTrigInfo(Trigger *t, char const *info)
|
||||
return OK;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
TrigInfoHeadersAreTheSame(char const *i1, char const *i2)
|
||||
{
|
||||
char const *c1 = strchr(i1, ':');
|
||||
@@ -779,7 +799,7 @@ TrigInfoHeadersAreTheSame(char const *i1, char const *i2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
TrigInfoIsValid(char const *info)
|
||||
{
|
||||
char const *t;
|
||||
|
||||
35
src/types.h
35
src/types.h
@@ -105,7 +105,10 @@ typedef struct var {
|
||||
struct hash_link link;
|
||||
char name[VAR_NAME_LEN+1];
|
||||
char preserve;
|
||||
char nonconstant;
|
||||
char is_constant;
|
||||
char used_since_set;
|
||||
char const *filename;
|
||||
int lineno;
|
||||
Value v;
|
||||
} Var;
|
||||
|
||||
@@ -133,6 +136,8 @@ typedef struct {
|
||||
int from;
|
||||
int adj_for_last; /* Adjust month/year for use of LAST */
|
||||
int need_wkday; /* Set if we *need* a weekday */
|
||||
int is_todo; /* This is a TODO reminder */
|
||||
int complete_through; /* DSE of complete-through date */
|
||||
int priority;
|
||||
int duration_days; /* Duration converted to days to search */
|
||||
int eventstart; /* Original event start (datetime) */
|
||||
@@ -191,6 +196,7 @@ typedef Parser *ParsePtr; /* Pointer to parser structure */
|
||||
#define AFTER_SKIP 3
|
||||
|
||||
#define NO_TIME INT_MAX
|
||||
#define NO_SCANFROM INT_MIN
|
||||
|
||||
#define NO_PRIORITY 5000 /* Default priority is midway between 0 and 9999 */
|
||||
|
||||
@@ -218,19 +224,22 @@ typedef Parser *ParsePtr; /* Pointer to parser structure */
|
||||
#define DB_HASHSTATS 0x080
|
||||
#define DB_TRANSLATE 0x100
|
||||
#define DB_NONCONST 0x200
|
||||
#define DB_UNUSED_VARS 0x400
|
||||
|
||||
/* Enumeration of the tokens */
|
||||
enum TokTypes
|
||||
{ T_Illegal,
|
||||
T_AddOmit, T_At, T_Back, T_BackAdj, T_Banner, T_Clr, T_Comment,
|
||||
T_AddOmit, T_At, T_Back, T_BackAdj, T_Banner, T_Clr, T_Comment, T_CompleteThrough,
|
||||
T_Date, T_DateTime, T_Day, T_Debug, T_Delta, T_Dumpvars, T_Duration,
|
||||
T_Else, T_Empty, T_EndIf, T_ErrMsg, T_Exit, T_Expr,
|
||||
T_Flush, T_Frename, T_Fset, T_Funset, T_If, T_IfTrig, T_In,
|
||||
T_Include, T_IncludeCmd, T_IncludeR, T_IncludeSys, T_Info, T_LastBack,
|
||||
T_LongTime, T_MaybeUncomputable, T_Month, T_NoQueue, T_Number, T_Omit,
|
||||
T_OmitFunc, T_Once, T_Ordinal, T_Pop, T_Preserve, T_Priority, T_Push,T_Rem,
|
||||
T_RemType, T_Rep, T_Scanfrom, T_Sched, T_Set, T_Skip, T_Tag, T_Through,
|
||||
T_Time, T_Translate, T_UnSet, T_Until, T_Warn, T_WkDay, T_Year
|
||||
T_Else, T_Empty, T_EndIf, T_ErrMsg, T_Exit, T_Expr, T_Flush,
|
||||
T_Frename, T_Fset, T_Funset, T_If, T_IfTrig, T_In, T_Include,
|
||||
T_IncludeCmd, T_IncludeR, T_IncludeSys, T_Info, T_LastBack,
|
||||
T_LongTime, T_MaybeUncomputable, T_Month, T_NoQueue, T_Number,
|
||||
T_Omit, T_OmitFunc, T_Once, T_Ordinal, T_Pop, T_PopFuncs, T_PopVars,
|
||||
T_Preserve, T_Priority, T_Push, T_PushFuncs, T_PushVars, T_Rem,
|
||||
T_RemType, T_Rep, T_Return, T_Scanfrom, T_Sched, T_Set, T_Skip, T_Tag,
|
||||
T_Through, T_Time, T_Todo, T_Translate, T_UnSet, T_Until, T_Warn, T_WkDay,
|
||||
T_Year
|
||||
};
|
||||
|
||||
/* The structure of a token */
|
||||
@@ -252,6 +261,7 @@ typedef struct {
|
||||
#define RUN_CMDLINE 0x01
|
||||
#define RUN_SCRIPT 0x02
|
||||
#define RUN_NOTOWNER 0x04
|
||||
#define RUN_IN_EVAL 0x08
|
||||
|
||||
/* Flags for the SimpleCalendar format */
|
||||
#define SC_AMPM 0 /* Time shown as 3:00am, etc. */
|
||||
@@ -305,4 +315,11 @@ typedef struct udf_struct {
|
||||
int lineno;
|
||||
int lineno_start;
|
||||
int recurse_flag;
|
||||
int been_pushed;
|
||||
} UserFunc;
|
||||
|
||||
/* A pushed systtem variable */
|
||||
typedef struct {
|
||||
char const *name;
|
||||
Value v;
|
||||
} PushedSysvar;
|
||||
|
||||
280
src/userfns.c
280
src/userfns.c
@@ -36,16 +36,16 @@ static void FUnset (char const *name);
|
||||
static void FSet (UserFunc *f);
|
||||
static void RenameUserFunc(char const *oldname, char const *newname);
|
||||
|
||||
static unsigned int HashUserFunc(void *x)
|
||||
static unsigned int HashUserFunc(void const *x)
|
||||
{
|
||||
UserFunc *f = (UserFunc *) x;
|
||||
UserFunc const *f = (UserFunc const *) x;
|
||||
return HashVal_preservecase(f->name);
|
||||
}
|
||||
|
||||
static int CompareUserFuncs(void *a, void *b)
|
||||
static int CompareUserFuncs(void const *a, void const *b)
|
||||
{
|
||||
UserFunc *f = (UserFunc *) a;
|
||||
UserFunc *g = (UserFunc *) b;
|
||||
UserFunc const *f = (UserFunc const *) a;
|
||||
UserFunc const *g = (UserFunc const *) b;
|
||||
return strcmp(f->name, g->name);
|
||||
}
|
||||
|
||||
@@ -181,12 +181,34 @@ int DoFset(ParsePtr p)
|
||||
Var *locals = NULL;
|
||||
Var local_array[MAX_FUNC_ARGS];
|
||||
int orig_namelen;
|
||||
int suppress_redefined_function_warning = 0;
|
||||
int ch;
|
||||
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
|
||||
|
||||
ch = ParseNonSpaceChar(p, &r, 1);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
if (ch == '-') {
|
||||
r = ParseToken(p, &buf);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
if (strcmp(DBufValue(&buf), "-")) {
|
||||
DBufFree(&buf);
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
suppress_redefined_function_warning = 1;
|
||||
DBufFree(&buf);
|
||||
}
|
||||
|
||||
/* Get the function name */
|
||||
if ( (r=ParseIdentifier(p, &buf)) ) return r;
|
||||
if ( (r=ParseIdentifier(p, &buf)) ) {
|
||||
return r;
|
||||
}
|
||||
if (*DBufValue(&buf) == '$') {
|
||||
DBufFree(&buf);
|
||||
return E_BAD_ID;
|
||||
@@ -214,7 +236,7 @@ int DoFset(ParsePtr p)
|
||||
file, do nothing */
|
||||
existing = FindUserFunc(DBufValue(&buf));
|
||||
if (existing) {
|
||||
if (!strcmp(existing->filename, FileName) &&
|
||||
if (!strcmp(existing->filename, GetCurrentFilename()) &&
|
||||
strcmp(existing->filename, "[cmdline]") &&
|
||||
existing->lineno == LineNo) {
|
||||
DBufFree(&buf);
|
||||
@@ -222,8 +244,10 @@ int DoFset(ParsePtr p)
|
||||
return OK;
|
||||
}
|
||||
/* Warn about redefinition */
|
||||
Wprint(tr("Function `%s' redefined: previously defined at %s(%s)"),
|
||||
existing->name, existing->filename, line_range(existing->lineno_start, existing->lineno));
|
||||
if (!suppress_redefined_function_warning && !existing->been_pushed) {
|
||||
Wprint(tr("Function `%s' redefined: previously defined at %s(%s)"),
|
||||
existing->name, existing->filename, line_range(existing->lineno_start, existing->lineno));
|
||||
}
|
||||
}
|
||||
|
||||
/* Should be followed by '(' */
|
||||
@@ -242,18 +266,15 @@ int DoFset(ParsePtr p)
|
||||
DBufFree(&buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
if (FileName) {
|
||||
func->filename = StrDup(FileName);
|
||||
if (GetCurrentFilename()) {
|
||||
func->filename = GetCurrentFilename();
|
||||
} else {
|
||||
func->filename = StrDup("[cmdline]");
|
||||
}
|
||||
if (!func->filename) {
|
||||
free(func);
|
||||
return E_NO_MEM;
|
||||
func->filename = "[cmdline]";
|
||||
}
|
||||
func->lineno = LineNo;
|
||||
func->lineno_start = LineNoStart;
|
||||
func->recurse_flag = 0;
|
||||
func->been_pushed = 0;
|
||||
if (in_constant_context()) {
|
||||
func->is_constant = 1;
|
||||
} else {
|
||||
@@ -358,6 +379,10 @@ int DoFset(ParsePtr p)
|
||||
/* Save the argument names */
|
||||
if (func->nargs) {
|
||||
func->args = calloc(func->nargs, sizeof(char *));
|
||||
if (!func->args) {
|
||||
DestroyUserFunc(func);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
for (i=0; i<func->nargs; i++) {
|
||||
func->args[i] = StrDup(local_array[i].name);
|
||||
if (!func->args[i]) {
|
||||
@@ -393,9 +418,6 @@ static void DestroyUserFunc(UserFunc *f)
|
||||
/* Free the function definition */
|
||||
if (f->node) free_expr_tree(f->node);
|
||||
|
||||
/* Free the filename */
|
||||
if (f->filename) free( (char *) f->filename);
|
||||
|
||||
/* Free arg names */
|
||||
if (f->args) {
|
||||
for (i=0; i<f->nargs; i++) {
|
||||
@@ -532,3 +554,223 @@ dump_userfunc_hash_stats(void)
|
||||
hash_table_dump_stats(&FuncHash, ErrFp);
|
||||
}
|
||||
|
||||
typedef struct pushed_userfuncs {
|
||||
struct pushed_userfuncs *next;
|
||||
char const *filename;
|
||||
int lineno;
|
||||
int num_funcs;
|
||||
int alloc_funcs;
|
||||
UserFunc **funcs;
|
||||
} PushedUserFuncs;
|
||||
|
||||
static PushedUserFuncs *UserFuncStack = NULL;
|
||||
static UserFunc *clone_userfunc(char const *name, int *r)
|
||||
{
|
||||
int i;
|
||||
UserFunc *src;
|
||||
UserFunc *dest = NEW(UserFunc);
|
||||
*r = E_NO_MEM;
|
||||
if (!dest) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find the source function */
|
||||
src = FindUserFunc(name);
|
||||
|
||||
/* If it doesn't exist, use sentinal values to indicate that */
|
||||
if (!src) {
|
||||
*r = OK;
|
||||
StrnCpy(dest->name, name, VAR_NAME_LEN);
|
||||
dest->is_constant = 0;
|
||||
dest->node = NULL;
|
||||
dest->args = NULL;
|
||||
dest->nargs = -1;
|
||||
dest->filename = NULL;
|
||||
dest->lineno = -1;
|
||||
dest->lineno_start = -1;
|
||||
dest->recurse_flag = 0;
|
||||
dest->been_pushed = 0;
|
||||
return dest;
|
||||
}
|
||||
/* Copy the whole thing; then adjust */
|
||||
*dest = *src;
|
||||
|
||||
/* Allow warning-free redefinition of original function */
|
||||
src->been_pushed = 1;
|
||||
|
||||
/* For safety */
|
||||
dest->node = NULL;
|
||||
dest->args = NULL;
|
||||
|
||||
/* Copy args */
|
||||
if (dest->nargs) {
|
||||
dest->args = calloc(dest->nargs, sizeof(char *));
|
||||
if (!dest->args) {
|
||||
DestroyUserFunc(dest);
|
||||
return NULL;
|
||||
}
|
||||
for (i=0; i<dest->nargs; i++) {
|
||||
dest->args[i] = StrDup(src->args[i]);
|
||||
if (!dest->args[i]) {
|
||||
DestroyUserFunc(dest);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy expr */
|
||||
dest->node = clone_expr_tree(src->node, r);
|
||||
if (!dest->node) {
|
||||
DestroyUserFunc(dest);
|
||||
return NULL;
|
||||
}
|
||||
*r = OK;
|
||||
return dest;
|
||||
}
|
||||
|
||||
static int add_func_to_push(char const *name, PushedUserFuncs *pf)
|
||||
{
|
||||
int r;
|
||||
UserFunc *clone = clone_userfunc(name, &r);
|
||||
if (!clone) {
|
||||
return r;
|
||||
}
|
||||
if (!pf->alloc_funcs) {
|
||||
pf->funcs = calloc(4, sizeof(UserFunc *));
|
||||
if (!pf->funcs) {
|
||||
DestroyUserFunc(clone);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
pf->alloc_funcs = 4;
|
||||
} else {
|
||||
if (pf->num_funcs == pf->alloc_funcs) {
|
||||
pf->funcs = realloc(pf->funcs, 2 * pf->alloc_funcs * sizeof(UserFunc *));
|
||||
if (!pf->funcs) {
|
||||
DestroyUserFunc(clone);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
pf->alloc_funcs *= 2;
|
||||
}
|
||||
}
|
||||
pf->funcs[pf->num_funcs] = clone;
|
||||
pf->num_funcs++;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static void free_pushed_funcs(PushedUserFuncs *pf)
|
||||
{
|
||||
int i;
|
||||
if (pf->funcs) {
|
||||
for(i=0; i<pf->num_funcs; i++) {
|
||||
if (pf->funcs[i]) {
|
||||
DestroyUserFunc(pf->funcs[i]);
|
||||
}
|
||||
}
|
||||
free(pf->funcs);
|
||||
}
|
||||
free(pf);
|
||||
}
|
||||
|
||||
int PushUserFuncs(ParsePtr p)
|
||||
{
|
||||
int r;
|
||||
DynamicBuffer buf;
|
||||
char const *name;
|
||||
|
||||
DBufInit(&buf);
|
||||
PushedUserFuncs *pf = NEW(PushedUserFuncs);
|
||||
if (!pf) {
|
||||
return E_NO_MEM;
|
||||
}
|
||||
pf->next = NULL;
|
||||
pf->funcs = NULL;
|
||||
pf->filename = GetCurrentFilename();
|
||||
pf->lineno = LineNo;
|
||||
pf->num_funcs = 0;
|
||||
pf->alloc_funcs = 0;
|
||||
|
||||
while(1) {
|
||||
r = ParseIdentifier(p, &buf);
|
||||
if (r == E_EOLN) {
|
||||
break;
|
||||
}
|
||||
if (r) {
|
||||
DBufFree(&buf);
|
||||
free_pushed_funcs(pf);
|
||||
return r;
|
||||
}
|
||||
name = DBufValue(&buf);
|
||||
if (*name == '$') {
|
||||
DBufFree(&buf);
|
||||
free_pushed_funcs(pf);
|
||||
return E_BAD_ID;
|
||||
}
|
||||
|
||||
r = add_func_to_push(name, pf);
|
||||
|
||||
DBufFree(&buf);
|
||||
if (r != OK) {
|
||||
free_pushed_funcs(pf);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
if (pf->num_funcs == 0) {
|
||||
free_pushed_funcs(pf);
|
||||
return E_EOLN;
|
||||
}
|
||||
pf->next = UserFuncStack;
|
||||
UserFuncStack = pf;
|
||||
return OK;
|
||||
}
|
||||
|
||||
int PopUserFuncs(ParsePtr p)
|
||||
{
|
||||
int i;
|
||||
PushedUserFuncs *pf = UserFuncStack;
|
||||
int r = VerifyEoln(p);
|
||||
if (r != OK) {
|
||||
return r;
|
||||
}
|
||||
if (!pf) {
|
||||
return E_POPF_NO_PUSH;
|
||||
}
|
||||
UserFuncStack = UserFuncStack->next;
|
||||
if (strcmp(pf->filename, GetCurrentFilename())) {
|
||||
Wprint(tr("POP-FUNCS at %s:%d matches PUSH-FUNCS in different file: %s:%d"), GetCurrentFilename(), LineNo, pf->filename, pf->lineno);
|
||||
}
|
||||
for (i=0; i<pf->num_funcs; i++) {
|
||||
UserFunc *clone = pf->funcs[i];
|
||||
FUnset(clone->name);
|
||||
if (clone->nargs < 0 && !clone->node) {
|
||||
/* Popping a function that should simply be unset... we are done */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Insert the clone into the hash table */
|
||||
FSet(clone);
|
||||
|
||||
/* Make sure we don't free the clone! */
|
||||
pf->funcs[i] = NULL;
|
||||
}
|
||||
free_pushed_funcs(pf);
|
||||
return OK;
|
||||
}
|
||||
|
||||
int EmptyUserFuncStack(int print_unmatched)
|
||||
{
|
||||
int j = 0;
|
||||
PushedUserFuncs *next;
|
||||
while(UserFuncStack) {
|
||||
if (print_unmatched) {
|
||||
Wprint(tr("Unmatched PUSH-FUNCS at %s(%d)"),
|
||||
UserFuncStack->filename,
|
||||
UserFuncStack->lineno);
|
||||
}
|
||||
j++;
|
||||
next = UserFuncStack->next;
|
||||
free_pushed_funcs(UserFuncStack);
|
||||
UserFuncStack = next;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
|
||||
@@ -247,7 +247,7 @@ print_callstack_aux(FILE *fp, cs *entry)
|
||||
{
|
||||
int i = 0;
|
||||
char const *in = tr("In");
|
||||
cs *prev = NULL;
|
||||
cs const *prev = NULL;
|
||||
while(entry) {
|
||||
if (prev) {
|
||||
in = tr("Called from");
|
||||
|
||||
388
src/var.c
388
src/var.c
@@ -37,14 +37,16 @@ static int IntMax = INT_MAX;
|
||||
|
||||
static hash_table VHashTbl;
|
||||
static int SetSysVarHelper(SysVar *v, Value *value);
|
||||
static unsigned int HashVal_ignorecase(char const *str);
|
||||
static void set_lat_and_long_from_components(void);
|
||||
|
||||
static unsigned int VarHashFunc(void *x)
|
||||
static unsigned int VarHashFunc(void const *x)
|
||||
{
|
||||
Var *v = (Var *) x;
|
||||
Var const *v = (Var const *) x;
|
||||
return HashVal_ignorecase(v->name);
|
||||
}
|
||||
|
||||
static int VarCompareFunc(void *a, void *b)
|
||||
static int VarCompareFunc(void const *a, void const *b)
|
||||
{
|
||||
Var *x = (Var *) a;
|
||||
Var *y = (Var *) b;
|
||||
@@ -153,7 +155,7 @@ static int latitude_longitude_func(int do_set, Value *val, double *var, double m
|
||||
if (loc) {
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%f", *var);
|
||||
snprintf(buf, sizeof(buf), "%.8f", *var);
|
||||
if (loc) {
|
||||
setlocale(LC_NUMERIC, loc);
|
||||
}
|
||||
@@ -285,7 +287,7 @@ static int trig_until_func(int do_set, Value *val)
|
||||
|
||||
static int trig_day_func(int do_set, Value *val)
|
||||
{
|
||||
int y, m, d;
|
||||
int d;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
if (!LastTrigValid) {
|
||||
@@ -293,7 +295,7 @@ static int trig_day_func(int do_set, Value *val)
|
||||
return OK;
|
||||
}
|
||||
|
||||
FromDSE(LastTriggerDate, &y, &m, &d);
|
||||
FromDSE(LastTriggerDate, NULL, NULL, &d);
|
||||
val->v.val = d;
|
||||
return OK;
|
||||
}
|
||||
@@ -312,7 +314,7 @@ static int timet_is_64_func(int do_set, Value *val)
|
||||
|
||||
static int trig_mon_func(int do_set, Value *val)
|
||||
{
|
||||
int y, m, d;
|
||||
int m;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
if (!LastTrigValid) {
|
||||
@@ -320,14 +322,14 @@ static int trig_mon_func(int do_set, Value *val)
|
||||
return OK;
|
||||
}
|
||||
|
||||
FromDSE(LastTriggerDate, &y, &m, &d);
|
||||
FromDSE(LastTriggerDate, NULL, &m, NULL);
|
||||
val->v.val = m+1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int trig_year_func(int do_set, Value *val)
|
||||
{
|
||||
int y, m, d;
|
||||
int y;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
if (!LastTrigValid) {
|
||||
@@ -335,7 +337,7 @@ static int trig_year_func(int do_set, Value *val)
|
||||
return OK;
|
||||
}
|
||||
|
||||
FromDSE(LastTriggerDate, &y, &m, &d);
|
||||
FromDSE(LastTriggerDate, &y, NULL, NULL);
|
||||
val->v.val = y;
|
||||
return OK;
|
||||
}
|
||||
@@ -362,30 +364,30 @@ static int today_date_func(int do_set, Value *val)
|
||||
}
|
||||
static int today_day_func(int do_set, Value *val)
|
||||
{
|
||||
int y, m, d;
|
||||
int d;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
FromDSE(DSEToday, &y, &m, &d);
|
||||
FromDSE(DSEToday, NULL, NULL, &d);
|
||||
val->v.val = d;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int today_mon_func(int do_set, Value *val)
|
||||
{
|
||||
int y, m, d;
|
||||
int m;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
FromDSE(DSEToday, &y, &m, &d);
|
||||
FromDSE(DSEToday, NULL, &m, NULL);
|
||||
val->v.val = m+1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int today_year_func(int do_set, Value *val)
|
||||
{
|
||||
int y, m, d;
|
||||
int y;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
FromDSE(DSEToday, &y, &m, &d);
|
||||
FromDSE(DSEToday, &y, NULL, NULL);
|
||||
val->v.val = y;
|
||||
return OK;
|
||||
}
|
||||
@@ -523,7 +525,7 @@ static int time_sep_func(int do_set, Value *val)
|
||||
/* Given a string, compute the hash value case-insensitively */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
unsigned int HashVal_ignorecase(char const *str)
|
||||
static unsigned int HashVal_ignorecase(char const *str)
|
||||
{
|
||||
unsigned int h = 0, high;
|
||||
while(*str) {
|
||||
@@ -560,6 +562,9 @@ Var *FindVar(char const *str, int create)
|
||||
v->v.type = INT_TYPE;
|
||||
v->v.v.val = 0;
|
||||
v->preserve = 0;
|
||||
v->is_constant = 1;
|
||||
v->filename = "";
|
||||
v->lineno = 0;
|
||||
StrnCpy(v->name, str, VAR_NAME_LEN);
|
||||
|
||||
hash_table_insert(&VHashTbl, v);
|
||||
@@ -573,12 +578,15 @@ Var *FindVar(char const *str, int create)
|
||||
/* string and delete it. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DeleteVar(char const *str)
|
||||
static int DeleteVar(char const *str)
|
||||
{
|
||||
Var *v;
|
||||
|
||||
v = FindVar(str, 0);
|
||||
if (!v) return E_NOSUCH_VAR;
|
||||
if ((DebugFlag & DB_UNUSED_VARS) && !v->used_since_set) {
|
||||
Eprint(tr("`%s' UNSET without being used (previous SET: %s:%d)"), str, v->filename, v->lineno);
|
||||
}
|
||||
DestroyValue(v->v);
|
||||
hash_table_delete(&VHashTbl, v);
|
||||
return OK;
|
||||
@@ -593,36 +601,29 @@ int DeleteVar(char const *str)
|
||||
/***************************************************************/
|
||||
int SetVar(char const *str, Value const *val, int nonconst_expr)
|
||||
{
|
||||
Var *v = FindVar(str, 1);
|
||||
Var *v = NULL;
|
||||
|
||||
if (DebugFlag & DB_UNUSED_VARS) {
|
||||
v = FindVar(str, 0);
|
||||
if (v && !(v->used_since_set)) {
|
||||
Eprint(tr("`%s' re-SET without being used (previous SET: %s:%d)"), str, v->filename, v->lineno);
|
||||
}
|
||||
}
|
||||
|
||||
if (!v) {
|
||||
v = FindVar(str, 1);
|
||||
}
|
||||
if (!v) return E_NO_MEM; /* Only way FindVar can fail */
|
||||
|
||||
DestroyValue(v->v);
|
||||
v->v = *val;
|
||||
v->nonconstant = nonconst_expr;
|
||||
v->is_constant = ! nonconst_expr;
|
||||
v->used_since_set = 0;
|
||||
v->filename = GetCurrentFilename();
|
||||
v->lineno = LineNo;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* GetVarValue */
|
||||
/* */
|
||||
/* Get a copy of the value of the variable. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int GetVarValue(char const *str, Value *val)
|
||||
{
|
||||
Var *v;
|
||||
|
||||
v=FindVar(str, 0);
|
||||
|
||||
if (!v) {
|
||||
Eprint("%s: `%s'", GetErr(E_NOSUCH_VAR), str);
|
||||
return E_NOSUCH_VAR;
|
||||
}
|
||||
return CopyValue(val, &v->v);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoSet - set a variable. */
|
||||
@@ -641,7 +642,13 @@ int DoSet (Parser *p)
|
||||
Var *var;
|
||||
|
||||
r = ParseIdentifier(p, &buf);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
DBufFree(&buf);
|
||||
if (ignoring) {
|
||||
return OK;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
if (ignoring) {
|
||||
/* We're only here to mark a variable as non-const */
|
||||
@@ -651,8 +658,8 @@ int DoSet (Parser *p)
|
||||
}
|
||||
var = FindVar(DBufValue(&buf), 0);
|
||||
if (var) {
|
||||
nonconst_debug(var->nonconstant, tr("Potential variable assignment considered non-constant because of context"));
|
||||
var->nonconstant = 1;
|
||||
nonconst_debug(!var->is_constant, tr("Potential variable assignment considered non-constant because of context"));
|
||||
var->is_constant = 0;
|
||||
}
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
@@ -785,7 +792,7 @@ int DoDump(ParsePtr p)
|
||||
fprintf(ErrFp, "%s ", v->name);
|
||||
PrintValue(&(v->v), ErrFp);
|
||||
if (dump_constness) {
|
||||
if (!v->nonconstant) {
|
||||
if (v->is_constant) {
|
||||
fprintf(ErrFp, " <const>");
|
||||
}
|
||||
}
|
||||
@@ -820,7 +827,7 @@ void DumpVarTable(int dump_constness)
|
||||
fprintf(ErrFp, "%s ", v->name);
|
||||
PrintValue(&(v->v), ErrFp);
|
||||
if (dump_constness) {
|
||||
if (!v->nonconstant) {
|
||||
if (v->is_constant) {
|
||||
fprintf(ErrFp, " <const>");
|
||||
}
|
||||
}
|
||||
@@ -828,6 +835,23 @@ void DumpVarTable(int dump_constness)
|
||||
}
|
||||
}
|
||||
|
||||
void DumpUnusedVars(void)
|
||||
{
|
||||
Var *v;
|
||||
int done_header = 0;
|
||||
|
||||
hash_table_for_each(v, &VHashTbl) {
|
||||
if (v->used_since_set) {
|
||||
continue;
|
||||
}
|
||||
if (!done_header) {
|
||||
fprintf(ErrFp, "%s\n", tr("The following variables were set, but not subsequently used:"));
|
||||
done_header = 1;
|
||||
}
|
||||
fprintf(ErrFp, "\t%s - %s %s:%d\n", v->name, tr("defined at"), v->filename, v->lineno);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DestroyVars */
|
||||
@@ -871,6 +895,8 @@ int PreserveVar(char const *name)
|
||||
v = FindVar(name, 1);
|
||||
if (!v) return E_NO_MEM;
|
||||
v->preserve = 1;
|
||||
/* Assume we're gonna use the variable */
|
||||
v->used_since_set = 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -886,11 +912,10 @@ int DoPreserve (Parser *p)
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
|
||||
r = ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (!DBufLen(&buf)) {
|
||||
r = ParseIdentifier(p, &buf);
|
||||
if (r) {
|
||||
DBufFree(&buf);
|
||||
return E_EOLN;
|
||||
return r;
|
||||
}
|
||||
|
||||
r = PreserveVar(DBufValue(&buf));
|
||||
@@ -899,12 +924,14 @@ int DoPreserve (Parser *p)
|
||||
|
||||
/* Keep going... */
|
||||
while(1) {
|
||||
r = ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (!DBufLen(&buf)) {
|
||||
r = ParseIdentifier(p, &buf);
|
||||
if (r == E_EOLN) {
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
}
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
r = PreserveVar(DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
@@ -1052,14 +1079,263 @@ static SysVar SysVarArr[] = {
|
||||
};
|
||||
|
||||
#define NUMSYSVARS ( sizeof(SysVarArr) / sizeof(SysVar) )
|
||||
|
||||
typedef struct pushed_vars {
|
||||
struct pushed_vars *next;
|
||||
char const *filename;
|
||||
int lineno;
|
||||
int num_sysvars;
|
||||
int num_vars;
|
||||
int alloc_sysvars;
|
||||
int alloc_vars;
|
||||
PushedSysvar *sysvars;
|
||||
Var *vars;
|
||||
} PushedVars;
|
||||
|
||||
static void free_pushedvars(PushedVars *pv);
|
||||
|
||||
static PushedVars *VarStack = NULL;
|
||||
|
||||
int EmptyVarStack(int print_unmatched)
|
||||
{
|
||||
int j=0;
|
||||
PushedVars *next;
|
||||
while(VarStack) {
|
||||
if (print_unmatched) {
|
||||
Wprint(tr("Unmatched PUSH-VARS at %s(%d)"),
|
||||
VarStack->filename,
|
||||
VarStack->lineno);
|
||||
}
|
||||
j++;
|
||||
next = VarStack->next;
|
||||
free_pushedvars(VarStack);
|
||||
VarStack = next;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
static int add_sysvar_to_push(char const *name, PushedVars *pv)
|
||||
{
|
||||
int n = pv->alloc_sysvars;
|
||||
if (*name == '$') {
|
||||
name++;
|
||||
}
|
||||
SysVar *v = FindSysVar(name);
|
||||
if (!v) {
|
||||
return E_NOSUCH_VAR;
|
||||
}
|
||||
if (!v->modifiable) {
|
||||
Eprint("%s: `$%s'", GetErr(E_CANT_MODIFY), v->name);
|
||||
return E_CANT_MODIFY;
|
||||
}
|
||||
if (!n) {
|
||||
n = 4;
|
||||
pv->sysvars = malloc(n * sizeof(PushedSysvar));
|
||||
pv->alloc_sysvars = n;
|
||||
} else {
|
||||
if (pv->num_sysvars >= n) {
|
||||
n *= 2;
|
||||
pv->sysvars = realloc(pv->sysvars, n * sizeof(PushedSysvar));
|
||||
pv->alloc_sysvars = n;
|
||||
}
|
||||
}
|
||||
if (!pv->sysvars) {
|
||||
return E_NO_MEM;
|
||||
}
|
||||
n = pv->num_sysvars;
|
||||
pv->num_sysvars++;
|
||||
pv->sysvars[n].name = v->name;
|
||||
pv->sysvars[n].v.type = ERR_TYPE;
|
||||
return GetSysVar(name, &(pv->sysvars[n].v));
|
||||
}
|
||||
|
||||
static int add_var_to_push(char const *name, PushedVars *pv)
|
||||
{
|
||||
int n = pv->alloc_vars;
|
||||
if (!n) {
|
||||
n = 4;
|
||||
pv->vars = malloc(n * sizeof(Var));
|
||||
pv->alloc_vars = n;
|
||||
} else {
|
||||
if (pv->num_vars >= n) {
|
||||
n *= 2;
|
||||
pv->vars = realloc(pv->vars, n * sizeof(Var));
|
||||
pv->alloc_vars = n;
|
||||
}
|
||||
}
|
||||
if (!pv->vars) {
|
||||
return E_NO_MEM;
|
||||
}
|
||||
n = pv->num_vars;
|
||||
pv->num_vars++;
|
||||
Var *v = FindVar(name, 0);
|
||||
Var *dest = &(pv->vars[n]);
|
||||
int r = OK;
|
||||
if (!v) {
|
||||
StrnCpy(dest->name, name, VAR_NAME_LEN);
|
||||
dest->preserve = 0;
|
||||
dest->is_constant = 0;
|
||||
dest->used_since_set = 0;
|
||||
dest->filename = NULL;
|
||||
dest->lineno = -1;
|
||||
dest->v.type = ERR_TYPE;
|
||||
dest->v.v.val = E_NOSUCH_VAR;
|
||||
} else {
|
||||
StrnCpy(dest->name, v->name, VAR_NAME_LEN);
|
||||
dest->preserve = v->preserve;
|
||||
dest->is_constant = v->is_constant;
|
||||
dest->used_since_set = v->used_since_set;
|
||||
dest->filename = v->filename;
|
||||
dest->lineno = v->lineno;
|
||||
r = CopyValue(&(dest->v), &(v->v));
|
||||
/* Pretend we've used v */
|
||||
v->used_since_set = 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static void free_pushedvars(PushedVars *pv)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<pv->num_sysvars; i++) {
|
||||
DestroyValue(pv->sysvars[i].v);
|
||||
}
|
||||
for (i=0; i<pv->num_vars; i++) {
|
||||
DestroyValue(pv->vars[i].v);
|
||||
}
|
||||
if (pv->sysvars) {
|
||||
free(pv->sysvars);
|
||||
}
|
||||
if (pv->vars) {
|
||||
free(pv->vars);
|
||||
}
|
||||
free(pv);
|
||||
}
|
||||
|
||||
int
|
||||
PushVars(ParsePtr p)
|
||||
{
|
||||
int r;
|
||||
DynamicBuffer buf;
|
||||
char const *name;
|
||||
|
||||
PushedVars *pv = NEW(PushedVars);
|
||||
if (!pv) {
|
||||
return E_NO_MEM;
|
||||
}
|
||||
pv->next = NULL;
|
||||
pv->filename = GetCurrentFilename();
|
||||
pv->lineno = LineNo;
|
||||
pv->num_sysvars = 0;
|
||||
pv->num_vars = 0;
|
||||
pv->alloc_sysvars = 0;
|
||||
pv->alloc_vars = 0;
|
||||
pv->sysvars = NULL;
|
||||
pv->vars = NULL;
|
||||
|
||||
DBufInit(&buf);
|
||||
while(1) {
|
||||
r = ParseIdentifier(p, &buf);
|
||||
if (r == E_EOLN) {
|
||||
break;
|
||||
}
|
||||
if (r) {
|
||||
DBufFree(&buf);
|
||||
free_pushedvars(pv);
|
||||
return r;
|
||||
}
|
||||
name = DBufValue(&buf);
|
||||
if (*name == '$') {
|
||||
r = add_sysvar_to_push(name+1, pv);
|
||||
} else {
|
||||
r = add_var_to_push(name, pv);
|
||||
}
|
||||
DBufFree(&buf);
|
||||
if (r != OK) {
|
||||
free_pushedvars(pv);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
if ((pv->num_vars + pv->num_sysvars) == 0) {
|
||||
free_pushedvars(pv);
|
||||
return E_EOLN;
|
||||
}
|
||||
pv->next = VarStack;
|
||||
VarStack = pv;
|
||||
return OK;
|
||||
}
|
||||
|
||||
int
|
||||
PopVars(ParsePtr p)
|
||||
{
|
||||
int r = VerifyEoln(p);
|
||||
int i;
|
||||
int ret = OK;
|
||||
PushedVars *pv = VarStack;
|
||||
if (r != OK) {
|
||||
return r;
|
||||
}
|
||||
if (!pv) {
|
||||
return E_POPV_NO_PUSH;
|
||||
}
|
||||
VarStack = VarStack->next;
|
||||
if (strcmp(pv->filename, GetCurrentFilename())) {
|
||||
Wprint(tr("POP-VARS at %s:%d matches PUSH-VARS in different file: %s:%d"), GetCurrentFilename(), LineNo, pv->filename, pv->lineno);
|
||||
}
|
||||
|
||||
/* Pop the sysvars */
|
||||
for (i=0; i<pv->num_sysvars; i++) {
|
||||
r = SetSysVar(pv->sysvars[i].name, &(pv->sysvars[i].v));
|
||||
if (r != OK) {
|
||||
ret = r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pop the vars */
|
||||
for (i=0; i<pv->num_vars; i++) {
|
||||
Var *src = &(pv->vars[i]);
|
||||
if (src->v.type == ERR_TYPE && src->v.v.val == E_NOSUCH_VAR) {
|
||||
/* Delete the variable if it exists */
|
||||
(void) DeleteVar(src->name);
|
||||
} else {
|
||||
Var *dest = FindVar(src->name, 0);
|
||||
if ((DebugFlag & DB_UNUSED_VARS) && dest && !dest->used_since_set) {
|
||||
Eprint(tr("`%s' UNSET without being used (previous SET: %s:%d)"), dest->name, dest->filename, dest->lineno);
|
||||
}
|
||||
if (!dest) {
|
||||
dest = FindVar(src->name, 1);
|
||||
}
|
||||
if (!dest) {
|
||||
ret = E_NO_MEM;
|
||||
continue;
|
||||
}
|
||||
dest->preserve = src->preserve;
|
||||
dest->is_constant = src->is_constant;
|
||||
dest->used_since_set = src->used_since_set;
|
||||
dest->filename = src->filename;
|
||||
dest->lineno = src->lineno;
|
||||
DestroyValue(dest->v);
|
||||
|
||||
/* Destructively copy value */
|
||||
dest->v = src->v;
|
||||
|
||||
/* Make sure free_pushedvars doesn't destroy our value! */
|
||||
src->v.type = ERR_TYPE;
|
||||
src->v.v.val = 0;
|
||||
}
|
||||
}
|
||||
free_pushedvars(pv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void DumpSysVar (char const *name, const SysVar *v);
|
||||
|
||||
static int SetTranslatableVariable(SysVar *v, Value *value)
|
||||
static int SetTranslatableVariable(SysVar const *v, Value const *value)
|
||||
{
|
||||
return InsertTranslation((char const *) v->value, value->v.str);
|
||||
}
|
||||
|
||||
static int GetTranslatableVariable(SysVar *v, Value *value)
|
||||
static int GetTranslatableVariable(SysVar const *v, Value *value)
|
||||
{
|
||||
char const *translated = tr((char const *) v->value);
|
||||
if (translated) {
|
||||
@@ -1210,7 +1486,7 @@ SysVar *FindSysVar(char const *name)
|
||||
void DumpSysVarByName(char const *name)
|
||||
{
|
||||
size_t i;
|
||||
SysVar *v;
|
||||
SysVar const *v;
|
||||
|
||||
if (!name || !*name) {
|
||||
for (i=0; i<NUMSYSVARS; i++) DumpSysVar(name, SysVarArr + i);
|
||||
@@ -1287,7 +1563,7 @@ static void DumpSysVar(char const *name, const SysVar *v)
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
set_lat_and_long_from_components(void)
|
||||
{
|
||||
Latitude = (double) LatDeg + ((double) LatMin) / 60.0 + ((double) LatSec) / 3600.0;
|
||||
|
||||
@@ -65,8 +65,8 @@ FSET not_const(x) x+nonconst(a)
|
||||
REM [const(5)] Jan 1992 MSG expired... should be commented out
|
||||
REM [const(a)] Jan 1992 MSG expired... should be commented out
|
||||
REM [not_const(5)] Jan 1992 MSG nonconstant expression
|
||||
REM [value("a")] Jan 1992 MSG nonconstant expression
|
||||
|
||||
REM [value("a")] Jan 1992 MSG constant expression
|
||||
REM [value("__cabbage", 1)] Jan 1992 MSG non-constant expression
|
||||
IF 0
|
||||
# A comment in a false IF block
|
||||
#!P This should be nuked
|
||||
@@ -83,6 +83,8 @@ UNSET a
|
||||
CLEAR-OMIT-CONTEXT
|
||||
PUSH-OMIT-CONTEXT
|
||||
POP-OMIT-CONTEXT
|
||||
PUSH-VARS foo
|
||||
POP-VARS
|
||||
BANNER wow
|
||||
DEBUG +x
|
||||
DEBUG -x
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user