aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/expressions.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/expressions.c')
-rw-r--r--src/expressions.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/src/expressions.c b/src/expressions.c
index 57e2f71..ee6b4dc 100644
--- a/src/expressions.c
+++ b/src/expressions.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2023 Robin Haberkorn
+ * Copyright (C) 2012-2024 Robin Haberkorn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -86,7 +86,7 @@ teco_int_t
teco_expressions_pop_num(guint index)
{
teco_int_t n = 0;
- teco_operator_t op = teco_expressions_pop_op(0);
+ G_GNUC_UNUSED teco_operator_t op = teco_expressions_pop_op(0);
g_assert(op == TECO_OP_NUMBER);
@@ -114,11 +114,12 @@ teco_expressions_pop_num_calc(teco_int_t *ret, teco_int_t imply, GError **error)
}
void
-teco_expressions_add_digit(gchar digit)
+teco_expressions_add_digit(gunichar digit)
{
teco_int_t n = teco_expressions_args() > 0 ? teco_expressions_pop_num(0) : 0;
- teco_expressions_push(n*teco_radix + (n < 0 ? -1 : 1)*(digit - '0'));
+ /* use g_unichar_digit_value()? */
+ teco_expressions_push(n*teco_radix + (n < 0 ? -1 : 1)*((gint)digit - '0'));
}
void
@@ -184,7 +185,28 @@ teco_expressions_calc(GError **error)
switch (op) {
case TECO_OP_POW:
- for (result = 1; vright--; result *= vleft);
+ if (!vright) {
+ result = vleft < 0 ? -1 : 1;
+ break;
+ }
+ if (vright < 0) {
+ if (!vleft) {
+ g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED,
+ "Negative power of 0 is not defined");
+ return FALSE;
+ }
+ result = ABS(vleft) == 1 ? vleft : 0;
+ break;
+ }
+ result = 1;
+ for (;;) {
+ if (vright & 1)
+ result *= vleft;
+ vright >>= 1;
+ if (!vright)
+ break;
+ vleft *= vleft;
+ }
break;
case TECO_OP_MUL:
result = vleft * vright;
@@ -297,6 +319,9 @@ guint teco_brace_level = 0;
void
teco_expressions_brace_open(void)
{
+ while (teco_operators->len > 0 && teco_expressions_peek_op(0) == TECO_OP_NEW)
+ teco_expressions_pop_op(0);
+
teco_expressions_push_op(TECO_OP_BRACE);
teco_undo_guint(teco_brace_level)++;
}
@@ -374,11 +399,9 @@ teco_expressions_format(gchar *buffer, teco_int_t number)
return p;
}
-#ifndef NDEBUG
-static void __attribute__((destructor))
+static void TECO_DEBUG_CLEANUP
teco_expressions_cleanup(void)
{
g_array_free(teco_numbers, TRUE);
g_array_free(teco_operators, TRUE);
}
-#endif