mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 14:28:40 +02:00
Compare commits
75 Commits
05.04.00-B
...
05.05.00
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
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
|
||||
|
||||
33
README.md
33
README.md
@@ -55,6 +55,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, 05.05.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" "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"
|
||||
"RUN" "SATISFY" "SCAN" "SCANFROM" "SCHED" "SECOND" "SET"
|
||||
"SKIP" "SPECIAL" "SYSINCLUDE" "TAG" "THIRD" "THROUGH"
|
||||
"TRANSLATE" "TRANS" "UNSET" "UNTIL" "WARN")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,51 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* VERSION 5.4 Patch 0 - 2025-??-??
|
||||
* 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
|
||||
@@ -26,6 +71,20 @@ CHANGES TO REMIND
|
||||
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)
|
||||
|
||||
@@ -1500,10 +1559,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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -14,9 +14,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
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
if !defined("__autolang__")
|
||||
SET __autolang__ 1
|
||||
PRESERVE __autolang__
|
||||
PUSH-VARS autolang
|
||||
SET autolang getenv("REMIND_LANG")
|
||||
|
||||
IF autolang == ""
|
||||
@@ -23,6 +24,6 @@ if !defined("__autolang__")
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
UNSET autolang
|
||||
POP-VARS
|
||||
ENDIF
|
||||
|
||||
|
||||
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>
|
||||
163
man/remind.1.in
163
man/remind.1.in
@@ -2579,7 +2579,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
|
||||
@@ -3125,7 +3125,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
|
||||
@@ -3431,9 +3467,11 @@ in unwanted reminders being purged in Purge Mode. See also the section
|
||||
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
|
||||
@@ -3450,11 +3488,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])
|
||||
@@ -3467,8 +3507,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.
|
||||
@@ -3774,10 +3818,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
|
||||
@@ -4595,7 +4649,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()
|
||||
@@ -5052,29 +5108,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
|
||||
@@ -6760,12 +6856,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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -102,7 +102,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:
|
||||
|
||||
@@ -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]);
|
||||
@@ -1805,6 +1806,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;
|
||||
@@ -2342,7 +2355,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);
|
||||
@@ -2782,7 +2795,7 @@ static void WriteCalDays(void)
|
||||
/* This takes into account duration */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
char const *
|
||||
static char const *
|
||||
CalendarTime(int tim, int duration)
|
||||
{
|
||||
static char buf[128];
|
||||
|
||||
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;
|
||||
|
||||
14
src/dorem.c
14
src/dorem.c
@@ -29,8 +29,8 @@ 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);
|
||||
|
||||
static int
|
||||
ensure_expr_references_first_local_arg(expr_node *node)
|
||||
@@ -179,7 +179,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) {
|
||||
@@ -1115,7 +1115,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 r, y, m, d;
|
||||
int adjusted_for_newline = 0;
|
||||
@@ -1427,7 +1427,7 @@ 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;
|
||||
*err = 0;
|
||||
@@ -1554,6 +1554,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);
|
||||
@@ -1702,7 +1704,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;
|
||||
|
||||
@@ -54,7 +54,7 @@ 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 curtime = MinutesPastMidnight(0);
|
||||
|
||||
24
src/err.h
24
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
|
||||
@@ -151,25 +151,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",
|
||||
|
||||
81
src/expr.c
81
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 */
|
||||
@@ -443,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);
|
||||
@@ -833,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);
|
||||
@@ -1835,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 */
|
||||
@@ -2712,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;
|
||||
@@ -2961,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;
|
||||
|
||||
16
src/files.c
16
src/files.c
@@ -114,16 +114,16 @@ static int CheckSafetyAux (struct stat *statbuf);
|
||||
static int PopFile (void);
|
||||
static int IncludeCmd(char const *);
|
||||
|
||||
static unsigned int FnHashFunc(void *x)
|
||||
static unsigned int FnHashFunc(void const *x)
|
||||
{
|
||||
FilenameHashEntry *e = (FilenameHashEntry *) x;
|
||||
FilenameHashEntry const *e = (FilenameHashEntry const *) x;
|
||||
return HashVal_preservecase(e->fname);
|
||||
}
|
||||
|
||||
static int FnCompareFunc(void *a, void *b)
|
||||
static int FnCompareFunc(void const *a, void const *b)
|
||||
{
|
||||
FilenameHashEntry *e1 = (FilenameHashEntry *) a;
|
||||
FilenameHashEntry *e2 = (FilenameHashEntry *) b;
|
||||
FilenameHashEntry const *e1 = (FilenameHashEntry const *) a;
|
||||
FilenameHashEntry const *e2 = (FilenameHashEntry const *) b;
|
||||
return strcmp(e1->fname, e2->fname);
|
||||
}
|
||||
|
||||
@@ -179,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;
|
||||
@@ -381,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;
|
||||
@@ -1151,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));
|
||||
|
||||
239
src/funcs.c
239
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
|
||||
@@ -265,7 +269,7 @@ BuiltinFunc Func[] = {
|
||||
{ "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 },
|
||||
@@ -365,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 },
|
||||
@@ -376,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 */
|
||||
@@ -461,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);
|
||||
@@ -528,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;
|
||||
@@ -540,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;
|
||||
|
||||
@@ -757,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;
|
||||
@@ -809,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;
|
||||
@@ -846,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)
|
||||
@@ -1163,7 +1184,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;
|
||||
@@ -1299,7 +1320,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();
|
||||
@@ -1366,7 +1387,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(", ?");
|
||||
@@ -1403,7 +1424,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));
|
||||
@@ -1414,14 +1435,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));
|
||||
@@ -1429,7 +1450,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("*) => ");
|
||||
@@ -1478,7 +1499,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(", ?");
|
||||
@@ -1488,6 +1509,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;
|
||||
}
|
||||
@@ -1505,7 +1527,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;
|
||||
@@ -1695,26 +1717,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 {
|
||||
v->used_since_set = 1;
|
||||
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;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -1939,19 +2027,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;
|
||||
}
|
||||
|
||||
@@ -1964,13 +2062,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);
|
||||
|
||||
@@ -2216,7 +2314,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(", ");
|
||||
@@ -2239,7 +2337,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));
|
||||
@@ -2247,7 +2345,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;
|
||||
@@ -2268,7 +2366,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(") => ");
|
||||
@@ -2756,7 +2854,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;
|
||||
@@ -2765,7 +2863,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;
|
||||
}
|
||||
|
||||
@@ -2809,7 +2907,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);
|
||||
@@ -2817,7 +2915,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;
|
||||
}
|
||||
|
||||
@@ -2892,7 +2990,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];
|
||||
|
||||
@@ -3281,7 +3380,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;
|
||||
|
||||
@@ -3312,7 +3411,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;
|
||||
|
||||
@@ -3723,7 +3822,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 */
|
||||
@@ -3845,7 +3944,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);
|
||||
}
|
||||
|
||||
@@ -3903,7 +4002,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -1017,11 +1017,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));
|
||||
@@ -1063,7 +1058,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);
|
||||
|
||||
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
|
||||
|
||||
69
src/main.c
69
src/main.c
@@ -50,11 +50,15 @@
|
||||
#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 */
|
||||
@@ -177,8 +181,18 @@ 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));
|
||||
} else if (!Daemon && !NextMode && !NumTriggered) {
|
||||
@@ -231,6 +245,8 @@ PerIterationInit(void)
|
||||
{
|
||||
ClearGlobalOmits();
|
||||
DestroyOmitContexts(1);
|
||||
EmptyVarStack(1);
|
||||
EmptyUserFuncStack(1);
|
||||
DestroyVars(0);
|
||||
DefaultColorR = -1;
|
||||
DefaultColorG = -1;
|
||||
@@ -362,6 +378,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) {
|
||||
@@ -459,6 +487,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);
|
||||
@@ -467,9 +504,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;
|
||||
}
|
||||
@@ -935,6 +969,10 @@ void Eprint(char const *fmt, ...)
|
||||
return;
|
||||
}
|
||||
|
||||
if (should_ignore_line()) {
|
||||
return;
|
||||
}
|
||||
|
||||
char const *fname = GetCurrentFilename();
|
||||
if (!fname) {
|
||||
return;
|
||||
@@ -1057,7 +1095,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;
|
||||
|
||||
@@ -1097,7 +1135,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) {
|
||||
@@ -1271,7 +1309,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;
|
||||
@@ -1377,7 +1415,7 @@ int DoDebug(ParsePtr p)
|
||||
/* reminder is issued. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DoBanner(ParsePtr p)
|
||||
static int DoBanner(ParsePtr p)
|
||||
{
|
||||
int err;
|
||||
int c;
|
||||
@@ -1561,7 +1599,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 +1994,7 @@ FreeTrig(Trigger *t)
|
||||
t->infos = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
ClearLastTriggers(void)
|
||||
{
|
||||
LastTrigger.expired = 0;
|
||||
@@ -1990,9 +2029,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 +2054,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;
|
||||
|
||||
@@ -121,12 +121,9 @@ int PushOmitContext(ParsePtr p)
|
||||
context = NEW(OmitContext);
|
||||
if (!context) return E_NO_MEM;
|
||||
|
||||
if (GetCurrentFilename()) {
|
||||
context->filename = GetCurrentFilename();
|
||||
} else {
|
||||
context->filename = "";
|
||||
}
|
||||
context->filename = GetCurrentFilename();
|
||||
context->lineno = LineNo;
|
||||
|
||||
context->numfull = NumFullOmits;
|
||||
context->numpart = NumPartialOmits;
|
||||
context->weekdaysave = WeekdayOmits;
|
||||
@@ -242,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;
|
||||
|
||||
42
src/protos.h
42
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 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);
|
||||
@@ -109,8 +106,6 @@ int DoEndif (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,12 +144,16 @@ 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);
|
||||
@@ -164,7 +162,6 @@ 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);
|
||||
@@ -175,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);
|
||||
@@ -199,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);
|
||||
@@ -210,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);
|
||||
@@ -226,7 +213,6 @@ 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);
|
||||
@@ -279,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);
|
||||
|
||||
14
src/queue.c
14
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>
|
||||
@@ -91,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) {
|
||||
@@ -103,7 +97,7 @@ char const *SimpleTimeNoSpace(int tim)
|
||||
return s;
|
||||
}
|
||||
|
||||
static void del_reminder(QueuedRem *qid)
|
||||
static void del_reminder(QueuedRem const *qid)
|
||||
{
|
||||
QueuedRem *q = QueueHead;
|
||||
QueuedRem *next;
|
||||
@@ -143,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;
|
||||
|
||||
@@ -215,7 +209,7 @@ maybe_close(int fd)
|
||||
(void) close(new_fd);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
SigContHandler(int d)
|
||||
{
|
||||
UNUSED(d);
|
||||
|
||||
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;
|
||||
|
||||
|
||||
21
src/token.c
21
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.
|
||||
@@ -90,12 +90,16 @@ 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 },
|
||||
{ "run", 3, T_RemType, RUN_TYPE },
|
||||
{ "satisfy", 7, T_RemType, SAT_TYPE },
|
||||
@@ -122,6 +126,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 +252,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 +448,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 +460,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;
|
||||
@@ -310,15 +312,15 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
{
|
||||
int simple, mod, omit;
|
||||
|
||||
/* First: Have we passed the UNTIL date? */
|
||||
/* First: Have we passed the UNTIL date? */
|
||||
if (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 */
|
||||
/* 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 +341,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 +378,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 +387,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 +408,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 +425,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;
|
||||
}
|
||||
|
||||
@@ -524,7 +531,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 +543,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
trig->expired = 0;
|
||||
if (save_in_globals) {
|
||||
LastTrigValid = 0;
|
||||
LastTriggerDate = -1;
|
||||
}
|
||||
|
||||
/* Assume everything works */
|
||||
@@ -574,7 +582,6 @@ 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) {
|
||||
@@ -630,8 +637,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",
|
||||
GetCurrentFilename(), 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;
|
||||
@@ -677,7 +685,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 +709,7 @@ NewTrigInfo(char const *i)
|
||||
/* Free a TrigInfo objects. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void
|
||||
static void
|
||||
FreeTrigInfo(TrigInfo *ti)
|
||||
{
|
||||
if (ti->info) {
|
||||
@@ -768,7 +776,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 +787,7 @@ TrigInfoHeadersAreTheSame(char const *i1, char const *i2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
TrigInfoIsValid(char const *info)
|
||||
{
|
||||
char const *t;
|
||||
|
||||
23
src/types.h
23
src/types.h
@@ -228,13 +228,15 @@ enum TokTypes
|
||||
{ T_Illegal,
|
||||
T_AddOmit, T_At, T_Back, T_BackAdj, T_Banner, T_Clr, T_Comment,
|
||||
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_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
|
||||
};
|
||||
|
||||
/* The structure of a token */
|
||||
@@ -310,4 +312,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;
|
||||
|
||||
265
src/userfns.c
265
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;
|
||||
@@ -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 '(' */
|
||||
@@ -250,6 +274,7 @@ int DoFset(ParsePtr p)
|
||||
func->lineno = LineNo;
|
||||
func->lineno_start = LineNoStart;
|
||||
func->recurse_flag = 0;
|
||||
func->been_pushed = 0;
|
||||
if (in_constant_context()) {
|
||||
func->is_constant = 1;
|
||||
} else {
|
||||
@@ -354,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]) {
|
||||
@@ -525,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");
|
||||
|
||||
341
src/var.c
341
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,7 @@ 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);
|
||||
@@ -575,7 +578,7 @@ Var *FindVar(char const *str, int create)
|
||||
/* string and delete it. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DeleteVar(char const *str)
|
||||
static int DeleteVar(char const *str)
|
||||
{
|
||||
Var *v;
|
||||
|
||||
@@ -621,27 +624,6 @@ int SetVar(char const *str, Value const *val, int nonconst_expr)
|
||||
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;
|
||||
}
|
||||
v->used_since_set = 1;
|
||||
return CopyValue(val, &v->v);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoSet - set a variable. */
|
||||
@@ -660,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 */
|
||||
@@ -907,7 +895,6 @@ 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;
|
||||
@@ -925,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));
|
||||
@@ -938,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;
|
||||
@@ -1091,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) {
|
||||
@@ -1249,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);
|
||||
@@ -1326,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
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
# If you're writing a back-end, test it by feeding it the output
|
||||
# of: remind -pp test-for-backends.rem
|
||||
|
||||
# All back-ends should endeavour to support: WEEK, SHADE, MOON, and
|
||||
# COLOR/COLOUR. They may support other back-end-specific SPECIALs.
|
||||
|
||||
# Color and shade
|
||||
REM 1 SPECIAL COLOR 128 0 0 Red
|
||||
REM 2 SPECIAL COLOUR 0 128 0 British Green
|
||||
@@ -17,11 +20,18 @@ REM [moondate(3)] SPECIAL MOON 3 -1 -1 [moontime(3)]
|
||||
# Week
|
||||
REM Monday SPECIAL WEEK (W[weekno()])
|
||||
|
||||
# PostScript
|
||||
REM Wed PS Border Border 2 div moveto /Helvetica-Oblique findfont 6 scalefont setfont (oof!) show
|
||||
# A normal reminder
|
||||
REM 16 MSG A normal reminder
|
||||
|
||||
# PostScript - currently only supported by rem2ps
|
||||
REM Wed PS Border Border 2 div moveto /Helvetica-Oblique findfont 6 scalefont setfont (oof PostScript!) show
|
||||
|
||||
# A SPECIAL that should be ignored
|
||||
REM 15 SPECIAL RANDOM-STUFF ignore me and be happy
|
||||
|
||||
# A normal reminder
|
||||
REM 16 MSG A normal reminder
|
||||
# HTML - currently only supported by rem2html
|
||||
REM 17 SPECIAL HTML I am <b>bold</b> HTML
|
||||
|
||||
# Pango - currently only supported by rem2pdf
|
||||
REM 18 SPECIAL PANGO I am <b>bold</b> PANGO
|
||||
|
||||
|
||||
1841
tests/test.cmp
1841
tests/test.cmp
File diff suppressed because one or more lines are too long
111
tests/test.rem
111
tests/test.rem
@@ -224,7 +224,7 @@ REM 1 March OMITFUNC _ofunc AFTER MSG OmitFunc Test
|
||||
REM 8 March OMITFUNC _ofunc -1 MSG OmitFunc Test 2
|
||||
|
||||
# omitfunc ignores local/global omits
|
||||
fset _ofunc(x) 0
|
||||
fset - _ofunc(x) 0
|
||||
OMIT 1 March
|
||||
OMIT 2 March 1991
|
||||
REM 1 March OMIT Sun OMITFUNC _ofunc AFTER MSG Should trigger 1 March
|
||||
@@ -272,7 +272,7 @@ set $LatDeg 30
|
||||
set $LatMin 30
|
||||
set $LatSec 0
|
||||
set $LongDeg -25
|
||||
set $LongMin 15
|
||||
set $LongMin -15
|
||||
set $LongSec 0
|
||||
|
||||
set a000 abs(1)
|
||||
@@ -478,7 +478,16 @@ REM MAYBE-UNCOMPUTABLE Mon OMIT Mon SKIP MSG Never ever ever...
|
||||
REM MAYBE-UNCOMPUTABLE Mon SATISFY [wkdaynum($T) == 3] MSG Nope nope...
|
||||
|
||||
dump
|
||||
dump $
|
||||
set axx 1
|
||||
PUSH-VARS $Tomorrow $Latitude $DefaultColor axx bxbxbx
|
||||
set $Tomorrow "HAHA, tomorrow"
|
||||
set $Latitude "0"
|
||||
set $DefaultColor "42 42 42"
|
||||
set bxbxbx 1
|
||||
dump $Tomorrow $Latitude $DefaultColor axx bxbxbx a136 $Today
|
||||
POP-VARS
|
||||
dump $Tomorrow $Latitude $DefaultColor axx bxbxbx a136 $Today
|
||||
|
||||
msg [$April]%
|
||||
msg [$August]%
|
||||
msg [$CalcUTC]%
|
||||
@@ -1587,6 +1596,13 @@ FUNSET i
|
||||
set a "eval(\"1\")+ shell(\"ls\")"
|
||||
set b eval(a)
|
||||
|
||||
# "value" should use lazy evaluation
|
||||
set a value(4:33)
|
||||
set a value('2020-01-01', 42)
|
||||
set a value("nosuchvar")
|
||||
set a value("nosuchvar", 42)
|
||||
set a value("a", 42)
|
||||
set a value("a")
|
||||
DEBUG -x
|
||||
|
||||
DEBUG -e
|
||||
@@ -1599,9 +1615,98 @@ set a eval(a)
|
||||
REM 9 Feb 1991 *7 MSG Base: [trigbase()]
|
||||
REM 9 Feb 1991 *1 MSG Base: [$Tb]
|
||||
|
||||
# The UNTIL bug
|
||||
DEBUG +t
|
||||
REM SECOND SATURDAY +300 UNTIL 1991-02-02 MSG [$T]
|
||||
REM SECOND SATURDAY +300 UNTIL 1991-02-16 MSG [$T]
|
||||
DEBUG -t
|
||||
|
||||
# Fully-specified trigger date in the past
|
||||
REM 14 Jan 1991 MSG In the past
|
||||
set a trigvalid()
|
||||
set b trigdate()
|
||||
|
||||
REM MSG trigvalid = [a]; trigdate = [b]
|
||||
|
||||
# SATISFY clause that's never satisfied...
|
||||
REM 14 Jan 1991 SATISFY [$Ty == 2022] MSG I can't get no satisfaction
|
||||
set a trigvalid()
|
||||
set b trigdate()
|
||||
|
||||
REM MSG trigvalid = [a]; trigdate = [b]
|
||||
|
||||
DEBUG +x
|
||||
set a daysinmon(2, 2000)
|
||||
set a daysinmon(2, 2001)
|
||||
set a daysinmon(3, 2000)
|
||||
set a daysinmon(3, 2001)
|
||||
|
||||
set a daysinmon("Feb", 2000)
|
||||
set a daysinmon("Feb", 2001)
|
||||
set a daysinmon("March", 2000)
|
||||
set a daysinmon("March", 2001)
|
||||
set a daysinmon("Cabbage", 2001)
|
||||
|
||||
set a daysinmon('2000-02-14')
|
||||
set a daysinmon('2001-02-14')
|
||||
set a daysinmon('2000-04-14')
|
||||
set a daysinmon('2001-04-14')
|
||||
|
||||
set a date(2020, "April", 15)
|
||||
set a date(2020, "Carrot", 12)
|
||||
set a datetime(2020, "April", 13, 4:44)
|
||||
set a datetime(2020, "April", 13, 4, 44)
|
||||
set a datetime(2020, "Lettuce", 13, 4:44)
|
||||
set a datetime(2020, "Lettuce", 13, 4, 44)
|
||||
|
||||
set a wkdaynum("Tue")
|
||||
set a wkdaynum("Wednesday")
|
||||
set a wkdaynum("telephone")
|
||||
|
||||
DEBUG -x
|
||||
# Output expression-node stats
|
||||
DEBUG +h
|
||||
|
||||
# Long list of pushing/popping variables
|
||||
PUSH-VARS $AddBlankLines $Ago $Am $And $April $At $August $CalcUTC $DateSep $DateTimeSep $December $DedupeReminders $DefaultColor $DefaultDelta $DefaultPrio $DefaultTDelta $EndSent $EndSentIg $ExpressionTimeLimit $February $FirstIndent $FoldYear $FormWidth $Friday $Fromnow $Hour $Hplu $Is $January $July $June $LatDeg $Latitude $LatMin $LatSec $Location $LongDeg $Longitude $LongMin $LongSec $March $MaxLateMinutes $MaxSatIter $MaxStringLen $May $MinsFromUTC $Minute $Monday $Mplu $November $Now $October $On $OnceFile $ParseUntriggered $Pm $Saturday $September $SubsIndent $Sunday $SuppressImplicitWarnings $SuppressLRM $Thursday $TimeSep $Today $Tomorrow $Tuesday $Was $Wednesday a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 a21 a22 a23 a24 a25 a26 a27 a28 a29 a30 a31 a32 a33 a34 a35 a36 a37 a38 a39 a40 a41 a42 a43 a44 a45 a46 a47 a48 a49 a50 a51 a52 a53 a54 a55 a56 a57 a58 a59 a60 a61 a62 a63 a64 a65 a66 a67 a68 a69 a70 a71 a72 a73 a74 a75 a76 a77 a78 a79 a80 a81 a82 a83 a84 a85 a86 a87 a88 a89 a90 a91 a92 a93 a94 a95 a96 a97 a98 a99 a100 a101 a102 a103 a104 a105 a106 a107 a108 a109 a110 a111 a112 a113 a114 a115 a116 a117 a118 a119 a120 a121 a122 a123 a124 a125 a126 a127 a128 a129 a130 a131 a132 a133 a134 a135 a136 a137 a138 a139 a140 a141 a142 a143 a144 a145 a146 a147 a148 a149 a150 a151 a152 a153 a154 a155 a156 a157 a158 a159 a160 a161 a162 a163 a164 a165 a166 a167 a168 a169 a170 a171 a172 a173 a174 a175 a176 a177 a178 a179 a180 a181 a182 a183 a184 a185 a186 a187 a188 a189 a190 a191 a192 a193 a194 a195 a196 a197 a198 a199 a200 a201 a202 a203 a204 a205 a206 a207 a208 a209 a210 a211 a212 a213 a214 a215 a216 a217 a218 a219 a220 a221 a222 a223 a224 a225 a226 a227 a228 a229 a230 a231 a232 a233 a234 a235 a236 a237 a238 a239 a240 a241 a242 a243 a244 a245 a246 a247 a248 a249 a250 a251 a252 a253 a254 a255 a256 a257 a258 a259 a260 a261 a262 a263 a264 a265 a266 a267 a268 a269 a270 a271 a272 a273 a274 a275 a276 a277 a278 a279 a280 a281 a282 a283 a284 a285 a286 a287 a288 a289 a290 a291 a292 a293 a294 a295 a296 a297 a298 a299 a300
|
||||
POP-VARS
|
||||
|
||||
# Try pushing a read-only one
|
||||
PUSH-VARS $NumTrig
|
||||
POP-VARS
|
||||
|
||||
# Test push/pop of functions
|
||||
DEBUG +xe
|
||||
|
||||
FUNSET a
|
||||
FSET b(x, y) x*y
|
||||
FSET c() 33
|
||||
|
||||
set a a(2)
|
||||
set a b(2)
|
||||
set a b(2, 3)
|
||||
set a c()
|
||||
|
||||
PUSH-FUNCS a b c
|
||||
|
||||
FSET a(x) 42
|
||||
FSET b(x, y) x*y*2
|
||||
FSET c() 66
|
||||
|
||||
set a a(2)
|
||||
set a b(2)
|
||||
set a b(2, 3)
|
||||
set a c()
|
||||
|
||||
POP-FUNCS
|
||||
|
||||
set a a(2)
|
||||
set a b(2)
|
||||
set a b(2, 3)
|
||||
set a c()
|
||||
|
||||
DEBUG -xe
|
||||
|
||||
# Don't want Remind to queue reminders
|
||||
EXIT
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user