mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-05-02 13:57:07 +02:00
Compare commits
22 Commits
7ee4073c7a
...
05.00.03
| Author | SHA1 | Date | |
|---|---|---|---|
| bf2aabd610 | |||
| c019221d15 | |||
| b7bd6faf07 | |||
| 80d58220fe | |||
| cd8624e176 | |||
| 8515fb7ddd | |||
| 84f9f4ae0a | |||
| e201ebcfa4 | |||
| 4e15c3ec35 | |||
| 1adccf9b1f | |||
| a1aa5c2ad9 | |||
| 1e0d650737 | |||
| 553d092ca8 | |||
| dc62841517 | |||
| 326e7bfc53 | |||
| b9dc7c16ad | |||
| abd54b016b | |||
| db02b54067 | |||
| 40a78dfbbb | |||
| c860b46baa | |||
| 1458ba8856 | |||
| 7b9b6ebc96 |
@@ -1,5 +1,45 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* VERSION 5.0 Patch 3 - 2024-08-28
|
||||
|
||||
* IMPROVEMENT: remind: Preserve newlines ("%_" sequences) in calendar
|
||||
mode in most cases. See the remind man page for details.
|
||||
|
||||
* IMPROVEMENT: rem2pdf: rem2pdf can now produce PostScript and
|
||||
Encapsulated PostScript output in addition to PDF and SVG.
|
||||
|
||||
* IMPROVEMENT: remind: Emit warnings if a subst_XXX function takes the
|
||||
wrong number of arguments, or for custom sequences, if the function
|
||||
is not defined.
|
||||
|
||||
* IMPROVEMENT: remind: Emit warnings if WARN/SCHED/OMITFUNC functions
|
||||
do not reference their argument.
|
||||
|
||||
* IMPROVEMENT: remind: Allow strings to be used with logical
|
||||
operators. The empty string "" is considered false and all other
|
||||
strings are considered true.
|
||||
|
||||
* IMPROVEMENT: remind: Emit warnings for lines that are implicitly
|
||||
treated as REM commands; add warnings for REM commands that are
|
||||
implicitly treated as MSG-type reminders.
|
||||
|
||||
* IMPROVEMENT: remind: Add an optional fourth argument to the built-in
|
||||
ampm() function that specifies not to suppress a leading zero in the
|
||||
hour component.
|
||||
|
||||
* IMPROVEMENT: remind: If a SATISFY expression is not constant and
|
||||
doesn't reference the trigger date somehow, issue a warning.
|
||||
|
||||
* IMPROVEMENT: remind: Add a warning if a user-defined function is
|
||||
redefined. If you do have a use-case that requires you to redefine
|
||||
a function, simply FUNSET it first before FSETting it for the second
|
||||
time.
|
||||
|
||||
* DOCUMENTATION FIX: Clarify man pages and remove some information that
|
||||
has become incorrect as Remind has evolved.
|
||||
|
||||
* BUG FIX: Fix typos in man pages
|
||||
|
||||
* VERSION 5.0 Patch 2 - 2024-07-26
|
||||
|
||||
* IMPROVEMENT: Remind: Revamp how ONCE works. You can now set a
|
||||
|
||||
+44
-14
@@ -1570,7 +1570,35 @@ is replaced with "\fIyy\fR", the last two digits of the year.
|
||||
.TP
|
||||
.B %_
|
||||
(percent-underscore) is replaced with a newline. You can use this to
|
||||
achieve multi-line reminders.
|
||||
achieve multi-line reminders. Note that calendar back-ends vary in
|
||||
how they handle multi-line reminders:
|
||||
.RS
|
||||
.TP
|
||||
.B o
|
||||
Running \fBremind -c\fR preserves newlines in the terminal calendar output.
|
||||
.TP
|
||||
.B o
|
||||
\fBrem2pdf\fR preserves newlines if \fBremind\fR is invoked with the \fB\-pp\fR
|
||||
or \fB\-ppp\fR option.
|
||||
.TP
|
||||
.B o
|
||||
\fBrem2html\fR preserves newlines if \fBremind\fR is invoked with the
|
||||
\fB\-pp\fR option.
|
||||
.TP
|
||||
.B o
|
||||
\fBtkremind\fR preserves newlines.\fR
|
||||
.TP
|
||||
.B o
|
||||
\fBrem2ps\fR converts newlines to spaces. But \fBrem2ps\fR is deprecated;
|
||||
use \fBrem2pdf\fR instead.
|
||||
.TP
|
||||
.B o
|
||||
The "simple calendar" formats (ie, \fBremind\fR's \fB\-s\fR, \fB\-n\fR and
|
||||
\fB\-p\fR options) convert newlines to spaces.
|
||||
.PP
|
||||
All calendar back-ends collapse multiple spaces to a single space and
|
||||
multiple newlines to a single newline.
|
||||
.RE
|
||||
.TP
|
||||
.B %1
|
||||
is replaced with "now", "\fIm\fR minutes from now", "\fIm\fR minutes ago",
|
||||
@@ -2189,8 +2217,8 @@ also to \fBDATETIME\fR constants.
|
||||
.PP
|
||||
.B ZERO VALUES
|
||||
.PP
|
||||
The non-string types all have an associated \fIzero\fR value, which is
|
||||
treated as "false" by the IF command and the logical operators. The
|
||||
All types have an associated \fIzero value\fR, which is
|
||||
treated as \fIfalse\fR by the IF command and the logical operators. The
|
||||
zero values are:
|
||||
.PP
|
||||
.RS
|
||||
@@ -2202,10 +2230,11 @@ zero values are:
|
||||
\fBTIME\fR - 00:00
|
||||
.PP
|
||||
\fBDATETIME\fR - '1990-01-01@00:00'
|
||||
.PP
|
||||
\fBSTRING\fR - "" (the empty string)
|
||||
.RE
|
||||
.PP
|
||||
Additionally, for the purpose of the IF command (but \fInot\fR the
|
||||
logical operators) the empty string "" is considered a false value.
|
||||
Any value other than the \fIzero value\fR is treated as \fItrue\fR.
|
||||
.PP
|
||||
.B OPERATORS
|
||||
.PP
|
||||
@@ -2228,8 +2257,8 @@ C operators.
|
||||
.PP
|
||||
.TP
|
||||
.B !
|
||||
Logical negation. Can be applied to an \fBINT\fR type. If the operand
|
||||
is non-zero, returns zero. Otherwise, returns 1.
|
||||
Logical negation. Can be applied to any type. If the operand
|
||||
is non-zero, returns 0. Otherwise, returns 1.
|
||||
.TP
|
||||
.B \-
|
||||
Unary minus. Can be applied to an \fBINT\fR. Returns the negative
|
||||
@@ -2333,15 +2362,16 @@ If the operands are not of the same type, == returns 0 and != returns
|
||||
.RE
|
||||
.TP
|
||||
.B &&
|
||||
This is the logical AND operator. Neither of its operands can be
|
||||
\fBSTRING\fR type. Returns the second operand if both operands are
|
||||
non-zero. Otherwise, returns whichever operand is zero.
|
||||
This is the logical AND operator. Returns the second operand if both
|
||||
operands are non-zero. Otherwise, returns whichever operand is zero.
|
||||
Operands can be any type and "zero" is interpreted as appropriate for
|
||||
each operand's type.
|
||||
.TP
|
||||
.B ||
|
||||
This is the logical OR operator. Neither of its operands can be
|
||||
\fBSTRING\fR type. It returns the first operand that is non-zero; if
|
||||
both operands are zero, then returns the second operand.
|
||||
|
||||
This is the logical OR operator. It returns the first operand that is
|
||||
non-zero; if both operands are zero, then returns the second operand.
|
||||
Operands can be any type and "zero" is interpreted as appropriate for
|
||||
each operand's type.
|
||||
.PP
|
||||
.B NOTES
|
||||
.PP
|
||||
|
||||
+21
-3
@@ -374,19 +374,37 @@ sub parse_input
|
||||
($1 % 256), ($1 % 256), ($1 % 256));
|
||||
}
|
||||
} elsif ($special eq 'COLOR' || $special eq 'COLOUR') {
|
||||
if ($body =~ /(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/) {
|
||||
if ($body =~ /(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/s) {
|
||||
my($r, $g, $b, $text) = ($1, $2, $3, $4);
|
||||
my $color = sprintf("style=\"color: #%02X%02X%02X;\"",
|
||||
$r % 256, $g % 256, $b % 256);
|
||||
push(@{$days->[$d]}, "<p$class $color>" . escape_html($text) . '</p>');
|
||||
push(@{$days->[$d]}, "<p$class $color>" . fix_whitespace(escape_html($text)) . '</p>');
|
||||
}
|
||||
} elsif ($special eq '*') {
|
||||
push(@{$days->[$d]}, "<p$class>" . escape_html($body) . '</p>');
|
||||
push(@{$days->[$d]}, "<p$class>" . fix_whitespace(escape_html($body)) . '</p>');
|
||||
}
|
||||
}
|
||||
return $found_data;
|
||||
}
|
||||
|
||||
sub fix_whitespace
|
||||
{
|
||||
my ($text) = @_;
|
||||
|
||||
# Collapse multiple spaces/tabs to a single space
|
||||
$text =~ s/[ \t]+/ /gs;
|
||||
|
||||
# Remove whitespace before/after newlines
|
||||
$text =~ s/\s+\n/\n/gs;
|
||||
$text =~ s/\n\s+/\n/gs;
|
||||
# Collapse multiple newlines to a single newline
|
||||
$text =~ s/\n+/\n/gs;
|
||||
|
||||
# Convert newlines to <br />
|
||||
$text =~ s|\n|<br />|g;
|
||||
return $text;
|
||||
}
|
||||
|
||||
sub small_calendar
|
||||
{
|
||||
my($month, $monlen, $url, $first_col) = @_;
|
||||
|
||||
@@ -85,6 +85,18 @@ sub render
|
||||
} else {
|
||||
$body = $self->{body};
|
||||
}
|
||||
|
||||
# Clean up the body:
|
||||
|
||||
# Collapse multiple spaces/tabs to a single space
|
||||
$body =~ s/[ \t]+/ /gs;
|
||||
|
||||
# Remove whitespace before/after newlines
|
||||
$body =~ s/\s+\n/\n/gs;
|
||||
$body =~ s/\n\s+/\n/gs;
|
||||
# Collapse multiple newlines to a single newline
|
||||
$body =~ s/\n+/\n/gs;
|
||||
|
||||
$layout->set_text(Encode::decode('UTF-8', $body));
|
||||
my $desc = Pango::FontDescription->from_string($settings->{entry_font} . ' ' . $settings->{entry_size} . 'px');
|
||||
$layout->set_font_description($desc);
|
||||
|
||||
@@ -1217,6 +1217,13 @@ proc FillCalWindow {} {
|
||||
continue
|
||||
}
|
||||
.cal.t$n configure -state normal
|
||||
|
||||
# Canonicalize spaces and newlines
|
||||
set stuff [regsub -all {[ \t]+} $stuff " "]
|
||||
set stuff [regsub -all {[ \t]+\n} $stuff "\n"]
|
||||
set stuff [regsub -all {\n[ \t]} $stuff "\n"]
|
||||
set stuff [regsub -all {\n+} $stuff "\n"]
|
||||
|
||||
if {[regexp {TKTAG([0-9]+)} $tag all tagno] && "$fntag" != "x"} {
|
||||
.cal.t$n insert end [string trim $stuff] [list REM TAGGED "TKTAG$tagno" "date_$date" $extratags $fntag]
|
||||
.cal.t$n tag bind "TKTAG$tagno" <Enter> "TaggedEnter .cal.t$n"
|
||||
|
||||
+2
-2
@@ -1412,7 +1412,7 @@ static int WriteOneColLine(int col)
|
||||
/* Find the last space char within the column. */
|
||||
width = 0;
|
||||
while (width <= ColSpaces) {
|
||||
if (!*ws) {
|
||||
if (!*ws || *ws == '\n') {
|
||||
wspace = ws;
|
||||
break;
|
||||
}
|
||||
@@ -1518,7 +1518,7 @@ static int WriteOneColLine(int col)
|
||||
|
||||
/* Find the last space char within the column. */
|
||||
while (s - e->pos <= ColSpaces) {
|
||||
if (!*s) {space = s; break;}
|
||||
if (!*s || *s == '\n') {space = s; break;}
|
||||
if (isspace(*s)) space = s;
|
||||
s++;
|
||||
}
|
||||
|
||||
+54
@@ -32,6 +32,55 @@ 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
|
||||
ensure_expr_references_first_local_arg(expr_node *node)
|
||||
{
|
||||
expr_node *other;
|
||||
|
||||
if (!node) {
|
||||
return 0;
|
||||
}
|
||||
if (node->type == N_LOCAL_VAR && node->u.arg == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (ensure_expr_references_first_local_arg(node->child)) {
|
||||
return 1;
|
||||
}
|
||||
other = node->sibling;
|
||||
while (other) {
|
||||
if (ensure_expr_references_first_local_arg(other)) {
|
||||
return 1;
|
||||
}
|
||||
other = other->sibling;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
check_trigger_function(char const *fname, char const *type)
|
||||
{
|
||||
UserFunc *f;
|
||||
if (!*fname) {
|
||||
return;
|
||||
}
|
||||
f = FindUserFunc(fname);
|
||||
if (!f) {
|
||||
if (strcmp(type, "WARN")) {
|
||||
/* Undefined WARN functions are diagnosed elsewhere... */
|
||||
Wprint("Undefined %s function: `%s'", type, fname);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (f->nargs != 1) {
|
||||
Wprint("%s function `%s' defined at %s:%d should take 1 argument but actually takes %d", type, fname, f->filename, f->lineno, f->nargs);
|
||||
return;
|
||||
}
|
||||
if (ensure_expr_references_first_local_arg(f->node)) {
|
||||
return;
|
||||
}
|
||||
Wprint("%s function `%s' defined at %s:%d does not use its argument", type, fname, f->filename, f->lineno);
|
||||
}
|
||||
|
||||
static int
|
||||
ensure_satnode_mentions_trigdate_aux(expr_node *node)
|
||||
{
|
||||
@@ -667,6 +716,11 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
trig->scanfrom = DSEToday;
|
||||
}
|
||||
|
||||
/* Check that any SCHED / WARN / OMITFUNC functions refer to
|
||||
their arguments */
|
||||
check_trigger_function(trig->sched, "SCHED");
|
||||
check_trigger_function(trig->warn, "WARN");
|
||||
check_trigger_function(trig->omitfunc, "OMITFUNC");
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
+32
-7
@@ -31,6 +31,19 @@
|
||||
|
||||
#define SHIP_OUT(s) if(DBufPuts(dbuf, s) != OK) return E_NO_MEM
|
||||
|
||||
static int
|
||||
check_subst_args(UserFunc *f, int n)
|
||||
{
|
||||
if (!f) {
|
||||
return 0;
|
||||
}
|
||||
if (f->nargs == n) {
|
||||
return 1;
|
||||
}
|
||||
Wprint("Function `%s' defined at %s:%d should take %d argument%s, but actually takes %d",
|
||||
f->name, f->filename, f->lineno, n, (n == 1 ? "" : "s"), f->nargs);
|
||||
return 0;
|
||||
}
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoSubst */
|
||||
@@ -67,6 +80,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
int altmode;
|
||||
int r;
|
||||
Value v;
|
||||
UserFunc *func;
|
||||
|
||||
FromDSE(dse, &y, &m, &d);
|
||||
|
||||
@@ -100,7 +114,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
L_AMPM_OVERRIDE (pm, h)
|
||||
#else
|
||||
r = -1;
|
||||
if (UserFuncExists("subst_ampm") == 1) {
|
||||
func = FindUserFunc("subst_ampm");
|
||||
if (func && check_subst_args(func, 1)) {
|
||||
snprintf(s, sizeof(s), "subst_ampm(%d)", h);
|
||||
expr = (char const *) s;
|
||||
r = EvalExpr(&expr, &v, NULL);
|
||||
@@ -129,7 +144,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
L_AMPM_OVERRIDE (cpm, ch)
|
||||
#else
|
||||
r = -1;
|
||||
if (UserFuncExists("subst_ampm") == 1) {
|
||||
func = FindUserFunc("subst_ampm");
|
||||
if (func && check_subst_args(func, 1)) {
|
||||
snprintf(s, sizeof(s), "subst_ampm(%d)", ch);
|
||||
expr = (char const *) s;
|
||||
r = EvalExpr(&expr, &v, NULL);
|
||||
@@ -154,7 +170,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
#ifdef L_ORDINAL_OVERRIDE
|
||||
L_ORDINAL_OVERRIDE;
|
||||
#else
|
||||
if (UserFuncExists("subst_ordinal") == 1) {
|
||||
func = FindUserFunc("subst_ordinal");
|
||||
if (func && check_subst_args(func, 1)) {
|
||||
snprintf(s, sizeof(s), "subst_ordinal(%d)", d);
|
||||
expr = (char const *) s;
|
||||
r = EvalExpr(&expr, &v, NULL);
|
||||
@@ -250,7 +267,13 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
if (!c) {
|
||||
Wprint("Warning: Unterminated %%{...} substitution sequence");
|
||||
}
|
||||
if (UserFuncExists(s) != 3) {
|
||||
func = FindUserFunc(s);
|
||||
if (!func) {
|
||||
Wprint("No substition function `%s' defined", s);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!check_subst_args(func, 3)) {
|
||||
continue;
|
||||
}
|
||||
snprintf(ss, sizeof(s) - (ss-s), "(%d,'%04d-%02d-%02d',%02d:%02d)",
|
||||
@@ -270,7 +293,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
}
|
||||
done = 0;
|
||||
snprintf(uf, sizeof(uf), "subst_%c", tolower(c));
|
||||
if (UserFuncExists(uf) == 3) {
|
||||
func = FindUserFunc(uf);
|
||||
if (func && check_subst_args(func, 3)) {
|
||||
snprintf(s, sizeof(s), "subst_%c(%d,'%04d-%02d-%02d',%02d:%02d)",
|
||||
tolower(c), altmode ? 1 : 0, y, m+1, d, h, min);
|
||||
expr = (char const *) s;
|
||||
@@ -345,7 +369,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
|
||||
if (!done) {
|
||||
snprintf(uf, sizeof(uf), "subst_%cx", tolower(c));
|
||||
if (UserFuncExists(uf) == 3) {
|
||||
func = FindUserFunc(uf);
|
||||
if (func && check_subst_args(func, 3)) {
|
||||
snprintf(s, sizeof(s), "subst_%cx(%d,'%04d-%02d-%02d',%02d:%02d)",
|
||||
tolower(c), altmode ? 1 : 0, y, m+1, d, h, min);
|
||||
expr = (char const *) s;
|
||||
@@ -797,7 +822,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
break;
|
||||
|
||||
case '_':
|
||||
if (PsCal == PSCAL_LEVEL2 || PsCal == PSCAL_LEVEL3 || (mode != CAL_MODE && mode != ADVANCE_MODE && !(MsgCommand && *MsgCommand))) {
|
||||
if (PsCal == PSCAL_LEVEL2 || PsCal == PSCAL_LEVEL3 || DoCalendar || (mode != CAL_MODE && mode != ADVANCE_MODE && !(MsgCommand && *MsgCommand))) {
|
||||
snprintf(s, sizeof(s), "%s", NL);
|
||||
} else {
|
||||
snprintf(s, sizeof(s), " ");
|
||||
|
||||
@@ -241,7 +241,7 @@ EXTERN char *ErrMsg[]
|
||||
/* E_NOREMINDERS */ "No reminders.",
|
||||
/* M_QUEUED */ "%d reminder(s) queued for later today.\n",
|
||||
/* E_EXPECTING_NUMBER */ "Expecting number",
|
||||
/* M_BAD_WARN_FUNC */ "Bad function in WARN clause",
|
||||
/* M_BAD_WARN_FUNC */ "Undefined WARN function",
|
||||
/* E_CANT_CONVERT_TZ */ "Can't convert between time zones",
|
||||
/* E_NO_MATCHING_REMS */ "No files matching *.rem",
|
||||
/* E_STRING_TOO_LONG */ "String too long",
|
||||
|
||||
+23
-31
@@ -1394,17 +1394,23 @@ static int logical_not(expr_node *node, Value *locals, Value *ans, int *nonconst
|
||||
{
|
||||
int r;
|
||||
Value v1;
|
||||
int truthy;
|
||||
|
||||
r = evaluate_expr_node(node->child, locals, &v1, nonconst);
|
||||
if (r != OK) return r;
|
||||
if (v1.type != INT_TYPE) {
|
||||
DBG(debug_evaluation_unop(ans, E_BAD_TYPE, &v1, "!"));
|
||||
DestroyValue(v1);
|
||||
return E_BAD_TYPE;
|
||||
if (v1.type == STR_TYPE) {
|
||||
if (*(v1.v.str)) {
|
||||
truthy = 1;
|
||||
} else {
|
||||
truthy = 0;
|
||||
}
|
||||
} else {
|
||||
truthy = v1.v.val;
|
||||
}
|
||||
ans->type = INT_TYPE;
|
||||
ans->v.val = !(v1.v.val);
|
||||
ans->v.val = !(truthy);
|
||||
DBG(debug_evaluation_unop(ans, OK, &v1, "!"));
|
||||
DestroyValue(v1);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -1446,6 +1452,8 @@ static int logical_binop(expr_node *node, Value *locals, Value *ans, int *noncon
|
||||
Value v;
|
||||
char const *opname = (is_and) ? "&&" : "||";
|
||||
|
||||
int truthy;
|
||||
|
||||
/* Evaluate first arg */
|
||||
int r = evaluate_expr_node(node->child, locals, &v, nonconst);
|
||||
|
||||
@@ -1453,21 +1461,25 @@ static int logical_binop(expr_node *node, Value *locals, Value *ans, int *noncon
|
||||
if (r != OK) return r;
|
||||
|
||||
if (v.type == STR_TYPE) {
|
||||
DBG(debug_evaluation_binop(ans, E_BAD_TYPE, &v, NULL, opname));
|
||||
DestroyValue(v);
|
||||
return E_BAD_TYPE;
|
||||
if (*(v.v.str)) {
|
||||
truthy = 1;
|
||||
} else {
|
||||
truthy = 0;
|
||||
}
|
||||
} else {
|
||||
truthy = v.v.val;
|
||||
}
|
||||
|
||||
if (is_and) {
|
||||
/* If first arg is false, return it */
|
||||
if (!v.v.val) {
|
||||
if (!truthy) {
|
||||
*ans = v;
|
||||
DBG(debug_evaluation_binop(ans, OK, &v, NULL, opname));
|
||||
return OK;
|
||||
}
|
||||
} else {
|
||||
/* If first arg is true, return it */
|
||||
if (v.v.val) {
|
||||
if (truthy) {
|
||||
*ans = v;
|
||||
DBG(debug_evaluation_binop(ans, OK, &v, NULL, opname));
|
||||
return OK;
|
||||
@@ -1476,12 +1488,8 @@ static int logical_binop(expr_node *node, Value *locals, Value *ans, int *noncon
|
||||
|
||||
/* Otherwise, evaluate and return second arg */
|
||||
r = evaluate_expr_node(node->child->sibling, locals, ans, nonconst);
|
||||
if (r == OK && ans->type == STR_TYPE) {
|
||||
DBG(debug_evaluation_binop(ans, E_BAD_TYPE, &v, ans, opname));
|
||||
DestroyValue(*ans);
|
||||
return E_BAD_TYPE;
|
||||
}
|
||||
DBG(debug_evaluation_binop(ans, r, &v, ans, opname));
|
||||
DestroyValue(v);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -2167,22 +2175,6 @@ static expr_node *parse_factor(char const **e, int *r, Var *locals, int level)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If the child is a constant int, optimize! */
|
||||
if (node->type == N_CONSTANT &&
|
||||
node->u.value.type == INT_TYPE) {
|
||||
if (op == '-') {
|
||||
if (node->u.value.v.val == INT_MIN) {
|
||||
*r = E_2LOW;
|
||||
return free_expr_tree(node);
|
||||
}
|
||||
node->u.value.v.val = -node->u.value.v.val;
|
||||
} else {
|
||||
node->u.value.v.val = !node->u.value.v.val;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Not a constant int; we need to add a node */
|
||||
factor_node = alloc_expr_node(r);
|
||||
if (!factor_node) {
|
||||
free_expr_tree(node);
|
||||
|
||||
@@ -583,6 +583,9 @@ rm -f ../tests/once.timestamp
|
||||
tail +2 ../tests/once.timestamp >> ../tests/test.out 2>&1
|
||||
rm -f ../tests/once.timestamp
|
||||
|
||||
# Newlines in calendar output
|
||||
(echo 'REM 16 MSG foo%_bar%_baz wookie quux apple %_ %_ %_ blech'; echo "REM 16 MSG ANOTHER") | ../src/remind -c -w80 - 1 sep 2024 >> ../tests/test.out 2>&1
|
||||
|
||||
# Remove references to SysInclude, which is build-specific
|
||||
grep -F -v '$SysInclude' < ../tests/test.out > ../tests/test.out.1 && mv -f ../tests/test.out.1 ../tests/test.out
|
||||
|
||||
|
||||
+828
-21432
File diff suppressed because one or more lines are too long
+78
-11900
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user