1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
/*
* Copyright (C) 2012-2021 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include "sciteco.h"
#include "undo.h"
/**
* Defines a function undo__insert_val__ARRAY() to insert a value into
* a fixed GArray.
*
* @note
* This optimizes undo token memory consumption under the assumption
* that ARRAY is a global object that does not have to be stored in
* the undo tokens.
* Otherwise, you could simply undo__g_array_insert_val(...).
*
* @fixme
* If we only ever use INDEX == ARRAY->len, we might simplify this
* to undo__append_val__ARRAY().
*/
#define TECO_DEFINE_ARRAY_UNDO_INSERT_VAL(ARRAY, TYPE) \
static inline void \
insert_val__##ARRAY(guint index, TYPE value) \
{ \
g_array_insert_val(ARRAY, index, value); \
} \
TECO_DEFINE_UNDO_CALL(insert_val__##ARRAY, guint, TYPE)
/**
* Defines a function undo__remove_index__ARRAY() to remove a value from
* a fixed GArray.
*
* @note
* See TECO_DEFINE_ARRAY_UNDO_INSERT_VAL().
* undo__g_array_remove_index(...) would also be possible.
*
* @fixme
* If we only ever use INDEX == ARRAY->len-1, we might simplify this
* to undo__pop__ARRAY().
*/
#define TECO_DEFINE_ARRAY_UNDO_REMOVE_INDEX(ARRAY) \
static inline void \
remove_index__##ARRAY(guint index) \
{ \
g_array_remove_index(ARRAY, index); \
} \
TECO_DEFINE_UNDO_CALL(remove_index__##ARRAY, guint)
/**
* Operator type.
* The enumeration value divided by 16 represents
* its precedence (small values mean low precedence).
* In other words, the value's lower nibble is
* reserved for enumerating operators of the
* same precedence.
*/
typedef enum {
/*
* Pseudo operators
*/
TECO_OP_NIL = 0x00,
TECO_OP_NEW,
TECO_OP_BRACE,
TECO_OP_NUMBER,
/*
* Real operators
*/
TECO_OP_POW = 0x60, // ^*
TECO_OP_MOD = 0x50, // ^/
TECO_OP_DIV, // /
TECO_OP_MUL, // *
TECO_OP_SUB = 0x40, // -
TECO_OP_ADD, // +
TECO_OP_AND = 0x30, // &
TECO_OP_XOR = 0x20, // ^#
TECO_OP_OR = 0x10 // #
} teco_operator_t;
extern gint teco_num_sign;
static inline void
teco_set_num_sign(gint sign)
{
teco_undo_gint(teco_num_sign) = sign;
}
extern gint teco_radix;
static inline void
teco_set_radix(gint r)
{
teco_undo_gint(teco_radix) = r;
}
void teco_expressions_push_int(teco_int_t number);
/** Push characters of a C-string. */
static inline void
teco_expressions_push_str(const gchar *str)
{
while (*str)
teco_expressions_push_int(*str++);
}
teco_int_t teco_expressions_peek_num(guint index);
teco_int_t teco_expressions_pop_num(guint index);
gboolean teco_expressions_pop_num_calc(teco_int_t *ret, teco_int_t imply, GError **error);
void teco_expressions_add_digit(gchar digit);
void teco_expressions_push_op(teco_operator_t op);
gboolean teco_expressions_push_calc(teco_operator_t op, GError **error);
/*
* FIXME: Does not work for TECO_OP_* constants as they are treated like int.
*/
#define teco_expressions_push(X) \
(_Generic((X), default : teco_expressions_push_int, \
char * : teco_expressions_push_str, \
const char * : teco_expressions_push_str)(X))
teco_operator_t teco_expressions_peek_op(guint index);
teco_operator_t teco_expressions_pop_op(guint index);
gboolean teco_expressions_eval(gboolean pop_brace, GError **error);
guint teco_expressions_args(void);
gint teco_expressions_first_op(void);
gboolean teco_expressions_discard_args(GError **error);
extern guint teco_brace_level;
void teco_expressions_brace_open(void);
gboolean teco_expressions_brace_return(guint keep_braces, guint args, GError **error);
gboolean teco_expressions_brace_close(GError **error);
void teco_expressions_clear(void);
/** Maximum size required to format a number if teco_radix == 2 */
#define TECO_EXPRESSIONS_FORMAT_LEN \
(1 + sizeof(teco_int_t)*8 + 1)
gchar *teco_expressions_format(gchar *buffer, teco_int_t number);
|