Compare commits

...

30 Commits

Author SHA1 Message Date
Dianne Skoll
79f45169c8 Set release date. 2025-03-23 13:37:51 -04:00
Dianne Skoll
b9f09b9a2d Fix some cppcheck warnings. 2025-03-23 13:24:38 -04:00
Dianne Skoll
f53a174d65 Update WHATSNEW 2025-03-23 13:15:14 -04:00
Dianne Skoll
ed15b7deb5 Update JSON parser to latest version from https://github.com/udp/json-parser 2025-03-22 12:09:30 -04:00
Dianne Skoll
caf5f81eb0 Add a few more removals to "make distclean" 2025-03-22 11:18:56 -04:00
Dianne Skoll
d48910eca9 Update "make distclean" target; remove obsolete unconfigure script. 2025-03-22 11:16:54 -04:00
Dianne Skoll
c004944a59 Replace '1440' with 'MINUTES_PER_DAY' in a bunch of spots. 2025-03-20 17:20:25 -04:00
Dianne Skoll
f2d1a21a4e Update docs. 2025-03-20 15:40:33 -04:00
Dianne Skoll
81a5241097 Add tests for soleq. 2025-03-20 11:53:11 -04:00
Dianne Skoll
eced4de4a2 Explicitly supply date. 2025-03-20 11:45:11 -04:00
Dianne Skoll
2c8fa39af0 Add tests for astronomical functions. 2025-03-20 11:38:18 -04:00
Dianne Skoll
6ac5e96260 Fix logic bug in astro. 2025-03-20 10:20:08 -04:00
Dianne Skoll
deda94a69e Comment and code cleanups. 2025-03-19 18:08:28 -04:00
Dianne Skoll
abb8cbb1bf Update docs 2025-03-19 17:43:38 -04:00
Dianne Skoll
ee4e3e9073 Bump version to 05.03.05. 2025-03-19 17:38:33 -04:00
Dianne Skoll
220014e60f Document moonrise and moonset functions. 2025-03-19 17:31:29 -04:00
Dianne Skoll
3d0d07ce29 Remove note about OS/2. 2025-03-19 15:41:15 -04:00
Dianne Skoll
38615adb41 Update tests for fixes to 12:XXam 2025-03-19 12:38:36 -04:00
Dianne Skoll
3d8f0e3907 Code cleanup; fix astro example. 2025-03-19 12:35:51 -04:00
Dianne Skoll
160f85a1f8 Fix %2 and %@ formatters to print "12:XXam" instead of "0:XXam" 2025-03-19 12:35:25 -04:00
Dianne Skoll
5cb062166c Add moonrise/moonset to astro example. 2025-03-19 12:18:19 -04:00
Dianne Skoll
81fa6c667f Update unit test. 2025-03-19 11:57:23 -04:00
Dianne Skoll
190dfa3a8f Add moonrisedir and moonsetdir functions. 2025-03-19 11:57:01 -04:00
Dianne Skoll
a22c674846 Add moonrise and moonset functions. 2025-03-19 11:45:34 -04:00
Dianne Skoll
ba224445b1 Allocate 256 expr_nodes in a chunk instead of 64. 2025-03-16 10:55:42 -04:00
Dianne Skoll
6aeee47bfa Remove unused code. 2025-03-16 10:47:54 -04:00
Dianne Skoll
c506fa4613 Refactor code. 2025-03-13 23:51:22 -04:00
Dianne Skoll
04404a252e Remove check for '%' in parse_atom. 2025-03-13 23:45:21 -04:00
Dianne Skoll
be746f9fa7 Print placeholder args when printing error message for user function invoked with incorrect number of arguments. 2025-03-13 23:33:19 -04:00
Dianne Skoll
2393a86970 Fix typo that broke opening reminder file from queue listing. 2025-03-10 17:52:59 -04:00
22 changed files with 878 additions and 187 deletions

View File

@@ -43,8 +43,9 @@ test:
@$(MAKE) -C src -s test
distclean: clean
-rm -f config.cache config.log config.status src/Makefile 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 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
-rm -rf autom4te.cache rem2html/Makefile rem2html/rem2html.1
src/Makefile: src/Makefile.in
./configure

18
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.71 for remind 05.03.04.
# Generated by GNU Autoconf 2.71 for remind 05.03.05.
#
#
# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
@@ -608,8 +608,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='remind'
PACKAGE_TARNAME='remind'
PACKAGE_VERSION='05.03.04'
PACKAGE_STRING='remind 05.03.04'
PACKAGE_VERSION='05.03.05'
PACKAGE_STRING='remind 05.03.05'
PACKAGE_BUGREPORT=''
PACKAGE_URL='https://dianne.skoll.ca/projects/remind/'
@@ -1265,7 +1265,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures remind 05.03.04 to adapt to many kinds of systems.
\`configure' configures remind 05.03.05 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1327,7 +1327,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of remind 05.03.04:";;
short | recursive ) echo "Configuration of remind 05.03.05:";;
esac
cat <<\_ACEOF
@@ -1415,7 +1415,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
remind configure 05.03.04
remind configure 05.03.05
generated by GNU Autoconf 2.71
Copyright (C) 2021 Free Software Foundation, Inc.
@@ -1865,7 +1865,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by remind $as_me 05.03.04, which was
It was created by remind $as_me 05.03.05, which was
generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw
@@ -4710,7 +4710,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by remind $as_me 05.03.04, which was
This file was extended by remind $as_me 05.03.05, which was
generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -4775,7 +4775,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
remind config.status 05.03.04
remind config.status 05.03.05
configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"

View File

@@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(remind, 05.03.04, , , https://dianne.skoll.ca/projects/remind/)
AC_INIT(remind, 05.03.05, , , https://dianne.skoll.ca/projects/remind/)
AC_CONFIG_SRCDIR([src/queue.c])
cat <<'EOF'

View File

@@ -1,5 +1,26 @@
CHANGES TO REMIND
* VERSION 5.3 Patch 5 - 2025-03-23
- NEW FEATURE: remind: Add moonrise, moonset, moonrisedir and moonsetdir
functions. The first two functions calculate the time of the next
moonrise and moonset, and the second two calculate in which direction
the moon will rise or set. See the examples/astro script for examples
of how to use the moonrise/moonset functions.
- CODE CLEANUPS: remind: Some minor code cleanups with no user-visible effects.
- IMPROVEMENT: Add tests for the astronomical calculation functions.
- UPDATE: Update the included json.c and json.h files to the latest versions
from https://github.com/udp/json-parser
- BUG FIX: remind: The %2 and %@ sequences would print "0:34am" for the
time 00:34, instead of the correct "12:34am". This has been fixed.
- BUG FIX: TkRemind: Fix bug that broke the ability to open a text editor
on a reminder from the "Queue..." listing.
* VERSION 5.3 Patch 4 - 2025-03-09
- BUG FIX: remind: "make test" could fail if Remind was built in a locale
@@ -21,7 +42,7 @@ CHANGES TO REMIND
- MINOR IMPROVEMENT: include/holidays/misc.rem: Add a few new holidays and
URL INFO strings.
- CHANGE: remind: Issue a warning if a time-related subsitution sequence
- CHANGE: remind: Issue a warning if a time-related substitution sequence
is used with a non-timed REM command.
- BUG FIX: remind: Fix a memory leak.

View File

@@ -32,6 +32,24 @@ EOF
remind -g "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
SET $AddBlankLines 0
FSET angle_to_direction(x) \
IIF(x > 348 || x <= 11, "North", \
x > 11 && x <= 34, "North North-East", \
x > 34 && x <= 56, "North-East", \
x > 56 && x <= 79, "East North-East", \
x > 79 && x <= 101, "East", \
x > 101 && x <= 124, "East South-East", \
x > 124 && x <= 146, "South-East", \
x > 146 && x <= 169, "South South-East", \
x > 169 && x <= 191, "South", \
x > 191 && x <= 214, "South South-West", \
x > 214 && x <= 236, "South-West", \
x > 236 && x <= 259, "West South-West", \
x > 259 && x <= 281, "West", \
x > 281 && x <= 304, "West North-West", \
x > 304 && x <= 326, "North-West", \
"North North-West")
BANNER %
IF $TerminalBackground == 0
REM [moondatetime(0)] +60 SPECIAL COLOR 255 255 0 New moon: 🌑 [$T] %3 (%b)
@@ -48,6 +66,50 @@ EOF
echo ""
remind -g "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
SET $AddBlankLines 0
FSET angle_to_direction(x) \
IIF(x > 348 && x <= 11, "North", \
x > 11 && x <= 34, "North North-East", \
x > 34 && x <= 56, "North-East", \
x > 56 && x <= 79, "East North-East", \
x > 79 && x <= 101, "East", \
x > 101 && x <= 124, "East South-East", \
x > 124 && x <= 146, "South-East", \
x > 146 && x <= 169, "South South-East", \
x > 169 && x <= 191, "South", \
x > 191 && x <= 214, "South South-West", \
x > 214 && x <= 236, "South-West", \
x > 236 && x <= 259, "West South-West", \
x > 259 && x <= 281, "West", \
x > 281 && x <= 304, "West North-West", \
x > 304 && x <= 326, "North-West", \
"North North-West")
BANNER %
set mr moonrise()
set ms moonset()
set mr_a moonrisedir()
set ms_a moonsetdir()
IF mr < ms
REM NOQUEUE [mr] MSG The moon rises %3 in the [angle_to_direction(mr_a)] ([mr_a] degrees)
REM NOQUEUE [ms] MSG The moon sets %3 in the [angle_to_direction(ms_a)] ([ms_a] degrees)
ELSE
REM NOQUEUE [ms] MSG The moon sets %3 in the [angle_to_direction(ms_a)] ([ms_a] degrees)
REM NOQUEUE [mr] MSG The moon rises %3 in the [angle_to_direction(mr_a)] ([mr_a] degrees)
ENDIF
IF (datepart(mr) != today())
REM MSG There is no moonrise today
ENDIF
IF (datepart(ms) != today())
REM MSG There is no moonset today
ENDIF
EOF
echo ""
remind -g "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
SET $AddBlankLines 0
BANNER %

View File

@@ -3711,6 +3711,43 @@ which default to \fBtoday()\fR and midnight, respectively. The returned
value is an integer from 0 to 359, representing the phase of the moon
in degrees. 0 is a new moon, 180 is a full moon, 90 is first-quarter, etc.
.TP
.B moonrise([d_date])
This function returns a DATETIME result giving the date and time of the
first moonrise on or after midnight on \fIdate\fR. If \fIdate\fR is not
supplied, it defaults to \fBtoday()\fR.
.RS
.PP
Note that it is not uncommon for a day to have no moonrise, so the date
part of the return value may not be the same as the \fIdate\fR argument.
So if you want a calendar of moonrise times, you could use something
like this:
.PP
.nf
SET mr moonrise()
IF datepart(mr) == today()
REM NOQUEUE [mr] MSG Moon rises at %3.
ELSE
REM MSG No moonrise today
ENDIF
.fi
.PP
.RE
.TP
.B moonrisedir([d_date])
This function returns an INT result giving the direction from which
the moon will rise on the first moonrise on or after midnight on
\fIdate\fR. If \fIdate\fR is not supplied, it defaults to
\fBtoday()\fR. The return value ranges from 0 to 359, where 0 is North,
90 is East, 180 is South and 270 is West.
.TP
.B moonset([d_date])
This function is analogous to \fBmoonrise()\fR but returns the DATETIME of
the next moonset on or after midnight on \fIdate\fR.
.TP
.B moonsetdir([d_date])
This function is analogous to \fBmoonrisedir()\fR but returns the
direction of moonset.
.TP
.B multitrig(s_trig1 [,s_trig2, [... s_trigN]])
\fBmultitrig\fR evaluates each string as a trigger, similar to \fBevaltrig\fR,
and returns the \fIearliest\fR trigger date that is on or after \fBtoday()\fR.
@@ -6460,14 +6497,15 @@ Do not hard-code the above directory in your reminder files. Instead,
use the value of the $SysInclude system variable.
.SH AUTHOR
.PP
Dianne Skoll <dianne@skoll.ca> wrote \fBRemind\fR. The moon code was
copied largely unmodified from "moontool" by John Walker. The sunrise
and sunset functions use ideas from programs by Michael Schwartz and
Marc T. Kaufman. The Hebrew calendar support was taken from "hdate"
by Amos Shapir. OS/2 support was done by Darrel Hankerson, Russ
Herman, and Norman Walsh. The supported languages and their
translators are listed below. Languages marked "complete" support
error messages in that language; all others only support the
Dianne Skoll <dianne@skoll.ca> wrote \fBRemind\fR. The moon phase
code was copied largely unmodified from "moontool" by John Walker.
The moonrise/moonset code comes from
https://github.com/signetica/MoonRise by Stephen R. Schmitt and Cyrus
Rahman. The sunrise and sunset functions use ideas from programs by
Michael Schwartz and Marc T. Kaufman. The Hebrew calendar support was
taken from "hdate" by Amos Shapir. The supported languages and
their translators are listed below. Languages marked "complete"
support error messages in that language; all others only support the
substitution filter mechanism and month/day names.
.PP
\fBGerman\fR --

View File

@@ -2872,10 +2872,10 @@ proc ShowQueue { queue } {
set fntag ""
catch {
set fname [dict get $q filename]
if {[dict exists $obj lineno_start]} {
set lineno [dict get $obj lineno_start]
if {[dict exists $q lineno_start]} {
set lineno [dict get $q lineno_start]
} else {
set lineno [dict get $obj lineno]
set lineno [dict get $q lineno]
}
set fntag [string cat "FILE_" $lineno "_" $fname]
}

View File

@@ -125,7 +125,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
pm = (h < 12) ? tr("am") : tr("pm");
}
hh = (h == 12) ? 12 : h % 12;
hh = (h == 12 || h == 0) ? 12 : h % 12;
ch = curtime / 60;
cmin = curtime % 60;
@@ -151,7 +151,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
if (r != OK) {
cpm = (h < 12) ? tr("am") : tr("pm");
}
chh = (ch == 12) ? 12 : ch % 12;
chh = (ch == 0 || ch == 12) ? 12 : ch % 12;
func = FindUserFunc("subst_ordinal");
if (func && check_subst_args(func, 1)) {

View File

@@ -197,7 +197,7 @@ static char const *get_operator_name(expr_node *node);
static UserFunc *CurrentUserFunc = NULL;
/* How many expr_node objects to allocate at a time */
#define ALLOC_CHUNK 64
#define ALLOC_CHUNK 256
static char const *
find_end_of_expr(char const *s)
@@ -626,6 +626,18 @@ debug_exit_userfunc(expr_node *node, Value *ans, int r, Value *locals, int nargs
fprintf(ErrFp, "\n");
}
static void
print_placeholders(int n)
{
int i;
for (i=0; i<n; i++) {
if (i > 0) {
fprintf(ErrFp, ", ");
}
fprintf(ErrFp, "?");
}
}
/***************************************************************/
/* */
/* eval_userfunc - evaluate a user-defined function */
@@ -667,12 +679,12 @@ eval_userfunc(expr_node *node, Value *locals, Value *ans, int *nonconst)
/* Make sure we have the right number of arguments */
if (node->num_kids < f->nargs) {
DBG(fprintf(ErrFp, "%s(...) => %s\n", fname, GetErr(E_2FEW_ARGS)));
DBG(fprintf(ErrFp, "%s(", fname); print_placeholders(node->num_kids); fprintf(ErrFp, ") => %s\n", GetErr(E_2FEW_ARGS)));
Eprint("%s(): %s", f->name, GetErr(E_2FEW_ARGS));
return E_2FEW_ARGS;
}
if (node->num_kids > f->nargs) {
DBG(fprintf(ErrFp, "%s(...) => %s\n", fname, GetErr(E_2MANY_ARGS)));
DBG(fprintf(ErrFp, "%s(", fname); print_placeholders(node->num_kids); fprintf(ErrFp, ") => %s\n", GetErr(E_2MANY_ARGS)));
Eprint("%s(): %s", f->name, GetErr(E_2MANY_ARGS));
return E_2MANY_ARGS;
}
@@ -2190,7 +2202,6 @@ static expr_node *parse_atom(char const **e, int *r, Var *locals, int level)
return NULL;
}
if (!ISID(*s) &&
*s != '%' &&
*s != '$' &&
*s != '"' &&
*s != '\'') {

View File

@@ -125,6 +125,10 @@ static int FMonnum (func_info *);
static int FMoondate (func_info *);
static int FMoondatetime (func_info *);
static int FMoonphase (func_info *);
static int FMoonrise (func_info *);
static int FMoonrisedir (func_info *);
static int FMoonset (func_info *);
static int FMoonsetdir (func_info *);
static int FMoontime (func_info *);
static int FMultiTrig (func_info *);
static int FNDawn (func_info *);
@@ -286,6 +290,10 @@ BuiltinFunc Func[] = {
{ "moondate", 1, 3, 0, FMoondate, NULL },
{ "moondatetime", 1, 3, 0, FMoondatetime, NULL },
{ "moonphase", 0, 2, 0, FMoonphase, NULL },
{ "moonrise", 0, 1, 0, FMoonrise, NULL },
{ "moonrisedir", 0, 1, 0, FMoonrisedir, NULL },
{ "moonset", 0, 1, 0, FMoonset, NULL },
{ "moonsetdir", 0, 1, 0, FMoonsetdir, NULL },
{ "moontime", 1, 3, 0, FMoontime, NULL },
{ "multitrig", 1, NO_MAX, 0, FMultiTrig, NULL },
{ "ndawn", 0, 1, 0, FNDawn, NULL },
@@ -3316,6 +3324,54 @@ static int FMoondatetime(func_info *info)
return MoonStuff(DATETIME_TYPE, info);
}
static int FMoonrise(func_info *info)
{
int start = DSEToday;
if (Nargs >= 1) {
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
start = DATEPART(ARG(0));
}
RetVal.type = DATETIME_TYPE;
RETVAL = GetMoonrise(start);
return OK;
}
static int FMoonset(func_info *info)
{
int start = DSEToday;
if (Nargs >= 1) {
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
start = DATEPART(ARG(0));
}
RetVal.type = DATETIME_TYPE;
RETVAL = GetMoonset(start);
return OK;
}
static int FMoonrisedir(func_info *info)
{
int start = DSEToday;
if (Nargs >= 1) {
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
start = DATEPART(ARG(0));
}
RetVal.type = INT_TYPE;
RETVAL = GetMoonrise_angle(start);
return OK;
}
static int FMoonsetdir(func_info *info)
{
int start = DSEToday;
if (Nargs >= 1) {
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
start = DATEPART(ARG(0));
}
RetVal.type = INT_TYPE;
RETVAL = GetMoonset_angle(start);
return OK;
}
static int MoonStuff(int type_wanted, func_info *info)
{
int startdate, starttim;

View File

@@ -367,8 +367,8 @@ void InitRemind(int argc, char const *argv[])
PARSENUM(DefaultTDelta, arg);
if (DefaultTDelta < 0) {
DefaultTDelta = 0;
} else if (DefaultTDelta > 1440) {
DefaultTDelta = 1440;
} else if (DefaultTDelta > MINUTES_PER_DAY) {
DefaultTDelta = MINUTES_PER_DAY;
}
}
} else if (!*arg) {

View File

@@ -1,7 +1,7 @@
/* vim: set et ts=3 sw=3 sts=3 ft=c:
*
* Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
* https://github.com/udp/json-parser
* Copyright (C) 2012-2021 the json-parser authors All rights reserved.
* https://github.com/json-parser/json-parser
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,36 +29,49 @@
#include "json.h"
#define UNUSED(x) ( (void) x )
#ifdef _MSC_VER
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 might give us uintptr_t and UINTPTR_MAX but they also might not be provided */
#include <stdint.h>
#endif
const struct _json_value json_value_none;
#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 <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#ifndef JSON_INT_MAX
#define JSON_INT_MAX (json_int_t)(((unsigned json_int_t)(-1)) / (unsigned json_int_t)2);
#endif
typedef unsigned int json_uchar;
/* There has to be a better way to do this */
static const json_int_t JSON_INT_MAX = sizeof(json_int_t) == 1
? INT8_MAX
: (sizeof(json_int_t) == 2
? INT16_MAX
: (sizeof(json_int_t) == 4
? INT32_MAX
: INT64_MAX));
const struct _json_value json_value_none;
static unsigned char hex_value (json_char c)
{
if (isdigit(c))
if (isdigit((unsigned char)c))
return c - '0';
switch (c) {
@@ -79,10 +92,7 @@ static int would_overflow (json_int_t value, json_char b)
typedef struct
{
unsigned long used_memory;
unsigned int uint_max;
unsigned long ulong_max;
size_t used_memory;
json_settings settings;
int first_pass;
@@ -94,19 +104,19 @@ typedef struct
static void * default_alloc (size_t size, int zero, void * user_data)
{
UNUSED(user_data);
return zero ? calloc (1, size) : malloc (size);
(void)user_data; /* ignore unused-parameter warn */
return zero ? calloc (1, size) : malloc (size);
}
static void default_free (void * ptr, void * user_data)
{
UNUSED(user_data);
free (ptr);
(void)user_data; /* ignore unused-parameter warn */
free (ptr);
}
static void * json_alloc (json_state * state, unsigned long size, int zero)
static void * json_alloc (json_state * state, size_t size, int zero)
{
if ((state->ulong_max - state->used_memory) < size)
if ((ULONG_MAX - 8 - state->used_memory) < size)
return 0;
if (state->settings.max_memory
@@ -123,7 +133,7 @@ static int new_value (json_state * state,
json_type type)
{
json_value * value;
int values_size;
size_t values_size;
if (!state->first_pass)
{
@@ -157,14 +167,16 @@ static int new_value (json_state * state,
values_size = sizeof (*value->u.object.values) * value->u.object.length;
if (! (value->u.object.values = (json_object_entry *) json_alloc
(state, values_size + ((unsigned long) value->u.object.values), 0)) )
#ifdef UINTPTR_MAX
(state, values_size + ((uintptr_t) value->u.object.values), 0)) )
#else
(state, values_size + ((size_t) value->u.object.values), 0)) )
#endif
{
return 0;
}
char *s = (char *) value->u.object.values;
s += values_size;
value->_reserved.object_mem = s;
value->_reserved.object_mem = (void *) (((char *) value->u.object.values) + values_size);
value->u.object.length = 0;
break;
@@ -213,8 +225,8 @@ static int new_value (json_state * state,
}
#define whitespace \
case '\n': ++ state.cur_line; state.cur_col = 0; /* FALLTHRU */ \
case ' ': case '\t': case '\r'
case '\n': ++ state.cur_line; state.cur_col = 0; /* FALLTHRU */ \
case ' ': /* FALLTHRU */ case '\t': /* FALLTHRU */ case '\r'
#define string_add(b) \
do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0);
@@ -245,13 +257,13 @@ json_value * json_parse_ex (json_settings * settings,
size_t length,
char * error_buf)
{
json_char error [json_error_max];
char error [json_error_max];
const json_char * end;
json_value * top, * root, * alloc = 0;
json_state state = { 0 };
long flags;
double num_digits = 0, num_e = 0;
double num_fraction = 0;
int num_digits = 0;
double num_e = 0, num_fraction = 0;
/* Skip UTF-8 BOM
*/
@@ -274,12 +286,6 @@ json_value * json_parse_ex (json_settings * settings,
if (!state.settings.mem_free)
state.settings.mem_free = default_free;
memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));
state.uint_max -= 8; /* limit of how much can be added before next check */
state.ulong_max -= 8;
for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass)
{
json_uchar uchar;
@@ -299,11 +305,11 @@ json_value * json_parse_ex (json_settings * settings,
if (flags & flag_string)
{
if (!b)
{ snprintf (error, sizeof(error), "Unexpected EOF in string (at %u:%u)", line_and_col);
{ sprintf (error, "%u:%u: Unexpected EOF in string", line_and_col);
goto e_failed;
}
if (string_length > state.uint_max)
if (string_length > UINT_MAX - 8)
goto e_overflow;
if (flags & flag_escaped)
@@ -325,7 +331,7 @@ json_value * json_parse_ex (json_settings * settings,
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
{
snprintf (error, sizeof(error), "Invalid character value `%c` (at %u:%u)", b, line_and_col);
sprintf (error, "%u:%u: Invalid character value `%c`", line_and_col, b);
goto e_failed;
}
@@ -342,7 +348,7 @@ json_value * json_parse_ex (json_settings * settings,
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
{
snprintf (error, sizeof(error), "Invalid character value `%c` (at %u:%u)", b, line_and_col);
sprintf (error, "%u:%u: Invalid character value `%c`", line_and_col, b);
goto e_failed;
}
@@ -426,11 +432,12 @@ json_value * json_parse_ex (json_settings * settings,
case json_object:
if (state.first_pass) {
char *s = (char *) top->u.object.values;
s += string_length+1;
top->u.object.values = (void *) s;
} else {
if (state.first_pass) {
json_char **chars = (json_char **) &top->u.object.values;
chars[0] += string_length + 1;
}
else
{
top->u.object.values [top->u.object.length].name
= (json_char *) top->_reserved.object_mem;
@@ -472,7 +479,7 @@ json_value * json_parse_ex (json_settings * settings,
if (flags & flag_block_comment)
{
if (!b)
{ snprintf (error, sizeof(error), "%u:%u: Unexpected EOF in block comment", line_and_col);
{ sprintf (error, "%u:%u: Unexpected EOF in block comment", line_and_col);
goto e_failed;
}
@@ -488,12 +495,12 @@ json_value * json_parse_ex (json_settings * settings,
else if (b == '/')
{
if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
{ snprintf (error, sizeof(error), "%u:%u: Comment not allowed here", line_and_col);
{ sprintf (error, "%u:%u: Comment not allowed here", line_and_col);
goto e_failed;
}
if (++ state.ptr == end)
{ snprintf (error, sizeof(error), "%u:%u: EOF unexpected", line_and_col);
{ sprintf (error, "%u:%u: EOF unexpected", line_and_col);
goto e_failed;
}
@@ -508,7 +515,7 @@ json_value * json_parse_ex (json_settings * settings,
continue;
default:
snprintf (error, sizeof(error), "%u:%u: Unexpected `%c` in comment opening sequence", line_and_col, b);
sprintf (error, "%u:%u: Unexpected `%c` in comment opening sequence", line_and_col, b);
goto e_failed;
};
}
@@ -526,8 +533,8 @@ json_value * json_parse_ex (json_settings * settings,
default:
snprintf (error, sizeof(error), "%u:%u: Trailing garbage: `%c`",
state.cur_line, state.cur_col, b);
sprintf (error, "%u:%u: Trailing garbage: `%c`",
line_and_col, b);
goto e_failed;
};
@@ -545,7 +552,7 @@ json_value * json_parse_ex (json_settings * settings,
if (top && top->type == json_array)
flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
else
{ snprintf (error, sizeof(error), "%u:%u: Unexpected ]", line_and_col);
{ sprintf (error, "%u:%u: Unexpected `]`", line_and_col);
goto e_failed;
}
@@ -561,8 +568,8 @@ json_value * json_parse_ex (json_settings * settings,
}
else
{
snprintf (error, sizeof(error), "%u:%u: Expected , before %c",
state.cur_line, state.cur_col, b);
sprintf (error, "%u:%u: Expected `,` before `%c`",
line_and_col, b);
goto e_failed;
}
@@ -576,8 +583,8 @@ json_value * json_parse_ex (json_settings * settings,
}
else
{
snprintf (error, sizeof(error), "%u:%u: Expected : before %c",
state.cur_line, state.cur_col, b);
sprintf (error, "%u:%u: Expected `:` before `%c`",
line_and_col, b);
goto e_failed;
}
@@ -616,7 +623,7 @@ json_value * json_parse_ex (json_settings * settings,
case 't':
if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' ||
if ((end - state.ptr) <= 3 || *(++ state.ptr) != 'r' ||
*(++ state.ptr) != 'u' || *(++ state.ptr) != 'e')
{
goto e_unknown_value;
@@ -632,7 +639,7 @@ json_value * json_parse_ex (json_settings * settings,
case 'f':
if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' ||
if ((end - state.ptr) <= 4 || *(++ state.ptr) != 'a' ||
*(++ state.ptr) != 'l' || *(++ state.ptr) != 's' ||
*(++ state.ptr) != 'e')
{
@@ -647,7 +654,7 @@ json_value * json_parse_ex (json_settings * settings,
case 'n':
if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' ||
if ((end - state.ptr) <= 3 || *(++ state.ptr) != 'u' ||
*(++ state.ptr) != 'l' || *(++ state.ptr) != 'l')
{
goto e_unknown_value;
@@ -661,14 +668,14 @@ json_value * json_parse_ex (json_settings * settings,
default:
if (isdigit (b) || b == '-')
if (isdigit ((unsigned char) b) || b == '-')
{
if (!new_value (&state, &top, &root, &alloc, json_integer))
goto e_alloc_failure;
if (!state.first_pass)
{
while (isdigit (b) || b == '+' || b == '-'
while (isdigit ((unsigned char) b) || b == '+' || b == '-'
|| b == 'e' || b == 'E' || b == '.')
{
if ( (++ state.ptr) == end)
@@ -702,7 +709,7 @@ json_value * json_parse_ex (json_settings * settings,
continue;
}
else
{ snprintf (error, sizeof(error), "%u:%u: Unexpected %c when seeking value", line_and_col, b);
{ sprintf (error, "%u:%u: Unexpected `%c` when seeking value", line_and_col, b);
goto e_failed;
}
};
@@ -722,7 +729,7 @@ json_value * json_parse_ex (json_settings * settings,
case '"':
if (flags & flag_need_comma)
{ snprintf (error, sizeof(error), "%u:%u: Expected , before \"", line_and_col);
{ sprintf (error, "%u:%u: Expected `,` before `\"`", line_and_col);
goto e_failed;
}
@@ -744,10 +751,10 @@ json_value * json_parse_ex (json_settings * settings,
{
flags &= ~ flag_need_comma;
break;
}
/* FALLTHROUGH */
} /* FALLTHRU */
default:
snprintf (error, sizeof(error), "%u:%u: Unexpected `%c` in object", line_and_col, b);
sprintf (error, "%u:%u: Unexpected `%c` in object", line_and_col, b);
goto e_failed;
};
@@ -756,7 +763,7 @@ json_value * json_parse_ex (json_settings * settings,
case json_integer:
case json_double:
if (isdigit (b))
if (isdigit ((unsigned char)b))
{
++ num_digits;
@@ -765,7 +772,7 @@ json_value * json_parse_ex (json_settings * settings,
if (! (flags & flag_num_e))
{
if (flags & flag_num_zero)
{ snprintf (error, sizeof(error), "%u:%u: Unexpected `0` before `%c`", line_and_col, b);
{ sprintf (error, "%u:%u: Unexpected `0` before `%c`", line_and_col, b);
goto e_failed;
}
@@ -780,10 +787,12 @@ json_value * json_parse_ex (json_settings * settings,
}
if (would_overflow(top->u.integer, b))
{ -- num_digits;
{
json_int_t integer = top->u.integer;
-- num_digits;
-- state.ptr;
top->type = json_double;
top->u.dbl = (double)top->u.integer;
top->u.dbl = (double)integer;
continue;
}
@@ -813,13 +822,15 @@ json_value * json_parse_ex (json_settings * settings,
}
else if (b == '.' && top->type == json_integer)
{
json_int_t integer = top->u.integer;
if (!num_digits)
{ snprintf (error, sizeof(error), "%u:%u: Expected digit before `.`", line_and_col);
{ sprintf (error, "%u:%u: Expected digit before `.`", line_and_col);
goto e_failed;
}
top->type = json_double;
top->u.dbl = (double) top->u.integer;
top->u.dbl = (double) integer;
flags |= flag_num_got_decimal;
num_digits = 0;
@@ -831,7 +842,7 @@ json_value * json_parse_ex (json_settings * settings,
if (top->type == json_double)
{
if (!num_digits)
{ snprintf (error, sizeof(error), "%u:%u: Expected digit after `.`", line_and_col);
{ sprintf (error, "%u:%u: Expected digit after `.`", line_and_col);
goto e_failed;
}
@@ -844,8 +855,9 @@ json_value * json_parse_ex (json_settings * settings,
if (top->type == json_integer)
{
json_int_t integer = top->u.integer;
top->type = json_double;
top->u.dbl = (double) top->u.integer;
top->u.dbl = (double) integer;
}
num_digits = 0;
@@ -857,7 +869,7 @@ json_value * json_parse_ex (json_settings * settings,
else
{
if (!num_digits)
{ snprintf (error, sizeof(error), "%u:%u: Expected digit after `e`", line_and_col);
{ sprintf (error, "%u:%u: Expected digit after `e`", line_and_col);
goto e_failed;
}
@@ -926,7 +938,7 @@ json_value * json_parse_ex (json_settings * settings,
};
}
if ( (++ top->parent->u.array.length) > state.uint_max)
if ( (++ top->parent->u.array.length) > UINT_MAX - 8)
goto e_overflow;
top = top->parent;
@@ -942,7 +954,7 @@ json_value * json_parse_ex (json_settings * settings,
e_unknown_value:
snprintf (error, sizeof(error), "%u:%u: Unknown value", line_and_col);
sprintf (error, "%u:%u: Unknown value", line_and_col);
goto e_failed;
e_alloc_failure:
@@ -952,7 +964,7 @@ e_alloc_failure:
e_overflow:
snprintf (error, sizeof(error), "%u:%u: Too long (caught overflow)", line_and_col);
sprintf (error, "%u:%u: Too long (caught overflow)", line_and_col);
goto e_failed;
e_failed:

View File

@@ -1,7 +1,8 @@
/* vim: set et ts=3 sw=3 sts=3 ft=c:
*
* Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
* https://github.com/udp/json-parser
* Copyright (C) 2012-2021 the json-parser authors All rights reserved.
* https://github.com/json-parser/json-parser
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,15 +36,22 @@
#endif
#ifndef json_int_t
#ifndef _MSC_VER
#include <inttypes.h>
#define json_int_t int64_t
#else
#undef JSON_INT_T_OVERRIDDEN
#if defined(_MSC_VER)
#define json_int_t __int64
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__cplusplus) && __cplusplus >= 201103L)
/* C99 and C++11 */
#include <stdint.h>
#define json_int_t int_fast64_t
#else
/* C89 */
#define json_int_t long
#endif
#else
#define JSON_INT_T_OVERRIDDEN 1
#endif
#include <stdlib.h>
#include <stddef.h>
#ifdef __cplusplus
@@ -56,7 +64,7 @@
typedef struct
{
unsigned long max_memory;
unsigned long max_memory; /* should be size_t, but would modify the API */
int settings;
/* Custom allocator support (leave null to use malloc/free)
@@ -122,11 +130,11 @@ typedef struct _json_value
json_object_entry * values;
#if defined(__cplusplus) && __cplusplus >= 201103L
decltype(values) begin () const
#if defined(__cplusplus)
json_object_entry * begin () const
{ return values;
}
decltype(values) end () const
json_object_entry * end () const
{ return values + length;
}
#endif
@@ -138,11 +146,11 @@ typedef struct _json_value
unsigned int length;
struct _json_value ** values;
#if defined(__cplusplus) && __cplusplus >= 201103L
decltype(values) begin () const
#if defined(__cplusplus)
_json_value ** begin () const
{ return values;
}
decltype(values) end () const
_json_value ** end () const
{ return values + length;
}
#endif

View File

@@ -1132,8 +1132,7 @@ int DoIf(ParsePtr p)
syndrome = IF_TRUE | BEFORE_ELSE;
Eprint("%s", GetErr(r));
} else
if ( (v.type != STR_TYPE && v.v.val) ||
(v.type == STR_TYPE && strcmp(v.v.str, "")) ) {
if (truthy(&v)) {
syndrome = IF_TRUE | BEFORE_ELSE;
} else {
syndrome = IF_FALSE | BEFORE_ELSE;
@@ -2037,7 +2036,6 @@ SaveLastTimeTrig(TimeTrig const *t)
void
System(char const *cmd, int is_queued)
{
int r;
pid_t kid;
int fd;
int status;
@@ -2070,15 +2068,12 @@ System(char const *cmd, int is_queued)
}
}
/* This is the child process or original if we never forked */
r = system(cmd);
(void) system(cmd);
if (do_exit) {
/* In the child process, so exit! */
exit(0);
}
if (r == 0) {
return;
}
return;
}
char const *

View File

@@ -525,7 +525,7 @@ void HuntPhase(int startdate, int starttim, int phas, int *date, int *time)
/* Convert from Remind representation to year/mon/day */
FromDSE(utcd, &y, &m, &d);
/* Convert to a true Julian date */
jdorig = jtime(y, m, d, (utct / 60), (utct % 60), 0);
jdorig = jtime(y, m, d, (utct / 60), (utct % 60), 0);
jd = jdorig - 45.0;
nt1 = meanphase(jd, 0.0, &k1);
while(1) {
@@ -546,3 +546,409 @@ void HuntPhase(int startdate, int starttim, int phas, int *date, int *time)
t1 = h*60 + min;
UTCToLocal(d1, t1, date, time);
}
/*
Moonrise and Moonset calculations
Derived from: https://github.com/signetica/MoonRise
Original license from that project:
Copyright 2007 Stephen R. Schmitt
Subsequent work Copyright 2020 Cyrus Rahman
You may use or modify this source code in any way you find useful,
provided that you agree that the author(s) have no warranty,
obligations or liability. You must determine the suitability of this
source code for your use.
Redistributions of this source code must retain this copyright notice.
*/
/* How many hours to search for moonrise / moonset? We search
half a window on either side of the starting point */
#define MR_WINDOW 48
/* K1 tide cycle is 1.0027379 cycles per solar day */
#define K1 15*(PI/180)*1.0027379
#define remainder(x, y) ((x) - (y) * rint((x)/(y)))
struct MoonInfo {
time_t queryTime;
time_t riseTime;
time_t setTime;
double riseAz;
double setAz;
int hasRise;
int hasSet;
int isVisible;
};
static void init_moon_info(struct MoonInfo *info)
{
info->queryTime = (time_t) 0;
info->riseTime = (time_t) 0;
info->setTime = (time_t) 0;
info->riseAz = 0.0;
info->setAz = 0.0;
info->hasRise = 0;
info->hasSet = 0;
info->isVisible = 0;
}
/*
Local Sidereal Time
Provides local sidereal time in degrees, requires longitude in degrees
and time in fractional Julian days since Jan 1, 2000, 1200UTC (e.g. the
Julian date - 2451545).
cf. USNO Astronomical Almanac and
https://astronomy.stackexchange.com/questions/24859/local-sidereal-time
*/
static double local_sidereal_time(double offset_days, double longitude)
{
double ltime = (15.0L * (6.697374558L + 0.06570982441908L * offset_days +
remainder(offset_days, 1) * 24 + 12 +
0.000026 * (offset_days / 36525) * (offset_days / 36525)) + longitude) / 360.0;
ltime -= floor(ltime);
return ltime * 360.0;
}
static double julian_from_time_t(time_t t)
{
return ((double) t) / 86400.0L + 2440587.5L;
}
static time_t time_t_from_dse(int dse)
{
int y, m, d;
struct tm local;
FromDSE(dse, &y, &m, &d);
local.tm_sec = 0;
local.tm_min = 0;
local.tm_hour = 0;
local.tm_mday = d;
local.tm_mon = m;
local.tm_year = y-1900;
local.tm_isdst = -1;
return mktime(&local);
}
static int datetime_from_time_t(time_t t)
{
struct tm *local;
int ans;
/* Round to nearest minute */
int min_offset = ((long) t) % 60;
if (min_offset >= 30) {
t += (60 - min_offset);
} else {
t -= min_offset;
}
local = localtime(&t);
ans = DSE(local->tm_year + 1900, local->tm_mon, local->tm_mday) * MINUTES_PER_DAY;
ans += local->tm_hour * 60;
ans += local->tm_min;
return ans;
}
/* 3-point interpolation */
static double interpolate(double f0, double f1, double f2, double p)
{
double a = f1-f0;
double b = f2-f1-a;
return f0 + p * (2*a + b * (2*p - 1));
}
/* Moon position using fundamental arguments
Van Flandern & Pulkkinen, 1979) */
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;
double f = 0.259091 + 0.03674819520 * dayOffset;
double d = 0.827362 + 0.03386319198 * dayOffset;
double n = 0.347343 - 0.00014709391 * dayOffset;
double g = 0.993126 + 0.00273777850 * dayOffset;
l = 2 * PI * (l - floor(l));
m = 2 * PI * (m - floor(m));
f = 2 * PI * (f - floor(f));
d = 2 * PI * (d - floor(d));
n = 2 * PI * (n - floor(n));
g = 2 * PI * (g - floor(g));
double v, u, w;
v = 0.39558 * sin(f + n)
+ 0.08200 * sin(f)
+ 0.03257 * sin(m - f - n)
+ 0.01092 * sin(m + f + n)
+ 0.00666 * sin(m - f)
- 0.00644 * sin(m + f - 2*d + n)
- 0.00331 * sin(f - 2*d + n)
- 0.00304 * sin(f - 2*d)
- 0.00240 * sin(m - f - 2*d - n)
+ 0.00226 * sin(m + f)
- 0.00108 * sin(m + f - 2*d)
- 0.00079 * sin(f - n)
+ 0.00078 * sin(f + 2*d + n);
u = 1
- 0.10828 * cos(m)
- 0.01880 * cos(m - 2*d)
- 0.01479 * cos(2*d)
+ 0.00181 * cos(2*m - 2*d)
- 0.00147 * cos(2*m)
- 0.00105 * cos(2*d - g)
- 0.00075 * cos(m - 2*d + g);
w = 0.10478 * sin(m)
- 0.04105 * sin(2*f + 2*n)
- 0.02130 * sin(m - 2*d)
- 0.01779 * sin(2*f + n)
+ 0.01774 * sin(n)
+ 0.00987 * sin(2*d)
- 0.00338 * sin(m - 2*f - 2*n)
- 0.00309 * sin(g)
- 0.00190 * sin(2*f)
- 0.00144 * sin(m + n)
- 0.00144 * sin(m - 2*f - n)
- 0.00113 * sin(m + 2*f + 2*n)
- 0.00094 * sin(m - 2*d + g)
- 0.00092 * sin(2*m - 2*d);
double s;
s = w / sqrt(u - v*v);
*ra = l + atan(s / sqrt(1 - s*s)); // Right ascension
s = v / sqrt(u);
*declination = atan(s / sqrt(1 - s*s)); // Declination
*distance = 60.40974 * sqrt(u); // Distance
}
/* Search for moonrise / moonset events during an hour */
static void test_moon_event(int k, double offset_days, struct MoonInfo *moon_info,
double latitude, double longitude,
double const ra[], double declination[], double const distance[])
{
double ha[3], VHz[3];
double lSideTime;
/* Get (local_sidereal_time - MR_WINDOW / 2) hours in radians. */
lSideTime = local_sidereal_time(offset_days, longitude) * PI / 180.0;
/* Calculate hour angle */
ha[0] = lSideTime - ra[0] + k*K1;
ha[2] = lSideTime - ra[2] + k*K1 + K1;
// Hour Angle and declination at half hour.
ha[1] = (ha[2] + ha[0])/2;
declination[1] = (declination[2] + declination[0])/2;
double s = sin((PI / 180) * latitude);
double c = cos((PI / 180) * latitude);
// refraction + semidiameter at horizon + distance correction
double z = cos((PI / 180) * (90.567 - 41.685 / distance[0]));
VHz[0] = s * sin(declination[0]) + c * cos(declination[0]) * cos(ha[0]) - z;
VHz[2] = s * sin(declination[2]) + c * cos(declination[2]) * cos(ha[2]) - z;
if (signbit(VHz[0]) == signbit(VHz[2]))
goto noevent; // No event this hour.
VHz[1] = s * sin(declination[1]) + c * cos(declination[1]) * cos(ha[1]) - z;
double a, b, d, e, time;
a = 2 * VHz[2] - 4 * VHz[1] + 2 * VHz[0];
b = 4 * VHz[1] - 3 * VHz[0] - VHz[2];
d = b * b - 4 * a * VHz[0];
if (d < 0)
goto noevent; // No event this hour.
d = sqrt(d);
e = (-b + d) / (2 * a);
if ((e < 0) || (e > 1))
e = (-b - d) / (2 * a);
time = k + e + 1 / 120; // Time since k=0 of event (in hours).
// The time we started searching + the time from the start of the search to the
// event is the time of the event. Add (time since k=0) - window/2 hours.
time_t eventTime;
eventTime = moon_info->queryTime + (time - MR_WINDOW / 2) *60 *60;
double hz, nz, dz, az;
hz = ha[0] + e * (ha[2] - ha[0]); // Azimuth of the moon at the event.
nz = -cos(declination[1]) * sin(hz);
dz = c * sin(declination[1]) - s * cos(declination[1]) * cos(hz);
az = atan2(nz, dz) * (180 / PI);
if (az < 0) {
az += 360;
}
// If there is no previously recorded event of this type, save this event.
//
// If this event is previous to queryTime, and is the nearest event to queryTime
// of events of its type previous to queryType, save this event, replacing the
// previously recorded event of its type. Events subsequent to queryTime are
// treated similarly, although since events are tested in chronological order
// no replacements will occur as successive events will be further from
// queryTime.
//
// If this event is subsequent to queryTime and there is an event of its type
// previous to queryTime, then there is an event of the other type between the
// two events of this event's type. If the event of the other type is
// previous to queryTime, then it is the nearest event to queryTime that is
// previous to queryTime. In this case save the current event, replacing
// the previously recorded event of its type. Otherwise discard the current
// event.
//
if ((VHz[0] < 0) && (VHz[2] > 0)) {
if (!moon_info->hasRise ||
((moon_info->riseTime < moon_info->queryTime) == (eventTime < moon_info->queryTime) &&
labs(moon_info->riseTime - moon_info->queryTime) > labs(eventTime - moon_info->queryTime)) ||
((moon_info->riseTime < moon_info->queryTime) != (eventTime < moon_info->queryTime) &&
(moon_info->hasSet &&
(moon_info->riseTime < moon_info->queryTime) == (moon_info->setTime < moon_info->queryTime)))) {
moon_info->riseTime = eventTime;
moon_info->riseAz = az;
moon_info->hasRise = 1;
}
}
if ((VHz[0] > 0) && (VHz[2] < 0)) {
if (!moon_info->hasSet ||
((moon_info->setTime < moon_info->queryTime) == (eventTime < moon_info->queryTime) &&
labs(moon_info->setTime - moon_info->queryTime) > labs(eventTime - moon_info->queryTime)) ||
((moon_info->setTime < moon_info->queryTime) != (eventTime < moon_info->queryTime) &&
(moon_info->hasRise &&
(moon_info->setTime < moon_info->queryTime) == (moon_info->riseTime < moon_info->queryTime)))) {
moon_info->setTime = eventTime;
moon_info->setAz = az;
moon_info->hasSet = 1;
}
}
noevent:
// There are obscure cases in the polar regions that require extra logic.
if (!moon_info->hasRise && !moon_info->hasSet)
moon_info->isVisible = !signbit(VHz[2]);
else if (moon_info->hasRise && !moon_info->hasSet)
moon_info->isVisible = (moon_info->queryTime > moon_info->riseTime);
else if (!moon_info->hasRise && moon_info->hasSet)
moon_info->isVisible = (moon_info->queryTime < moon_info->setTime);
else
moon_info->isVisible = ((moon_info->riseTime < moon_info->setTime && moon_info->riseTime < moon_info->queryTime && moon_info->setTime > moon_info->queryTime) ||
(moon_info->riseTime > moon_info->setTime && (moon_info->riseTime < moon_info->queryTime || moon_info->setTime > moon_info->queryTime)));
return;
}
static void
calculate_moonrise_moonset(double latitude, double longitude, time_t t,
struct MoonInfo *mi)
{
double ra[3], declination[3], distance[3];
double offset_days;
int i;
init_moon_info(mi);
mi->queryTime = t;
/* Days since Jan 1, 2000 12:00UTC */
offset_days = julian_from_time_t(t) - 2451545L;
offset_days -= (double) MR_WINDOW / (2.0 * 24.0);
for (i=0; i<3; i++) {
moon_position(offset_days + i * ((double) MR_WINDOW / (2.0 * 24.0)), &ra[i], &declination[i], &distance[i]);
}
if (ra[1] <= ra[0]) {
ra[1] += 2*PI;
}
if (ra[2] <= ra[1]) {
ra[2] += 2*PI;
}
double window_ra[3], window_declination[3], window_distance[3];
window_ra[0] = ra[0];
window_declination[0] = declination[0];
window_distance[0] = distance[0];
for (int k=0; k < MR_WINDOW; k++) {
double ph = (double) (k+1) / (double) MR_WINDOW;
window_ra[2] = interpolate(ra[0], ra[1], ra[2], ph);
window_declination[2] = interpolate(declination[0], declination[1], declination[2], ph);
window_distance[2] = interpolate(distance[0], distance[1], distance[2], ph);
test_moon_event(k, offset_days, mi, latitude, longitude, window_ra, window_declination, window_distance);
/* Step to next interval */
window_ra[0] = window_ra[2];
window_declination[0] = window_declination[2];
window_distance[0] = window_distance[2];
}
}
/* Get next moonrise or moonset in minutes after midnight of BASEYR
starting from given DSE.
Returns 0 if no moonrise could be computed
If want_angle is true, then returns the azimuth of the event rather
than the time of the event */
#define ME_SEARCH_DAYS 180
static int GetMoonevent(int dse, int is_rise, int want_angle)
{
int i;
int angle;
struct MoonInfo mi;
time_t t = time_t_from_dse(dse);
for (i=0; i<ME_SEARCH_DAYS; i++) {
calculate_moonrise_moonset(Latitude, Longitude, t + i * 86400, &mi);
if (is_rise) {
if (mi.hasRise && mi.riseTime >= t) {
if (want_angle) {
angle = (int) (mi.riseAz + 0.5);
return angle;
} else {
return datetime_from_time_t(mi.riseTime);
}
}
} else {
if (mi.hasSet && mi.setTime >= t) {
if (want_angle) {
angle = (int) (mi.setAz + 0.5);
return angle;
} else {
return datetime_from_time_t(mi.setTime);
}
}
}
}
if (want_angle) {
return -1;
} else {
return 0;
}
}
int GetMoonrise(int dse)
{
return GetMoonevent(dse, 1, 0);
}
int GetMoonset(int dse)
{
return GetMoonevent(dse, 0, 0);
}
int GetMoonrise_angle(int dse)
{
return GetMoonevent(dse, 1, 1);
}
int GetMoonset_angle(int dse)
{
return GetMoonevent(dse, 0, 1);
}

View File

@@ -285,3 +285,7 @@ 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);
int GetMoonrise(int dse);
int GetMoonset(int dse);
int GetMoonrise_angle(int dse);
int GetMoonset_angle(int dse);

View File

@@ -862,7 +862,7 @@ static SysVar SysVarArr[] = {
{"DefaultColor", 1, SPECIAL_TYPE, default_color_func, 0, 0 },
{"DefaultDelta", 1, INT_TYPE, &DefaultDelta, 0, 10000 },
{"DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999 },
{"DefaultTDelta", 1, INT_TYPE, &DefaultTDelta, 0, 1440 },
{"DefaultTDelta", 1, INT_TYPE, &DefaultTDelta, 0, MINUTES_PER_DAY },
{"DeltaOverride", 0, INT_TYPE, &DeltaOverride, 0, 0 },
{"DontFork", 0, INT_TYPE, &DontFork, 0, 0 },
{"DontQueue", 0, INT_TYPE, &DontQueue, 0, 0 },
@@ -898,7 +898,7 @@ static SysVar SysVarArr[] = {
{"LongSec", 1, SPECIAL_TYPE, longsec_func, 0, 0 },
{"March", 1, TRANS_TYPE, "March", 0, 0 },
{"MaxFullOmits", 0, CONST_INT_TYPE, NULL, MAX_FULL_OMITS, 0},
{"MaxLateMinutes", 1, INT_TYPE, &MaxLateMinutes, 0, 1440 },
{"MaxLateMinutes", 1, INT_TYPE, &MaxLateMinutes, 0, MINUTES_PER_DAY },
{"MaxPartialOmits",0, CONST_INT_TYPE, NULL, MAX_PARTIAL_OMITS, 0},
{"MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY },
{"MaxStringLen", 1, INT_TYPE, &MaxStringLen, -1, ANY },

View File

@@ -1,13 +0,0 @@
SET $LatDeg 45
SET $LatMin 24
SET $LatSec 0
SET $LongDeg 75
SET $LongMin 39
SET $LongSec 0
SET $MinsFromUTC -300
SET $CalcUTC 0
MSG Dawn: [dawn()]
MSG Sunrise: [sunrise()]
MSG Sunset: [sunset()]
MSG Dusk: [dusk()]

93
tests/sunmoon.rem Normal file
View File

@@ -0,0 +1,93 @@
set $AddBlankLines 0
banner %
set d '2011-01-01'
set x adawn(d)
if x < 5:53 || x > 5:57
REM MSG adawn() is inaccurate! - [x]
endif
set x dawn(d)
if x < 7:06 || x > 7:10
REM MSG dawn() is inaccurate! - [x]
endif
set x sunrise(d)
if x < 7:40 || x > 7:44
REM MSG sunrise() is inaccurate! - [x]
endif
set x sunset(d)
if x < 16:28 || x > 16:32
REM MSG sunset() is inaccurate! - [x]
endif
set x dusk(d)
if x < 17:02 || x > 17:06
REM MSG dusk() is inaccurate! - [x]
endif
set x adusk(d)
if x < 18:15 || x > 18:19
REM MSG adusk() is inaccurate! - [x]
endif
set x moonrise(d)
if x < '2011-01-01@5:14' || x > '2011-01-01@5:18'
REM MSG moonrise() is inaccurate! - [x]
endif
set x moonset(d)
if x < '2011-01-01@13:59' || x > '2011-01-01@14:03'
REM MSG moonset() is inaccurate! - [x]
endif
set x moonphase(d, 0:00)
if x < 319 || x > 323
REM MSG moonphase() is inaccurate! - [x]
endif
set x moondatetime(0, d, 0:00)
if x < '2011-01-04@04:02' || x > '2011-01-04@04:06'
REM MSG moondatetime(0) is inaccurate! - [x]
endif
set x moondatetime(1, d, 0:00)
if x < '2011-01-12@06:31' || x > '2011-01-12@06:35'
REM MSG moondatetime(1) is inaccurate! - [x]
endif
set x moondatetime(2, d, 0:00)
if x < '2011-01-19@16:20' || x > '2011-01-19@16:24'
REM MSG moondatetime(2) is inaccurate! - [x]
endif
set x moondatetime(3, d, 0:00)
if x < '2011-01-26@07:57' || x > '2011-01-26@08:01'
REM MSG moondatetime(3) is inaccurate! - [x]
endif
set x soleq(0, 2011)
if x < '2011-03-20@19:18' || x > '2011-03-20@19:22'
REM MSG soleq(0) is inaccurate! - [x]
endif
set x soleq(1, 2011)
if x < '2011-06-21@13:14' || x > '2011-06-21@13:18'
REM MSG soleq(1) is inaccurate! - [x]
endif
set x soleq(2, 2011)
if x < '2011-09-23@05:02' || x > '2011-09-23@05:06'
REM MSG soleq(2) is inaccurate! - [x]
endif
set x soleq(3, 2011)
if x < '2011-12-22@00:28' || x > '2011-12-22@00:32'
REM MSG soleq(3) is inaccurate! - [x]
endif
if $NumTrig == 0
REM MSG All astronomical functions look OK
endif

View File

@@ -153,9 +153,7 @@ rm -f ../tests/purge_dir/*.rem.purged >> ../tests/test.out 2>&1
../src/remind -p ../tests/shade.rem 1 August 2009 | ../src/rem2ps -e -l -c3 >> ../tests/test.out 2>&1
../src/remind -pp ../tests/shade.rem 1 August 2009 | ../src/rem2ps -e -l -c3 >> ../tests/test.out 2>&1
# The sun tests can fail due to math roundoff error changing the times
# by a minute...
# ../src/remind -p12 ../tests/sun.rem 1 Jan 2011 >> ../tests/test.out 2>&1
TZ=America/Toronto ../src/remind ../tests/sunmoon.rem 1 Jan 2011 >> ../tests/test.out 2>&1
# Test -a vs -aa
../src/remind -q -a - 1 Jan 2012 9:00 <<'EOF' >> ../tests/test.out 2>&1

View File

@@ -1047,7 +1047,7 @@ set a057 value("a05"+"6")
"a05" + "6" => "a056"
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
set a058 version()
version() => "05.03.04"
version() => "05.03.05"
set a059 wkday(today())
today() => 1991-02-16
wkday(1991-02-16) => "Saturday"
@@ -2611,7 +2611,7 @@ a056 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a007 "1991-02-16"
a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a008 "11:44"
a058 "05.03.04"
a058 "05.03.05"
a059 "Saturday"
a010 12
a060 6
@@ -5632,8 +5632,8 @@ REM SATISFY ""
REM SATISFY [version() > "01.00.00"]
../tests/test.rem(1050): SATISFY: expression has no reference to trigdate() or $T...
../tests/test.rem(1050): Trig = Saturday, 16 February, 1991
version() => "05.03.04"
"05.03.04" > "01.00.00" => 1
version() => "05.03.05"
"05.03.05" > "01.00.00" => 1
../tests/test.rem(1050): Trig(satisfied) = Saturday, 16 February, 1991
REM SATISFY [max(x, max(x, 1, 2, 3), 4, 5, 6) * 5]
../tests/test.rem(1051): SATISFY: expression has no reference to trigdate() or $T...
@@ -5833,10 +5833,10 @@ max()
fset dooby(x) 1
set zxk dooby()
dooby(...) => Not enough arguments
dooby() => Not enough arguments
../tests/test.rem(1123): dooby(): Not enough arguments
set zxk dooby(1, 2)
dooby(...) => Too many arguments
dooby(?, ?) => Too many arguments
../tests/test.rem(1124): dooby(): Too many arguments
set zxk dooby(1)
Entering UserFN dooby(1)
@@ -16271,7 +16271,7 @@ Translation hash table statistics:
Entries: 1; Buckets: 7; Non-empty Buckets: 1
Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000
Growths: 0; Shrinks: 0
Expression nodes allocated: 300096
Expression nodes allocated: 300288
Expression nodes high-water: 300073
Expression nodes leaked: 0
Parse level high-water: 25
@@ -22332,6 +22332,7 @@ grestore
showpage
%%Trailer
%%Pages: 1
All astronomical functions look OK
Reminders for Sunday, 1st January, 2012:
1
@@ -23200,7 +23201,7 @@ SECURITY: Won't read world-writable file or directory!
Error reading include_dir/ww: Can't open file
SECURITY: Won't read world-writable file or directory!
Error reading include_dir/ww: No files matching *.rem
05.03.04
05.03.05
Enabling test mode: This is meant for the acceptance test.
Do not use --test in production.
In test mode, the system time is fixed at 2025-01-06@19:00
@@ -24123,6 +24124,10 @@ monnum
moondate
moondatetime
moonphase
moonrise
moonrisedir
moonset
moonsetdir
moontime
multitrig
ndawn
@@ -25133,7 +25138,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "13 horas i 34 minuts fa" and %*1 yields: "13 horas i 34 minuts fa"
%2 yields: "a les 0:00am" and %*2 yields: "0:00am"
%2 yields: "a les 12:00am" and %*2 yields: "12:00am"
%3 yields: "a les 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -26035,7 +26040,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "13 timer og 34 minutter siden" and %*1 yields: "13 timer og 34 minutter siden"
%2 yields: "kl. 0:00 om natten" and %*2 yields: "0:00 om natten"
%2 yields: "kl. 12:00 om natten" and %*2 yields: "12:00 om natten"
%3 yields: "kl. 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -26937,7 +26942,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "13 Stunden und 34 Minuten vorher" and %*1 yields: "13 Stunden und 34 Minuten vorher"
%2 yields: "um 0:00 nachts" and %*2 yields: "0:00 nachts"
%2 yields: "um 12:00 nachts" and %*2 yields: "12:00 nachts"
%3 yields: "um 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -27839,7 +27844,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "13 hours and 34 minutes ago" and %*1 yields: "13 hours and 34 minutes ago"
%2 yields: "at 0:00am" and %*2 yields: "0:00am"
%2 yields: "at 12:00am" and %*2 yields: "12:00am"
%3 yields: "at 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -28741,7 +28746,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "13 horas y 34 minutos hace" and %*1 yields: "13 horas y 34 minutos hace"
%2 yields: "a las 0:00am" and %*2 yields: "0:00am"
%2 yields: "a las 12:00am" and %*2 yields: "12:00am"
%3 yields: "a las 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -29643,7 +29648,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "13 tuntia 34 minuuttia sitten" and %*1 yields: "13 tuntia 34 minuuttia sitten"
%2 yields: "klo 0:00 ap." and %*2 yields: "0:00 ap."
%2 yields: "klo 12:00 ap." and %*2 yields: "12:00 ap."
%3 yields: "klo 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -30545,7 +30550,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "il y a 13 heures et 34 minutes" and %*1 yields: "il y a 13 heures et 34 minutes"
%2 yields: "à 0:00am" and %*2 yields: "0:00am"
%2 yields: "à 12:00am" and %*2 yields: "12:00am"
%3 yields: "à 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -31447,7 +31452,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "13 ώρες και 34 λεπτά πριν" and %*1 yields: "13 ώρες και 34 λεπτά πριν"
%2 yields: "στις 0:00πμ" and %*2 yields: "0:00πμ"
%2 yields: "στις 12:00πμ" and %*2 yields: "12:00πμ"
%3 yields: "στις 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -32349,7 +32354,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "13 klukkustundir og 34 mínútur síðan" and %*1 yields: "13 klukkustundir og 34 mínútur síðan"
%2 yields: "kl. 0:00fh" and %*2 yields: "0:00fh"
%2 yields: "kl. 12:00fh" and %*2 yields: "12:00fh"
%3 yields: "kl. 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -33251,7 +33256,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "13 ore e 34 minuti fa" and %*1 yields: "13 ore e 34 minuti fa"
%2 yields: "alle 0:00am" and %*2 yields: "0:00am"
%2 yields: "alle 12:00am" and %*2 yields: "12:00am"
%3 yields: "alle 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -34153,7 +34158,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "13 uren en 34 minuten geleden" and %*1 yields: "13 uren en 34 minuten geleden"
%2 yields: "op 0:00am" and %*2 yields: "0:00am"
%2 yields: "op 12:00am" and %*2 yields: "12:00am"
%3 yields: "op 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -35055,7 +35060,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "13 timer og 34 minutter siden" and %*1 yields: "13 timer og 34 minutter siden"
%2 yields: "kl. 0:00am" and %*2 yields: "0:00am"
%2 yields: "kl. 12:00am" and %*2 yields: "12:00am"
%3 yields: "kl. 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -35957,7 +35962,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "13 godzin i 34 minuty temu" and %*1 yields: "13 godzin i 34 minuty temu"
%2 yields: "o 0:00 w nocy" and %*2 yields: "0:00 w nocy"
%2 yields: "o 12:00 w nocy" and %*2 yields: "12:00 w nocy"
%3 yields: "o 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -36859,7 +36864,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "13 horas e 34 minutos atrás" and %*1 yields: "13 horas e 34 minutos atrás"
%2 yields: "as 0:00am" and %*2 yields: "0:00am"
%2 yields: "as 12:00am" and %*2 yields: "12:00am"
%3 yields: "as 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"
@@ -37761,7 +37766,7 @@ Time substitutions for 13:32 where now() = 13:34
Time substitutions for 00:00 where now() = 13:34
%1 yields: "acum 13 ore şi 34 minute" and %*1 yields: "acum 13 ore şi 34 minute"
%2 yields: "la ora 0:00 noaptea" and %*2 yields: "0:00 noaptea"
%2 yields: "la ora 12:00 noaptea" and %*2 yields: "12:00 noaptea"
%3 yields: "la ora 00:00" and %*3 yields: "00:00"
%4 yields: "-814" and %*4 yields: "-814"
%5 yields: "814" and %*5 yields: "814"

View File

@@ -1,6 +0,0 @@
#!/bin/sh
echo "Unconfiguring Remind..."
echo rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h www/Makefile rem2html/Makefile
rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h www/Makefile rem2html/Makefile
exit 0